diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.122-123.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.122-123.patch new file mode 100644 index 0000000000..8bc20b1521 --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.122-123.patch @@ -0,0 +1,2819 @@ +diff --git a/Makefile b/Makefile +index fd613135366c83..170507f68a9aad 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 122 ++SUBLEVEL = 123 + EXTRAVERSION = + NAME = Pinguïn Aangedreven + +diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c +index 19c494499746ee..032afb40dfa779 100644 +--- a/arch/arm64/kernel/signal.c ++++ b/arch/arm64/kernel/signal.c +@@ -202,29 +202,39 @@ static int preserve_fpsimd_context(struct fpsimd_context __user *ctx) + return err ? -EFAULT : 0; + } + +-static int restore_fpsimd_context(struct user_ctxs *user) ++static int read_fpsimd_context(struct user_fpsimd_state *fpsimd, ++ struct user_ctxs *user) + { +- struct user_fpsimd_state fpsimd; +- int err = 0; ++ int err; + + /* check the size information */ + if (user->fpsimd_size != sizeof(struct fpsimd_context)) + return -EINVAL; + + /* copy the FP and status/control registers */ +- err = __copy_from_user(fpsimd.vregs, &(user->fpsimd->vregs), +- sizeof(fpsimd.vregs)); +- __get_user_error(fpsimd.fpsr, &(user->fpsimd->fpsr), err); +- __get_user_error(fpsimd.fpcr, &(user->fpsimd->fpcr), err); ++ err = __copy_from_user(fpsimd->vregs, &(user->fpsimd->vregs), ++ sizeof(fpsimd->vregs)); ++ __get_user_error(fpsimd->fpsr, &(user->fpsimd->fpsr), err); ++ __get_user_error(fpsimd->fpcr, &(user->fpsimd->fpcr), err); ++ ++ return err ? -EFAULT : 0; ++} ++ ++static int restore_fpsimd_context(struct user_ctxs *user) ++{ ++ struct user_fpsimd_state fpsimd; ++ int err; ++ ++ err = read_fpsimd_context(&fpsimd, user); ++ if (err) ++ return err; + + clear_thread_flag(TIF_SVE); + current->thread.fp_type = FP_STATE_FPSIMD; + + /* load the hardware registers from the fpsimd_state structure */ +- if (!err) +- fpsimd_update_current_state(&fpsimd); +- +- return err ? -EFAULT : 0; ++ fpsimd_update_current_state(&fpsimd); ++ return 0; + } + + +@@ -276,6 +286,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user) + unsigned int vl, vq; + struct user_fpsimd_state fpsimd; + u16 user_vl, flags; ++ bool sm; + + if (user->sve_size < sizeof(*user->sve)) + return -EINVAL; +@@ -285,7 +296,8 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user) + if (err) + return err; + +- if (flags & SVE_SIG_FLAG_SM) { ++ sm = flags & SVE_SIG_FLAG_SM; ++ if (sm) { + if (!system_supports_sme()) + return -EINVAL; + +@@ -305,12 +317,17 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user) + if (user_vl != vl) + return -EINVAL; + +- if (user->sve_size == sizeof(*user->sve)) { +- clear_thread_flag(TIF_SVE); +- current->thread.svcr &= ~SVCR_SM_MASK; +- current->thread.fp_type = FP_STATE_FPSIMD; +- goto fpsimd_only; +- } ++ /* ++ * Non-streaming SVE state may be preserved without an SVE payload, in ++ * which case the SVE context only has a header with VL==0, and all ++ * state can be restored from the FPSIMD context. ++ * ++ * Streaming SVE state is always preserved with an SVE payload. For ++ * consistency and robustness, reject restoring streaming SVE state ++ * without an SVE payload. ++ */ ++ if (!sm && user->sve_size == sizeof(*user->sve)) ++ return restore_fpsimd_context(user); + + vq = sve_vq_from_vl(vl); + +@@ -327,12 +344,28 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user) + fpsimd_flush_task_state(current); + /* From now, fpsimd_thread_switch() won't touch thread.sve_state */ + ++ if (sm) { ++ sme_alloc(current, false); ++ if (!current->thread.sme_state) ++ return -ENOMEM; ++ } ++ + sve_alloc(current, true); + if (!current->thread.sve_state) { + clear_thread_flag(TIF_SVE); + return -ENOMEM; + } + ++ if (sm) { ++ current->thread.svcr |= SVCR_SM_MASK; ++ set_thread_flag(TIF_SME); ++ } else { ++ current->thread.svcr &= ~SVCR_SM_MASK; ++ set_thread_flag(TIF_SVE); ++ } ++ ++ current->thread.fp_type = FP_STATE_SVE; ++ + err = __copy_from_user(current->thread.sve_state, + (char __user const *)user->sve + + SVE_SIG_REGS_OFFSET, +@@ -340,25 +373,14 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user) + if (err) + return -EFAULT; + +- if (flags & SVE_SIG_FLAG_SM) +- current->thread.svcr |= SVCR_SM_MASK; +- else +- set_thread_flag(TIF_SVE); +- current->thread.fp_type = FP_STATE_SVE; +- +-fpsimd_only: +- /* copy the FP and status/control registers */ +- /* restore_sigframe() already checked that user->fpsimd != NULL. */ +- err = __copy_from_user(fpsimd.vregs, user->fpsimd->vregs, +- sizeof(fpsimd.vregs)); +- __get_user_error(fpsimd.fpsr, &user->fpsimd->fpsr, err); +- __get_user_error(fpsimd.fpcr, &user->fpsimd->fpcr, err); ++ err = read_fpsimd_context(&fpsimd, user); ++ if (err) ++ return err; + +- /* load the hardware registers from the fpsimd_state structure */ +- if (!err) +- fpsimd_update_current_state(&fpsimd); ++ /* Merge the FPSIMD registers into the SVE state */ ++ fpsimd_update_current_state(&fpsimd); + +- return err ? -EFAULT : 0; ++ return 0; + } + + #else /* ! CONFIG_ARM64_SVE */ +diff --git a/arch/riscv/include/asm/compat.h b/arch/riscv/include/asm/compat.h +index 6b79287baecc00..2290b8b9b16f5d 100644 +--- a/arch/riscv/include/asm/compat.h ++++ b/arch/riscv/include/asm/compat.h +@@ -2,7 +2,7 @@ + #ifndef __ASM_COMPAT_H + #define __ASM_COMPAT_H + +-#define COMPAT_UTS_MACHINE "riscv\0\0" ++#define COMPAT_UTS_MACHINE "riscv32\0\0" + + /* + * Architecture specific compatibility types +diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c +index 70320b8f1aa1c0..e38f3c4458c90a 100644 +--- a/drivers/bluetooth/hci_ldisc.c ++++ b/drivers/bluetooth/hci_ldisc.c +@@ -682,6 +682,8 @@ static int hci_uart_register_dev(struct hci_uart *hu) + return err; + } + ++ set_bit(HCI_UART_PROTO_INIT, &hu->flags); ++ + if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags)) + return 0; + +@@ -709,8 +711,6 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id) + + hu->proto = p; + +- set_bit(HCI_UART_PROTO_INIT, &hu->flags); +- + err = hci_uart_register_dev(hu); + if (err) { + return err; +diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c +index 633493b860f2d1..bf701766f4d05c 100644 +--- a/drivers/gpio/gpio-pca953x.c ++++ b/drivers/gpio/gpio-pca953x.c +@@ -811,6 +811,8 @@ static void pca953x_irq_shutdown(struct irq_data *d) + clear_bit(hwirq, chip->irq_trig_fall); + clear_bit(hwirq, chip->irq_trig_level_low); + clear_bit(hwirq, chip->irq_trig_level_high); ++ ++ pca953x_irq_mask(d); + } + + static void pca953x_irq_print_chip(struct irq_data *data, struct seq_file *p) +diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c +index 4173ea19550ef7..752bbc0c3d9db1 100644 +--- a/drivers/gpio/gpio-rockchip.c ++++ b/drivers/gpio/gpio-rockchip.c +@@ -18,7 +18,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -157,12 +156,6 @@ static int rockchip_gpio_set_direction(struct gpio_chip *chip, + unsigned long flags; + u32 data = input ? 0 : 1; + +- +- if (input) +- pinctrl_gpio_direction_input(bank->pin_base + offset); +- else +- pinctrl_gpio_direction_output(bank->pin_base + offset); +- + raw_spin_lock_irqsave(&bank->slock, flags); + rockchip_gpio_writel_bit(bank, offset, data, bank->gpio_regs->port_ddr); + raw_spin_unlock_irqrestore(&bank->slock, flags); +@@ -584,7 +577,6 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank) + gc->ngpio = bank->nr_pins; + gc->label = bank->name; + gc->parent = bank->dev; +- gc->can_sleep = true; + + ret = gpiochip_add_data(gc, bank); + if (ret) { +diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c +index 86de8740c0d466..69d4297ae57549 100644 +--- a/drivers/gpio/gpiolib-acpi.c ++++ b/drivers/gpio/gpiolib-acpi.c +@@ -1228,7 +1228,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, + mutex_unlock(&achip->conn_lock); + + if (function == ACPI_WRITE) +- gpiod_set_raw_value_cansleep(desc, !!(*value & BIT(i))); ++ gpiod_set_raw_value_cansleep(desc, !!(*value & BIT_ULL(i))); + else + *value |= (u64)gpiod_get_raw_value_cansleep(desc) << i; + } +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index 017552e79178fa..9481d450809b56 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -3582,7 +3582,6 @@ int amdgpu_device_init(struct amdgpu_device *adev, + mutex_init(&adev->grbm_idx_mutex); + mutex_init(&adev->mn_lock); + mutex_init(&adev->virt.vf_errors.lock); +- mutex_init(&adev->virt.rlcg_reg_lock); + hash_init(adev->mn_hash); + mutex_init(&adev->psp.mutex); + mutex_init(&adev->notifier_lock); +@@ -3604,6 +3603,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, + spin_lock_init(&adev->se_cac_idx_lock); + spin_lock_init(&adev->audio_endpt_idx_lock); + spin_lock_init(&adev->mm_stats.lock); ++ spin_lock_init(&adev->virt.rlcg_reg_lock); + + INIT_LIST_HEAD(&adev->shadow_list); + mutex_init(&adev->shadow_list_lock); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +index 0b6a0e149f1c4c..3c24637f3d6e97 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +@@ -452,7 +452,15 @@ void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr, + uint32_t hash; + uint64_t tmp; + +- ih = adev->irq.retry_cam_enabled ? &adev->irq.ih_soft : &adev->irq.ih1; ++ if (adev->irq.retry_cam_enabled) ++ return; ++ else if (adev->irq.ih1.ring_size) ++ ih = &adev->irq.ih1; ++ else if (adev->irq.ih_soft.enabled) ++ ih = &adev->irq.ih_soft; ++ else ++ return; ++ + /* Get the WPTR of the last entry in IH ring */ + last_wptr = amdgpu_ih_get_wptr(adev, ih); + /* Order wptr with ring data. */ +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +index 5a4b1b625f0371..0f4661d1f23be4 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +@@ -1007,6 +1007,7 @@ static u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v + void *scratch_reg2; + void *scratch_reg3; + void *spare_int; ++ unsigned long flags; + + if (!adev->gfx.rlc.rlcg_reg_access_supported) { + dev_err(adev->dev, +@@ -1028,7 +1029,7 @@ static u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v + scratch_reg2 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg2; + scratch_reg3 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg3; + +- mutex_lock(&adev->virt.rlcg_reg_lock); ++ spin_lock_irqsave(&adev->virt.rlcg_reg_lock, flags); + + if (reg_access_ctrl->spare_int) + spare_int = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->spare_int; +@@ -1086,7 +1087,7 @@ static u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v + + ret = readl(scratch_reg0); + +- mutex_unlock(&adev->virt.rlcg_reg_lock); ++ spin_unlock_irqrestore(&adev->virt.rlcg_reg_lock, flags); + + return ret; + } +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +index 891713757a8f5a..bffbb7ef40d26d 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +@@ -267,7 +267,8 @@ struct amdgpu_virt { + /* the ucode id to signal the autoload */ + uint32_t autoload_ucode_id; + +- struct mutex rlcg_reg_lock; ++ /* Spinlock to protect access to the RLCG register interface */ ++ spinlock_t rlcg_reg_lock; + }; + + struct amdgpu_video_codec_info; +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +index 53c99bc6abb333..1c29b4d04a2ca2 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +@@ -6459,7 +6459,7 @@ static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring) + memcpy_toio(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd)); + /* reset the ring */ + ring->wptr = 0; +- *ring->wptr_cpu_addr = 0; ++ atomic64_set((atomic64_t *)ring->wptr_cpu_addr, 0); + amdgpu_ring_clear_ring(ring); + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +index 7591a2803ae126..ed3e47a7eca1fe 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +@@ -3699,7 +3699,7 @@ static int gfx_v11_0_gfx_init_queue(struct amdgpu_ring *ring) + memcpy_toio(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd)); + /* reset the ring */ + ring->wptr = 0; +- *ring->wptr_cpu_addr = 0; ++ atomic64_set((atomic64_t *)ring->wptr_cpu_addr, 0); + amdgpu_ring_clear_ring(ring); + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c +index 7819f5d584f597..115fdb6a25fa6e 100644 +--- a/drivers/gpu/drm/amd/amdgpu/soc21.c ++++ b/drivers/gpu/drm/amd/amdgpu/soc21.c +@@ -218,7 +218,13 @@ static u32 soc21_get_config_memsize(struct amdgpu_device *adev) + + static u32 soc21_get_xclk(struct amdgpu_device *adev) + { +- return adev->clock.spll.reference_freq; ++ u32 reference_clock = adev->clock.spll.reference_freq; ++ ++ /* reference clock is actually 99.81 Mhz rather than 100 Mhz */ ++ if ((adev->flags & AMD_IS_APU) && reference_clock == 10000) ++ return 9981; ++ ++ return reference_clock; + } + + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +index f0b472e84a53d7..e52c2bb1b6265b 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +@@ -781,7 +781,7 @@ enum dc_status dcn20_enable_stream_timing( + return DC_ERROR_UNEXPECTED; + } + +- fsleep(stream->timing.v_total * (stream->timing.h_total * 10000u / stream->timing.pix_clk_100hz)); ++ udelay(stream->timing.v_total * (stream->timing.h_total * 10000u / stream->timing.pix_clk_100hz)); + + params.vertical_total_min = stream->adjust.v_total_min; + params.vertical_total_max = stream->adjust.v_total_max; +diff --git a/drivers/gpu/drm/imx/ipuv3/imx-tve.c b/drivers/gpu/drm/imx/ipuv3/imx-tve.c +index d6832f506322cd..b9391ccb6d3cb3 100644 +--- a/drivers/gpu/drm/imx/ipuv3/imx-tve.c ++++ b/drivers/gpu/drm/imx/ipuv3/imx-tve.c +@@ -521,6 +521,13 @@ static const struct component_ops imx_tve_ops = { + .bind = imx_tve_bind, + }; + ++static void imx_tve_put_device(void *_dev) ++{ ++ struct device *dev = _dev; ++ ++ put_device(dev); ++} ++ + static int imx_tve_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -542,6 +549,12 @@ static int imx_tve_probe(struct platform_device *pdev) + if (ddc_node) { + tve->ddc = of_find_i2c_adapter_by_node(ddc_node); + of_node_put(ddc_node); ++ if (tve->ddc) { ++ ret = devm_add_action_or_reset(dev, imx_tve_put_device, ++ &tve->ddc->dev); ++ if (ret) ++ return ret; ++ } + } + + tve->mode = of_get_tve_mode(np); +diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +index 4654c0f362c7de..6666d8f6c17a60 100644 +--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c ++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +@@ -690,8 +690,6 @@ const struct adreno_reglist a690_hwcg[] = { + {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111}, + {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555}, + {REG_A6XX_GPU_GMU_AO_GMU_CGC_MODE_CNTL, 0x20200}, +- {REG_A6XX_GPU_GMU_AO_GMU_CGC_DELAY_CNTL, 0x10111}, +- {REG_A6XX_GPU_GMU_AO_GMU_CGC_HYST_CNTL, 0x5555}, + {} + }; + +diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c +index 6d5e828fa39e3d..1462837fda5a80 100644 +--- a/drivers/gpu/drm/radeon/radeon_fence.c ++++ b/drivers/gpu/drm/radeon/radeon_fence.c +@@ -362,14 +362,6 @@ static bool radeon_fence_is_signaled(struct dma_fence *f) + return true; + } + +- if (down_read_trylock(&rdev->exclusive_lock)) { +- radeon_fence_process(rdev, ring); +- up_read(&rdev->exclusive_lock); +- +- if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq) { +- return true; +- } +- } + return false; + } + +diff --git a/drivers/misc/mei/mei-trace.h b/drivers/misc/mei/mei-trace.h +index fe46ff2b9d69f5..770e7897b88cc1 100644 +--- a/drivers/misc/mei/mei-trace.h ++++ b/drivers/misc/mei/mei-trace.h +@@ -21,18 +21,18 @@ TRACE_EVENT(mei_reg_read, + TP_ARGS(dev, reg, offs, val), + TP_STRUCT__entry( + __string(dev, dev_name(dev)) +- __field(const char *, reg) ++ __string(reg, reg) + __field(u32, offs) + __field(u32, val) + ), + TP_fast_assign( + __assign_str(dev, dev_name(dev)); +- __entry->reg = reg; ++ __assign_str(reg, reg); + __entry->offs = offs; + __entry->val = val; + ), + TP_printk("[%s] read %s:[%#x] = %#x", +- __get_str(dev), __entry->reg, __entry->offs, __entry->val) ++ __get_str(dev), __get_str(reg), __entry->offs, __entry->val) + ); + + TRACE_EVENT(mei_reg_write, +@@ -40,18 +40,18 @@ TRACE_EVENT(mei_reg_write, + TP_ARGS(dev, reg, offs, val), + TP_STRUCT__entry( + __string(dev, dev_name(dev)) +- __field(const char *, reg) ++ __string(reg, reg) + __field(u32, offs) + __field(u32, val) + ), + TP_fast_assign( + __assign_str(dev, dev_name(dev)); +- __entry->reg = reg; ++ __assign_str(reg, reg); + __entry->offs = offs; + __entry->val = val; + ), + TP_printk("[%s] write %s[%#x] = %#x", +- __get_str(dev), __entry->reg, __entry->offs, __entry->val) ++ __get_str(dev), __get_str(reg), __entry->offs, __entry->val) + ); + + TRACE_EVENT(mei_pci_cfg_read, +@@ -59,18 +59,18 @@ TRACE_EVENT(mei_pci_cfg_read, + TP_ARGS(dev, reg, offs, val), + TP_STRUCT__entry( + __string(dev, dev_name(dev)) +- __field(const char *, reg) ++ __string(reg, reg) + __field(u32, offs) + __field(u32, val) + ), + TP_fast_assign( + __assign_str(dev, dev_name(dev)); +- __entry->reg = reg; ++ __assign_str(reg, reg); + __entry->offs = offs; + __entry->val = val; + ), + TP_printk("[%s] pci cfg read %s:[%#x] = %#x", +- __get_str(dev), __entry->reg, __entry->offs, __entry->val) ++ __get_str(dev), __get_str(reg), __entry->offs, __entry->val) + ); + + #endif /* _MEI_TRACE_H_ */ +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 9385c3ac0c83c7..4373e300879d92 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -3137,8 +3137,8 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 + __func__, &sip); + return; + } +- slave->last_rx = jiffies; +- slave->target_last_arp_rx[i] = jiffies; ++ WRITE_ONCE(slave->last_rx, jiffies); ++ WRITE_ONCE(slave->target_last_arp_rx[i], jiffies); + } + + static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, +@@ -3357,8 +3357,8 @@ static void bond_validate_na(struct bonding *bond, struct slave *slave, + __func__, saddr); + return; + } +- slave->last_rx = jiffies; +- slave->target_last_arp_rx[i] = jiffies; ++ WRITE_ONCE(slave->last_rx, jiffies); ++ WRITE_ONCE(slave->target_last_arp_rx[i], jiffies); + } + + static int bond_na_rcv(const struct sk_buff *skb, struct bonding *bond, +@@ -3428,7 +3428,7 @@ int bond_rcv_validate(const struct sk_buff *skb, struct bonding *bond, + (slave_do_arp_validate_only(bond) && is_ipv6) || + #endif + !slave_do_arp_validate_only(bond)) +- slave->last_rx = jiffies; ++ WRITE_ONCE(slave->last_rx, jiffies); + return RX_HANDLER_ANOTHER; + } else if (is_arp) { + return bond_arp_rcv(skb, bond, slave); +@@ -3496,7 +3496,7 @@ static void bond_loadbalance_arp_mon(struct bonding *bond) + + if (slave->link != BOND_LINK_UP) { + if (bond_time_in_interval(bond, last_tx, 1) && +- bond_time_in_interval(bond, slave->last_rx, 1)) { ++ bond_time_in_interval(bond, READ_ONCE(slave->last_rx), 1)) { + + bond_propose_link_state(slave, BOND_LINK_UP); + slave_state_changed = 1; +@@ -3520,8 +3520,10 @@ static void bond_loadbalance_arp_mon(struct bonding *bond) + * when the source ip is 0, so don't take the link down + * if we don't know our ip yet + */ +- if (!bond_time_in_interval(bond, last_tx, bond->params.missed_max) || +- !bond_time_in_interval(bond, slave->last_rx, bond->params.missed_max)) { ++ if (!bond_time_in_interval(bond, last_tx, ++ bond->params.missed_max) || ++ !bond_time_in_interval(bond, READ_ONCE(slave->last_rx), ++ bond->params.missed_max)) { + + bond_propose_link_state(slave, BOND_LINK_DOWN); + slave_state_changed = 1; +diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c +index a2fa068193e3be..5a2a935945c4cf 100644 +--- a/drivers/net/bonding/bond_options.c ++++ b/drivers/net/bonding/bond_options.c +@@ -1124,7 +1124,7 @@ static void _bond_options_arp_ip_target_set(struct bonding *bond, int slot, + + if (slot >= 0 && slot < BOND_MAX_ARP_TARGETS) { + bond_for_each_slave(bond, slave, iter) +- slave->target_last_arp_rx[slot] = last_rx; ++ WRITE_ONCE(slave->target_last_arp_rx[slot], last_rx); + targets[slot] = target; + } + } +@@ -1193,8 +1193,8 @@ static int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target) + bond_for_each_slave(bond, slave, iter) { + targets_rx = slave->target_last_arp_rx; + for (i = ind; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++) +- targets_rx[i] = targets_rx[i+1]; +- targets_rx[i] = 0; ++ WRITE_ONCE(targets_rx[i], READ_ONCE(targets_rx[i+1])); ++ WRITE_ONCE(targets_rx[i], 0); + } + for (i = ind; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++) + targets[i] = targets[i+1]; +@@ -1349,7 +1349,7 @@ static void _bond_options_ns_ip6_target_set(struct bonding *bond, int slot, + + if (slot >= 0 && slot < BOND_MAX_NS_TARGETS) { + bond_for_each_slave(bond, slave, iter) { +- slave->target_last_arp_rx[slot] = last_rx; ++ WRITE_ONCE(slave->target_last_arp_rx[slot], last_rx); + slave_set_ns_maddr(bond, slave, target, &targets[slot]); + } + targets[slot] = *target; +diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c +index 63439affd59d56..7a3c6493a35360 100644 +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -607,7 +607,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + { + struct gs_usb *parent = urb->context; + struct gs_can *dev; +- struct net_device *netdev; ++ struct net_device *netdev = NULL; + int rc; + struct net_device_stats *stats; + struct gs_host_frame *hf = urb->transfer_buffer; +@@ -765,7 +765,7 @@ device_detach: + } + } else if (rc != -ESHUTDOWN && net_ratelimit()) { + netdev_info(netdev, "failed to re-submit IN URB: %pe\n", +- ERR_PTR(urb->status)); ++ ERR_PTR(rc)); + } + } + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +index f0647286c68b25..3127f335e0b7b2 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +@@ -1272,7 +1272,7 @@ struct bcmasp_intf *bcmasp_interface_create(struct bcmasp_priv *priv, + netdev_err(intf->ndev, "invalid PHY mode: %s for port %d\n", + phy_modes(intf->phy_interface), intf->port); + ret = -EINVAL; +- goto err_free_netdev; ++ goto err_deregister_fixed_link; + } + + ret = of_get_ethdev_address(ndev_dn, ndev); +@@ -1295,6 +1295,9 @@ struct bcmasp_intf *bcmasp_interface_create(struct bcmasp_priv *priv, + + return intf; + ++err_deregister_fixed_link: ++ if (of_phy_is_fixed_link(ndev_dn)) ++ of_phy_deregister_fixed_link(ndev_dn); + err_free_netdev: + free_netdev(ndev); + err: +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index e846246261b940..72e394dc68f4e7 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -6711,7 +6711,6 @@ void ice_update_vsi_stats(struct ice_vsi *vsi) + pf->stats.illegal_bytes + + pf->stats.rx_len_errors + + pf->stats.rx_undersize + +- pf->hw_csum_rx_error + + pf->stats.rx_jabber + + pf->stats.rx_fragments + + pf->stats.rx_oversize; +diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c +index d2757cc1161391..038382a0b8e9f8 100644 +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c +@@ -1389,7 +1389,7 @@ int mvpp2_ethtool_cls_rule_ins(struct mvpp2_port *port, + efs->rule.flow_type = mvpp2_cls_ethtool_flow_to_type(info->fs.flow_type); + if (efs->rule.flow_type < 0) { + ret = efs->rule.flow_type; +- goto clean_rule; ++ goto clean_eth_rule; + } + + ret = mvpp2_cls_rfs_parse_rule(&efs->rule); +diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c +index 7a30095b3486f3..c385084546639d 100644 +--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c ++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c +@@ -998,7 +998,7 @@ int octep_device_setup(struct octep_device *oct) + + ret = octep_ctrl_net_init(oct); + if (ret) +- return ret; ++ goto unsupported_dev; + + atomic_set(&oct->hb_miss_cnt, 0); + INIT_DELAYED_WORK(&oct->hb_task, octep_hb_timeout_task); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +index 5161bf51fa110c..fdf664e9c46e94 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +@@ -350,7 +350,8 @@ void mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry, + attrs->replay_esn.esn = sa_entry->esn_state.esn; + attrs->replay_esn.esn_msb = sa_entry->esn_state.esn_msb; + attrs->replay_esn.overlap = sa_entry->esn_state.overlap; +- if (attrs->dir == XFRM_DEV_OFFLOAD_OUT) ++ if (attrs->dir == XFRM_DEV_OFFLOAD_OUT || ++ x->xso.type != XFRM_DEV_OFFLOAD_PACKET) + goto skip_replay_window; + + switch (x->replay_esn->replay_window) { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 03201bcda1a689..71749497ec27a3 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -3743,6 +3743,8 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) + mlx5e_queue_update_stats(priv); + } + ++ netdev_stats_to_stats64(stats, &dev->stats); ++ + if (mlx5e_is_uplink_rep(priv)) { + struct mlx5e_vport_stats *vstats = &priv->stats.vport; + +@@ -3759,20 +3761,21 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) + mlx5e_fold_sw_stats64(priv, stats); + } + +- stats->rx_missed_errors = priv->stats.qcnt.rx_out_of_buffer; ++ stats->rx_missed_errors += priv->stats.qcnt.rx_out_of_buffer; ++ stats->rx_dropped += PPORT_2863_GET(pstats, if_in_discards); + +- stats->rx_length_errors = ++ stats->rx_length_errors += + PPORT_802_3_GET(pstats, a_in_range_length_errors) + + PPORT_802_3_GET(pstats, a_out_of_range_length_field) + + PPORT_802_3_GET(pstats, a_frame_too_long_errors) + + VNIC_ENV_GET(&priv->stats.vnic, eth_wqe_too_small); +- stats->rx_crc_errors = ++ stats->rx_crc_errors += + PPORT_802_3_GET(pstats, a_frame_check_sequence_errors); +- stats->rx_frame_errors = PPORT_802_3_GET(pstats, a_alignment_errors); +- stats->tx_aborted_errors = PPORT_2863_GET(pstats, if_out_discards); +- stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors + +- stats->rx_frame_errors; +- stats->tx_errors = stats->tx_aborted_errors + stats->tx_carrier_errors; ++ stats->rx_frame_errors += PPORT_802_3_GET(pstats, a_alignment_errors); ++ stats->tx_aborted_errors += PPORT_2863_GET(pstats, if_out_discards); ++ stats->rx_errors += stats->rx_length_errors + stats->rx_crc_errors + ++ stats->rx_frame_errors; ++ stats->tx_errors += stats->tx_aborted_errors + stats->tx_carrier_errors; + } + + static void mlx5e_nic_set_rx_mode(struct mlx5e_priv *priv) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +index 2be9c69daad5fe..f1f42250573115 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +@@ -2025,11 +2025,14 @@ static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow, + + static void mlx5e_tc_del_fdb_peers_flow(struct mlx5e_tc_flow *flow) + { ++ struct mlx5_devcom_comp_dev *devcom; ++ struct mlx5_devcom_comp_dev *pos; ++ struct mlx5_eswitch *peer_esw; + int i; + +- for (i = 0; i < MLX5_MAX_PORTS; i++) { +- if (i == mlx5_get_dev_index(flow->priv->mdev)) +- continue; ++ devcom = flow->priv->mdev->priv.eswitch->devcom; ++ mlx5_devcom_for_each_peer_entry(devcom, peer_esw, pos) { ++ i = mlx5_get_dev_index(peer_esw->dev); + mlx5e_tc_del_fdb_peer_flow(flow, i); + } + } +@@ -5404,12 +5407,16 @@ int mlx5e_tc_num_filters(struct mlx5e_priv *priv, unsigned long flags) + + void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw) + { ++ struct mlx5_devcom_comp_dev *devcom; ++ struct mlx5_devcom_comp_dev *pos; + struct mlx5e_tc_flow *flow, *tmp; ++ struct mlx5_eswitch *peer_esw; + int i; + +- for (i = 0; i < MLX5_MAX_PORTS; i++) { +- if (i == mlx5_get_dev_index(esw->dev)) +- continue; ++ devcom = esw->devcom; ++ ++ mlx5_devcom_for_each_peer_entry(devcom, peer_esw, pos) { ++ i = mlx5_get_dev_index(peer_esw->dev); + list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows[i], peer[i]) + mlx5e_tc_del_fdb_peers_flow(flow); + } +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 093ed86a0acd8c..db51c500ed3593 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 +@@ -188,7 +188,7 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw, + if (IS_ERR(vport->ingress.acl)) { + err = PTR_ERR(vport->ingress.acl); + vport->ingress.acl = NULL; +- return err; ++ goto out; + } + + err = esw_acl_ingress_lgcy_groups_create(esw, vport); +diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c +index 2e2826c901fcca..b741d335b1dc45 100644 +--- a/drivers/net/ethernet/rocker/rocker_main.c ++++ b/drivers/net/ethernet/rocker/rocker_main.c +@@ -1525,9 +1525,8 @@ static void rocker_world_port_post_fini(struct rocker_port *rocker_port) + { + struct rocker_world_ops *wops = rocker_port->rocker->wops; + +- if (!wops->port_post_fini) +- return; +- wops->port_post_fini(rocker_port); ++ if (wops->port_post_fini) ++ wops->port_post_fini(rocker_port); + kfree(rocker_port->wpriv); + } + +diff --git a/drivers/net/tap.c b/drivers/net/tap.c +index e7212a64a59183..2c4f9d19827f38 100644 +--- a/drivers/net/tap.c ++++ b/drivers/net/tap.c +@@ -1330,9 +1330,9 @@ int tap_queue_resize(struct tap_dev *tap) + list_for_each_entry(q, &tap->queue_list, next) + rings[i++] = &q->ring; + +- ret = ptr_ring_resize_multiple(rings, n, +- dev->tx_queue_len, GFP_KERNEL, +- __skb_array_destroy_skb); ++ ret = ptr_ring_resize_multiple_bh(rings, n, ++ dev->tx_queue_len, GFP_KERNEL, ++ __skb_array_destroy_skb); + + kfree(rings); + return ret; +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 9baa1380893327..deb6eb3a240a03 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -1184,10 +1184,6 @@ static int team_port_add(struct team *team, struct net_device *port_dev, + return -EPERM; + } + +- err = team_dev_type_check_change(dev, port_dev); +- if (err) +- return err; +- + if (port_dev->flags & IFF_UP) { + NL_SET_ERR_MSG(extack, "Device is up. Set it down before adding it as a team port"); + netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n", +@@ -1205,10 +1201,16 @@ static int team_port_add(struct team *team, struct net_device *port_dev, + INIT_LIST_HEAD(&port->qom_list); + + port->orig.mtu = port_dev->mtu; +- err = dev_set_mtu(port_dev, dev->mtu); +- if (err) { +- netdev_dbg(dev, "Error %d calling dev_set_mtu\n", err); +- goto err_set_mtu; ++ /* ++ * MTU assignment will be handled in team_dev_type_check_change ++ * if dev and port_dev are of different types ++ */ ++ if (dev->type == port_dev->type) { ++ err = dev_set_mtu(port_dev, dev->mtu); ++ if (err) { ++ netdev_dbg(dev, "Error %d calling dev_set_mtu\n", err); ++ goto err_set_mtu; ++ } + } + + memcpy(port->orig.dev_addr, port_dev->dev_addr, port_dev->addr_len); +@@ -1283,6 +1285,10 @@ static int team_port_add(struct team *team, struct net_device *port_dev, + } + } + ++ err = team_dev_type_check_change(dev, port_dev); ++ if (err) ++ goto err_set_dev_type; ++ + if (dev->flags & IFF_UP) { + netif_addr_lock_bh(dev); + dev_uc_sync_multiple(port_dev, dev); +@@ -1301,6 +1307,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev, + + return 0; + ++err_set_dev_type: + err_set_slave_promisc: + __team_option_inst_del_port(team, port); + +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index c1fdf8804d60b6..97dbec8d78077d 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -3682,9 +3682,9 @@ static int tun_queue_resize(struct tun_struct *tun) + list_for_each_entry(tfile, &tun->disabled, next) + rings[i++] = &tfile->tx_ring; + +- ret = ptr_ring_resize_multiple(rings, n, +- dev->tx_queue_len, GFP_KERNEL, +- tun_ptr_free); ++ ret = ptr_ring_resize_multiple_bh(rings, n, ++ dev->tx_queue_len, GFP_KERNEL, ++ tun_ptr_free); + + kfree(rings); + return ret; +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index dc54ea16c12af6..ed1ea61c814203 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -5093,7 +5093,7 @@ static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, int mac_id, + struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data; + const struct ath11k_hw_hal_params *hal_params; + void *ring_entry; +- void *mon_dst_srng; ++ struct hal_srng *mon_dst_srng; + u32 ppdu_id; + u32 rx_bufs_used; + u32 ring_id; +@@ -5117,6 +5117,7 @@ static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, int mac_id, + + spin_lock_bh(&pmon->mon_lock); + ++ spin_lock_bh(&mon_dst_srng->lock); + ath11k_hal_srng_access_begin(ar->ab, mon_dst_srng); + + ppdu_id = pmon->mon_ppdu_info.ppdu_id; +@@ -5175,6 +5176,7 @@ static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, int mac_id, + mon_dst_srng); + } + ath11k_hal_srng_access_end(ar->ab, mon_dst_srng); ++ spin_unlock_bh(&mon_dst_srng->lock); + + spin_unlock_bh(&pmon->mon_lock); + +@@ -5564,7 +5566,7 @@ static int ath11k_dp_full_mon_process_rx(struct ath11k_base *ab, int mac_id, + struct hal_sw_mon_ring_entries *sw_mon_entries; + struct ath11k_pdev_mon_stats *rx_mon_stats; + struct sk_buff *head_msdu, *tail_msdu; +- void *mon_dst_srng = &ar->ab->hal.srng_list[dp->rxdma_mon_dst_ring.ring_id]; ++ struct hal_srng *mon_dst_srng; + void *ring_entry; + u32 rx_bufs_used = 0, mpdu_rx_bufs_used; + int quota = 0, ret; +@@ -5580,6 +5582,9 @@ static int ath11k_dp_full_mon_process_rx(struct ath11k_base *ab, int mac_id, + goto reap_status_ring; + } + ++ mon_dst_srng = &ar->ab->hal.srng_list[dp->rxdma_mon_dst_ring.ring_id]; ++ spin_lock_bh(&mon_dst_srng->lock); ++ + ath11k_hal_srng_access_begin(ar->ab, mon_dst_srng); + while ((ring_entry = ath11k_hal_srng_dst_peek(ar->ab, mon_dst_srng))) { + head_msdu = NULL; +@@ -5623,6 +5628,7 @@ next_entry: + } + + ath11k_hal_srng_access_end(ar->ab, mon_dst_srng); ++ spin_unlock_bh(&mon_dst_srng->lock); + spin_unlock_bh(&pmon->mon_lock); + + if (rx_bufs_used) { +diff --git a/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c b/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c +index 7c4a11f60f9111..52b036fe6cfeae 100644 +--- a/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c ++++ b/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c +@@ -394,6 +394,7 @@ static int t7xx_dpmaif_set_frag_to_skb(const struct dpmaif_rx_queue *rxq, + struct sk_buff *skb) + { + unsigned long long data_bus_addr, data_base_addr; ++ struct skb_shared_info *shinfo = skb_shinfo(skb); + struct device *dev = rxq->dpmaif_ctrl->dev; + struct dpmaif_bat_page *page_info; + unsigned int data_len; +@@ -401,18 +402,22 @@ static int t7xx_dpmaif_set_frag_to_skb(const struct dpmaif_rx_queue *rxq, + + page_info = rxq->bat_frag->bat_skb; + page_info += t7xx_normal_pit_bid(pkt_info); +- dma_unmap_page(dev, page_info->data_bus_addr, page_info->data_len, DMA_FROM_DEVICE); + + if (!page_info->page) + return -EINVAL; + ++ if (shinfo->nr_frags >= MAX_SKB_FRAGS) ++ return -EINVAL; ++ ++ dma_unmap_page(dev, page_info->data_bus_addr, page_info->data_len, DMA_FROM_DEVICE); ++ + data_bus_addr = le32_to_cpu(pkt_info->pd.data_addr_h); + data_bus_addr = (data_bus_addr << 32) + le32_to_cpu(pkt_info->pd.data_addr_l); + data_base_addr = page_info->data_bus_addr; + data_offset = data_bus_addr - data_base_addr; + data_offset += page_info->offset; + data_len = FIELD_GET(PD_PIT_DATA_LEN, le32_to_cpu(pkt_info->header)); +- skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page_info->page, ++ skb_add_rx_frag(skb, shinfo->nr_frags, page_info->page, + data_offset, data_len, page_info->data_len); + + page_info->page = NULL; +diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c +index 5cc00fdc48d840..4f613f9082083f 100644 +--- a/drivers/pinctrl/meson/pinctrl-meson.c ++++ b/drivers/pinctrl/meson/pinctrl-meson.c +@@ -618,7 +618,7 @@ static int meson_gpiolib_register(struct meson_pinctrl *pc) + pc->chip.set = meson_gpio_set; + pc->chip.base = -1; + pc->chip.ngpio = pc->data->num_pins; +- pc->chip.can_sleep = false; ++ pc->chip.can_sleep = true; + + ret = gpiochip_add_data(&pc->chip, pc); + if (ret) { +diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c +index b5a02335617d77..0c2382480c24ef 100644 +--- a/drivers/pinctrl/pinctrl-rockchip.c ++++ b/drivers/pinctrl/pinctrl-rockchip.c +@@ -2749,10 +2749,9 @@ static int rockchip_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, + return 0; + } + +-static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, +- struct pinctrl_gpio_range *range, +- unsigned offset, +- bool input) ++static int rockchip_pmx_gpio_request_enable(struct pinctrl_dev *pctldev, ++ struct pinctrl_gpio_range *range, ++ unsigned int offset) + { + struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + struct rockchip_pin_bank *bank; +@@ -2766,7 +2765,7 @@ static const struct pinmux_ops rockchip_pmx_ops = { + .get_function_name = rockchip_pmx_get_func_name, + .get_function_groups = rockchip_pmx_get_groups, + .set_mux = rockchip_pmx_set, +- .gpio_set_direction = rockchip_pmx_gpio_set_direction, ++ .gpio_request_enable = rockchip_pmx_gpio_request_enable, + }; + + /* +diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig +index f84c0d3b79517b..36d7ef4097c0fd 100644 +--- a/drivers/pinctrl/qcom/Kconfig ++++ b/drivers/pinctrl/qcom/Kconfig +@@ -60,13 +60,14 @@ config PINCTRL_LPASS_LPI + (Low Power Island) found on the Qualcomm Technologies Inc SoCs. + + config PINCTRL_SC7280_LPASS_LPI +- tristate "Qualcomm Technologies Inc SC7280 LPASS LPI pin controller driver" ++ tristate "Qualcomm Technologies Inc SC7280 and SM8350 LPASS LPI pin controller driver" + depends on ARM64 || COMPILE_TEST + depends on PINCTRL_LPASS_LPI + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI +- (Low Power Island) found on the Qualcomm Technologies Inc SC7280 platform. ++ (Low Power Island) found on the Qualcomm Technologies Inc SC7280 ++ and SM8350 platforms. + + config PINCTRL_SM6115_LPASS_LPI + tristate "Qualcomm Technologies Inc SM6115 LPASS LPI pin controller driver" +@@ -86,16 +87,6 @@ config PINCTRL_SM8250_LPASS_LPI + Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI + (Low Power Island) found on the Qualcomm Technologies Inc SM8250 platform. + +-config PINCTRL_SM8350_LPASS_LPI +- tristate "Qualcomm Technologies Inc SM8350 LPASS LPI pin controller driver" +- depends on ARM64 || COMPILE_TEST +- depends on PINCTRL_LPASS_LPI +- help +- This is the pinctrl, pinmux, pinconf and gpiolib driver for the +- Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI +- (Low Power Island) found on the Qualcomm Technologies Inc SM8350 +- platform. +- + config PINCTRL_SM8450_LPASS_LPI + tristate "Qualcomm Technologies Inc SM8450 LPASS LPI pin controller driver" + depends on ARM64 || COMPILE_TEST +diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile +index 5910e08c84ceca..d1179d8b2c42b4 100644 +--- a/drivers/pinctrl/qcom/Makefile ++++ b/drivers/pinctrl/qcom/Makefile +@@ -53,7 +53,6 @@ obj-$(CONFIG_PINCTRL_SM8150) += pinctrl-sm8150.o + obj-$(CONFIG_PINCTRL_SM8250) += pinctrl-sm8250.o + obj-$(CONFIG_PINCTRL_SM8250_LPASS_LPI) += pinctrl-sm8250-lpass-lpi.o + obj-$(CONFIG_PINCTRL_SM8350) += pinctrl-sm8350.o +-obj-$(CONFIG_PINCTRL_SM8350_LPASS_LPI) += pinctrl-sm8350-lpass-lpi.o + obj-$(CONFIG_PINCTRL_SM8450) += pinctrl-sm8450.o + obj-$(CONFIG_PINCTRL_SM8450_LPASS_LPI) += pinctrl-sm8450-lpass-lpi.o + obj-$(CONFIG_PINCTRL_SM8550) += pinctrl-sm8550.o +diff --git a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c +index 2b32da357af374..a17c71b3bc8b58 100644 +--- a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c ++++ b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c +@@ -279,6 +279,22 @@ static const struct pinconf_ops lpi_gpio_pinconf_ops = { + .pin_config_group_set = lpi_config_set, + }; + ++static int lpi_gpio_get_direction(struct gpio_chip *chip, unsigned int pin) ++{ ++ unsigned long config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, 0); ++ struct lpi_pinctrl *state = gpiochip_get_data(chip); ++ unsigned long arg; ++ int ret; ++ ++ ret = lpi_config_get(state->ctrl, pin, &config); ++ if (ret) ++ return ret; ++ ++ arg = pinconf_to_config_argument(config); ++ ++ return arg ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; ++} ++ + static int lpi_gpio_direction_input(struct gpio_chip *chip, unsigned int pin) + { + struct lpi_pinctrl *state = gpiochip_get_data(chip); +@@ -377,6 +393,7 @@ static void lpi_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) + #endif + + static const struct gpio_chip lpi_gpio_template = { ++ .get_direction = lpi_gpio_get_direction, + .direction_input = lpi_gpio_direction_input, + .direction_output = lpi_gpio_direction_output, + .get = lpi_gpio_get, +diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c +index d615b6c55b8919..74cc5b4ac98204 100644 +--- a/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c ++++ b/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c +@@ -147,6 +147,9 @@ static const struct of_device_id lpi_pinctrl_of_match[] = { + { + .compatible = "qcom,sc7280-lpass-lpi-pinctrl", + .data = &sc7280_lpi_data, ++ }, { ++ .compatible = "qcom,sm8350-lpass-lpi-pinctrl", ++ .data = &sc7280_lpi_data, + }, + { } + }; +diff --git a/drivers/pinctrl/qcom/pinctrl-sm8350-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sm8350-lpass-lpi.c +deleted file mode 100644 +index f889c779bccd52..00000000000000 +--- a/drivers/pinctrl/qcom/pinctrl-sm8350-lpass-lpi.c ++++ /dev/null +@@ -1,167 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-only +-/* +- * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. +- * Copyright (c) 2020-2023 Linaro Ltd. +- */ +- +-#include +-#include +-#include +- +-#include "pinctrl-lpass-lpi.h" +- +-enum lpass_lpi_functions { +- LPI_MUX_dmic1_clk, +- LPI_MUX_dmic1_data, +- LPI_MUX_dmic2_clk, +- LPI_MUX_dmic2_data, +- LPI_MUX_dmic3_clk, +- LPI_MUX_dmic3_data, +- LPI_MUX_i2s1_clk, +- LPI_MUX_i2s1_data, +- LPI_MUX_i2s1_ws, +- LPI_MUX_i2s2_clk, +- LPI_MUX_i2s2_data, +- LPI_MUX_i2s2_ws, +- LPI_MUX_qua_mi2s_data, +- LPI_MUX_qua_mi2s_sclk, +- LPI_MUX_qua_mi2s_ws, +- LPI_MUX_swr_rx_clk, +- LPI_MUX_swr_rx_data, +- LPI_MUX_swr_tx_clk, +- LPI_MUX_swr_tx_data, +- LPI_MUX_wsa_swr_clk, +- LPI_MUX_wsa_swr_data, +- LPI_MUX_gpio, +- LPI_MUX__, +-}; +- +-static int gpio0_pins[] = { 0 }; +-static int gpio1_pins[] = { 1 }; +-static int gpio2_pins[] = { 2 }; +-static int gpio3_pins[] = { 3 }; +-static int gpio4_pins[] = { 4 }; +-static int gpio5_pins[] = { 5 }; +-static int gpio6_pins[] = { 6 }; +-static int gpio7_pins[] = { 7 }; +-static int gpio8_pins[] = { 8 }; +-static int gpio9_pins[] = { 9 }; +-static int gpio10_pins[] = { 10 }; +-static int gpio11_pins[] = { 11 }; +-static int gpio12_pins[] = { 12 }; +-static int gpio13_pins[] = { 13 }; +-static int gpio14_pins[] = { 14 }; +- +-static const struct pinctrl_pin_desc sm8350_lpi_pins[] = { +- PINCTRL_PIN(0, "gpio0"), +- PINCTRL_PIN(1, "gpio1"), +- PINCTRL_PIN(2, "gpio2"), +- PINCTRL_PIN(3, "gpio3"), +- PINCTRL_PIN(4, "gpio4"), +- PINCTRL_PIN(5, "gpio5"), +- PINCTRL_PIN(6, "gpio6"), +- PINCTRL_PIN(7, "gpio7"), +- PINCTRL_PIN(8, "gpio8"), +- PINCTRL_PIN(9, "gpio9"), +- PINCTRL_PIN(10, "gpio10"), +- PINCTRL_PIN(11, "gpio11"), +- PINCTRL_PIN(12, "gpio12"), +- PINCTRL_PIN(13, "gpio13"), +- PINCTRL_PIN(14, "gpio14"), +-}; +- +-static const char * const swr_tx_clk_groups[] = { "gpio0" }; +-static const char * const swr_tx_data_groups[] = { "gpio1", "gpio2", "gpio5", "gpio14" }; +-static const char * const swr_rx_clk_groups[] = { "gpio3" }; +-static const char * const swr_rx_data_groups[] = { "gpio4", "gpio5" }; +-static const char * const dmic1_clk_groups[] = { "gpio6" }; +-static const char * const dmic1_data_groups[] = { "gpio7" }; +-static const char * const dmic2_clk_groups[] = { "gpio8" }; +-static const char * const dmic2_data_groups[] = { "gpio9" }; +-static const char * const i2s2_clk_groups[] = { "gpio10" }; +-static const char * const i2s2_ws_groups[] = { "gpio11" }; +-static const char * const dmic3_clk_groups[] = { "gpio12" }; +-static const char * const dmic3_data_groups[] = { "gpio13" }; +-static const char * const qua_mi2s_sclk_groups[] = { "gpio0" }; +-static const char * const qua_mi2s_ws_groups[] = { "gpio1" }; +-static const char * const qua_mi2s_data_groups[] = { "gpio2", "gpio3", "gpio4" }; +-static const char * const i2s1_clk_groups[] = { "gpio6" }; +-static const char * const i2s1_ws_groups[] = { "gpio7" }; +-static const char * const i2s1_data_groups[] = { "gpio8", "gpio9" }; +-static const char * const wsa_swr_clk_groups[] = { "gpio10" }; +-static const char * const wsa_swr_data_groups[] = { "gpio11" }; +-static const char * const i2s2_data_groups[] = { "gpio12", "gpio12" }; +- +-static const struct lpi_pingroup sm8350_groups[] = { +- LPI_PINGROUP(0, 0, swr_tx_clk, qua_mi2s_sclk, _, _), +- LPI_PINGROUP(1, 2, swr_tx_data, qua_mi2s_ws, _, _), +- LPI_PINGROUP(2, 4, swr_tx_data, qua_mi2s_data, _, _), +- LPI_PINGROUP(3, 8, swr_rx_clk, qua_mi2s_data, _, _), +- LPI_PINGROUP(4, 10, swr_rx_data, qua_mi2s_data, _, _), +- LPI_PINGROUP(5, 12, swr_tx_data, swr_rx_data, _, _), +- LPI_PINGROUP(6, LPI_NO_SLEW, dmic1_clk, i2s1_clk, _, _), +- LPI_PINGROUP(7, LPI_NO_SLEW, dmic1_data, i2s1_ws, _, _), +- LPI_PINGROUP(8, LPI_NO_SLEW, dmic2_clk, i2s1_data, _, _), +- LPI_PINGROUP(9, LPI_NO_SLEW, dmic2_data, i2s1_data, _, _), +- LPI_PINGROUP(10, 16, i2s2_clk, wsa_swr_clk, _, _), +- LPI_PINGROUP(11, 18, i2s2_ws, wsa_swr_data, _, _), +- LPI_PINGROUP(12, LPI_NO_SLEW, dmic3_clk, i2s2_data, _, _), +- LPI_PINGROUP(13, LPI_NO_SLEW, dmic3_data, i2s2_data, _, _), +- LPI_PINGROUP(14, 6, swr_tx_data, _, _, _), +-}; +- +-static const struct lpi_function sm8350_functions[] = { +- LPI_FUNCTION(dmic1_clk), +- LPI_FUNCTION(dmic1_data), +- LPI_FUNCTION(dmic2_clk), +- LPI_FUNCTION(dmic2_data), +- LPI_FUNCTION(dmic3_clk), +- LPI_FUNCTION(dmic3_data), +- LPI_FUNCTION(i2s1_clk), +- LPI_FUNCTION(i2s1_data), +- LPI_FUNCTION(i2s1_ws), +- LPI_FUNCTION(i2s2_clk), +- LPI_FUNCTION(i2s2_data), +- LPI_FUNCTION(i2s2_ws), +- LPI_FUNCTION(qua_mi2s_data), +- LPI_FUNCTION(qua_mi2s_sclk), +- LPI_FUNCTION(qua_mi2s_ws), +- LPI_FUNCTION(swr_rx_clk), +- LPI_FUNCTION(swr_rx_data), +- LPI_FUNCTION(swr_tx_clk), +- LPI_FUNCTION(swr_tx_data), +- LPI_FUNCTION(wsa_swr_clk), +- LPI_FUNCTION(wsa_swr_data), +-}; +- +-static const struct lpi_pinctrl_variant_data sm8350_lpi_data = { +- .pins = sm8350_lpi_pins, +- .npins = ARRAY_SIZE(sm8350_lpi_pins), +- .groups = sm8350_groups, +- .ngroups = ARRAY_SIZE(sm8350_groups), +- .functions = sm8350_functions, +- .nfunctions = ARRAY_SIZE(sm8350_functions), +-}; +- +-static const struct of_device_id lpi_pinctrl_of_match[] = { +- { +- .compatible = "qcom,sm8350-lpass-lpi-pinctrl", +- .data = &sm8350_lpi_data, +- }, +- { } +-}; +-MODULE_DEVICE_TABLE(of, lpi_pinctrl_of_match); +- +-static struct platform_driver lpi_pinctrl_driver = { +- .driver = { +- .name = "qcom-sm8350-lpass-lpi-pinctrl", +- .of_match_table = lpi_pinctrl_of_match, +- }, +- .probe = lpi_pinctrl_probe, +- .remove = lpi_pinctrl_remove, +-}; +-module_platform_driver(lpi_pinctrl_driver); +- +-MODULE_AUTHOR("Krzysztof Kozlowski "); +-MODULE_DESCRIPTION("QTI SM8350 LPI GPIO pin control driver"); +-MODULE_LICENSE("GPL"); +diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c +index 4e899ec1477d46..b1cba986f0fbd3 100644 +--- a/drivers/scsi/be2iscsi/be_mgmt.c ++++ b/drivers/scsi/be2iscsi/be_mgmt.c +@@ -1025,6 +1025,7 @@ unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba) + &nonemb_cmd->dma, + GFP_KERNEL); + if (!nonemb_cmd->va) { ++ free_mcc_wrb(ctrl, tag); + mutex_unlock(&ctrl->mbox_lock); + return 0; + } +diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c +index ef894dc80b8f95..d10389ee92ba4b 100644 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -4482,7 +4482,7 @@ fail_lsrjt: + fail_elsrej: + dma_pool_destroy(ha->purex_dma_pool); + fail_flt: +- dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE, ++ dma_free_coherent(&ha->pdev->dev, sizeof(struct qla_flt_header) + FLT_REGIONS_SIZE, + ha->flt, ha->flt_dma); + + fail_flt_buffer: +diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c +index 2a761bc0919389..ac20c3cd710615 100644 +--- a/drivers/target/sbp/sbp_target.c ++++ b/drivers/target/sbp/sbp_target.c +@@ -1961,12 +1961,12 @@ static struct se_portal_group *sbp_make_tpg(struct se_wwn *wwn, + container_of(wwn, struct sbp_tport, tport_wwn); + + struct sbp_tpg *tpg; +- unsigned long tpgt; ++ u16 tpgt; + int ret; + + if (strstr(name, "tpgt_") != name) + return ERR_PTR(-EINVAL); +- if (kstrtoul(name + 5, 10, &tpgt) || tpgt > UINT_MAX) ++ if (kstrtou16(name + 5, 10, &tpgt)) + return ERR_PTR(-EINVAL); + + if (tport->tpg) { +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index b21b5e0f89054f..0f05eb97925fdd 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -2847,6 +2847,19 @@ static noinline_for_stack int prealloc_file_extent_cluster( + * will re-read the whole page anyway. + */ + if (page) { ++ /* ++ * releasepage() could have cleared the page private data while ++ * we were not holding the lock. Reset the mapping if needed so ++ * subpage operations can access a valid private page state. ++ */ ++ ret = set_page_extent_mapped(page); ++ if (ret) { ++ unlock_page(page); ++ put_page(page); ++ ++ return ret; ++ } ++ + btrfs_subpage_clear_uptodate(fs_info, page, i_size, + round_up(i_size, PAGE_SIZE) - i_size); + unlock_page(page); +diff --git a/fs/efivarfs/vars.c b/fs/efivarfs/vars.c +index 13bc6069895571..b10aa5afd7f751 100644 +--- a/fs/efivarfs/vars.c ++++ b/fs/efivarfs/vars.c +@@ -609,7 +609,7 @@ int efivar_entry_get(struct efivar_entry *entry, u32 *attributes, + err = __efivar_entry_get(entry, attributes, size, data); + efivar_unlock(); + +- return 0; ++ return err; + } + + /** +diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c +index 274fae88b498e4..a1236a178a7b67 100644 +--- a/fs/fs-writeback.c ++++ b/fs/fs-writeback.c +@@ -2382,12 +2382,14 @@ static void wakeup_dirtytime_writeback(struct work_struct *w) + wb_wakeup(wb); + } + rcu_read_unlock(); +- schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ); ++ if (dirtytime_expire_interval) ++ schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ); + } + + static int __init start_dirtytime_writeback(void) + { +- schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ); ++ if (dirtytime_expire_interval) ++ schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ); + return 0; + } + __initcall(start_dirtytime_writeback); +@@ -2398,8 +2400,12 @@ int dirtytime_interval_handler(struct ctl_table *table, int write, + int ret; + + ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); +- if (ret == 0 && write) +- mod_delayed_work(system_wq, &dirtytime_work, 0); ++ if (ret == 0 && write) { ++ if (dirtytime_expire_interval) ++ mod_delayed_work(system_wq, &dirtytime_work, 0); ++ else ++ cancel_delayed_work_sync(&dirtytime_work); ++ } + return ret; + } + +diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c +index 450a9f8ca7c7b5..e344475a41bd16 100644 +--- a/fs/smb/server/mgmt/user_session.c ++++ b/fs/smb/server/mgmt/user_session.c +@@ -104,29 +104,32 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name) + if (!entry) + return -ENOMEM; + +- down_read(&sess->rpc_lock); + entry->method = method; + entry->id = id = ksmbd_ipc_id_alloc(); + if (id < 0) + goto free_entry; ++ ++ down_write(&sess->rpc_lock); + old = xa_store(&sess->rpc_handle_list, id, entry, GFP_KERNEL); +- if (xa_is_err(old)) ++ if (xa_is_err(old)) { ++ up_write(&sess->rpc_lock); + goto free_id; ++ } + + resp = ksmbd_rpc_open(sess, id); +- if (!resp) +- goto erase_xa; ++ if (!resp) { ++ xa_erase(&sess->rpc_handle_list, entry->id); ++ up_write(&sess->rpc_lock); ++ goto free_id; ++ } + +- up_read(&sess->rpc_lock); ++ up_write(&sess->rpc_lock); + kvfree(resp); + return id; +-erase_xa: +- xa_erase(&sess->rpc_handle_list, entry->id); + free_id: + ksmbd_rpc_id_free(entry->id); + free_entry: + kfree(entry); +- up_read(&sess->rpc_lock); + return -EINVAL; + } + +@@ -145,7 +148,9 @@ int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id) + { + struct ksmbd_session_rpc *entry; + ++ lockdep_assert_held(&sess->rpc_lock); + entry = xa_load(&sess->rpc_handle_list, id); ++ + return entry ? entry->method : 0; + } + +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index f4b3798279d92d..eacfb241d3d497 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -4614,8 +4614,15 @@ static int smb2_get_info_file_pipe(struct ksmbd_session *sess, + * pipe without opening it, checking error condition here + */ + id = req->VolatileFileId; +- if (!ksmbd_session_rpc_method(sess, id)) ++ ++ lockdep_assert_not_held(&sess->rpc_lock); ++ ++ down_read(&sess->rpc_lock); ++ if (!ksmbd_session_rpc_method(sess, id)) { ++ up_read(&sess->rpc_lock); + return -ENOENT; ++ } ++ up_read(&sess->rpc_lock); + + ksmbd_debug(SMB, "FileInfoClass %u, FileId 0x%llx\n", + req->FileInfoClass, req->VolatileFileId); +diff --git a/fs/smb/server/transport_ipc.c b/fs/smb/server/transport_ipc.c +index a5b90d0b9f2d68..53bfcf57f167a1 100644 +--- a/fs/smb/server/transport_ipc.c ++++ b/fs/smb/server/transport_ipc.c +@@ -778,6 +778,9 @@ struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle + if (!msg) + return NULL; + ++ lockdep_assert_not_held(&sess->rpc_lock); ++ ++ down_read(&sess->rpc_lock); + msg->type = KSMBD_EVENT_RPC_REQUEST; + req = (struct ksmbd_rpc_command *)msg->payload; + req->handle = handle; +@@ -786,6 +789,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle + req->flags |= KSMBD_RPC_WRITE_METHOD; + req->payload_sz = payload_sz; + memcpy(req->payload, payload, payload_sz); ++ up_read(&sess->rpc_lock); + + resp = ipc_msg_send_request(msg, req->handle); + ipc_msg_free(msg); +@@ -802,6 +806,9 @@ struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle) + if (!msg) + return NULL; + ++ lockdep_assert_not_held(&sess->rpc_lock); ++ ++ down_read(&sess->rpc_lock); + msg->type = KSMBD_EVENT_RPC_REQUEST; + req = (struct ksmbd_rpc_command *)msg->payload; + req->handle = handle; +@@ -809,6 +816,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle) + req->flags |= rpc_context_flags(sess); + req->flags |= KSMBD_RPC_READ_METHOD; + req->payload_sz = 0; ++ up_read(&sess->rpc_lock); + + resp = ipc_msg_send_request(msg, req->handle); + ipc_msg_free(msg); +@@ -829,6 +837,9 @@ struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle + if (!msg) + return NULL; + ++ lockdep_assert_not_held(&sess->rpc_lock); ++ ++ down_read(&sess->rpc_lock); + msg->type = KSMBD_EVENT_RPC_REQUEST; + req = (struct ksmbd_rpc_command *)msg->payload; + req->handle = handle; +@@ -837,6 +848,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle + req->flags |= KSMBD_RPC_IOCTL_METHOD; + req->payload_sz = payload_sz; + memcpy(req->payload, payload, payload_sz); ++ up_read(&sess->rpc_lock); + + resp = ipc_msg_send_request(msg, req->handle); + ipc_msg_free(msg); +diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c +index 91e85a1a154fdf..4bab3f89d2c872 100644 +--- a/fs/smb/server/transport_rdma.c ++++ b/fs/smb/server/transport_rdma.c +@@ -1108,14 +1108,12 @@ static int get_sg_list(void *buf, int size, struct scatterlist *sg_list, int nen + + static int get_mapped_sg_list(struct ib_device *device, void *buf, int size, + struct scatterlist *sg_list, int nentries, +- enum dma_data_direction dir) ++ enum dma_data_direction dir, int *npages) + { +- int npages; +- +- npages = get_sg_list(buf, size, sg_list, nentries); +- if (npages < 0) ++ *npages = get_sg_list(buf, size, sg_list, nentries); ++ if (*npages < 0) + return -EINVAL; +- return ib_dma_map_sg(device, sg_list, npages, dir); ++ return ib_dma_map_sg(device, sg_list, *npages, dir); + } + + static int post_sendmsg(struct smb_direct_transport *t, +@@ -1184,12 +1182,13 @@ static int smb_direct_post_send_data(struct smb_direct_transport *t, + for (i = 0; i < niov; i++) { + struct ib_sge *sge; + int sg_cnt; ++ int npages; + + sg_init_table(sg, SMB_DIRECT_MAX_SEND_SGES - 1); + sg_cnt = get_mapped_sg_list(t->cm_id->device, + iov[i].iov_base, iov[i].iov_len, + sg, SMB_DIRECT_MAX_SEND_SGES - 1, +- DMA_TO_DEVICE); ++ DMA_TO_DEVICE, &npages); + if (sg_cnt <= 0) { + pr_err("failed to map buffer\n"); + ret = -ENOMEM; +@@ -1197,7 +1196,7 @@ static int smb_direct_post_send_data(struct smb_direct_transport *t, + } else if (sg_cnt + msg->num_sge > SMB_DIRECT_MAX_SEND_SGES) { + pr_err("buffer not fitted into sges\n"); + ret = -E2BIG; +- ib_dma_unmap_sg(t->cm_id->device, sg, sg_cnt, ++ ib_dma_unmap_sg(t->cm_id->device, sg, npages, + DMA_TO_DEVICE); + goto err; + } +diff --git a/include/linux/ptr_ring.h b/include/linux/ptr_ring.h +index 808f9d3ee54654..65da2155cce252 100644 +--- a/include/linux/ptr_ring.h ++++ b/include/linux/ptr_ring.h +@@ -613,15 +613,14 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp, + /* + * Note: producer lock is nested within consumer lock, so if you + * resize you must make sure all uses nest correctly. +- * In particular if you consume ring in interrupt or BH context, you must +- * disable interrupts/BH when doing so. ++ * In particular if you consume ring in BH context, you must ++ * disable BH when doing so. + */ +-static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, +- unsigned int nrings, +- int size, +- gfp_t gfp, void (*destroy)(void *)) ++static inline int ptr_ring_resize_multiple_bh(struct ptr_ring **rings, ++ unsigned int nrings, ++ int size, gfp_t gfp, ++ void (*destroy)(void *)) + { +- unsigned long flags; + void ***queues; + int i; + +@@ -636,12 +635,12 @@ static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, + } + + for (i = 0; i < nrings; ++i) { +- spin_lock_irqsave(&(rings[i])->consumer_lock, flags); ++ spin_lock_bh(&(rings[i])->consumer_lock); + spin_lock(&(rings[i])->producer_lock); + queues[i] = __ptr_ring_swap_queue(rings[i], queues[i], + size, gfp, destroy); + spin_unlock(&(rings[i])->producer_lock); +- spin_unlock_irqrestore(&(rings[i])->consumer_lock, flags); ++ spin_unlock_bh(&(rings[i])->consumer_lock); + } + + for (i = 0; i < nrings; ++i) +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 9559501236af08..9c7c67efce346f 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -1800,6 +1800,11 @@ static __always_inline bool is_percpu_thread(void) + #endif + } + ++static __always_inline bool is_user_task(struct task_struct *task) ++{ ++ return task->mm && !(task->flags & (PF_KTHREAD | PF_USER_WORKER)); ++} ++ + /* Per-process atomic flags. */ + #define PFA_NO_NEW_PRIVS 0 /* May not gain new privileges. */ + #define PFA_SPREAD_PAGE 1 /* Spread page cache over cpuset */ +diff --git a/include/linux/skb_array.h b/include/linux/skb_array.h +index e2d45b7cb61980..6c7f856e211a1f 100644 +--- a/include/linux/skb_array.h ++++ b/include/linux/skb_array.h +@@ -198,16 +198,18 @@ static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp) + return ptr_ring_resize(&a->ring, size, gfp, __skb_array_destroy_skb); + } + +-static inline int skb_array_resize_multiple(struct skb_array **rings, +- int nrings, unsigned int size, +- gfp_t gfp) ++static inline int skb_array_resize_multiple_bh(struct skb_array **rings, ++ int nrings, ++ unsigned int size, ++ gfp_t gfp) + { + BUILD_BUG_ON(offsetof(struct skb_array, ring)); +- return ptr_ring_resize_multiple((struct ptr_ring **)rings, +- nrings, size, gfp, +- __skb_array_destroy_skb); ++ return ptr_ring_resize_multiple_bh((struct ptr_ring **)rings, ++ nrings, size, gfp, ++ __skb_array_destroy_skb); + } + ++ + static inline void skb_array_cleanup(struct skb_array *a) + { + ptr_ring_cleanup(&a->ring, __skb_array_destroy_skb); +diff --git a/include/net/bonding.h b/include/net/bonding.h +index 95f67b308c19a4..9fb40a59202091 100644 +--- a/include/net/bonding.h ++++ b/include/net/bonding.h +@@ -519,13 +519,14 @@ static inline int bond_is_ip6_target_ok(struct in6_addr *addr) + static inline unsigned long slave_oldest_target_arp_rx(struct bonding *bond, + struct slave *slave) + { ++ unsigned long tmp, ret = READ_ONCE(slave->target_last_arp_rx[0]); + int i = 1; +- unsigned long ret = slave->target_last_arp_rx[0]; +- +- for (; (i < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i]; i++) +- if (time_before(slave->target_last_arp_rx[i], ret)) +- ret = slave->target_last_arp_rx[i]; + ++ for (; (i < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i]; i++) { ++ tmp = READ_ONCE(slave->target_last_arp_rx[i]); ++ if (time_before(tmp, ret)) ++ ret = tmp; ++ } + return ret; + } + +@@ -535,7 +536,7 @@ static inline unsigned long slave_last_rx(struct bonding *bond, + if (bond->params.arp_all_targets == BOND_ARP_TARGETS_ALL) + return slave_oldest_target_arp_rx(bond, slave); + +- return slave->last_rx; ++ return READ_ONCE(slave->last_rx); + } + + static inline void slave_update_last_tx(struct slave *slave) +diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h +index 5dee575fbe86ae..b82f4f2a27fb81 100644 +--- a/include/net/nfc/nfc.h ++++ b/include/net/nfc/nfc.h +@@ -215,6 +215,8 @@ static inline void nfc_free_device(struct nfc_dev *dev) + + int nfc_register_device(struct nfc_dev *dev); + ++void nfc_unregister_rfkill(struct nfc_dev *dev); ++void nfc_remove_device(struct nfc_dev *dev); + void nfc_unregister_device(struct nfc_dev *dev); + + /** +diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h +index 69b472604b86f5..660c22521a292e 100644 +--- a/include/net/xdp_sock.h ++++ b/include/net/xdp_sock.h +@@ -63,9 +63,6 @@ struct xdp_sock { + + struct xsk_queue *tx ____cacheline_aligned_in_smp; + struct list_head tx_list; +- /* Protects generic receive. */ +- spinlock_t rx_lock; +- + /* Statistics */ + u64 rx_dropped; + u64 rx_queue_full; +diff --git a/include/net/xsk_buff_pool.h b/include/net/xsk_buff_pool.h +index b0bdff26fc882c..f0d6ce4bda7a28 100644 +--- a/include/net/xsk_buff_pool.h ++++ b/include/net/xsk_buff_pool.h +@@ -54,6 +54,8 @@ struct xsk_buff_pool { + refcount_t users; + struct xdp_umem *umem; + struct work_struct work; ++ /* Protects generic receive in shared and non-shared umem mode. */ ++ spinlock_t rx_lock; + struct list_head free_list; + struct list_head xskb_list; + u32 heads_cnt; +diff --git a/kernel/dma/pool.c b/kernel/dma/pool.c +index b3b9c7ec5fc543..8a15b5008b20c5 100644 +--- a/kernel/dma/pool.c ++++ b/kernel/dma/pool.c +@@ -268,15 +268,20 @@ struct page *dma_alloc_from_pool(struct device *dev, size_t size, + { + struct gen_pool *pool = NULL; + struct page *page; ++ bool pool_found = false; + + while ((pool = dma_guess_pool(pool, gfp))) { ++ pool_found = true; + page = __dma_alloc_from_pool(dev, size, pool, cpu_addr, + phys_addr_ok); + if (page) + return page; + } + +- WARN(1, "Failed to get suitable pool for %s\n", dev_name(dev)); ++ if (pool_found) ++ WARN(!(gfp & __GFP_NOWARN), "DMA pool exhausted for %s\n", dev_name(dev)); ++ else ++ WARN(1, "Failed to get suitable pool for %s\n", dev_name(dev)); + return NULL; + } + +diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c +index ee01cfcc35064a..0bd9cb625111b4 100644 +--- a/kernel/events/callchain.c ++++ b/kernel/events/callchain.c +@@ -206,7 +206,7 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user, + + if (user && !crosstask) { + if (!user_mode(regs)) { +- if (current->flags & (PF_KTHREAD | PF_USER_WORKER)) ++ if (!is_user_task(current)) + regs = NULL; + else + regs = task_pt_regs(current); +diff --git a/kernel/events/core.c b/kernel/events/core.c +index c9a3fb6fdb2f64..9a6be06176bb41 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -6985,7 +6985,7 @@ static void perf_sample_regs_user(struct perf_regs *regs_user, + if (user_mode(regs)) { + regs_user->abi = perf_reg_abi(current); + regs_user->regs = regs; +- } else if (!(current->flags & (PF_KTHREAD | PF_USER_WORKER))) { ++ } else if (is_user_task(current)) { + perf_get_regs_user(regs_user, regs); + } else { + regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE; +@@ -7612,7 +7612,7 @@ static u64 perf_virt_to_phys(u64 virt) + * Try IRQ-safe get_user_page_fast_only first. + * If failed, leave phys_addr as 0. + */ +- if (!(current->flags & (PF_KTHREAD | PF_USER_WORKER))) { ++ if (is_user_task(current)) { + struct page *p; + + pagefault_disable(); +@@ -7725,7 +7725,7 @@ perf_callchain(struct perf_event *event, struct pt_regs *regs) + { + bool kernel = !event->attr.exclude_callchain_kernel; + bool user = !event->attr.exclude_callchain_user && +- !(current->flags & (PF_KTHREAD | PF_USER_WORKER)); ++ is_user_task(current); + /* Disallow cross-task user callchains. */ + bool crosstask = event->ctx->task && event->ctx->task != current; + const u32 max_stack = event->attr.sample_max_stack; +diff --git a/lib/flex_proportions.c b/lib/flex_proportions.c +index 83332fefa6f42e..27193fa008f6c0 100644 +--- a/lib/flex_proportions.c ++++ b/lib/flex_proportions.c +@@ -64,13 +64,14 @@ void fprop_global_destroy(struct fprop_global *p) + bool fprop_new_period(struct fprop_global *p, int periods) + { + s64 events = percpu_counter_sum(&p->events); ++ unsigned long flags; + + /* + * Don't do anything if there are no events. + */ + if (events <= 1) + return false; +- preempt_disable_nested(); ++ local_irq_save(flags); + write_seqcount_begin(&p->sequence); + if (periods < 64) + events -= events >> periods; +@@ -78,7 +79,7 @@ bool fprop_new_period(struct fprop_global *p, int periods) + percpu_counter_add(&p->events, -events); + p->period += periods; + write_seqcount_end(&p->sequence); +- preempt_enable_nested(); ++ local_irq_restore(flags); + + return true; + } +diff --git a/mm/kfence/core.c b/mm/kfence/core.c +index 937bbae2611fee..16a6ecca95fce3 100644 +--- a/mm/kfence/core.c ++++ b/mm/kfence/core.c +@@ -577,7 +577,7 @@ static unsigned long kfence_init_pool(void) + { + unsigned long addr; + struct page *pages; +- int i; ++ int i, rand; + + if (!arch_kfence_init_pool()) + return (unsigned long)__kfence_pool; +@@ -626,13 +626,27 @@ static unsigned long kfence_init_pool(void) + INIT_LIST_HEAD(&meta->list); + raw_spin_lock_init(&meta->lock); + meta->state = KFENCE_OBJECT_UNUSED; +- meta->addr = addr; /* Initialize for validation in metadata_to_pageaddr(). */ +- list_add_tail(&meta->list, &kfence_freelist); ++ /* Use addr to randomize the freelist. */ ++ meta->addr = i; + + /* Protect the right redzone. */ +- if (unlikely(!kfence_protect(addr + PAGE_SIZE))) ++ if (unlikely(!kfence_protect(addr + 2 * i * PAGE_SIZE + PAGE_SIZE))) + goto reset_slab; ++ } ++ ++ for (i = CONFIG_KFENCE_NUM_OBJECTS; i > 0; i--) { ++ rand = get_random_u32_below(i); ++ swap(kfence_metadata_init[i - 1].addr, kfence_metadata_init[rand].addr); ++ } + ++ for (i = 0; i < CONFIG_KFENCE_NUM_OBJECTS; i++) { ++ struct kfence_metadata *meta_1 = &kfence_metadata_init[i]; ++ struct kfence_metadata *meta_2 = &kfence_metadata_init[meta_1->addr]; ++ ++ list_add_tail(&meta_2->list, &kfence_freelist); ++ } ++ for (i = 0; i < CONFIG_KFENCE_NUM_OBJECTS; i++) { ++ kfence_metadata_init[i].addr = addr; + addr += 2 * PAGE_SIZE; + } + +@@ -645,6 +659,7 @@ static unsigned long kfence_init_pool(void) + return 0; + + reset_slab: ++ addr += 2 * i * PAGE_SIZE; + for (i = 0; i < KFENCE_POOL_SIZE / PAGE_SIZE; i++) { + struct slab *slab = page_slab(nth_page(pages, i)); + +diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c +index 2d5b81ebbaa6d0..847fe03a08ee80 100644 +--- a/net/bridge/br_input.c ++++ b/net/bridge/br_input.c +@@ -260,7 +260,7 @@ static int nf_hook_bridge_pre(struct sk_buff *skb, struct sk_buff **pskb) + int ret; + + net = dev_net(skb->dev); +-#ifdef HAVE_JUMP_LABEL ++#ifdef CONFIG_JUMP_LABEL + if (!static_key_false(&nf_hooks_needed[NFPROTO_BRIDGE][NF_BR_PRE_ROUTING])) + goto frame_finish; + #endif +diff --git a/net/core/dev.c b/net/core/dev.c +index 8a7a5e16da00a6..206194bb8fcadd 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -78,7 +78,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -218,31 +217,6 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex) + return &net->dev_index_head[ifindex & (NETDEV_HASHENTRIES - 1)]; + } + +-#ifndef CONFIG_PREEMPT_RT +- +-static DEFINE_STATIC_KEY_FALSE(use_backlog_threads_key); +- +-static int __init setup_backlog_napi_threads(char *arg) +-{ +- static_branch_enable(&use_backlog_threads_key); +- return 0; +-} +-early_param("thread_backlog_napi", setup_backlog_napi_threads); +- +-static bool use_backlog_threads(void) +-{ +- return static_branch_unlikely(&use_backlog_threads_key); +-} +- +-#else +- +-static bool use_backlog_threads(void) +-{ +- return true; +-} +- +-#endif +- + static inline void rps_lock_irqsave(struct softnet_data *sd, + unsigned long *flags) + { +@@ -4533,7 +4507,6 @@ EXPORT_SYMBOL(__dev_direct_xmit); + /************************************************************************* + * Receiver routines + *************************************************************************/ +-static DEFINE_PER_CPU(struct task_struct *, backlog_napi); + + int netdev_max_backlog __read_mostly = 1000; + EXPORT_SYMBOL(netdev_max_backlog); +@@ -4566,16 +4539,18 @@ static inline void ____napi_schedule(struct softnet_data *sd, + */ + thread = READ_ONCE(napi->thread); + if (thread) { +- if (use_backlog_threads() && thread == raw_cpu_read(backlog_napi)) +- goto use_local_napi; +- +- set_bit(NAPI_STATE_SCHED_THREADED, &napi->state); ++ /* Avoid doing set_bit() if the thread is in ++ * INTERRUPTIBLE state, cause napi_thread_wait() ++ * makes sure to proceed with napi polling ++ * if the thread is explicitly woken from here. ++ */ ++ if (READ_ONCE(thread->__state) != TASK_INTERRUPTIBLE) ++ set_bit(NAPI_STATE_SCHED_THREADED, &napi->state); + wake_up_process(thread); + return; + } + } + +-use_local_napi: + list_add_tail(&napi->poll_list, &sd->poll_list); + WRITE_ONCE(napi->list_owner, smp_processor_id()); + /* If not called from net_rx_action() +@@ -4821,11 +4796,6 @@ static void napi_schedule_rps(struct softnet_data *sd) + + #ifdef CONFIG_RPS + if (sd != mysd) { +- if (use_backlog_threads()) { +- __napi_schedule_irqoff(&sd->backlog); +- return; +- } +- + sd->rps_ipi_next = mysd->rps_ipi_list; + mysd->rps_ipi_list = sd; + +@@ -6049,7 +6019,7 @@ static void net_rps_action_and_irq_enable(struct softnet_data *sd) + #ifdef CONFIG_RPS + struct softnet_data *remsd = sd->rps_ipi_list; + +- if (!use_backlog_threads() && remsd) { ++ if (remsd) { + sd->rps_ipi_list = NULL; + + local_irq_enable(); +@@ -6064,7 +6034,7 @@ static void net_rps_action_and_irq_enable(struct softnet_data *sd) + static bool sd_has_rps_ipi_waiting(struct softnet_data *sd) + { + #ifdef CONFIG_RPS +- return !use_backlog_threads() && sd->rps_ipi_list; ++ return sd->rps_ipi_list != NULL; + #else + return false; + #endif +@@ -6108,7 +6078,7 @@ static int process_backlog(struct napi_struct *napi, int quota) + * We can use a plain write instead of clear_bit(), + * and we dont need an smp_mb() memory barrier. + */ +- napi->state &= NAPIF_STATE_THREADED; ++ napi->state = 0; + again = false; + } else { + skb_queue_splice_tail_init(&sd->input_pkt_queue, +@@ -6731,6 +6701,8 @@ static int napi_poll(struct napi_struct *n, struct list_head *repoll) + + static int napi_thread_wait(struct napi_struct *napi) + { ++ bool woken = false; ++ + set_current_state(TASK_INTERRUPTIBLE); + + while (!kthread_should_stop()) { +@@ -6739,13 +6711,15 @@ static int napi_thread_wait(struct napi_struct *napi) + * Testing SCHED bit is not enough because SCHED bit might be + * set by some other busy poll thread or by napi_disable(). + */ +- if (test_bit(NAPI_STATE_SCHED_THREADED, &napi->state)) { ++ if (test_bit(NAPI_STATE_SCHED_THREADED, &napi->state) || woken) { + WARN_ON(!list_empty(&napi->poll_list)); + __set_current_state(TASK_RUNNING); + return 0; + } + + schedule(); ++ /* woken being true indicates this thread owns this napi. */ ++ woken = true; + set_current_state(TASK_INTERRUPTIBLE); + } + __set_current_state(TASK_RUNNING); +@@ -6774,48 +6748,43 @@ static void skb_defer_free_flush(struct softnet_data *sd) + } + } + +-static void napi_threaded_poll_loop(struct napi_struct *napi) ++static int napi_threaded_poll(void *data) + { ++ struct napi_struct *napi = data; + struct softnet_data *sd; +- unsigned long last_qs = jiffies; ++ void *have; + +- for (;;) { +- bool repoll = false; +- void *have; ++ while (!napi_thread_wait(napi)) { ++ unsigned long last_qs = jiffies; + +- local_bh_disable(); +- sd = this_cpu_ptr(&softnet_data); +- sd->in_napi_threaded_poll = true; ++ for (;;) { ++ bool repoll = false; + +- have = netpoll_poll_lock(napi); +- __napi_poll(napi, &repoll); +- netpoll_poll_unlock(have); ++ local_bh_disable(); ++ sd = this_cpu_ptr(&softnet_data); ++ sd->in_napi_threaded_poll = true; + +- sd->in_napi_threaded_poll = false; +- barrier(); ++ have = netpoll_poll_lock(napi); ++ __napi_poll(napi, &repoll); ++ netpoll_poll_unlock(have); + +- if (sd_has_rps_ipi_waiting(sd)) { +- local_irq_disable(); +- net_rps_action_and_irq_enable(sd); +- } +- skb_defer_free_flush(sd); +- local_bh_enable(); ++ sd->in_napi_threaded_poll = false; ++ barrier(); + +- if (!repoll) +- break; +- +- rcu_softirq_qs_periodic(last_qs); +- cond_resched(); +- } +-} +- +-static int napi_threaded_poll(void *data) +-{ +- struct napi_struct *napi = data; ++ if (sd_has_rps_ipi_waiting(sd)) { ++ local_irq_disable(); ++ net_rps_action_and_irq_enable(sd); ++ } ++ skb_defer_free_flush(sd); ++ local_bh_enable(); + +- while (!napi_thread_wait(napi)) +- napi_threaded_poll_loop(napi); ++ if (!repoll) ++ break; + ++ rcu_softirq_qs_periodic(last_qs); ++ cond_resched(); ++ } ++ } + return 0; + } + +@@ -11400,7 +11369,7 @@ static int dev_cpu_dead(unsigned int oldcpu) + + list_del_init(&napi->poll_list); + if (napi->poll == process_backlog) +- napi->state &= NAPIF_STATE_THREADED; ++ napi->state = 0; + else + ____napi_schedule(sd, napi); + } +@@ -11408,14 +11377,12 @@ static int dev_cpu_dead(unsigned int oldcpu) + raise_softirq_irqoff(NET_TX_SOFTIRQ); + local_irq_enable(); + +- if (!use_backlog_threads()) { + #ifdef CONFIG_RPS +- remsd = oldsd->rps_ipi_list; +- oldsd->rps_ipi_list = NULL; ++ remsd = oldsd->rps_ipi_list; ++ oldsd->rps_ipi_list = NULL; + #endif +- /* send out pending IPI's on offline CPU */ +- net_rps_send_ipi(remsd); +- } ++ /* send out pending IPI's on offline CPU */ ++ net_rps_send_ipi(remsd); + + /* Process offline CPU's input_pkt_queue */ + while ((skb = __skb_dequeue(&oldsd->process_queue))) { +@@ -11678,38 +11645,6 @@ static struct pernet_operations __net_initdata default_device_ops = { + * + */ + +-static int backlog_napi_should_run(unsigned int cpu) +-{ +- struct softnet_data *sd = per_cpu_ptr(&softnet_data, cpu); +- struct napi_struct *napi = &sd->backlog; +- +- return test_bit(NAPI_STATE_SCHED_THREADED, &napi->state); +-} +- +-static void run_backlog_napi(unsigned int cpu) +-{ +- struct softnet_data *sd = per_cpu_ptr(&softnet_data, cpu); +- +- napi_threaded_poll_loop(&sd->backlog); +-} +- +-static void backlog_napi_setup(unsigned int cpu) +-{ +- struct softnet_data *sd = per_cpu_ptr(&softnet_data, cpu); +- struct napi_struct *napi = &sd->backlog; +- +- napi->thread = this_cpu_read(backlog_napi); +- set_bit(NAPI_STATE_THREADED, &napi->state); +-} +- +-static struct smp_hotplug_thread backlog_threads = { +- .store = &backlog_napi, +- .thread_should_run = backlog_napi_should_run, +- .thread_fn = run_backlog_napi, +- .thread_comm = "backlog_napi/%u", +- .setup = backlog_napi_setup, +-}; +- + /* + * This is called single threaded during boot, so no need + * to take the rtnl semaphore. +@@ -11760,10 +11695,7 @@ static int __init net_dev_init(void) + init_gro_hash(&sd->backlog); + sd->backlog.poll = process_backlog; + sd->backlog.weight = weight_p; +- INIT_LIST_HEAD(&sd->backlog.poll_list); + } +- if (use_backlog_threads()) +- smpboot_register_percpu_thread(&backlog_threads); + + dev_boot_phase = 0; + +diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c +index fd91fd139d76cf..c7e815b7ca0870 100644 +--- a/net/ipv6/icmp.c ++++ b/net/ipv6/icmp.c +@@ -768,7 +768,9 @@ static enum skb_drop_reason icmpv6_echo_reply(struct sk_buff *skb) + fl6.daddr = ipv6_hdr(skb)->saddr; + if (saddr) + fl6.saddr = *saddr; +- fl6.flowi6_oif = icmp6_iif(skb); ++ fl6.flowi6_oif = ipv6_addr_loopback(&fl6.daddr) ? ++ skb->dev->ifindex : ++ icmp6_iif(skb); + fl6.fl6_icmp_type = type; + fl6.flowi6_mark = mark; + fl6.flowi6_uid = sock_net_uid(net, NULL); +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 44aad3394084bd..639268d70f96d4 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -530,7 +530,7 @@ struct ieee80211_if_managed { + + /* TDLS support */ + u8 tdls_peer[ETH_ALEN] __aligned(2); +- struct delayed_work tdls_peer_del_work; ++ struct wiphy_delayed_work tdls_peer_del_work; + struct sk_buff *orig_teardown_skb; /* The original teardown skb */ + struct sk_buff *teardown_skb; /* A copy to send through the AP */ + spinlock_t teardown_lock; /* To lock changing teardown_skb */ +@@ -2599,7 +2599,7 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, + const u8 *extra_ies, size_t extra_ies_len); + int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, enum nl80211_tdls_operation oper); +-void ieee80211_tdls_peer_del_work(struct work_struct *wk); ++void ieee80211_tdls_peer_del_work(struct wiphy *wiphy, struct wiphy_work *wk); + int ieee80211_tdls_channel_switch(struct wiphy *wiphy, struct net_device *dev, + const u8 *addr, u8 oper_class, + struct cfg80211_chan_def *chandef); +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index aa7cee830b0045..78b9206f99f469 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -6866,8 +6866,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) + ieee80211_beacon_connection_loss_work); + wiphy_work_init(&ifmgd->csa_connection_drop_work, + ieee80211_csa_connection_drop_work); +- INIT_DELAYED_WORK(&ifmgd->tdls_peer_del_work, +- ieee80211_tdls_peer_del_work); ++ wiphy_delayed_work_init(&ifmgd->tdls_peer_del_work, ++ ieee80211_tdls_peer_del_work); + wiphy_delayed_work_init(&ifmgd->ml_reconf_work, + ieee80211_ml_reconf_work); + timer_setup(&ifmgd->timer, ieee80211_sta_timer, 0); +@@ -7881,7 +7881,8 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) + &ifmgd->beacon_connection_loss_work); + wiphy_work_cancel(sdata->local->hw.wiphy, + &ifmgd->csa_connection_drop_work); +- cancel_delayed_work_sync(&ifmgd->tdls_peer_del_work); ++ wiphy_delayed_work_cancel(sdata->local->hw.wiphy, ++ &ifmgd->tdls_peer_del_work); + wiphy_delayed_work_cancel(sdata->local->hw.wiphy, + &ifmgd->ml_reconf_work); + +diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c +index f3cdbd2133f67c..0fd353fec9fc66 100644 +--- a/net/mac80211/tdls.c ++++ b/net/mac80211/tdls.c +@@ -21,7 +21,7 @@ + /* give usermode some time for retries in setting up the TDLS session */ + #define TDLS_PEER_SETUP_TIMEOUT (15 * HZ) + +-void ieee80211_tdls_peer_del_work(struct work_struct *wk) ++void ieee80211_tdls_peer_del_work(struct wiphy *wiphy, struct wiphy_work *wk) + { + struct ieee80211_sub_if_data *sdata; + struct ieee80211_local *local; +@@ -1224,9 +1224,9 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev, + return ret; + } + +- ieee80211_queue_delayed_work(&sdata->local->hw, +- &sdata->u.mgd.tdls_peer_del_work, +- TDLS_PEER_SETUP_TIMEOUT); ++ wiphy_delayed_work_queue(sdata->local->hw.wiphy, ++ &sdata->u.mgd.tdls_peer_del_work, ++ TDLS_PEER_SETUP_TIMEOUT); + return 0; + + out_unlock: +@@ -1526,7 +1526,8 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, + } + + if (ret == 0 && ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) { +- cancel_delayed_work(&sdata->u.mgd.tdls_peer_del_work); ++ wiphy_delayed_work_cancel(sdata->local->hw.wiphy, ++ &sdata->u.mgd.tdls_peer_del_work); + eth_zero_addr(sdata->u.mgd.tdls_peer); + } + +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index 0dbf2e0d9762d7..f3856856aa446b 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -796,11 +796,8 @@ static bool __mptcp_ofo_queue(struct mptcp_sock *msk) + + static bool __mptcp_subflow_error_report(struct sock *sk, struct sock *ssk) + { +- int err = sock_error(ssk); + int ssk_state; +- +- if (!err) +- return false; ++ int err; + + /* only propagate errors on fallen-back sockets or + * on MPC connect +@@ -808,6 +805,10 @@ static bool __mptcp_subflow_error_report(struct sock *sk, struct sock *ssk) + if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(mptcp_sk(sk))) + return false; + ++ err = sock_error(ssk); ++ if (!err) ++ return false; ++ + /* We need to propagate only transition to CLOSE state. + * Orphaned socket will see such state change via + * subflow_sched_work_if_closed() and that path will properly +@@ -2553,8 +2554,8 @@ out: + void mptcp_close_ssk(struct sock *sk, struct sock *ssk, + struct mptcp_subflow_context *subflow) + { +- /* The first subflow can already be closed and still in the list */ +- if (subflow->close_event_done) ++ /* The first subflow can already be closed or disconnected */ ++ if (subflow->close_event_done || READ_ONCE(subflow->local_id) < 0) + return; + + subflow->close_event_done = true; +diff --git a/net/nfc/core.c b/net/nfc/core.c +index 5352571b621484..a02ede8b067bd3 100644 +--- a/net/nfc/core.c ++++ b/net/nfc/core.c +@@ -1147,14 +1147,14 @@ int nfc_register_device(struct nfc_dev *dev) + EXPORT_SYMBOL(nfc_register_device); + + /** +- * nfc_unregister_device - unregister a nfc device in the nfc subsystem ++ * nfc_unregister_rfkill - unregister a nfc device in the rfkill subsystem + * + * @dev: The nfc device to unregister + */ +-void nfc_unregister_device(struct nfc_dev *dev) ++void nfc_unregister_rfkill(struct nfc_dev *dev) + { +- int rc; + struct rfkill *rfk = NULL; ++ int rc; + + pr_debug("dev_name=%s\n", dev_name(&dev->dev)); + +@@ -1175,7 +1175,16 @@ void nfc_unregister_device(struct nfc_dev *dev) + rfkill_unregister(rfk); + rfkill_destroy(rfk); + } ++} ++EXPORT_SYMBOL(nfc_unregister_rfkill); + ++/** ++ * nfc_remove_device - remove a nfc device in the nfc subsystem ++ * ++ * @dev: The nfc device to remove ++ */ ++void nfc_remove_device(struct nfc_dev *dev) ++{ + if (dev->ops->check_presence) { + del_timer_sync(&dev->check_pres_timer); + cancel_work_sync(&dev->check_pres_work); +@@ -1188,6 +1197,18 @@ void nfc_unregister_device(struct nfc_dev *dev) + device_del(&dev->dev); + mutex_unlock(&nfc_devlist_mutex); + } ++EXPORT_SYMBOL(nfc_remove_device); ++ ++/** ++ * nfc_unregister_device - unregister a nfc device in the nfc subsystem ++ * ++ * @dev: The nfc device to unregister ++ */ ++void nfc_unregister_device(struct nfc_dev *dev) ++{ ++ nfc_unregister_rfkill(dev); ++ nfc_remove_device(dev); ++} + EXPORT_SYMBOL(nfc_unregister_device); + + static int __init nfc_init(void) +diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c +index e2680a3bef7995..b652323bc2c12b 100644 +--- a/net/nfc/llcp_commands.c ++++ b/net/nfc/llcp_commands.c +@@ -778,8 +778,23 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, + if (likely(frag_len > 0)) + skb_put_data(pdu, msg_ptr, frag_len); + ++ spin_lock(&local->tx_queue.lock); ++ ++ if (list_empty(&local->list)) { ++ spin_unlock(&local->tx_queue.lock); ++ ++ kfree_skb(pdu); ++ ++ len -= remaining_len; ++ if (len == 0) ++ len = -ENXIO; ++ break; ++ } ++ + /* No need to check for the peer RW for UI frames */ +- skb_queue_tail(&local->tx_queue, pdu); ++ __skb_queue_tail(&local->tx_queue, pdu); ++ ++ spin_unlock(&local->tx_queue.lock); + + remaining_len -= frag_len; + msg_ptr += frag_len; +diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c +index 18be13fb9b75a3..ced99d2a90cc10 100644 +--- a/net/nfc/llcp_core.c ++++ b/net/nfc/llcp_core.c +@@ -314,7 +314,9 @@ static struct nfc_llcp_local *nfc_llcp_remove_local(struct nfc_dev *dev) + spin_lock(&llcp_devices_lock); + list_for_each_entry_safe(local, tmp, &llcp_devices, list) + if (local->dev == dev) { +- list_del(&local->list); ++ spin_lock(&local->tx_queue.lock); ++ list_del_init(&local->list); ++ spin_unlock(&local->tx_queue.lock); + spin_unlock(&llcp_devices_lock); + return local; + } +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index c4d2932c590322..b7d4952a7dcf88 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -1292,6 +1292,8 @@ void nci_unregister_device(struct nci_dev *ndev) + { + struct nci_conn_info *conn_info, *n; + ++ nfc_unregister_rfkill(ndev->nfc_dev); ++ + /* This set_bit is not protected with specialized barrier, + * However, it is fine because the mutex_lock(&ndev->req_lock); + * in nci_close_device() will help to emit one. +@@ -1309,7 +1311,7 @@ void nci_unregister_device(struct nci_dev *ndev) + /* conn_info is allocated with devm_kzalloc */ + } + +- nfc_unregister_device(ndev->nfc_dev); ++ nfc_remove_device(ndev->nfc_dev); + } + EXPORT_SYMBOL(nci_unregister_device); + +diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c +index 567a58d30df8dc..58c1ab02bd0d2b 100644 +--- a/net/sched/act_ife.c ++++ b/net/sched/act_ife.c +@@ -649,9 +649,9 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, + + memset(&opt, 0, sizeof(opt)); + +- opt.index = ife->tcf_index, +- opt.refcnt = refcount_read(&ife->tcf_refcnt) - ref, +- opt.bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, ++ opt.index = ife->tcf_index; ++ opt.refcnt = refcount_read(&ife->tcf_refcnt) - ref; ++ opt.bindcnt = atomic_read(&ife->tcf_bindcnt) - bind; + + spin_lock_bh(&ife->tcf_lock); + opt.action = ife->tcf_action; +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index 1b51b3038b4bd6..c1c67da2d3fc43 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -910,8 +910,8 @@ static int pfifo_fast_change_tx_queue_len(struct Qdisc *sch, + bands[prio] = q; + } + +- return skb_array_resize_multiple(bands, PFIFO_FAST_BANDS, new_len, +- GFP_KERNEL); ++ return skb_array_resize_multiple_bh(bands, PFIFO_FAST_BANDS, new_len, ++ GFP_KERNEL); + } + + struct Qdisc_ops pfifo_fast_ops __read_mostly = { +diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c +index 93c802cfb9c6ab..569d39f19c5695 100644 +--- a/net/xdp/xsk.c ++++ b/net/xdp/xsk.c +@@ -339,13 +339,14 @@ int xsk_generic_rcv(struct xdp_sock *xs, struct xdp_buff *xdp) + u32 len = xdp_get_buff_len(xdp); + int err; + +- spin_lock_bh(&xs->rx_lock); + err = xsk_rcv_check(xs, xdp, len); + if (!err) { ++ spin_lock_bh(&xs->pool->rx_lock); + err = __xsk_rcv(xs, xdp, len); + xsk_flush(xs); ++ spin_unlock_bh(&xs->pool->rx_lock); + } +- spin_unlock_bh(&xs->rx_lock); ++ + return err; + } + +@@ -1647,7 +1648,6 @@ static int xsk_create(struct net *net, struct socket *sock, int protocol, + xs = xdp_sk(sk); + xs->state = XSK_READY; + mutex_init(&xs->mutex); +- spin_lock_init(&xs->rx_lock); + + INIT_LIST_HEAD(&xs->map_list); + spin_lock_init(&xs->map_list_lock); +diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c +index e83b707da25b51..380b0b3f3d8d0c 100644 +--- a/net/xdp/xsk_buff_pool.c ++++ b/net/xdp/xsk_buff_pool.c +@@ -85,6 +85,7 @@ struct xsk_buff_pool *xp_create_and_assign_umem(struct xdp_sock *xs, + XDP_PACKET_HEADROOM; + pool->umem = umem; + pool->addrs = umem->addrs; ++ spin_lock_init(&pool->rx_lock); + INIT_LIST_HEAD(&pool->free_list); + INIT_LIST_HEAD(&pool->xskb_list); + INIT_LIST_HEAD(&pool->xsk_tx_list); +diff --git a/scripts/Makefile.build b/scripts/Makefile.build +index 5c4e437f9d854d..b897c780671129 100644 +--- a/scripts/Makefile.build ++++ b/scripts/Makefile.build +@@ -294,7 +294,7 @@ $(obj)/%.o: $(src)/%.rs FORCE + quiet_cmd_rustc_rsi_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@ + cmd_rustc_rsi_rs = \ + $(rust_common_cmd) -Zunpretty=expanded $< >$@; \ +- command -v $(RUSTFMT) >/dev/null && $(RUSTFMT) $@ ++ command -v $(RUSTFMT) >/dev/null && $(RUSTFMT) --config-path $(srctree)/.rustfmt.toml $@ + + $(obj)/%.rsi: $(src)/%.rs FORCE + $(call if_changed_dep,rustc_rsi_rs) +diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py +index c99173e4b8f3ea..99d5b177a43c6c 100755 +--- a/scripts/generate_rust_analyzer.py ++++ b/scripts/generate_rust_analyzer.py +@@ -73,7 +73,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs): + append_crate( + "compiler_builtins", + srctree / "rust" / "compiler_builtins.rs", +- [], ++ ["core"], + ) + + append_crate( +diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c +index 54dac6bfc9d180..00e4ffeb6fb00a 100644 +--- a/sound/soc/amd/yc/acp6x-mach.c ++++ b/sound/soc/amd/yc/acp6x-mach.c +@@ -661,6 +661,14 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "GOH-X"), + } + }, ++ { ++ .driver_data = &acp6x_card, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "RB"), ++ DMI_MATCH(DMI_BOARD_NAME, "XyloD5_RBU"), ++ } ++ }, ++ + {} + }; + +diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c +index bb304de5cc38a3..01f656e0e092b3 100644 +--- a/sound/soc/fsl/imx-card.c ++++ b/sound/soc/fsl/imx-card.c +@@ -314,7 +314,6 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream, + SND_SOC_DAIFMT_PDM; + } else { + slots = 2; +- slot_width = params_physical_width(params); + fmt = (rtd->dai_link->dai_fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) | + SND_SOC_DAIFMT_I2S; + } +diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c +index 9904a9e33cccbe..c9d9381c76796f 100644 +--- a/sound/soc/intel/boards/sof_es8336.c ++++ b/sound/soc/intel/boards/sof_es8336.c +@@ -120,7 +120,7 @@ static void pcm_pop_work_events(struct work_struct *work) + gpiod_set_value_cansleep(priv->gpio_speakers, priv->speaker_en); + + if (quirk & SOF_ES8336_HEADPHONE_GPIO) +- gpiod_set_value_cansleep(priv->gpio_headphone, priv->speaker_en); ++ gpiod_set_value_cansleep(priv->gpio_headphone, !priv->speaker_en); + + } + +diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c +index b05ad2eb623db6..17ae74b067c5ef 100644 +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -1386,7 +1386,8 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, + if (ep->packsize[1] > ep->maxpacksize) { + usb_audio_dbg(chip, "Too small maxpacksize %u for rate %u / pps %u\n", + ep->maxpacksize, ep->cur_rate, ep->pps); +- return -EINVAL; ++ err = -EINVAL; ++ goto unlock; + } + + /* calculate the frequency in 16.16 format */ +diff --git a/tools/testing/selftests/bpf/progs/test_select_reuseport_kern.c b/tools/testing/selftests/bpf/progs/test_select_reuseport_kern.c +index 5eb25c6ad75b1a..a5be3267dbb013 100644 +--- a/tools/testing/selftests/bpf/progs/test_select_reuseport_kern.c ++++ b/tools/testing/selftests/bpf/progs/test_select_reuseport_kern.c +@@ -1,7 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* Copyright (c) 2018 Facebook */ + +-#include + #include + #include + #include +diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh +index 2c025c73e19fc4..c571563a42c596 100755 +--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh +@@ -2203,17 +2203,16 @@ signal_address_tests() + ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=1 + speed=slow \ + run_tests $ns1 $ns2 10.0.1.1 ++ chk_join_nr 3 3 3 + + # It is not directly linked to the commit introducing this + # symbol but for the parent one which is linked anyway. +- if ! mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then +- chk_join_nr 3 3 2 +- chk_add_nr 4 4 +- else +- chk_join_nr 3 3 3 ++ if mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then + # the server will not signal the address terminating + # the MPC subflow + chk_add_nr 3 3 ++ else ++ chk_add_nr 4 4 + fi + fi + } +@@ -3544,21 +3543,28 @@ userspace_pm_chk_get_addr() + fi + } + +-# $1: ns ; $2: event type ; $3: count ++# $1: ns ; $2: event type ; $3: count ; [ $4: attr ; $5: attr count ] + chk_evt_nr() + { + local ns=${1} + local evt_name="${2}" + local exp="${3}" ++ local attr="${4}" ++ local attr_exp="${5}" + + local evts="${evts_ns1}" + local evt="${!evt_name}" ++ local attr_name + local count + ++ if [ -n "${attr}" ]; then ++ attr_name=", ${attr}: ${attr_exp}" ++ fi ++ + evt_name="${evt_name:16}" # without MPTCP_LIB_EVENT_ + [ "${ns}" == "ns2" ] && evts="${evts_ns2}" + +- print_check "event ${ns} ${evt_name} (${exp})" ++ print_check "event ${ns} ${evt_name} (${exp}${attr_name})" + + if [[ "${evt_name}" = "LISTENER_"* ]] && + ! mptcp_lib_kallsyms_has "mptcp_event_pm_listener$"; then +@@ -3569,11 +3575,42 @@ chk_evt_nr() + count=$(grep -cw "type:${evt}" "${evts}") + if [ "${count}" != "${exp}" ]; then + fail_test "got ${count} events, expected ${exp}" ++ cat "${evts}" ++ return ++ elif [ -z "${attr}" ]; then ++ print_ok ++ return ++ fi ++ ++ count=$(grep -w "type:${evt}" "${evts}" | grep -c ",${attr}:") ++ if [ "${count}" != "${attr_exp}" ]; then ++ fail_test "got ${count} event attributes, expected ${attr_exp}" ++ grep -w "type:${evt}" "${evts}" + else + print_ok + fi + } + ++# $1: ns ; $2: event type ; $3: expected count ++wait_event() ++{ ++ local ns="${1}" ++ local evt_name="${2}" ++ local exp="${3}" ++ ++ local evt="${!evt_name}" ++ local evts="${evts_ns1}" ++ local count ++ ++ [ "${ns}" == "ns2" ] && evts="${evts_ns2}" ++ ++ for _ in $(seq 100); do ++ count=$(grep -cw "type:${evt}" "${evts}") ++ [ "${count}" -ge "${exp}" ] && break ++ sleep 0.1 ++ done ++} ++ + userspace_tests() + { + # userspace pm type prevents add_addr +@@ -3730,6 +3767,36 @@ userspace_tests() + kill_events_pids + mptcp_lib_kill_group_wait $tests_pid + fi ++ ++ # userspace pm no duplicated spurious close events after an error ++ if reset_with_events "userspace pm no dup close events after error" && ++ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then ++ set_userspace_pm $ns2 ++ pm_nl_set_limits $ns1 0 2 ++ { timeout_test=120 test_linkfail=128 speed=slow \ ++ run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null ++ local tests_pid=$! ++ wait_event ns2 MPTCP_LIB_EVENT_ESTABLISHED 1 ++ userspace_pm_add_sf $ns2 10.0.3.2 20 ++ chk_mptcp_info subflows 1 subflows 1 ++ chk_subflows_total 2 2 ++ ++ # force quick loss ++ ip netns exec $ns2 sysctl -q net.ipv4.tcp_syn_retries=1 ++ if ip netns exec "${ns1}" ${iptables} -A INPUT -s "10.0.1.2" \ ++ -p tcp --tcp-option 30 -j REJECT --reject-with tcp-reset && ++ ip netns exec "${ns2}" ${iptables} -A INPUT -d "10.0.1.2" \ ++ -p tcp --tcp-option 30 -j REJECT --reject-with tcp-reset; then ++ wait_event ns2 MPTCP_LIB_EVENT_SUB_CLOSED 1 ++ wait_event ns1 MPTCP_LIB_EVENT_SUB_CLOSED 1 ++ chk_subflows_total 1 1 ++ userspace_pm_add_sf $ns2 10.0.1.2 0 ++ wait_event ns2 MPTCP_LIB_EVENT_SUB_CLOSED 2 ++ chk_evt_nr ns2 MPTCP_LIB_EVENT_SUB_CLOSED 2 error 2 ++ fi ++ kill_events_pids ++ mptcp_lib_kill_group_wait $tests_pid ++ fi + } + + endpoint_tests() diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.123-124.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.123-124.patch new file mode 100644 index 0000000000..254e8012d5 --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.123-124.patch @@ -0,0 +1,2540 @@ +diff --git a/Makefile b/Makefile +index 170507f68a9aad..4ec8ec24a35414 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 123 ++SUBLEVEL = 124 + EXTRAVERSION = + NAME = Pinguïn Aangedreven + +diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h +index 6c607c68f3ad75..c35250c4991bc7 100644 +--- a/arch/arm/include/asm/string.h ++++ b/arch/arm/include/asm/string.h +@@ -42,7 +42,10 @@ static inline void *memset32(uint32_t *p, uint32_t v, __kernel_size_t n) + extern void *__memset64(uint64_t *, uint32_t low, __kernel_size_t, uint32_t hi); + static inline void *memset64(uint64_t *p, uint64_t v, __kernel_size_t n) + { +- return __memset64(p, v, n * 8, v >> 32); ++ if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN)) ++ return __memset64(p, v, n * 8, v >> 32); ++ else ++ return __memset64(p, v >> 32, n * 8, v); + } + + /* +diff --git a/arch/loongarch/kernel/traps.c b/arch/loongarch/kernel/traps.c +index d7291b8ea65aac..0529bd32c1f178 100644 +--- a/arch/loongarch/kernel/traps.c ++++ b/arch/loongarch/kernel/traps.c +@@ -508,10 +508,15 @@ out: + asmlinkage void noinstr do_ade(struct pt_regs *regs) + { + irqentry_state_t state = irqentry_enter(regs); ++ unsigned int esubcode = FIELD_GET(CSR_ESTAT_ESUBCODE, regs->csr_estat); ++ ++ if ((esubcode == EXSUBCODE_ADEM) && fixup_exception(regs)) ++ goto out; + + die_if_kernel("Kernel ade access", regs); + force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)regs->csr_badvaddr); + ++out: + irqentry_exit(regs, state); + } + +diff --git a/arch/loongarch/mm/cache.c b/arch/loongarch/mm/cache.c +index 6be04d36ca0769..496916845ff764 100644 +--- a/arch/loongarch/mm/cache.c ++++ b/arch/loongarch/mm/cache.c +@@ -160,8 +160,8 @@ void cpu_cache_init(void) + + static const pgprot_t protection_map[16] = { + [VM_NONE] = __pgprot(_CACHE_CC | _PAGE_USER | +- _PAGE_PROTNONE | _PAGE_NO_EXEC | +- _PAGE_NO_READ), ++ _PAGE_NO_EXEC | _PAGE_NO_READ | ++ (_PAGE_PROTNONE ? : _PAGE_PRESENT)), + [VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID | + _PAGE_USER | _PAGE_PRESENT | + _PAGE_NO_EXEC), +@@ -180,8 +180,8 @@ static const pgprot_t protection_map[16] = { + [VM_EXEC | VM_WRITE | VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID | + _PAGE_USER | _PAGE_PRESENT), + [VM_SHARED] = __pgprot(_CACHE_CC | _PAGE_USER | +- _PAGE_PROTNONE | _PAGE_NO_EXEC | +- _PAGE_NO_READ), ++ _PAGE_NO_EXEC | _PAGE_NO_READ | ++ (_PAGE_PROTNONE ? : _PAGE_PRESENT)), + [VM_SHARED | VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID | + _PAGE_USER | _PAGE_PRESENT | + _PAGE_NO_EXEC), +diff --git a/arch/x86/include/asm/kfence.h b/arch/x86/include/asm/kfence.h +index acf9ffa1a17183..dfd5c74ba41a2f 100644 +--- a/arch/x86/include/asm/kfence.h ++++ b/arch/x86/include/asm/kfence.h +@@ -42,7 +42,7 @@ static inline bool kfence_protect_page(unsigned long addr, bool protect) + { + unsigned int level; + pte_t *pte = lookup_address(addr, &level); +- pteval_t val; ++ pteval_t val, new; + + if (WARN_ON(!pte || level != PG_LEVEL_4K)) + return false; +@@ -57,11 +57,12 @@ static inline bool kfence_protect_page(unsigned long addr, bool protect) + return true; + + /* +- * Otherwise, invert the entire PTE. This avoids writing out an ++ * Otherwise, flip the Present bit, taking care to avoid writing an + * L1TF-vulnerable PTE (not present, without the high address bits + * set). + */ +- set_pte(pte, __pte(~val)); ++ new = val ^ _PAGE_PRESENT; ++ set_pte(pte, __pte(flip_protnone_guard(val, new, PTE_PFN_MASK))); + + /* + * If the page was protected (non-present) and we're making it +diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c +index 2c90e5de0acd94..cb2a381193d13f 100644 +--- a/block/bfq-cgroup.c ++++ b/block/bfq-cgroup.c +@@ -380,7 +380,7 @@ static void bfqg_stats_add_aux(struct bfqg_stats *to, struct bfqg_stats *from) + blkg_rwstat_add_aux(&to->merged, &from->merged); + blkg_rwstat_add_aux(&to->service_time, &from->service_time); + blkg_rwstat_add_aux(&to->wait_time, &from->wait_time); +- bfq_stat_add_aux(&from->time, &from->time); ++ bfq_stat_add_aux(&to->time, &from->time); + bfq_stat_add_aux(&to->avg_queue_size_sum, &from->avg_queue_size_sum); + bfq_stat_add_aux(&to->avg_queue_size_samples, + &from->avg_queue_size_samples); +diff --git a/drivers/android/binder.c b/drivers/android/binder.c +index e5096fcfad5760..43f11f66970b25 100644 +--- a/drivers/android/binder.c ++++ b/drivers/android/binder.c +@@ -3663,8 +3663,9 @@ static void binder_transaction(struct binder_proc *proc, + return; + + err_dead_proc_or_thread: +- binder_txn_error("%d:%d dead process or thread\n", +- thread->pid, proc->pid); ++ binder_txn_error("%d:%d %s process or thread\n", ++ proc->pid, thread->pid, ++ return_error == BR_FROZEN_REPLY ? "frozen" : "dead"); + return_error_line = __LINE__; + binder_dequeue_work(proc, tcomplete); + err_translate_failed: +diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c +index 81effec17b3d63..2967170e09c8da 100644 +--- a/drivers/android/binderfs.c ++++ b/drivers/android/binderfs.c +@@ -130,8 +130,8 @@ static int binderfs_binder_device_create(struct inode *ref_inode, + mutex_lock(&binderfs_minors_mutex); + if (++info->device_count <= info->mount_opts.max) + minor = ida_alloc_max(&binderfs_minors, +- use_reserve ? BINDERFS_MAX_MINOR : +- BINDERFS_MAX_MINOR_CAPPED, ++ use_reserve ? BINDERFS_MAX_MINOR - 1 : ++ BINDERFS_MAX_MINOR_CAPPED - 1, + GFP_KERNEL); + else + minor = -ENOSPC; +@@ -421,8 +421,8 @@ static int binderfs_binder_ctl_create(struct super_block *sb) + /* Reserve a new minor number for the new device. */ + mutex_lock(&binderfs_minors_mutex); + minor = ida_alloc_max(&binderfs_minors, +- use_reserve ? BINDERFS_MAX_MINOR : +- BINDERFS_MAX_MINOR_CAPPED, ++ use_reserve ? BINDERFS_MAX_MINOR - 1 : ++ BINDERFS_MAX_MINOR_CAPPED - 1, + GFP_KERNEL); + mutex_unlock(&binderfs_minors_mutex); + if (minor < 0) { +diff --git a/drivers/base/regmap/regcache-maple.c b/drivers/base/regmap/regcache-maple.c +index fb5761a5ef6ee2..86de71ce2c1919 100644 +--- a/drivers/base/regmap/regcache-maple.c ++++ b/drivers/base/regmap/regcache-maple.c +@@ -96,12 +96,13 @@ static int regcache_maple_write(struct regmap *map, unsigned int reg, + + mas_unlock(&mas); + +- if (ret == 0) { +- kfree(lower); +- kfree(upper); ++ if (ret) { ++ kfree(entry); ++ return ret; + } +- +- return ret; ++ kfree(lower); ++ kfree(upper); ++ return 0; + } + + static int regcache_maple_drop(struct regmap *map, unsigned int min, +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index 6fcd7f0fe4f03e..6f68c2a7436105 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -3495,11 +3495,29 @@ static void rbd_img_object_requests(struct rbd_img_request *img_req) + rbd_assert(!need_exclusive_lock(img_req) || + __rbd_is_lock_owner(rbd_dev)); + +- if (rbd_img_is_write(img_req)) { +- rbd_assert(!img_req->snapc); ++ if (test_bit(IMG_REQ_CHILD, &img_req->flags)) { ++ rbd_assert(!rbd_img_is_write(img_req)); ++ } else { ++ struct request *rq = blk_mq_rq_from_pdu(img_req); ++ u64 off = (u64)blk_rq_pos(rq) << SECTOR_SHIFT; ++ u64 len = blk_rq_bytes(rq); ++ u64 mapping_size; ++ + down_read(&rbd_dev->header_rwsem); +- img_req->snapc = ceph_get_snap_context(rbd_dev->header.snapc); ++ mapping_size = rbd_dev->mapping.size; ++ if (rbd_img_is_write(img_req)) { ++ rbd_assert(!img_req->snapc); ++ img_req->snapc = ++ ceph_get_snap_context(rbd_dev->header.snapc); ++ } + up_read(&rbd_dev->header_rwsem); ++ ++ if (unlikely(off + len > mapping_size)) { ++ rbd_warn(rbd_dev, "beyond EOD (%llu~%llu > %llu)", ++ off, len, mapping_size); ++ img_req->pending.result = -EIO; ++ return; ++ } + } + + for_each_obj_request(img_req, obj_req) { +@@ -4725,7 +4743,6 @@ static void rbd_queue_workfn(struct work_struct *work) + struct request *rq = blk_mq_rq_from_pdu(img_request); + u64 offset = (u64)blk_rq_pos(rq) << SECTOR_SHIFT; + u64 length = blk_rq_bytes(rq); +- u64 mapping_size; + int result; + + /* Ignore/skip any zero-length requests */ +@@ -4738,17 +4755,9 @@ static void rbd_queue_workfn(struct work_struct *work) + blk_mq_start_request(rq); + + down_read(&rbd_dev->header_rwsem); +- mapping_size = rbd_dev->mapping.size; + rbd_img_capture_header(img_request); + up_read(&rbd_dev->header_rwsem); + +- if (offset + length > mapping_size) { +- rbd_warn(rbd_dev, "beyond EOD (%llu~%llu > %llu)", offset, +- length, mapping_size); +- result = -EIO; +- goto err_img_request; +- } +- + dout("%s rbd_dev %p img_req %p %s %llu~%llu\n", __func__, rbd_dev, + img_request, obj_op_name(op_type), offset, length); + +diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c +index 563b2a94d4c3cc..44f630a3f610bd 100644 +--- a/drivers/block/ublk_drv.c ++++ b/drivers/block/ublk_drv.c +@@ -1050,6 +1050,13 @@ static inline bool ubq_daemon_is_dying(struct ublk_queue *ubq) + return ubq->ubq_daemon->flags & PF_EXITING; + } + ++static void ublk_end_request(struct request *req, blk_status_t error) ++{ ++ local_bh_disable(); ++ blk_mq_end_request(req, error); ++ local_bh_enable(); ++} ++ + /* todo: handle partial completion */ + static inline void __ublk_complete_rq(struct request *req) + { +@@ -1057,6 +1064,7 @@ static inline void __ublk_complete_rq(struct request *req) + struct ublk_io *io = &ubq->ios[req->tag]; + unsigned int unmapped_bytes; + blk_status_t res = BLK_STS_OK; ++ bool requeue; + + /* called from ublk_abort_queue() code path */ + if (io->flags & UBLK_IO_FLAG_ABORTED) { +@@ -1094,14 +1102,30 @@ static inline void __ublk_complete_rq(struct request *req) + if (unlikely(unmapped_bytes < io->res)) + io->res = unmapped_bytes; + +- if (blk_update_request(req, BLK_STS_OK, io->res)) ++ /* ++ * Run bio->bi_end_io() with softirqs disabled. If the final fput ++ * happens off this path, then that will prevent ublk's blkdev_release() ++ * from being called on current's task work, see fput() implementation. ++ * ++ * Otherwise, ublk server may not provide forward progress in case of ++ * reading the partition table from bdev_open() with disk->open_mutex ++ * held, and causes dead lock as we could already be holding ++ * disk->open_mutex here. ++ * ++ * Preferably we would not be doing IO with a mutex held that is also ++ * used for release, but this work-around will suffice for now. ++ */ ++ local_bh_disable(); ++ requeue = blk_update_request(req, BLK_STS_OK, io->res); ++ local_bh_enable(); ++ if (requeue) + blk_mq_requeue_request(req, true); + else + __blk_mq_end_request(req, BLK_STS_OK); + + return; + exit: +- blk_mq_end_request(req, res); ++ ublk_end_request(req, res); + } + + static void ublk_complete_rq(struct kref *ref) +@@ -1160,7 +1184,7 @@ static inline void __ublk_abort_rq(struct ublk_queue *ubq, + if (ublk_queue_can_use_recovery(ubq)) + blk_mq_requeue_request(rq, false); + else +- blk_mq_end_request(rq, BLK_STS_IOERR); ++ ublk_end_request(rq, BLK_STS_IOERR); + + mod_delayed_work(system_wq, &ubq->dev->monitor_work, 0); + } +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +index b15ce4df747986..ded2cc47688053 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +@@ -2058,9 +2058,6 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, + return -ENODEV; + } + +- if (amdgpu_aspm == -1 && !pcie_aspm_enabled(pdev)) +- amdgpu_aspm = 0; +- + if (amdgpu_virtual_display || + amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK)) + supports_atomic = true; +diff --git a/drivers/gpu/drm/mgag200/mgag200_bmc.c b/drivers/gpu/drm/mgag200/mgag200_bmc.c +index 2ba2e3c5086a55..852a82f6309ba8 100644 +--- a/drivers/gpu/drm/mgag200/mgag200_bmc.c ++++ b/drivers/gpu/drm/mgag200/mgag200_bmc.c +@@ -1,13 +1,14 @@ + // SPDX-License-Identifier: GPL-2.0-only + + #include ++#include + + #include "mgag200_drv.h" + + void mgag200_bmc_disable_vidrst(struct mga_device *mdev) + { + u8 tmp; +- int iter_max; ++ int ret; + + /* + * 1 - The first step is to inform the BMC of an upcoming mode +@@ -37,30 +38,22 @@ void mgag200_bmc_disable_vidrst(struct mga_device *mdev) + + /* + * 3a- The third step is to verify if there is an active scan. +- * We are waiting for a 0 on remhsyncsts ). ++ * We are waiting for a 0 on remhsyncsts (). + */ +- iter_max = 300; +- while (!(tmp & 0x1) && iter_max) { +- WREG8(DAC_INDEX, MGA1064_SPAREREG); +- tmp = RREG8(DAC_DATA); +- udelay(1000); +- iter_max--; +- } ++ ret = read_poll_timeout(RREG_DAC, tmp, !(tmp & 0x1), ++ 1000, 300000, false, ++ MGA1064_SPAREREG); ++ if (ret == -ETIMEDOUT) ++ return; + + /* +- * 3b- This step occurs only if the remove is actually ++ * 3b- This step occurs only if the remote BMC is actually + * scanning. We are waiting for the end of the frame which is + * a 1 on remvsyncsts (XSPAREREG<1>) + */ +- if (iter_max) { +- iter_max = 300; +- while ((tmp & 0x2) && iter_max) { +- WREG8(DAC_INDEX, MGA1064_SPAREREG); +- tmp = RREG8(DAC_DATA); +- udelay(1000); +- iter_max--; +- } +- } ++ (void)read_poll_timeout(RREG_DAC, tmp, (tmp & 0x2), ++ 1000, 300000, false, ++ MGA1064_SPAREREG); + } + + void mgag200_bmc_enable_vidrst(struct mga_device *mdev) +diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h +index 765e49fd891112..44281713db462e 100644 +--- a/drivers/gpu/drm/mgag200/mgag200_drv.h ++++ b/drivers/gpu/drm/mgag200/mgag200_drv.h +@@ -115,6 +115,12 @@ + #define DAC_INDEX 0x3c00 + #define DAC_DATA 0x3c0a + ++#define RREG_DAC(reg) \ ++ ({ \ ++ WREG8(DAC_INDEX, reg); \ ++ RREG8(DAC_DATA); \ ++ }) \ ++ + #define WREG_DAC(reg, v) \ + do { \ + WREG8(DAC_INDEX, reg); \ +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index ca9c70c8f3cf14..931746cf363027 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -307,6 +307,7 @@ + #define USB_DEVICE_ID_CHICONY_ACER_SWITCH12 0x1421 + #define USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA 0xb824 + #define USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA2 0xb82c ++#define USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA3 0xb882 + + #define USB_VENDOR_ID_CHUNGHWAT 0x2247 + #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 +@@ -428,6 +429,9 @@ + #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001 + #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002 0xc002 + ++#define USB_VENDOR_ID_EDIFIER 0x2d99 ++#define USB_DEVICE_ID_EDIFIER_QR30 0xa101 /* EDIFIER Hal0 2.0 SE */ ++ + #define USB_VENDOR_ID_ELAN 0x04f3 + #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401 + #define USB_DEVICE_ID_HP_X2 0x074d +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index b9e67b408a4b93..6d9a85c5fc4097 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -379,6 +379,7 @@ static const struct mt_class mt_classes[] = { + { .name = MT_CLS_VTL, + .quirks = MT_QUIRK_ALWAYS_VALID | + MT_QUIRK_CONTACT_CNT_ACCURATE | ++ MT_QUIRK_STICKY_FINGERS | + MT_QUIRK_FORCE_GET_FEATURE, + }, + { .name = MT_CLS_GOOGLE, +diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c +index 8ac8f7b8e31730..32f65c45fdc8af 100644 +--- a/drivers/hid/hid-playstation.c ++++ b/drivers/hid/hid-playstation.c +@@ -711,11 +711,16 @@ static struct input_dev *ps_gamepad_create(struct hid_device *hdev, + if (IS_ERR(gamepad)) + return ERR_CAST(gamepad); + ++ /* Set initial resting state for joysticks to 128 (center) */ + input_set_abs_params(gamepad, ABS_X, 0, 255, 0, 0); ++ gamepad->absinfo[ABS_X].value = 128; + input_set_abs_params(gamepad, ABS_Y, 0, 255, 0, 0); ++ gamepad->absinfo[ABS_Y].value = 128; + input_set_abs_params(gamepad, ABS_Z, 0, 255, 0, 0); + input_set_abs_params(gamepad, ABS_RX, 0, 255, 0, 0); ++ gamepad->absinfo[ABS_RX].value = 128; + input_set_abs_params(gamepad, ABS_RY, 0, 255, 0, 0); ++ gamepad->absinfo[ABS_RY].value = 128; + input_set_abs_params(gamepad, ABS_RZ, 0, 255, 0, 0); + + input_set_abs_params(gamepad, ABS_HAT0X, -1, 1, 0, 0); +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index 192b8f63baaab7..1f531626192cdb 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -81,6 +81,7 @@ static const struct hid_device_id hid_quirks[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER), HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_EDIFIER, USB_DEVICE_ID_EDIFIER_QR30), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II), HID_QUIRK_MULTI_INPUT }, +@@ -763,6 +764,7 @@ static const struct hid_device_id hid_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA2) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI4713) }, +diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c +index 172b783274201b..0a350780407ecb 100644 +--- a/drivers/hid/i2c-hid/i2c-hid-core.c ++++ b/drivers/hid/i2c-hid/i2c-hid-core.c +@@ -254,6 +254,7 @@ static int i2c_hid_get_report(struct i2c_hid *ihid, + * In addition to report data device will supply data length + * in the first 2 bytes of the response, so adjust . + */ ++ recv_len = min(recv_len, ihid->bufsize - sizeof(__le16)); + error = i2c_hid_xfer(ihid, ihid->cmdbuf, length, + ihid->rawbuf, recv_len + sizeof(__le16)); + if (error) { +diff --git a/drivers/hid/intel-ish-hid/ishtp-hid-client.c b/drivers/hid/intel-ish-hid/ishtp-hid-client.c +index e3d70c5460e964..a0c1dc09414970 100644 +--- a/drivers/hid/intel-ish-hid/ishtp-hid-client.c ++++ b/drivers/hid/intel-ish-hid/ishtp-hid-client.c +@@ -496,6 +496,7 @@ static int ishtp_enum_enum_devices(struct ishtp_cl *hid_ishtp_cl) + int rv; + + /* Send HOSTIF_DM_ENUM_DEVICES */ ++ client_data->enum_devices_done = false; + memset(&msg, 0, sizeof(struct hostif_msg)); + msg.hdr.command = HOSTIF_DM_ENUM_DEVICES; + rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *)&msg, +diff --git a/drivers/hid/intel-ish-hid/ishtp/bus.c b/drivers/hid/intel-ish-hid/ishtp/bus.c +index 7fc738a2237556..4d97d043aae4b7 100644 +--- a/drivers/hid/intel-ish-hid/ishtp/bus.c ++++ b/drivers/hid/intel-ish-hid/ishtp/bus.c +@@ -240,9 +240,17 @@ static int ishtp_cl_bus_match(struct device *dev, struct device_driver *drv) + { + struct ishtp_cl_device *device = to_ishtp_cl_device(dev); + struct ishtp_cl_driver *driver = to_ishtp_cl_driver(drv); ++ struct ishtp_fw_client *client = device->fw_client; ++ const struct ishtp_device_id *id; + +- return(device->fw_client ? guid_equal(&driver->id[0].guid, +- &device->fw_client->props.protocol_name) : 0); ++ if (client) { ++ for (id = driver->id; !guid_is_null(&id->guid); id++) { ++ if (guid_equal(&id->guid, &client->props.protocol_name)) ++ return 1; ++ } ++ } ++ ++ return 0; + } + + /** +diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c +index 483f79b394298f..755926fa0bf7d9 100644 +--- a/drivers/hwmon/occ/common.c ++++ b/drivers/hwmon/occ/common.c +@@ -749,6 +749,7 @@ static ssize_t occ_show_extended(struct device *dev, + * are dynamically allocated, we cannot use the existing kernel macros which + * stringify the name argument. + */ ++__printf(7, 8) + static void occ_init_attribute(struct occ_attribute *attr, int mode, + ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf), + ssize_t (*store)(struct device *dev, struct device_attribute *attr, +diff --git a/drivers/net/ethernet/adi/adin1110.c b/drivers/net/ethernet/adi/adin1110.c +index 3c26176316a38b..2bf5c811953601 100644 +--- a/drivers/net/ethernet/adi/adin1110.c ++++ b/drivers/net/ethernet/adi/adin1110.c +@@ -1087,6 +1087,9 @@ static int adin1110_check_spi(struct adin1110_priv *priv) + + reset_gpio = devm_gpiod_get_optional(&priv->spidev->dev, "reset", + GPIOD_OUT_LOW); ++ if (IS_ERR(reset_gpio)) ++ return dev_err_probe(&priv->spidev->dev, PTR_ERR(reset_gpio), ++ "failed to get reset gpio\n"); + if (reset_gpio) { + /* MISO pin is used for internal configuration, can't have + * anyone else disturbing the SDO line. +diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c +index 100daadbea2a66..8e4e49d24dad81 100644 +--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c ++++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c +@@ -3519,6 +3519,23 @@ static int setup_nic_devices(struct octeon_device *octeon_dev) + */ + netdev->netdev_ops = &lionetdevops; + ++ lio = GET_LIO(netdev); ++ ++ memset(lio, 0, sizeof(struct lio)); ++ ++ lio->ifidx = ifidx_or_pfnum; ++ ++ props = &octeon_dev->props[i]; ++ props->gmxport = resp->cfg_info.linfo.gmxport; ++ props->netdev = netdev; ++ ++ /* Point to the properties for octeon device to which this ++ * interface belongs. ++ */ ++ lio->oct_dev = octeon_dev; ++ lio->octprops = props; ++ lio->netdev = netdev; ++ + retval = netif_set_real_num_rx_queues(netdev, num_oqueues); + if (retval) { + dev_err(&octeon_dev->pci_dev->dev, +@@ -3535,16 +3552,6 @@ static int setup_nic_devices(struct octeon_device *octeon_dev) + goto setup_nic_dev_free; + } + +- lio = GET_LIO(netdev); +- +- memset(lio, 0, sizeof(struct lio)); +- +- lio->ifidx = ifidx_or_pfnum; +- +- props = &octeon_dev->props[i]; +- props->gmxport = resp->cfg_info.linfo.gmxport; +- props->netdev = netdev; +- + lio->linfo.num_rxpciq = num_oqueues; + lio->linfo.num_txpciq = num_iqueues; + for (j = 0; j < num_oqueues; j++) { +@@ -3610,13 +3617,6 @@ static int setup_nic_devices(struct octeon_device *octeon_dev) + netdev->min_mtu = LIO_MIN_MTU_SIZE; + netdev->max_mtu = LIO_MAX_MTU_SIZE; + +- /* Point to the properties for octeon device to which this +- * interface belongs. +- */ +- lio->oct_dev = octeon_dev; +- lio->octprops = props; +- lio->netdev = netdev; +- + dev_dbg(&octeon_dev->pci_dev->dev, + "if%d gmx: %d hw_addr: 0x%llx\n", i, + lio->linfo.gmxport, CVM_CAST64(lio->linfo.hw_addr)); +@@ -3764,6 +3764,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev) + if (!devlink) { + device_unlock(&octeon_dev->pci_dev->dev); + dev_err(&octeon_dev->pci_dev->dev, "devlink alloc failed\n"); ++ i--; + goto setup_nic_dev_free; + } + +@@ -3779,11 +3780,11 @@ static int setup_nic_devices(struct octeon_device *octeon_dev) + + setup_nic_dev_free: + +- while (i--) { ++ do { + dev_err(&octeon_dev->pci_dev->dev, + "NIC ifidx:%d Setup failed\n", i); + liquidio_destroy_nic_device(octeon_dev, i); +- } ++ } while (i--); + + setup_nic_dev_done: + +diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c +index 62c2eadc33e35a..15ef647e8aad35 100644 +--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c ++++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c +@@ -2221,11 +2221,11 @@ static int setup_nic_devices(struct octeon_device *octeon_dev) + + setup_nic_dev_free: + +- while (i--) { ++ do { + dev_err(&octeon_dev->pci_dev->dev, + "NIC ifidx:%d Setup failed\n", i); + liquidio_destroy_nic_device(octeon_dev, i); +- } ++ } while (i--); + + setup_nic_dev_done: + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +index cdab37e9634d4f..37e3224262ed43 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +@@ -1530,6 +1530,10 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg) + } + + if_id = (status & 0xFFFF0000) >> 16; ++ if (if_id >= ethsw->sw_attr.num_ifs) { ++ dev_err(dev, "Invalid if_id %d in IRQ status\n", if_id); ++ goto out; ++ } + port_priv = ethsw->ports[if_id]; + + if (status & DPSW_IRQ_EVENT_LINK_CHANGED) { +@@ -2988,6 +2992,12 @@ static int dpaa2_switch_init(struct fsl_mc_device *sw_dev) + goto err_close; + } + ++ if (!ethsw->sw_attr.num_ifs) { ++ dev_err(dev, "DPSW device has no interfaces\n"); ++ err = -ENODEV; ++ goto err_close; ++ } ++ + err = dpsw_get_api_version(ethsw->mc_io, 0, + ðsw->major, + ðsw->minor); +diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c +index 22317acf16ba4d..b1c4df3bab2922 100644 +--- a/drivers/net/ethernet/google/gve/gve_ethtool.c ++++ b/drivers/net/ethernet/google/gve/gve_ethtool.c +@@ -156,10 +156,13 @@ gve_get_ethtool_stats(struct net_device *netdev, + { + u64 tmp_rx_pkts, tmp_rx_bytes, tmp_rx_skb_alloc_fail, + tmp_rx_buf_alloc_fail, tmp_rx_desc_err_dropped_pkt, +- tmp_tx_pkts, tmp_tx_bytes; ++ tmp_tx_pkts, tmp_tx_bytes, ++ tmp_xdp_tx_errors, tmp_xdp_redirect_errors; + u64 rx_buf_alloc_fail, rx_desc_err_dropped_pkt, rx_pkts, +- rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes, tx_dropped; +- int stats_idx, base_stats_idx, max_stats_idx; ++ rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes, tx_dropped, ++ xdp_tx_errors, xdp_redirect_errors; ++ int rx_base_stats_idx, max_rx_stats_idx, max_tx_stats_idx; ++ int stats_idx, stats_region_len, nic_stats_len; + struct stats *report_stats; + int *rx_qid_to_stats_idx; + int *tx_qid_to_stats_idx; +@@ -186,7 +189,9 @@ gve_get_ethtool_stats(struct net_device *netdev, + return; + } + for (rx_pkts = 0, rx_bytes = 0, rx_skb_alloc_fail = 0, +- rx_buf_alloc_fail = 0, rx_desc_err_dropped_pkt = 0, ring = 0; ++ rx_buf_alloc_fail = 0, rx_desc_err_dropped_pkt = 0, ++ xdp_tx_errors = 0, xdp_redirect_errors = 0, ++ ring = 0; + ring < priv->rx_cfg.num_queues; ring++) { + if (priv->rx) { + do { +@@ -200,6 +205,9 @@ gve_get_ethtool_stats(struct net_device *netdev, + tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail; + tmp_rx_desc_err_dropped_pkt = + rx->rx_desc_err_dropped_pkt; ++ tmp_xdp_tx_errors = rx->xdp_tx_errors; ++ tmp_xdp_redirect_errors = ++ rx->xdp_redirect_errors; + } while (u64_stats_fetch_retry(&priv->rx[ring].statss, + start)); + rx_pkts += tmp_rx_pkts; +@@ -207,6 +215,8 @@ gve_get_ethtool_stats(struct net_device *netdev, + rx_skb_alloc_fail += tmp_rx_skb_alloc_fail; + rx_buf_alloc_fail += tmp_rx_buf_alloc_fail; + rx_desc_err_dropped_pkt += tmp_rx_desc_err_dropped_pkt; ++ xdp_tx_errors += tmp_xdp_tx_errors; ++ xdp_redirect_errors += tmp_xdp_redirect_errors; + } + } + for (tx_pkts = 0, tx_bytes = 0, tx_dropped = 0, ring = 0; +@@ -231,8 +241,8 @@ gve_get_ethtool_stats(struct net_device *netdev, + data[i++] = rx_bytes; + data[i++] = tx_bytes; + /* total rx dropped packets */ +- data[i++] = rx_skb_alloc_fail + rx_buf_alloc_fail + +- rx_desc_err_dropped_pkt; ++ data[i++] = rx_skb_alloc_fail + rx_desc_err_dropped_pkt + ++ xdp_tx_errors + xdp_redirect_errors; + data[i++] = tx_dropped; + data[i++] = priv->tx_timeo_cnt; + data[i++] = rx_skb_alloc_fail; +@@ -246,14 +256,32 @@ gve_get_ethtool_stats(struct net_device *netdev, + data[i++] = priv->stats_report_trigger_cnt; + i = GVE_MAIN_STATS_LEN; + +- /* For rx cross-reporting stats, start from nic rx stats in report */ +- base_stats_idx = GVE_TX_STATS_REPORT_NUM * num_tx_queues + +- GVE_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues; +- max_stats_idx = NIC_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues + +- base_stats_idx; ++ rx_base_stats_idx = 0; ++ max_rx_stats_idx = 0; ++ max_tx_stats_idx = 0; ++ stats_region_len = priv->stats_report_len - ++ sizeof(struct gve_stats_report); ++ nic_stats_len = (NIC_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues + ++ NIC_TX_STATS_REPORT_NUM * num_tx_queues) * sizeof(struct stats); ++ if (unlikely((stats_region_len - ++ nic_stats_len) % sizeof(struct stats))) { ++ net_err_ratelimited("Starting index of NIC stats should be multiple of stats size"); ++ } else { ++ /* For rx cross-reporting stats, ++ * start from nic rx stats in report ++ */ ++ rx_base_stats_idx = (stats_region_len - nic_stats_len) / ++ sizeof(struct stats); ++ max_rx_stats_idx = NIC_RX_STATS_REPORT_NUM * ++ priv->rx_cfg.num_queues + ++ rx_base_stats_idx; ++ max_tx_stats_idx = NIC_TX_STATS_REPORT_NUM * ++ num_tx_queues + ++ max_rx_stats_idx; ++ } + /* Preprocess the stats report for rx, map queue id to start index */ + skip_nic_stats = false; +- for (stats_idx = base_stats_idx; stats_idx < max_stats_idx; ++ for (stats_idx = rx_base_stats_idx; stats_idx < max_rx_stats_idx; + stats_idx += NIC_RX_STATS_REPORT_NUM) { + u32 stat_name = be32_to_cpu(report_stats[stats_idx].stat_name); + u32 queue_id = be32_to_cpu(report_stats[stats_idx].queue_id); +@@ -281,6 +309,9 @@ gve_get_ethtool_stats(struct net_device *netdev, + tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail; + tmp_rx_desc_err_dropped_pkt = + rx->rx_desc_err_dropped_pkt; ++ tmp_xdp_tx_errors = rx->xdp_tx_errors; ++ tmp_xdp_redirect_errors = ++ rx->xdp_redirect_errors; + } while (u64_stats_fetch_retry(&priv->rx[ring].statss, + start)); + data[i++] = tmp_rx_bytes; +@@ -290,8 +321,9 @@ gve_get_ethtool_stats(struct net_device *netdev, + data[i++] = rx->rx_frag_alloc_cnt; + /* rx dropped packets */ + data[i++] = tmp_rx_skb_alloc_fail + +- tmp_rx_buf_alloc_fail + +- tmp_rx_desc_err_dropped_pkt; ++ tmp_rx_desc_err_dropped_pkt + ++ tmp_xdp_tx_errors + ++ tmp_xdp_redirect_errors; + data[i++] = rx->rx_copybreak_pkt; + data[i++] = rx->rx_copied_pkt; + /* stats from NIC */ +@@ -323,13 +355,9 @@ gve_get_ethtool_stats(struct net_device *netdev, + i += priv->rx_cfg.num_queues * NUM_GVE_RX_CNTS; + } + +- /* For tx cross-reporting stats, start from nic tx stats in report */ +- base_stats_idx = max_stats_idx; +- max_stats_idx = NIC_TX_STATS_REPORT_NUM * num_tx_queues + +- max_stats_idx; +- /* Preprocess the stats report for tx, map queue id to start index */ + skip_nic_stats = false; +- for (stats_idx = base_stats_idx; stats_idx < max_stats_idx; ++ /* NIC TX stats start right after NIC RX stats */ ++ for (stats_idx = max_rx_stats_idx; stats_idx < max_tx_stats_idx; + stats_idx += NIC_TX_STATS_REPORT_NUM) { + u32 stat_name = be32_to_cpu(report_stats[stats_idx].stat_name); + u32 queue_id = be32_to_cpu(report_stats[stats_idx].queue_id); +diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c +index 241a541b8edd2f..b2c648fe387525 100644 +--- a/drivers/net/ethernet/google/gve/gve_main.c ++++ b/drivers/net/ethernet/google/gve/gve_main.c +@@ -186,9 +186,9 @@ static int gve_alloc_stats_report(struct gve_priv *priv) + int tx_stats_num, rx_stats_num; + + tx_stats_num = (GVE_TX_STATS_REPORT_NUM + NIC_TX_STATS_REPORT_NUM) * +- gve_num_tx_queues(priv); ++ priv->tx_cfg.max_queues; + rx_stats_num = (GVE_RX_STATS_REPORT_NUM + NIC_RX_STATS_REPORT_NUM) * +- priv->rx_cfg.num_queues; ++ priv->rx_cfg.max_queues; + priv->stats_report_len = struct_size(priv->stats_report, stats, + size_add(tx_stats_num, rx_stats_num)); + priv->stats_report = +diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c +index 09db43ce317675..fea7352e2a470c 100644 +--- a/drivers/net/macvlan.c ++++ b/drivers/net/macvlan.c +@@ -1572,9 +1572,10 @@ destroy_macvlan_port: + /* the macvlan port may be freed by macvlan_uninit when fail to register. + * so we destroy the macvlan port only when it's valid. + */ +- if (create && macvlan_port_get_rtnl(lowerdev)) { ++ if (macvlan_port_get_rtnl(lowerdev)) { + macvlan_flush_sources(port, vlan); +- macvlan_port_destroy(port->dev); ++ if (create) ++ macvlan_port_destroy(port->dev); + } + return err; + } +diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c +index 9587eb98cdb3b8..213b4817cfdf6d 100644 +--- a/drivers/net/usb/sr9700.c ++++ b/drivers/net/usb/sr9700.c +@@ -539,6 +539,11 @@ static const struct usb_device_id products[] = { + USB_DEVICE(0x0fe6, 0x9700), /* SR9700 device */ + .driver_info = (unsigned long)&sr9700_driver_info, + }, ++ { ++ /* SR9700 with virtual driver CD-ROM - interface 0 is the CD-ROM device */ ++ USB_DEVICE_INTERFACE_NUMBER(0x0fe6, 0x9702, 1), ++ .driver_info = (unsigned long)&sr9700_driver_info, ++ }, + {}, /* END */ + }; + +diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c +index 7bd3ce2f08044d..75ad0966765615 100644 +--- a/drivers/net/wireless/ti/wlcore/tx.c ++++ b/drivers/net/wireless/ti/wlcore/tx.c +@@ -210,6 +210,11 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, + total_blocks = wlcore_hw_calc_tx_blocks(wl, total_len, spare_blocks); + + if (total_blocks <= wl->tx_blocks_available) { ++ if (skb_headroom(skb) < (total_len - skb->len) && ++ pskb_expand_head(skb, (total_len - skb->len), 0, GFP_ATOMIC)) { ++ wl1271_free_tx_id(wl, id); ++ return -EAGAIN; ++ } + desc = skb_push(skb, total_len - skb->len); + + wlcore_hw_set_tx_desc_blocks(wl, desc, total_blocks, +diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c +index 4fdb62ae996bf2..44de1bcd0c6575 100644 +--- a/drivers/nvme/host/fc.c ++++ b/drivers/nvme/host/fc.c +@@ -3550,6 +3550,8 @@ fail_ctrl: + + ctrl->ctrl.opts = NULL; + ++ if (ctrl->ctrl.admin_tagset) ++ nvme_remove_admin_tag_set(&ctrl->ctrl); + /* initiate nvme ctrl ref counting teardown */ + nvme_uninit_ctrl(&ctrl->ctrl); + +diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c +index 3bdff81eb3af83..4d1f260ae60abc 100644 +--- a/drivers/nvme/target/tcp.c ++++ b/drivers/nvme/target/tcp.c +@@ -333,11 +333,14 @@ static void nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd *cmd) + cmd->req.sg = NULL; + } + ++static void nvmet_tcp_fatal_error(struct nvmet_tcp_queue *queue); ++ + static void nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd *cmd) + { + struct bio_vec *iov = cmd->iov; + struct scatterlist *sg; + u32 length, offset, sg_offset; ++ unsigned int sg_remaining; + int nr_pages; + + length = cmd->pdu_len; +@@ -345,9 +348,22 @@ static void nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd *cmd) + offset = cmd->rbytes_done; + cmd->sg_idx = offset / PAGE_SIZE; + sg_offset = offset % PAGE_SIZE; ++ if (!cmd->req.sg_cnt || cmd->sg_idx >= cmd->req.sg_cnt) { ++ nvmet_tcp_fatal_error(cmd->queue); ++ return; ++ } + sg = &cmd->req.sg[cmd->sg_idx]; ++ sg_remaining = cmd->req.sg_cnt - cmd->sg_idx; + + while (length) { ++ if (!sg_remaining) { ++ nvmet_tcp_fatal_error(cmd->queue); ++ return; ++ } ++ if (!sg->length || sg->length <= sg_offset) { ++ nvmet_tcp_fatal_error(cmd->queue); ++ return; ++ } + u32 iov_len = min_t(u32, length, sg->length - sg_offset); + + bvec_set_page(iov, sg_page(sg), iov_len, +@@ -355,6 +371,7 @@ static void nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd *cmd) + + length -= iov_len; + sg = sg_next(sg); ++ sg_remaining--; + iov++; + sg_offset = 0; + } +@@ -1740,14 +1757,13 @@ static void nvmet_tcp_listen_data_ready(struct sock *sk) + + trace_sk_data_ready(sk); + ++ if (sk->sk_state != TCP_LISTEN) ++ return; ++ + read_lock_bh(&sk->sk_callback_lock); + port = sk->sk_user_data; +- if (!port) +- goto out; +- +- if (sk->sk_state == TCP_LISTEN) ++ if (port) + queue_work(nvmet_wq, &port->accept_work); +-out: + read_unlock_bh(&sk->sk_callback_lock); + } + +diff --git a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c +index e9bade74997bf2..ec7a74bee803a7 100644 +--- a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c ++++ b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c +@@ -701,6 +701,11 @@ static int hp_init_bios_package_attribute(enum hp_wmi_data_type attr_type, + return ret; + } + ++ if (!str_value || !str_value[0]) { ++ pr_debug("Ignoring attribute with empty name\n"); ++ goto pack_attr_exit; ++ } ++ + /* All duplicate attributes found are ignored */ + duplicate = kset_find_obj(temp_kset, str_value); + if (duplicate) { +diff --git a/drivers/platform/x86/intel/telemetry/debugfs.c b/drivers/platform/x86/intel/telemetry/debugfs.c +index 1d4d0fbfd63cc6..e533de621ac4b7 100644 +--- a/drivers/platform/x86/intel/telemetry/debugfs.c ++++ b/drivers/platform/x86/intel/telemetry/debugfs.c +@@ -449,7 +449,7 @@ static int telem_pss_states_show(struct seq_file *s, void *unused) + for (index = 0; index < debugfs_conf->pss_ltr_evts; index++) { + seq_printf(s, "%-32s\t%u\n", + debugfs_conf->pss_ltr_data[index].name, +- pss_s0ix_wakeup[index]); ++ pss_ltr_blkd[index]); + } + + seq_puts(s, "\n--------------------------------------\n"); +@@ -459,7 +459,7 @@ static int telem_pss_states_show(struct seq_file *s, void *unused) + for (index = 0; index < debugfs_conf->pss_wakeup_evts; index++) { + seq_printf(s, "%-32s\t%u\n", + debugfs_conf->pss_wakeup[index].name, +- pss_ltr_blkd[index]); ++ pss_s0ix_wakeup[index]); + } + + return 0; +diff --git a/drivers/platform/x86/intel/telemetry/pltdrv.c b/drivers/platform/x86/intel/telemetry/pltdrv.c +index 06311d0e945189..a574615c6faa64 100644 +--- a/drivers/platform/x86/intel/telemetry/pltdrv.c ++++ b/drivers/platform/x86/intel/telemetry/pltdrv.c +@@ -610,7 +610,7 @@ static int telemetry_setup(struct platform_device *pdev) + /* Get telemetry Info */ + events = (read_buf & TELEM_INFO_SRAMEVTS_MASK) >> + TELEM_INFO_SRAMEVTS_SHIFT; +- event_regs = read_buf & TELEM_INFO_SRAMEVTS_MASK; ++ event_regs = read_buf & TELEM_INFO_NENABLES_MASK; + if ((events < TELEM_MAX_EVENTS_SRAM) || + (event_regs < TELEM_MAX_EVENTS_SRAM)) { + dev_err(&pdev->dev, "PSS:Insufficient Space for SRAM Trace\n"); +diff --git a/drivers/platform/x86/toshiba_haps.c b/drivers/platform/x86/toshiba_haps.c +index 8c9f76286b0807..f2292d2412fd18 100644 +--- a/drivers/platform/x86/toshiba_haps.c ++++ b/drivers/platform/x86/toshiba_haps.c +@@ -183,7 +183,7 @@ static int toshiba_haps_add(struct acpi_device *acpi_dev) + + pr_info("Toshiba HDD Active Protection Sensor device\n"); + +- haps = kzalloc(sizeof(struct toshiba_haps_dev), GFP_KERNEL); ++ haps = devm_kzalloc(&acpi_dev->dev, sizeof(*haps), GFP_KERNEL); + if (!haps) + return -ENOMEM; + +diff --git a/drivers/pmdomain/imx/gpcv2.c b/drivers/pmdomain/imx/gpcv2.c +index 84d68c805cac85..4db6ec044926d7 100644 +--- a/drivers/pmdomain/imx/gpcv2.c ++++ b/drivers/pmdomain/imx/gpcv2.c +@@ -165,13 +165,11 @@ + #define IMX8M_VPU_HSK_PWRDNREQN BIT(5) + #define IMX8M_DISP_HSK_PWRDNREQN BIT(4) + +-#define IMX8MM_GPUMIX_HSK_PWRDNACKN BIT(29) +-#define IMX8MM_GPU_HSK_PWRDNACKN (BIT(27) | BIT(28)) ++#define IMX8MM_GPU_HSK_PWRDNACKN GENMASK(29, 27) + #define IMX8MM_VPUMIX_HSK_PWRDNACKN BIT(26) + #define IMX8MM_DISPMIX_HSK_PWRDNACKN BIT(25) + #define IMX8MM_HSIO_HSK_PWRDNACKN (BIT(23) | BIT(24)) +-#define IMX8MM_GPUMIX_HSK_PWRDNREQN BIT(11) +-#define IMX8MM_GPU_HSK_PWRDNREQN (BIT(9) | BIT(10)) ++#define IMX8MM_GPU_HSK_PWRDNREQN GENMASK(11, 9) + #define IMX8MM_VPUMIX_HSK_PWRDNREQN BIT(8) + #define IMX8MM_DISPMIX_HSK_PWRDNREQN BIT(7) + #define IMX8MM_HSIO_HSK_PWRDNREQN (BIT(5) | BIT(6)) +@@ -783,8 +781,6 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { + .bits = { + .pxx = IMX8MM_GPUMIX_SW_Pxx_REQ, + .map = IMX8MM_GPUMIX_A53_DOMAIN, +- .hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN, +- .hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN, + }, + .pgc = BIT(IMX8MM_PGC_GPUMIX), + .keep_clocks = true, +diff --git a/drivers/pmdomain/imx/imx8m-blk-ctrl.c b/drivers/pmdomain/imx/imx8m-blk-ctrl.c +index ce452c2b17464b..e5225369474796 100644 +--- a/drivers/pmdomain/imx/imx8m-blk-ctrl.c ++++ b/drivers/pmdomain/imx/imx8m-blk-ctrl.c +@@ -337,7 +337,7 @@ static int imx8m_blk_ctrl_remove(struct platform_device *pdev) + + of_genpd_del_provider(pdev->dev.of_node); + +- for (i = 0; bc->onecell_data.num_domains; i++) { ++ for (i = 0; i < bc->onecell_data.num_domains; i++) { + struct imx8m_blk_ctrl_domain *domain = &bc->domains[i]; + + pm_genpd_remove(&domain->genpd); +diff --git a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c +index faf643a4a5d06b..4c3a225c1e44a7 100644 +--- a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c ++++ b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c +@@ -53,6 +53,7 @@ struct imx8mp_blk_ctrl_domain_data { + const char * const *path_names; + int num_paths; + const char *gpc_name; ++ const unsigned int flags; + }; + + #define DOMAIN_MAX_CLKS 3 +@@ -65,6 +66,7 @@ struct imx8mp_blk_ctrl_domain { + struct icc_bulk_data paths[DOMAIN_MAX_PATHS]; + struct device *power_dev; + struct imx8mp_blk_ctrl *bc; ++ struct notifier_block power_nb; + int num_paths; + int id; + }; +@@ -264,10 +266,12 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = { + [IMX8MP_HSIOBLK_PD_USB_PHY1] = { + .name = "hsioblk-usb-phy1", + .gpc_name = "usb-phy1", ++ .flags = GENPD_FLAG_ACTIVE_WAKEUP, + }, + [IMX8MP_HSIOBLK_PD_USB_PHY2] = { + .name = "hsioblk-usb-phy2", + .gpc_name = "usb-phy2", ++ .flags = GENPD_FLAG_ACTIVE_WAKEUP, + }, + [IMX8MP_HSIOBLK_PD_PCIE] = { + .name = "hsioblk-pcie", +@@ -594,6 +598,20 @@ static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd) + return 0; + } + ++static int imx8mp_blk_ctrl_gpc_notifier(struct notifier_block *nb, ++ unsigned long action, void *data) ++{ ++ struct imx8mp_blk_ctrl_domain *domain = ++ container_of(nb, struct imx8mp_blk_ctrl_domain, power_nb); ++ ++ if (action == GENPD_NOTIFY_PRE_OFF) { ++ if (domain->genpd.status == GENPD_STATE_ON) ++ return NOTIFY_BAD; ++ } ++ ++ return NOTIFY_OK; ++} ++ + static struct lock_class_key blk_ctrl_genpd_lock_class; + + static int imx8mp_blk_ctrl_probe(struct platform_device *pdev) +@@ -695,15 +713,25 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev) + goto cleanup_pds; + } + ++ domain->power_nb.notifier_call = imx8mp_blk_ctrl_gpc_notifier; ++ ret = dev_pm_genpd_add_notifier(domain->power_dev, &domain->power_nb); ++ if (ret) { ++ dev_err_probe(dev, ret, "failed to add power notifier\n"); ++ dev_pm_domain_detach(domain->power_dev, true); ++ goto cleanup_pds; ++ } ++ + domain->genpd.name = data->name; + domain->genpd.power_on = imx8mp_blk_ctrl_power_on; + domain->genpd.power_off = imx8mp_blk_ctrl_power_off; ++ domain->genpd.flags = data->flags; + domain->bc = bc; + domain->id = i; + + ret = pm_genpd_init(&domain->genpd, NULL, true); + if (ret) { + dev_err_probe(dev, ret, "failed to init power domain\n"); ++ dev_pm_genpd_remove_notifier(domain->power_dev); + dev_pm_domain_detach(domain->power_dev, true); + goto cleanup_pds; + } +@@ -752,6 +780,7 @@ cleanup_provider: + cleanup_pds: + for (i--; i >= 0; i--) { + pm_genpd_remove(&bc->domains[i].genpd); ++ dev_pm_genpd_remove_notifier(bc->domains[i].power_dev); + dev_pm_domain_detach(bc->domains[i].power_dev, true); + } + +@@ -771,6 +800,7 @@ static int imx8mp_blk_ctrl_remove(struct platform_device *pdev) + struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i]; + + pm_genpd_remove(&domain->genpd); ++ dev_pm_genpd_remove_notifier(domain->power_dev); + dev_pm_domain_detach(domain->power_dev, true); + } + +diff --git a/drivers/pmdomain/qcom/rpmpd.c b/drivers/pmdomain/qcom/rpmpd.c +index 3135dd1dafe063..d70a2cb4b529e1 100644 +--- a/drivers/pmdomain/qcom/rpmpd.c ++++ b/drivers/pmdomain/qcom/rpmpd.c +@@ -825,7 +825,7 @@ static int rpmpd_aggregate_corner(struct rpmpd *pd) + + /* Clamp to the highest corner/level if sync_state isn't done yet */ + if (!pd->state_synced) +- this_active_corner = this_sleep_corner = pd->max_state - 1; ++ this_active_corner = this_sleep_corner = pd->max_state; + else + to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner); + +diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c +index 16054695bdb04a..f0a50f40a3ba16 100644 +--- a/drivers/spi/spi-hisi-kunpeng.c ++++ b/drivers/spi/spi-hisi-kunpeng.c +@@ -161,10 +161,8 @@ static const struct debugfs_reg32 hisi_spi_regs[] = { + static int hisi_spi_debugfs_init(struct hisi_spi *hs) + { + char name[32]; ++ struct spi_controller *host = dev_get_drvdata(hs->dev); + +- struct spi_controller *host; +- +- host = container_of(hs->dev, struct spi_controller, dev); + snprintf(name, 32, "hisi_spi%d", host->bus_num); + hs->debugfs = debugfs_create_dir(name, NULL); + if (IS_ERR(hs->debugfs)) +diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c +index 8d7ce4c556aa1d..c99f72c9ab1763 100644 +--- a/drivers/spi/spi-tegra114.c ++++ b/drivers/spi/spi-tegra114.c +@@ -978,11 +978,14 @@ static int tegra_spi_setup(struct spi_device *spi) + if (spi_get_csgpiod(spi, 0)) + gpiod_set_value(spi_get_csgpiod(spi, 0), 0); + ++ /* Update default register to include CS polarity and SPI mode */ + val = tspi->def_command1_reg; + if (spi->mode & SPI_CS_HIGH) + val &= ~SPI_CS_POL_INACTIVE(spi_get_chipselect(spi, 0)); + else + val |= SPI_CS_POL_INACTIVE(spi_get_chipselect(spi, 0)); ++ val &= ~SPI_CONTROL_MODE_MASK; ++ val |= SPI_MODE_SEL(spi->mode & 0x3); + tspi->def_command1_reg = val; + tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); + spin_unlock_irqrestore(&tspi->lock, flags); +diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c +index f5cd365c913a87..f450409156c643 100644 +--- a/drivers/spi/spi-tegra20-slink.c ++++ b/drivers/spi/spi-tegra20-slink.c +@@ -1086,8 +1086,10 @@ static int tegra_slink_probe(struct platform_device *pdev) + reset_control_deassert(tspi->rst); + + spi_irq = platform_get_irq(pdev, 0); +- if (spi_irq < 0) +- return spi_irq; ++ if (spi_irq < 0) { ++ ret = spi_irq; ++ goto exit_pm_put; ++ } + tspi->irq = spi_irq; + ret = request_threaded_irq(tspi->irq, tegra_slink_isr, + tegra_slink_isr_thread, IRQF_ONESHOT, +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index d9a487274b530e..f7677b960c342c 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -814,6 +814,7 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran + u32 command1, command2, speed = t->speed_hz; + u8 bits_per_word = t->bits_per_word; + u32 tx_tap = 0, rx_tap = 0; ++ unsigned long flags; + int req_mode; + + if (!has_acpi_companion(tqspi->dev) && speed != tqspi->cur_speed) { +@@ -821,10 +822,12 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran + tqspi->cur_speed = speed; + } + ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->cur_pos = 0; + tqspi->cur_rx_pos = 0; + tqspi->cur_tx_pos = 0; + tqspi->curr_xfer = t; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + + if (is_first_of_msg) { + tegra_qspi_mask_clear_irq(tqspi); +@@ -1061,6 +1064,7 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, + u32 address_value = 0; + u32 cmd_config = 0, addr_config = 0; + u8 cmd_value = 0, val = 0; ++ unsigned long flags; + + /* Enable Combined sequence mode */ + val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG); +@@ -1173,13 +1177,17 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, + tegra_qspi_transfer_end(spi); + spi_transfer_delay_exec(xfer); + } ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + transfer_phase++; + } + ret = 0; + + exit: ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + msg->status = ret; + + return ret; +@@ -1192,6 +1200,7 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, + struct spi_transfer *transfer; + bool is_first_msg = true; + int ret = 0, val = 0; ++ unsigned long flags; + + msg->status = 0; + msg->actual_length = 0; +@@ -1263,7 +1272,9 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, + msg->actual_length += xfer->len + dummy_bytes; + + complete_xfer: ++ spin_lock_irqsave(&tqspi->lock, flags); + tqspi->curr_xfer = NULL; ++ spin_unlock_irqrestore(&tqspi->lock, flags); + + if (ret < 0) { + tegra_qspi_transfer_end(spi); +@@ -1334,10 +1345,11 @@ static int tegra_qspi_transfer_one_message(struct spi_master *master, + + static irqreturn_t handle_cpu_based_xfer(struct tegra_qspi *tqspi) + { +- struct spi_transfer *t = tqspi->curr_xfer; ++ struct spi_transfer *t; + unsigned long flags; + + spin_lock_irqsave(&tqspi->lock, flags); ++ t = tqspi->curr_xfer; + + if (tqspi->tx_status || tqspi->rx_status) { + tegra_qspi_handle_error(tqspi); +@@ -1368,7 +1380,7 @@ exit: + + static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + { +- struct spi_transfer *t = tqspi->curr_xfer; ++ struct spi_transfer *t; + unsigned int total_fifo_words; + unsigned long flags; + long wait_status; +@@ -1405,6 +1417,7 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) + } + + spin_lock_irqsave(&tqspi->lock, flags); ++ t = tqspi->curr_xfer; + + if (err) { + tegra_qspi_dma_unmap_xfer(tqspi, t); +@@ -1444,15 +1457,30 @@ exit: + static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data) + { + struct tegra_qspi *tqspi = context_data; ++ u32 status; ++ ++ /* ++ * Read transfer status to check if interrupt was triggered by transfer ++ * completion ++ */ ++ status = tegra_qspi_readl(tqspi, QSPI_TRANS_STATUS); + + /* + * Occasionally the IRQ thread takes a long time to wake up (usually + * when the CPU that it's running on is excessively busy) and we have + * already reached the timeout before and cleaned up the timed out + * transfer. Avoid any processing in that case and bail out early. ++ * ++ * If no transfer is in progress, check if this was a real interrupt ++ * that the timeout handler already processed, or a spurious one. + */ +- if (!tqspi->curr_xfer) +- return IRQ_NONE; ++ if (!tqspi->curr_xfer) { ++ /* Spurious interrupt - transfer not ready */ ++ if (!(status & QSPI_RDY)) ++ return IRQ_NONE; ++ /* Real interrupt, already handled by timeout path */ ++ return IRQ_HANDLED; ++ } + + tqspi->status_reg = tegra_qspi_readl(tqspi, QSPI_FIFO_STATUS); + +diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c +index 91a75a4a7cc1a7..b7fa8eed213bb3 100644 +--- a/drivers/target/iscsi/iscsi_target_util.c ++++ b/drivers/target/iscsi/iscsi_target_util.c +@@ -785,8 +785,11 @@ void iscsit_dec_session_usage_count(struct iscsit_session *sess) + spin_lock_bh(&sess->session_usage_lock); + sess->session_usage_count--; + +- if (!sess->session_usage_count && sess->session_waiting_on_uc) ++ if (!sess->session_usage_count && sess->session_waiting_on_uc) { ++ spin_unlock_bh(&sess->session_usage_lock); + complete(&sess->session_waiting_on_uc_comp); ++ return; ++ } + + spin_unlock_bh(&sess->session_usage_lock); + } +@@ -854,8 +857,11 @@ void iscsit_dec_conn_usage_count(struct iscsit_conn *conn) + spin_lock_bh(&conn->conn_usage_lock); + conn->conn_usage_count--; + +- if (!conn->conn_usage_count && conn->conn_waiting_on_uc) ++ if (!conn->conn_usage_count && conn->conn_waiting_on_uc) { ++ spin_unlock_bh(&conn->conn_usage_lock); + complete(&conn->conn_waiting_on_uc_comp); ++ return; ++ } + + spin_unlock_bh(&conn->conn_usage_lock); + } +diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c +index 2dda388c985384..a08e03a74909a7 100644 +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -4156,7 +4156,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, + mutex_unlock(&fs_info->chunk_mutex); + } else { + /* Proceed with allocation */ +- space_info->chunk_alloc = 1; ++ space_info->chunk_alloc = true; + wait_for_alloc = false; + spin_unlock(&space_info->lock); + } +@@ -4205,7 +4205,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, + spin_lock(&space_info->lock); + if (ret < 0) { + if (ret == -ENOSPC) +- space_info->full = 1; ++ space_info->full = true; + else + goto out; + } else { +@@ -4215,7 +4215,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, + + space_info->force_alloc = CHUNK_ALLOC_NO_FORCE; + out: +- space_info->chunk_alloc = 0; ++ space_info->chunk_alloc = false; + spin_unlock(&space_info->lock); + mutex_unlock(&fs_info->chunk_mutex); + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 68bb5079aef74a..96edac307408c6 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -619,7 +619,7 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 size, + struct btrfs_drop_extents_args drop_args = { 0 }; + struct btrfs_root *root = inode->root; + struct btrfs_fs_info *fs_info = root->fs_info; +- struct btrfs_trans_handle *trans; ++ struct btrfs_trans_handle *trans = NULL; + u64 data_len = (compressed_size ?: size); + int ret; + struct btrfs_path *path; +@@ -637,13 +637,16 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 size, + return 1; + + path = btrfs_alloc_path(); +- if (!path) +- return -ENOMEM; ++ if (!path) { ++ ret = -ENOMEM; ++ goto out; ++ } + + trans = btrfs_join_transaction(root); + if (IS_ERR(trans)) { +- btrfs_free_path(path); +- return PTR_ERR(trans); ++ ret = PTR_ERR(trans); ++ trans = NULL; ++ goto out; + } + trans->block_rsv = &inode->block_rsv; + +@@ -690,7 +693,8 @@ out: + */ + btrfs_qgroup_free_data(inode, NULL, 0, PAGE_SIZE, NULL); + btrfs_free_path(path); +- btrfs_end_transaction(trans); ++ if (trans) ++ btrfs_end_transaction(trans); + return ret; + } + +diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c +index 00d596a8176ff0..12f8f55bb99384 100644 +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -182,7 +182,7 @@ void btrfs_clear_space_info_full(struct btrfs_fs_info *info) + struct btrfs_space_info *found; + + list_for_each_entry(found, head, list) +- found->full = 0; ++ found->full = false; + } + + /* +@@ -361,7 +361,7 @@ void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info, + found->bytes_readonly += block_group->bytes_super; + btrfs_space_info_update_bytes_zone_unusable(info, found, block_group->zone_unusable); + if (block_group->length > 0) +- found->full = 0; ++ found->full = false; + btrfs_try_granting_tickets(info, found); + spin_unlock(&found->lock); + +@@ -1103,7 +1103,7 @@ static void btrfs_async_reclaim_metadata_space(struct work_struct *work) + spin_lock(&space_info->lock); + to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info, space_info); + if (!to_reclaim) { +- space_info->flush = 0; ++ space_info->flush = false; + spin_unlock(&space_info->lock); + return; + } +@@ -1115,7 +1115,7 @@ static void btrfs_async_reclaim_metadata_space(struct work_struct *work) + flush_space(fs_info, space_info, to_reclaim, flush_state, false); + spin_lock(&space_info->lock); + if (list_empty(&space_info->tickets)) { +- space_info->flush = 0; ++ space_info->flush = false; + spin_unlock(&space_info->lock); + return; + } +@@ -1158,7 +1158,7 @@ static void btrfs_async_reclaim_metadata_space(struct work_struct *work) + flush_state = FLUSH_DELAYED_ITEMS_NR; + commit_cycles--; + } else { +- space_info->flush = 0; ++ space_info->flush = false; + } + } else { + flush_state = FLUSH_DELAYED_ITEMS_NR; +@@ -1320,7 +1320,7 @@ static void btrfs_async_reclaim_data_space(struct work_struct *work) + + spin_lock(&space_info->lock); + if (list_empty(&space_info->tickets)) { +- space_info->flush = 0; ++ space_info->flush = false; + spin_unlock(&space_info->lock); + return; + } +@@ -1331,7 +1331,7 @@ static void btrfs_async_reclaim_data_space(struct work_struct *work) + flush_space(fs_info, space_info, U64_MAX, ALLOC_CHUNK_FORCE, false); + spin_lock(&space_info->lock); + if (list_empty(&space_info->tickets)) { +- space_info->flush = 0; ++ space_info->flush = false; + spin_unlock(&space_info->lock); + return; + } +@@ -1348,7 +1348,7 @@ static void btrfs_async_reclaim_data_space(struct work_struct *work) + data_flush_states[flush_state], false); + spin_lock(&space_info->lock); + if (list_empty(&space_info->tickets)) { +- space_info->flush = 0; ++ space_info->flush = false; + spin_unlock(&space_info->lock); + return; + } +@@ -1365,7 +1365,7 @@ static void btrfs_async_reclaim_data_space(struct work_struct *work) + if (maybe_fail_all_tickets(fs_info, space_info)) + flush_state = 0; + else +- space_info->flush = 0; ++ space_info->flush = false; + } else { + flush_state = 0; + } +@@ -1381,7 +1381,7 @@ static void btrfs_async_reclaim_data_space(struct work_struct *work) + + aborted_fs: + maybe_fail_all_tickets(fs_info, space_info); +- space_info->flush = 0; ++ space_info->flush = false; + spin_unlock(&space_info->lock); + } + +@@ -1750,7 +1750,7 @@ static int __reserve_bytes(struct btrfs_fs_info *fs_info, + */ + maybe_clamp_preempt(fs_info, space_info); + +- space_info->flush = 1; ++ space_info->flush = true; + trace_btrfs_trigger_flush(fs_info, + space_info->flags, + orig_bytes, flush, +diff --git a/fs/btrfs/space-info.h b/fs/btrfs/space-info.h +index 0670f074902d07..6b93974a75a29c 100644 +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -126,11 +126,11 @@ struct btrfs_space_info { + flushing. The value is >> clamp, so turns + out to be a 2^clamp divisor. */ + +- unsigned int full:1; /* indicates that we cannot allocate any more ++ bool full; /* indicates that we cannot allocate any more + chunks for this space */ +- unsigned int chunk_alloc:1; /* set if we are allocating a chunk */ ++ bool chunk_alloc; /* set if we are allocating a chunk */ + +- unsigned int flush:1; /* set if we are trying to make space */ ++ bool flush; /* set if we are trying to make space */ + + unsigned int force_alloc; /* set if we need to force a chunk + alloc for this space */ +diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c +index 33154c720a4e9e..d23f8c4cd717ed 100644 +--- a/fs/hfsplus/dir.c ++++ b/fs/hfsplus/dir.c +@@ -204,7 +204,7 @@ static int hfsplus_readdir(struct file *file, struct dir_context *ctx) + fd.entrylength); + type = be16_to_cpu(entry.type); + len = NLS_MAX_CHARSET_SIZE * HFSPLUS_MAX_STRLEN; +- err = hfsplus_uni2asc(sb, &fd.key->cat.name, strbuf, &len); ++ err = hfsplus_uni2asc_str(sb, &fd.key->cat.name, strbuf, &len); + if (err) + goto out; + if (type == HFSPLUS_FOLDER) { +diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h +index e67b35cb5ccc7a..595e5fd4dfdd6b 100644 +--- a/fs/hfsplus/hfsplus_fs.h ++++ b/fs/hfsplus/hfsplus_fs.h +@@ -518,8 +518,12 @@ int hfsplus_strcasecmp(const struct hfsplus_unistr *s1, + const struct hfsplus_unistr *s2); + int hfsplus_strcmp(const struct hfsplus_unistr *s1, + const struct hfsplus_unistr *s2); +-int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, +- char *astr, int *len_p); ++int hfsplus_uni2asc_str(struct super_block *sb, ++ const struct hfsplus_unistr *ustr, char *astr, ++ int *len_p); ++int hfsplus_uni2asc_xattr_str(struct super_block *sb, ++ const struct hfsplus_attr_unistr *ustr, ++ char *astr, int *len_p); + int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr, + int max_unistr_len, const char *astr, int len); + int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str); +diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c +index ebd326799f35ac..11e08a4a18b295 100644 +--- a/fs/hfsplus/unicode.c ++++ b/fs/hfsplus/unicode.c +@@ -143,9 +143,8 @@ static u16 *hfsplus_compose_lookup(u16 *p, u16 cc) + return NULL; + } + +-int hfsplus_uni2asc(struct super_block *sb, +- const struct hfsplus_unistr *ustr, +- char *astr, int *len_p) ++static int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, ++ int max_len, char *astr, int *len_p) + { + const hfsplus_unichr *ip; + struct nls_table *nls = HFSPLUS_SB(sb)->nls; +@@ -158,8 +157,8 @@ int hfsplus_uni2asc(struct super_block *sb, + ip = ustr->unicode; + + ustrlen = be16_to_cpu(ustr->length); +- if (ustrlen > HFSPLUS_MAX_STRLEN) { +- ustrlen = HFSPLUS_MAX_STRLEN; ++ if (ustrlen > max_len) { ++ ustrlen = max_len; + pr_err("invalid length %u has been corrected to %d\n", + be16_to_cpu(ustr->length), ustrlen); + } +@@ -280,6 +279,21 @@ out: + return res; + } + ++inline int hfsplus_uni2asc_str(struct super_block *sb, ++ const struct hfsplus_unistr *ustr, char *astr, ++ int *len_p) ++{ ++ return hfsplus_uni2asc(sb, ustr, HFSPLUS_MAX_STRLEN, astr, len_p); ++} ++ ++inline int hfsplus_uni2asc_xattr_str(struct super_block *sb, ++ const struct hfsplus_attr_unistr *ustr, ++ char *astr, int *len_p) ++{ ++ return hfsplus_uni2asc(sb, (const struct hfsplus_unistr *)ustr, ++ HFSPLUS_ATTR_MAX_STRLEN, astr, len_p); ++} ++ + /* + * Convert one or more ASCII characters into a single unicode character. + * Returns the number of ASCII characters corresponding to the unicode char. +diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c +index d5fd8e068486e9..a86399942745c6 100644 +--- a/fs/hfsplus/xattr.c ++++ b/fs/hfsplus/xattr.c +@@ -737,9 +737,9 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size) + goto end_listxattr; + + xattr_name_len = NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN; +- if (hfsplus_uni2asc(inode->i_sb, +- (const struct hfsplus_unistr *)&fd.key->attr.key_name, +- strbuf, &xattr_name_len)) { ++ if (hfsplus_uni2asc_xattr_str(inode->i_sb, ++ &fd.key->attr.key_name, strbuf, ++ &xattr_name_len)) { + pr_err("unicode conversion failed\n"); + res = -EIO; + goto end_listxattr; +diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c +index d7f2835e0b1cc1..d436057ed77e32 100644 +--- a/fs/smb/client/smb2file.c ++++ b/fs/smb/client/smb2file.c +@@ -122,6 +122,7 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 + rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, + &err_buftype); + if (rc == -EACCES && retry_without_read_attributes) { ++ free_rsp_buf(err_buftype, err_iov.iov_base); + oparms->desired_access &= ~FILE_READ_ATTRIBUTES; + rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, + &err_buftype); +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index eacfb241d3d497..da4d914c87ad24 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -2274,7 +2274,7 @@ static noinline int create_smb2_pipe(struct ksmbd_work *work) + { + struct smb2_create_rsp *rsp; + struct smb2_create_req *req; +- int id; ++ int id = -1; + int err; + char *name; + +@@ -2331,6 +2331,9 @@ out: + break; + } + ++ if (id >= 0) ++ ksmbd_session_rpc_close(work->sess, id); ++ + if (!IS_ERR(name)) + kfree(name); + +@@ -2802,6 +2805,7 @@ static int parse_durable_handle_context(struct ksmbd_work *work, + SMB2_CLIENT_GUID_SIZE)) { + if (!(req->hdr.Flags & SMB2_FLAGS_REPLAY_OPERATION)) { + err = -ENOEXEC; ++ ksmbd_put_durable_fd(dh_info->fp); + goto out; + } + +@@ -2996,10 +3000,10 @@ int smb2_open(struct ksmbd_work *work) + file_info = FILE_OPENED; + + rc = ksmbd_vfs_getattr(&fp->filp->f_path, &stat); ++ ksmbd_put_durable_fd(fp); + if (rc) + goto err_out2; + +- ksmbd_put_durable_fd(fp); + goto reconnected_fp; + } + } else if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 3a558a3c2cca8a..69b392dc10aa37 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -4114,6 +4114,18 @@ skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer) + skb_headlen(skb), buffer); + } + ++/* Variant of skb_header_pointer() where @offset is user-controlled ++ * and potentially negative. ++ */ ++static inline void * __must_check ++skb_header_pointer_careful(const struct sk_buff *skb, int offset, ++ int len, void *buffer) ++{ ++ if (unlikely(offset < 0 && -offset > skb_headroom(skb))) ++ return NULL; ++ return skb_header_pointer(skb, offset, len, buffer); ++} ++ + static inline void * __must_check + skb_pointer_if_linear(const struct sk_buff *skb, int offset, int len) + { +diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c +index 91b1ee0d81fce4..2d0acdd32108ab 100644 +--- a/kernel/sched/rt.c ++++ b/kernel/sched/rt.c +@@ -1963,6 +1963,26 @@ static int find_lowest_rq(struct task_struct *task) + return -1; + } + ++static struct task_struct *pick_next_pushable_task(struct rq *rq) ++{ ++ struct task_struct *p; ++ ++ if (!has_pushable_tasks(rq)) ++ return NULL; ++ ++ p = plist_first_entry(&rq->rt.pushable_tasks, ++ struct task_struct, pushable_tasks); ++ ++ BUG_ON(rq->cpu != task_cpu(p)); ++ BUG_ON(task_current(rq, p)); ++ BUG_ON(p->nr_cpus_allowed <= 1); ++ ++ BUG_ON(!task_on_rq_queued(p)); ++ BUG_ON(!rt_task(p)); ++ ++ return p; ++} ++ + /* Will lock the rq it finds */ + static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq) + { +@@ -1993,18 +2013,16 @@ static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq) + /* + * We had to unlock the run queue. In + * the mean time, task could have +- * migrated already or had its affinity changed. +- * Also make sure that it wasn't scheduled on its rq. ++ * migrated already or had its affinity changed, ++ * therefore check if the task is still at the ++ * head of the pushable tasks list. + * It is possible the task was scheduled, set + * "migrate_disabled" and then got preempted, so we must + * check the task migration disable flag here too. + */ +- if (unlikely(task_rq(task) != rq || ++ if (unlikely(is_migration_disabled(task) || + !cpumask_test_cpu(lowest_rq->cpu, &task->cpus_mask) || +- task_on_cpu(rq, task) || +- !rt_task(task) || +- is_migration_disabled(task) || +- !task_on_rq_queued(task))) { ++ task != pick_next_pushable_task(rq))) { + + double_unlock_balance(rq, lowest_rq); + lowest_rq = NULL; +@@ -2024,26 +2042,6 @@ static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq) + return lowest_rq; + } + +-static struct task_struct *pick_next_pushable_task(struct rq *rq) +-{ +- struct task_struct *p; +- +- if (!has_pushable_tasks(rq)) +- return NULL; +- +- p = plist_first_entry(&rq->rt.pushable_tasks, +- struct task_struct, pushable_tasks); +- +- BUG_ON(rq->cpu != task_cpu(p)); +- BUG_ON(task_current(rq, p)); +- BUG_ON(p->nr_cpus_allowed <= 1); +- +- BUG_ON(!task_on_rq_queued(p)); +- BUG_ON(!rt_task(p)); +- +- return p; +-} +- + /* + * If the current CPU has more than one RT task, see if the non + * running task can migrate over to a CPU that is running a task +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index 62d93db72b0a9d..a305d1488387c2 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -2364,6 +2364,8 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size, + list) { + list_del_init(&bpage->list); + free_buffer_page(bpage); ++ ++ cond_resched(); + } + } + out_err_unlock: +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index c91f3c47ac642f..7ba372c21fee65 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -65,14 +65,17 @@ enum trace_type { + #undef __field_fn + #define __field_fn(type, item) type item; + ++#undef __field_packed ++#define __field_packed(type, item) type item; ++ + #undef __field_struct + #define __field_struct(type, item) __field(type, item) + + #undef __field_desc + #define __field_desc(type, container, item) + +-#undef __field_packed +-#define __field_packed(type, container, item) ++#undef __field_desc_packed ++#define __field_desc_packed(type, container, item) + + #undef __array + #define __array(type, item, size) type item[size]; +diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h +index c47422b2090859..3e3c08a18cafcd 100644 +--- a/kernel/trace/trace_entries.h ++++ b/kernel/trace/trace_entries.h +@@ -78,8 +78,8 @@ FTRACE_ENTRY_PACKED(funcgraph_entry, ftrace_graph_ent_entry, + + F_STRUCT( + __field_struct( struct ftrace_graph_ent, graph_ent ) +- __field_packed( unsigned long, graph_ent, func ) +- __field_packed( int, graph_ent, depth ) ++ __field_desc_packed( unsigned long, graph_ent, func ) ++ __field_desc_packed( int, graph_ent, depth ) + ), + + F_printk("--> %ps (%d)", (void *)__entry->func, __entry->depth) +@@ -94,12 +94,12 @@ FTRACE_ENTRY_PACKED(funcgraph_exit, ftrace_graph_ret_entry, + + F_STRUCT( + __field_struct( struct ftrace_graph_ret, ret ) +- __field_packed( unsigned long, ret, func ) +- __field_packed( unsigned long, ret, retval ) +- __field_packed( int, ret, depth ) +- __field_packed( unsigned int, ret, overrun ) +- __field_packed( unsigned long long, ret, calltime) +- __field_packed( unsigned long long, ret, rettime ) ++ __field_desc_packed( unsigned long, ret, func ) ++ __field_desc_packed( unsigned long, ret, retval ) ++ __field_desc_packed( int, ret, depth ) ++ __field_desc_packed( unsigned int, ret, overrun ) ++ __field_packed(unsigned long long, calltime) ++ __field_packed(unsigned long long, rettime ) + ), + + F_printk("<-- %ps (%d) (start: %llx end: %llx) over: %d retval: %lx", +@@ -116,11 +116,11 @@ FTRACE_ENTRY_PACKED(funcgraph_exit, ftrace_graph_ret_entry, + + F_STRUCT( + __field_struct( struct ftrace_graph_ret, ret ) +- __field_packed( unsigned long, ret, func ) +- __field_packed( int, ret, depth ) +- __field_packed( unsigned int, ret, overrun ) +- __field_packed( unsigned long long, ret, calltime) +- __field_packed( unsigned long long, ret, rettime ) ++ __field_desc_packed( unsigned long, ret, func ) ++ __field_desc_packed( int, ret, depth ) ++ __field_desc_packed( unsigned int, ret, overrun ) ++ __field_packed(unsigned long long, calltime) ++ __field_packed(unsigned long long, rettime ) + ), + + F_printk("<-- %ps (%d) (start: %llx end: %llx) over: %d", +diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c +index 1698fc22afa0a5..32a42ef31855d8 100644 +--- a/kernel/trace/trace_export.c ++++ b/kernel/trace/trace_export.c +@@ -42,11 +42,14 @@ static int ftrace_event_register(struct trace_event_call *call, + #undef __field_fn + #define __field_fn(type, item) type item; + ++#undef __field_packed ++#define __field_packed(type, item) type item; ++ + #undef __field_desc + #define __field_desc(type, container, item) type item; + +-#undef __field_packed +-#define __field_packed(type, container, item) type item; ++#undef __field_desc_packed ++#define __field_desc_packed(type, container, item) type item; + + #undef __array + #define __array(type, item, size) type item[size]; +@@ -104,11 +107,14 @@ static void __always_unused ____ftrace_check_##name(void) \ + #undef __field_fn + #define __field_fn(_type, _item) __field_ext(_type, _item, FILTER_TRACE_FN) + ++#undef __field_packed ++#define __field_packed(_type, _item) __field_ext_packed(_type, _item, FILTER_OTHER) ++ + #undef __field_desc + #define __field_desc(_type, _container, _item) __field_ext(_type, _item, FILTER_OTHER) + +-#undef __field_packed +-#define __field_packed(_type, _container, _item) __field_ext_packed(_type, _item, FILTER_OTHER) ++#undef __field_desc_packed ++#define __field_desc_packed(_type, _container, _item) __field_ext_packed(_type, _item, FILTER_OTHER) + + #undef __array + #define __array(_type, _item, _len) { \ +@@ -146,11 +152,14 @@ static struct trace_event_fields ftrace_event_fields_##name[] = { \ + #undef __field_fn + #define __field_fn(type, item) + ++#undef __field_packed ++#define __field_packed(type, item) ++ + #undef __field_desc + #define __field_desc(type, container, item) + +-#undef __field_packed +-#define __field_packed(type, container, item) ++#undef __field_desc_packed ++#define __field_desc_packed(type, container, item) + + #undef __array + #define __array(type, item, len) +diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c +index ed62c1026fe93e..f99e348c8f37fa 100644 +--- a/net/bridge/netfilter/ebtables.c ++++ b/net/bridge/netfilter/ebtables.c +@@ -1299,7 +1299,7 @@ int ebt_register_template(const struct ebt_table *t, int (*table_init)(struct ne + list_for_each_entry(tmpl, &template_tables, list) { + if (WARN_ON_ONCE(strcmp(t->name, tmpl->name) == 0)) { + mutex_unlock(&ebt_mutex); +- return -EEXIST; ++ return -EBUSY; + } + } + +diff --git a/net/core/filter.c b/net/core/filter.c +index 99e931bc9e9aa2..ddb6d3dd34deb7 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -2281,12 +2281,12 @@ static int __bpf_redirect_neigh_v6(struct sk_buff *skb, struct net_device *dev, + + err = bpf_out_neigh_v6(net, skb, dev, nh); + if (unlikely(net_xmit_eval(err))) +- DEV_STATS_INC(dev, tx_errors); ++ dev_core_stats_tx_dropped_inc(dev); + else + ret = NET_XMIT_SUCCESS; + goto out_xmit; + out_drop: +- DEV_STATS_INC(dev, tx_errors); ++ dev_core_stats_tx_dropped_inc(dev); + kfree_skb(skb); + out_xmit: + return ret; +@@ -2389,12 +2389,12 @@ static int __bpf_redirect_neigh_v4(struct sk_buff *skb, struct net_device *dev, + + err = bpf_out_neigh_v4(net, skb, dev, nh); + if (unlikely(net_xmit_eval(err))) +- DEV_STATS_INC(dev, tx_errors); ++ dev_core_stats_tx_dropped_inc(dev); + else + ret = NET_XMIT_SUCCESS; + goto out_xmit; + out_drop: +- DEV_STATS_INC(dev, tx_errors); ++ dev_core_stats_tx_dropped_inc(dev); + kfree_skb(skb); + out_xmit: + return ret; +diff --git a/net/core/gro.c b/net/core/gro.c +index b8cc44406e69bf..87889cb75d2194 100644 +--- a/net/core/gro.c ++++ b/net/core/gro.c +@@ -240,6 +240,8 @@ static void napi_gro_complete(struct napi_struct *napi, struct sk_buff *skb) + goto out; + } + ++ /* NICs can feed encapsulated packets into GRO */ ++ skb->encapsulation = 0; + rcu_read_lock(); + list_for_each_entry_rcu(ptype, head, list) { + if (ptype->type != type || !ptype->callbacks.gro_complete) +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index 646ff1276aff23..fe57884ca7238a 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -1136,7 +1136,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt, + fib6_set_expires(iter, rt->expires); + fib6_add_gc_list(iter); + } +- if (!(rt->fib6_flags & (RTF_ADDRCONF | RTF_PREFIX_RT))) { ++ if (!(rt->fib6_flags & (RTF_ADDRCONF | RTF_PREFIX_RT)) && ++ !iter->fib6_nh->fib_nh_gw_family) { + iter->fib6_flags &= ~RTF_ADDRCONF; + iter->fib6_flags &= ~RTF_PREFIX_RT; + } +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index a531fb2b14deea..c8c53f4d1bdbfa 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -347,6 +347,8 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata, + /* we hold the RTNL here so can safely walk the list */ + list_for_each_entry(nsdata, &local->interfaces, list) { + if (nsdata != sdata && ieee80211_sdata_running(nsdata)) { ++ struct ieee80211_link_data *link; ++ + /* + * Only OCB and monitor mode may coexist + */ +@@ -373,8 +375,10 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata, + * will not add another interface while any channel + * switch is active. + */ +- if (nsdata->vif.bss_conf.csa_active) +- return -EBUSY; ++ for_each_link_data(nsdata, link) { ++ if (link->conf->csa_active) ++ return -EBUSY; ++ } + + /* + * The remaining checks are only performed for interfaces +diff --git a/net/mac80211/key.c b/net/mac80211/key.c +index f5f1eb87797a47..327ae73434517e 100644 +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -981,7 +981,8 @@ void ieee80211_reenable_keys(struct ieee80211_sub_if_data *sdata) + + if (ieee80211_sdata_running(sdata)) { + list_for_each_entry(key, &sdata->key_list, list) { +- increment_tailroom_need_count(sdata); ++ if (!(key->flags & KEY_FLAG_TAINTED)) ++ increment_tailroom_need_count(sdata); + ieee80211_key_enable_hw_accel(key); + } + } +diff --git a/net/mac80211/ocb.c b/net/mac80211/ocb.c +index b44896e1452242..1800d59d8b1529 100644 +--- a/net/mac80211/ocb.c ++++ b/net/mac80211/ocb.c +@@ -48,6 +48,9 @@ void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata, + struct sta_info *sta; + int band; + ++ if (!ifocb->joined) ++ return; ++ + /* XXX: Consider removing the least recently used entry and + * allow new one to be added. + */ +diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c +index 64cf5589989bbb..9d7d7ee9d7ce28 100644 +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -1477,6 +1477,10 @@ static void __sta_info_destroy_part2(struct sta_info *sta, bool recalc) + } + } + ++ sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL); ++ if (sinfo) ++ sta_set_sinfo(sta, sinfo, true); ++ + if (sta->uploaded) { + ret = drv_sta_state(local, sdata, sta, IEEE80211_STA_NONE, + IEEE80211_STA_NOTEXIST); +@@ -1485,9 +1489,6 @@ static void __sta_info_destroy_part2(struct sta_info *sta, bool recalc) + + sta_dbg(sdata, "Removed STA %pM\n", sta->sta.addr); + +- sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL); +- if (sinfo) +- sta_set_sinfo(sta, sinfo, true); + cfg80211_del_sta_sinfo(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL); + kfree(sinfo); + +diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c +index e16f158388bbe5..75c812f157e206 100644 +--- a/net/netfilter/nf_log.c ++++ b/net/netfilter/nf_log.c +@@ -89,7 +89,7 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger) + if (pf == NFPROTO_UNSPEC) { + for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) { + if (rcu_access_pointer(loggers[i][logger->type])) { +- ret = -EEXIST; ++ ret = -EBUSY; + goto unlock; + } + } +@@ -97,7 +97,7 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger) + rcu_assign_pointer(loggers[i][logger->type], logger); + } else { + if (rcu_access_pointer(loggers[pf][logger->type])) { +- ret = -EEXIST; ++ ret = -EBUSY; + goto unlock; + } + rcu_assign_pointer(loggers[pf][logger->type], logger); +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index c00dd7dae5cb96..120d9bd53321ca 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -5608,7 +5608,7 @@ static void nft_map_catchall_activate(const struct nft_ctx *ctx, + + list_for_each_entry(catchall, &set->catchall_list, list) { + ext = nft_set_elem_ext(set, catchall->elem); +- if (!nft_set_elem_active(ext, genmask)) ++ if (nft_set_elem_active(ext, genmask)) + continue; + + nft_clear(ctx->net, ext); +diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c +index 4274831b6e67ba..ebd0f704c863c3 100644 +--- a/net/netfilter/nft_set_pipapo.c ++++ b/net/netfilter/nft_set_pipapo.c +@@ -667,6 +667,11 @@ static int pipapo_resize(struct nft_pipapo_field *f, int old_rules, int rules) + } + + mt: ++ if (rules > (INT_MAX / sizeof(*new_mt))) { ++ kvfree(new_lt); ++ return -ENOMEM; ++ } ++ + new_mt = kvmalloc(rules * sizeof(*new_mt), GFP_KERNEL); + if (!new_mt) { + kvfree(new_lt); +@@ -1359,6 +1364,9 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old) + src->bsize * sizeof(*dst->lt) * + src->groups * NFT_PIPAPO_BUCKETS(src->bb)); + ++ if (src->rules > (INT_MAX / sizeof(*src->mt))) ++ goto out_mt; ++ + dst->mt = kvmalloc(src->rules * sizeof(*src->mt), GFP_KERNEL); + if (!dst->mt) + goto out_mt; +diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c +index e50c23b9c9c41b..d892afc9a1acca 100644 +--- a/net/netfilter/x_tables.c ++++ b/net/netfilter/x_tables.c +@@ -1761,7 +1761,7 @@ EXPORT_SYMBOL_GPL(xt_hook_ops_alloc); + int xt_register_template(const struct xt_table *table, + int (*table_init)(struct net *net)) + { +- int ret = -EEXIST, af = table->af; ++ int ret = -EBUSY, af = table->af; + struct xt_template *t; + + mutex_lock(&xt[af].mutex); +diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c +index 67f27be1384874..1338d9b4c03a44 100644 +--- a/net/sched/cls_u32.c ++++ b/net/sched/cls_u32.c +@@ -161,10 +161,8 @@ next_knode: + int toff = off + key->off + (off2 & key->offmask); + __be32 *data, hdata; + +- if (skb_headroom(skb) + toff > INT_MAX) +- goto out; +- +- data = skb_header_pointer(skb, toff, 4, &hdata); ++ data = skb_header_pointer_careful(skb, toff, 4, ++ &hdata); + if (!data) + goto out; + if ((*data ^ key->val) & key->mask) { +@@ -214,8 +212,9 @@ check_terminal: + if (ht->divisor) { + __be32 *data, hdata; + +- data = skb_header_pointer(skb, off + n->sel.hoff, 4, +- &hdata); ++ data = skb_header_pointer_careful(skb, ++ off + n->sel.hoff, ++ 4, &hdata); + if (!data) + goto out; + sel = ht->divisor & u32_hash_fold(*data, &n->sel, +@@ -229,7 +228,7 @@ check_terminal: + if (n->sel.flags & TC_U32_VAROFFSET) { + __be16 *data, hdata; + +- data = skb_header_pointer(skb, ++ data = skb_header_pointer_careful(skb, + off + n->sel.offoff, + 2, &hdata); + if (!data) +diff --git a/net/tipc/crypto.c b/net/tipc/crypto.c +index ea5bb131ebd060..2721baf9fd2b32 100644 +--- a/net/tipc/crypto.c ++++ b/net/tipc/crypto.c +@@ -1219,7 +1219,7 @@ void tipc_crypto_key_flush(struct tipc_crypto *c) + rx = c; + tx = tipc_net(rx->net)->crypto_tx; + if (cancel_delayed_work(&rx->work)) { +- kfree(rx->skey); ++ kfree_sensitive(rx->skey); + rx->skey = NULL; + atomic_xchg(&rx->key_distr, 0); + tipc_node_put(rx->node); +@@ -2394,7 +2394,7 @@ static void tipc_crypto_work_rx(struct work_struct *work) + break; + default: + synchronize_rcu(); +- kfree(rx->skey); ++ kfree_sensitive(rx->skey); + rx->skey = NULL; + break; + } +diff --git a/net/wireless/util.c b/net/wireless/util.c +index 24e5af65da58ea..640ec502e82d29 100644 +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -1563,12 +1563,14 @@ static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate) + tmp = result; + tmp *= SCALE; + do_div(tmp, mcs_divisors[rate->mcs]); +- result = tmp; + + /* and take NSS, DCM into account */ +- result = (result * rate->nss) / 8; ++ tmp *= rate->nss; ++ do_div(tmp, 8); + if (rate->he_dcm) +- result /= 2; ++ do_div(tmp, 2); ++ ++ result = tmp; + + return result / 10000; + } +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 65c9d47f03af57..c60358a4a75728 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -10085,6 +10085,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x863e, "HP Spectre x360 15-df1xxx", ALC285_FIXUP_HP_SPECTRE_X360_DF1), + SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), + SND_PCI_QUIRK(0x103c, 0x86f9, "HP Spectre x360 13-aw0xxx", ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED), ++ SND_PCI_QUIRK(0x103c, 0x8706, "HP Laptop 15s-eq1xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), + SND_PCI_QUIRK(0x103c, 0x8716, "HP Elite Dragonfly G2 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x8720, "HP EliteBook x360 1040 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x8724, "HP EliteBook 850 G7", ALC285_FIXUP_HP_GPIO_LED), +@@ -10639,6 +10640,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1d05, 0x1409, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1d05, 0x300f, "TongFang X6AR5xxY", ALC2XX_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1d05, 0x3019, "TongFang X6FR5xxY", ALC2XX_FIXUP_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1d05, 0x3031, "TongFang X6AR55xU", ALC2XX_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1d17, 0x3288, "Haier Boyue G42", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS), + SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC), + SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE), +diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c +index c3b47e9bd23924..39223ff37b14ea 100644 +--- a/sound/soc/amd/renoir/acp3x-pdm-dma.c ++++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c +@@ -301,9 +301,11 @@ static int acp_pdm_dma_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) + { + struct pdm_dev_data *adata = dev_get_drvdata(component->dev); ++ struct pdm_stream_instance *rtd = substream->runtime->private_data; + + disable_pdm_interrupts(adata->acp_base); + adata->capture_stream = NULL; ++ kfree(rtd); + return 0; + } + +diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c +index 00e4ffeb6fb00a..b0456be5d921a3 100644 +--- a/sound/soc/amd/yc/acp6x-mach.c ++++ b/sound/soc/amd/yc/acp6x-mach.c +@@ -409,6 +409,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "M6500RC"), + } + }, ++ { ++ .driver_data = &acp6x_card, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "M6500RE"), ++ } ++ }, + { + .driver_data = &acp6x_card, + .matches = { +diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c +index 78d95b8be2f294..c4ffbc573412e5 100644 +--- a/sound/soc/codecs/tlv320adcx140.c ++++ b/sound/soc/codecs/tlv320adcx140.c +@@ -1157,6 +1157,9 @@ static int adcx140_i2c_probe(struct i2c_client *i2c) + adcx140->gpio_reset = devm_gpiod_get_optional(adcx140->dev, + "reset", GPIOD_OUT_LOW); + if (IS_ERR(adcx140->gpio_reset)) ++ return dev_err_probe(&i2c->dev, PTR_ERR(adcx140->gpio_reset), ++ "Failed to get Reset GPIO\n"); ++ if (!adcx140->gpio_reset) + dev_info(&i2c->dev, "Reset GPIO not defined\n"); + + adcx140->supply_areg = devm_regulator_get_optional(adcx140->dev, +diff --git a/sound/soc/ti/davinci-evm.c b/sound/soc/ti/davinci-evm.c +index 544cb3da50eb09..7cf900289dc79f 100644 +--- a/sound/soc/ti/davinci-evm.c ++++ b/sound/soc/ti/davinci-evm.c +@@ -196,27 +196,32 @@ static int davinci_evm_probe(struct platform_device *pdev) + return -EINVAL; + + dai->cpus->of_node = of_parse_phandle(np, "ti,mcasp-controller", 0); +- if (!dai->cpus->of_node) +- return -EINVAL; ++ if (!dai->cpus->of_node) { ++ ret = -EINVAL; ++ goto err_put; ++ } + + dai->platforms->of_node = dai->cpus->of_node; + + evm_soc_card.dev = &pdev->dev; + ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model"); + if (ret) +- return ret; ++ goto err_put; + + mclk = devm_clk_get(&pdev->dev, "mclk"); + if (PTR_ERR(mclk) == -EPROBE_DEFER) { +- return -EPROBE_DEFER; ++ ret = -EPROBE_DEFER; ++ goto err_put; + } else if (IS_ERR(mclk)) { + dev_dbg(&pdev->dev, "mclk not found.\n"); + mclk = NULL; + } + + drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); +- if (!drvdata) +- return -ENOMEM; ++ if (!drvdata) { ++ ret = -ENOMEM; ++ goto err_put; ++ } + + drvdata->mclk = mclk; + +@@ -226,7 +231,8 @@ static int davinci_evm_probe(struct platform_device *pdev) + if (!drvdata->mclk) { + dev_err(&pdev->dev, + "No clock or clock rate defined.\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_put; + } + drvdata->sysclk = clk_get_rate(drvdata->mclk); + } else if (drvdata->mclk) { +@@ -242,8 +248,25 @@ static int davinci_evm_probe(struct platform_device *pdev) + snd_soc_card_set_drvdata(&evm_soc_card, drvdata); + ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card); + +- if (ret) ++ if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); ++ goto err_put; ++ } ++ ++ return ret; ++ ++err_put: ++ dai->platforms->of_node = NULL; ++ ++ if (dai->cpus->of_node) { ++ of_node_put(dai->cpus->of_node); ++ dai->cpus->of_node = NULL; ++ } ++ ++ if (dai->codecs->of_node) { ++ of_node_put(dai->codecs->of_node); ++ dai->codecs->of_node = NULL; ++ } + + return ret; + } +diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile +index a3bb36fb3cfc55..d819994874df11 100644 +--- a/tools/testing/selftests/kvm/Makefile ++++ b/tools/testing/selftests/kvm/Makefile +@@ -212,6 +212,7 @@ LINUX_TOOL_ARCH_INCLUDE = $(top_srcdir)/tools/arch/$(ARCH)/include + endif + CFLAGS += -Wall -Wstrict-prototypes -Wuninitialized -O2 -g -std=gnu99 \ + -Wno-gnu-variable-sized-type-not-at-end -MD\ ++ -U_FORTIFY_SOURCE \ + -fno-builtin-memcmp -fno-builtin-memcpy -fno-builtin-memset \ + -fno-builtin-strnlen \ + -fno-stack-protector -fno-PIE -I$(LINUX_TOOL_INCLUDE) \ +diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c +index 89912a17f5d576..9ca20fc59b52f7 100644 +--- a/virt/kvm/eventfd.c ++++ b/virt/kvm/eventfd.c +@@ -156,21 +156,28 @@ irqfd_shutdown(struct work_struct *work) + } + + +-/* assumes kvm->irqfds.lock is held */ +-static bool +-irqfd_is_active(struct kvm_kernel_irqfd *irqfd) ++static bool irqfd_is_active(struct kvm_kernel_irqfd *irqfd) + { ++ /* ++ * Assert that either irqfds.lock or SRCU is held, as irqfds.lock must ++ * be held to prevent false positives (on the irqfd being active), and ++ * while false negatives are impossible as irqfds are never added back ++ * to the list once they're deactivated, the caller must at least hold ++ * SRCU to guard against routing changes if the irqfd is deactivated. ++ */ ++ lockdep_assert_once(lockdep_is_held(&irqfd->kvm->irqfds.lock) || ++ srcu_read_lock_held(&irqfd->kvm->irq_srcu)); ++ + return list_empty(&irqfd->list) ? false : true; + } + + /* + * Mark the irqfd as inactive and schedule it for removal +- * +- * assumes kvm->irqfds.lock is held + */ +-static void +-irqfd_deactivate(struct kvm_kernel_irqfd *irqfd) ++static void irqfd_deactivate(struct kvm_kernel_irqfd *irqfd) + { ++ lockdep_assert_held(&irqfd->kvm->irqfds.lock); ++ + BUG_ON(!irqfd_is_active(irqfd)); + + list_del_init(&irqfd->list); +@@ -211,8 +218,15 @@ irqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key) + seq = read_seqcount_begin(&irqfd->irq_entry_sc); + irq = irqfd->irq_entry; + } while (read_seqcount_retry(&irqfd->irq_entry_sc, seq)); +- /* An event has been signaled, inject an interrupt */ +- if (kvm_arch_set_irq_inatomic(&irq, kvm, ++ ++ /* ++ * An event has been signaled, inject an interrupt unless the ++ * irqfd is being deassigned (isn't active), in which case the ++ * routing information may be stale (once the irqfd is removed ++ * from the list, it will stop receiving routing updates). ++ */ ++ if (unlikely(!irqfd_is_active(irqfd)) || ++ kvm_arch_set_irq_inatomic(&irq, kvm, + KVM_USERSPACE_IRQ_SOURCE_ID, 1, + false) == -EWOULDBLOCK) + schedule_work(&irqfd->inject); +@@ -557,18 +571,8 @@ kvm_irqfd_deassign(struct kvm *kvm, struct kvm_irqfd *args) + spin_lock_irq(&kvm->irqfds.lock); + + list_for_each_entry_safe(irqfd, tmp, &kvm->irqfds.items, list) { +- if (irqfd->eventfd == eventfd && irqfd->gsi == args->gsi) { +- /* +- * This clearing of irq_entry.type is needed for when +- * another thread calls kvm_irq_routing_update before +- * we flush workqueue below (we synchronize with +- * kvm_irq_routing_update using irqfds.lock). +- */ +- write_seqcount_begin(&irqfd->irq_entry_sc); +- irqfd->irq_entry.type = 0; +- write_seqcount_end(&irqfd->irq_entry_sc); ++ if (irqfd->eventfd == eventfd && irqfd->gsi == args->gsi) + irqfd_deactivate(irqfd); +- } + } + + spin_unlock_irq(&kvm->irqfds.lock); diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.124-125.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.124-125.patch new file mode 100644 index 0000000000..7e128894a9 --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.124-125.patch @@ -0,0 +1,1213 @@ +diff --git a/Makefile b/Makefile +index 4ec8ec24a35414..4a944e80769044 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 124 ++SUBLEVEL = 125 + EXTRAVERSION = + NAME = Pinguïn Aangedreven + +diff --git a/drivers/base/base.h b/drivers/base/base.h +index 0b491449b022a1..35e14bebbfb2c2 100644 +--- a/drivers/base/base.h ++++ b/drivers/base/base.h +@@ -165,9 +165,18 @@ void device_set_deferred_probe_reason(const struct device *dev, struct va_format + static inline int driver_match_device(struct device_driver *drv, + struct device *dev) + { ++ device_lock_assert(dev); ++ + return drv->bus->match ? drv->bus->match(dev, drv) : 1; + } + ++static inline int driver_match_device_locked(struct device_driver *drv, ++ struct device *dev) ++{ ++ guard(device)(dev); ++ return driver_match_device(drv, dev); ++} ++ + static inline void dev_sync_state(struct device *dev) + { + if (dev->bus->sync_state) +diff --git a/drivers/base/bus.c b/drivers/base/bus.c +index b97e13a52c3308..27f8442a3aa9dd 100644 +--- a/drivers/base/bus.c ++++ b/drivers/base/bus.c +@@ -263,7 +263,7 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf, + int err = -ENODEV; + + dev = bus_find_device_by_name(bus, NULL, buf); +- if (dev && driver_match_device(drv, dev)) { ++ if (dev && driver_match_device_locked(drv, dev)) { + err = device_driver_attach(drv, dev); + if (!err) { + /* success */ +diff --git a/drivers/base/dd.c b/drivers/base/dd.c +index 7e2fb159bb895b..07f1332dd3a440 100644 +--- a/drivers/base/dd.c ++++ b/drivers/base/dd.c +@@ -1169,7 +1169,7 @@ static int __driver_attach(struct device *dev, void *data) + * is an error. + */ + +- ret = driver_match_device(drv, dev); ++ ret = driver_match_device_locked(drv, dev); + if (ret == 0) { + /* no match */ + return 0; +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 1309e9318bdb55..eaeacdadb20232 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -516,6 +516,8 @@ static const struct usb_device_id quirks_table[] = { + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x2001, 0x332a), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x7392, 0xe611), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, + + /* Realtek 8852AE Bluetooth devices */ + { USB_DEVICE(0x0bda, 0x2852), .driver_info = BTUSB_REALTEK | +diff --git a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c +index c4250e5fcf8f7b..11dfbd4beba9cd 100644 +--- a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c ++++ b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c +@@ -1336,7 +1336,7 @@ static ssize_t ucode_load_store(struct device *dev, + int del_grp_idx = -1; + int ucode_idx = 0; + +- if (strlen(buf) > OTX_CPT_UCODE_NAME_LENGTH) ++ if (count >= OTX_CPT_UCODE_NAME_LENGTH) + return -EINVAL; + + eng_grps = container_of(attr, struct otx_cpt_eng_grps, ucode_load_attr); +diff --git a/drivers/crypto/omap-crypto.c b/drivers/crypto/omap-crypto.c +index a4cc6bf146ec09..0345c9383d5097 100644 +--- a/drivers/crypto/omap-crypto.c ++++ b/drivers/crypto/omap-crypto.c +@@ -21,7 +21,7 @@ static int omap_crypto_copy_sg_lists(int total, int bs, + struct scatterlist *tmp; + + if (!(flags & OMAP_CRYPTO_FORCE_SINGLE_ENTRY)) { +- new_sg = kmalloc_array(n, sizeof(*sg), GFP_KERNEL); ++ new_sg = kmalloc_array(n, sizeof(*new_sg), GFP_KERNEL); + if (!new_sg) + return -ENOMEM; + +diff --git a/drivers/crypto/virtio/virtio_crypto_core.c b/drivers/crypto/virtio/virtio_crypto_core.c +index b909c6a2bf1c34..6ec9a95b4db073 100644 +--- a/drivers/crypto/virtio/virtio_crypto_core.c ++++ b/drivers/crypto/virtio/virtio_crypto_core.c +@@ -77,15 +77,20 @@ static void virtcrypto_done_task(unsigned long data) + struct data_queue *data_vq = (struct data_queue *)data; + struct virtqueue *vq = data_vq->vq; + struct virtio_crypto_request *vc_req; ++ unsigned long flags; + unsigned int len; + ++ spin_lock_irqsave(&data_vq->lock, flags); + do { + virtqueue_disable_cb(vq); + while ((vc_req = virtqueue_get_buf(vq, &len)) != NULL) { ++ spin_unlock_irqrestore(&data_vq->lock, flags); + if (vc_req->alg_cb) + vc_req->alg_cb(vc_req, len); ++ spin_lock_irqsave(&data_vq->lock, flags); + } + } while (!virtqueue_enable_cb(vq)); ++ spin_unlock_irqrestore(&data_vq->lock, flags); + } + + static void virtcrypto_dataq_callback(struct virtqueue *vq) +diff --git a/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c b/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c +index 23c41d87d835ff..487f60e35df193 100644 +--- a/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c ++++ b/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c +@@ -550,8 +550,6 @@ int virtio_crypto_skcipher_crypt_req( + if (ret < 0) + return ret; + +- virtqueue_kick(data_vq->vq); +- + return 0; + } + +diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c +index a927680c66f88d..772fddc02b8181 100644 +--- a/drivers/gpio/gpio-omap.c ++++ b/drivers/gpio/gpio-omap.c +@@ -799,10 +799,13 @@ static struct platform_device omap_mpuio_device = { + + static inline void omap_mpuio_init(struct gpio_bank *bank) + { +- platform_set_drvdata(&omap_mpuio_device, bank); ++ static bool registered; + +- if (platform_driver_register(&omap_mpuio_driver) == 0) +- (void) platform_device_register(&omap_mpuio_device); ++ platform_set_drvdata(&omap_mpuio_device, bank); ++ if (!registered) { ++ (void)platform_device_register(&omap_mpuio_device); ++ registered = true; ++ } + } + + /*---------------------------------------------------------------------*/ +@@ -1575,13 +1578,24 @@ static struct platform_driver omap_gpio_driver = { + */ + static int __init omap_gpio_drv_reg(void) + { +- return platform_driver_register(&omap_gpio_driver); ++ int ret; ++ ++ ret = platform_driver_register(&omap_mpuio_driver); ++ if (ret) ++ return ret; ++ ++ ret = platform_driver_register(&omap_gpio_driver); ++ if (ret) ++ platform_driver_unregister(&omap_mpuio_driver); ++ ++ return ret; + } + postcore_initcall(omap_gpio_drv_reg); + + static void __exit omap_gpio_exit(void) + { + platform_driver_unregister(&omap_gpio_driver); ++ platform_driver_unregister(&omap_mpuio_driver); + } + module_exit(omap_gpio_exit); + +diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c +index dc62f141f40382..ff438be4c186e1 100644 +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -431,6 +431,8 @@ static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id, + */ + linkmode_zero(modes); + linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, modes); ++ phy_interface_zero(interfaces); ++ __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces); + } + + #define SFP_QUIRK(_v, _p, _m, _f) \ +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index 0d0b5123b5fe28..c7396ae9256b9b 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -2401,10 +2401,10 @@ void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable) + + if (enable) { + rtw_write32_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); +- rtw_write32_clr(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE); ++ rtw_write8_clr(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE); + } else { + rtw_write32_clr(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); +- rtw_write32_set(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE); ++ rtw_write8_set(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE); + } + } + +diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c +index d2bddca7045aa1..4cef9a34934380 100644 +--- a/drivers/scsi/qla2xxx/qla_gs.c ++++ b/drivers/scsi/qla2xxx/qla_gs.c +@@ -3356,9 +3356,6 @@ login_logout: + atomic_read(&fcport->state) == FCS_ONLINE) || + do_delete) { + if (fcport->loop_id != FC_NO_LOOP_ID) { +- if (fcport->flags & FCF_FCP2_DEVICE) +- continue; +- + ql_log(ql_log_warn, vha, 0x20f0, + "%s %d %8phC post del sess\n", + __func__, __LINE__, +@@ -3625,8 +3622,8 @@ int qla_fab_async_scan(scsi_qla_host_t *vha, srb_t *sp) + if (vha->scan.scan_flags & SF_SCANNING) { + spin_unlock_irqrestore(&vha->work_lock, flags); + ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2012, +- "%s: scan active\n", __func__); +- return rval; ++ "%s: scan active for sp:%p\n", __func__, sp); ++ goto done_free_sp; + } + vha->scan.scan_flags |= SF_SCANNING; + if (!sp) +@@ -3791,23 +3788,25 @@ int qla_fab_async_scan(scsi_qla_host_t *vha, srb_t *sp) + return rval; + + done_free_sp: +- if (sp->u.iocb_cmd.u.ctarg.req) { +- dma_free_coherent(&vha->hw->pdev->dev, +- sp->u.iocb_cmd.u.ctarg.req_allocated_size, +- sp->u.iocb_cmd.u.ctarg.req, +- sp->u.iocb_cmd.u.ctarg.req_dma); +- sp->u.iocb_cmd.u.ctarg.req = NULL; +- } +- if (sp->u.iocb_cmd.u.ctarg.rsp) { +- dma_free_coherent(&vha->hw->pdev->dev, +- sp->u.iocb_cmd.u.ctarg.rsp_allocated_size, +- sp->u.iocb_cmd.u.ctarg.rsp, +- sp->u.iocb_cmd.u.ctarg.rsp_dma); +- sp->u.iocb_cmd.u.ctarg.rsp = NULL; +- } ++ if (sp) { ++ if (sp->u.iocb_cmd.u.ctarg.req) { ++ dma_free_coherent(&vha->hw->pdev->dev, ++ sp->u.iocb_cmd.u.ctarg.req_allocated_size, ++ sp->u.iocb_cmd.u.ctarg.req, ++ sp->u.iocb_cmd.u.ctarg.req_dma); ++ sp->u.iocb_cmd.u.ctarg.req = NULL; ++ } ++ if (sp->u.iocb_cmd.u.ctarg.rsp) { ++ dma_free_coherent(&vha->hw->pdev->dev, ++ sp->u.iocb_cmd.u.ctarg.rsp_allocated_size, ++ sp->u.iocb_cmd.u.ctarg.rsp, ++ sp->u.iocb_cmd.u.ctarg.rsp_dma); ++ sp->u.iocb_cmd.u.ctarg.rsp = NULL; ++ } + +- /* ref: INIT */ +- kref_put(&sp->cmd_kref, qla2x00_sp_release); ++ /* ref: INIT */ ++ kref_put(&sp->cmd_kref, qla2x00_sp_release); ++ } + + spin_lock_irqsave(&vha->work_lock, flags); + vha->scan.scan_flags &= ~SF_SCANNING; +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index e881d704b45d1b..b736575e2d9fc8 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -1859,15 +1859,6 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea) + case RSCN_PORT_ADDR: + fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1); + if (fcport) { +- if (ql2xfc2target && +- fcport->flags & FCF_FCP2_DEVICE && +- atomic_read(&fcport->state) == FCS_ONLINE) { +- ql_dbg(ql_dbg_disc, vha, 0x2115, +- "Delaying session delete for FCP2 portid=%06x %8phC ", +- fcport->d_id.b24, fcport->port_name); +- return; +- } +- + if (vha->hw->flags.edif_enabled && DBELL_ACTIVE(vha)) { + /* + * On ipsec start by remote port, Target port +@@ -2471,8 +2462,23 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea) + ea->sp->gen1, fcport->rscn_gen, + ea->data[0], ea->data[1], ea->iop[0], ea->iop[1]); + +- if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) || +- (fcport->fw_login_state == DSC_LS_PRLI_PEND)) { ++ if (fcport->fw_login_state == DSC_LS_PLOGI_PEND) { ++ ql_dbg(ql_dbg_disc, vha, 0x20ea, ++ "%s %d %8phC Remote is trying to login\n", ++ __func__, __LINE__, fcport->port_name); ++ /* ++ * If we get here, there is port thats already logged in, ++ * but it's state has not moved ahead. Recheck with FW on ++ * what state it is in and proceed ahead ++ */ ++ if (!N2N_TOPO(vha->hw)) { ++ fcport->fw_login_state = DSC_LS_PRLI_COMP; ++ qla24xx_post_gpdb_work(vha, fcport, 0); ++ } ++ return; ++ } ++ ++ if (fcport->fw_login_state == DSC_LS_PRLI_PEND) { + ql_dbg(ql_dbg_disc, vha, 0x20ea, + "%s %d %8phC Remote is trying to login\n", + __func__, __LINE__, fcport->port_name); +diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c +index ae2bea27a18a67..38214f8e30fa6d 100644 +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -1676,13 +1676,28 @@ skip_rio: + + /* Port logout */ + fcport = qla2x00_find_fcport_by_loopid(vha, mb[1]); +- if (!fcport) ++ if (!fcport) { ++ ql_dbg(ql_dbg_async, vha, 0x5011, ++ "Could not find fcport:%04x %04x %04x\n", ++ mb[1], mb[2], mb[3]); + break; +- if (atomic_read(&fcport->state) != FCS_ONLINE) ++ } ++ ++ if (atomic_read(&fcport->state) != FCS_ONLINE) { ++ ql_dbg(ql_dbg_async, vha, 0x5012, ++ "Port state is not online State:0x%x \n", ++ atomic_read(&fcport->state)); ++ ql_dbg(ql_dbg_async, vha, 0x5012, ++ "Scheduling session for deletion \n"); ++ fcport->logout_on_delete = 0; ++ qlt_schedule_sess_for_deletion(fcport); + break; ++ } ++ + ql_dbg(ql_dbg_async, vha, 0x508a, + "Marking port lost loopid=%04x portid=%06x.\n", + fcport->loop_id, fcport->d_id.b24); ++ + if (qla_ini_mode_enabled(vha)) { + fcport->logout_on_delete = 0; + qlt_schedule_sess_for_deletion(fcport); +diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c +index d10389ee92ba4b..b08abdf5ebf4e7 100644 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -1194,7 +1194,8 @@ qla2x00_wait_for_hba_ready(scsi_qla_host_t *vha) + while ((qla2x00_reset_active(vha) || ha->dpc_active || + ha->flags.mbox_busy) || + test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags) || +- test_bit(FX00_TARGET_SCAN, &vha->dpc_flags)) { ++ test_bit(FX00_TARGET_SCAN, &vha->dpc_flags) || ++ (vha->scan.scan_flags & SF_SCANNING)) { + if (test_bit(UNLOADING, &base_vha->dpc_flags)) + break; + msleep(1000); +diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c +index eed88aba2cfe92..3e7bf76be22bb7 100644 +--- a/drivers/spi/spi-cadence-quadspi.c ++++ b/drivers/spi/spi-cadence-quadspi.c +@@ -100,6 +100,8 @@ struct cqspi_st { + bool apb_ahb_hazard; + + bool is_jh7110; /* Flag for StarFive JH7110 SoC */ ++ refcount_t refcount; ++ refcount_t inflight_ops; + }; + + struct cqspi_driver_platdata { +@@ -705,6 +707,9 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata, + u8 *rxbuf_end = rxbuf + n_rx; + int ret = 0; + ++ if (!refcount_read(&cqspi->refcount)) ++ return -ENODEV; ++ + writel(from_addr, reg_base + CQSPI_REG_INDIRECTRDSTARTADDR); + writel(remaining, reg_base + CQSPI_REG_INDIRECTRDBYTES); + +@@ -1021,6 +1026,9 @@ static int cqspi_indirect_write_execute(struct cqspi_flash_pdata *f_pdata, + unsigned int write_bytes; + int ret; + ++ if (!refcount_read(&cqspi->refcount)) ++ return -ENODEV; ++ + writel(to_addr, reg_base + CQSPI_REG_INDIRECTWRSTARTADDR); + writel(remaining, reg_base + CQSPI_REG_INDIRECTWRBYTES); + +@@ -1412,11 +1420,29 @@ static int cqspi_mem_process(struct spi_mem *mem, const struct spi_mem_op *op) + static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) + { + int ret; ++ struct cqspi_st *cqspi = spi_controller_get_devdata(mem->spi->controller); ++ ++ if (refcount_read(&cqspi->inflight_ops) == 0) ++ return -ENODEV; ++ ++ if (!refcount_read(&cqspi->refcount)) ++ return -EBUSY; ++ ++ refcount_inc(&cqspi->inflight_ops); ++ ++ if (!refcount_read(&cqspi->refcount)) { ++ if (refcount_read(&cqspi->inflight_ops)) ++ refcount_dec(&cqspi->inflight_ops); ++ return -EBUSY; ++ } + + ret = cqspi_mem_process(mem, op); + if (ret) + dev_err(&mem->spi->dev, "operation failed with %d\n", ret); + ++ if (refcount_read(&cqspi->inflight_ops) > 1) ++ refcount_dec(&cqspi->inflight_ops); ++ + return ret; + } + +@@ -1847,6 +1873,9 @@ static int cqspi_probe(struct platform_device *pdev) + } + } + ++ refcount_set(&cqspi->refcount, 1); ++ refcount_set(&cqspi->inflight_ops, 1); ++ + ret = devm_request_irq(dev, irq, cqspi_irq_handler, 0, + pdev->name, cqspi); + if (ret) { +@@ -1899,6 +1928,11 @@ static void cqspi_remove(struct platform_device *pdev) + { + struct cqspi_st *cqspi = platform_get_drvdata(pdev); + ++ refcount_set(&cqspi->refcount, 0); ++ ++ if (!refcount_dec_and_test(&cqspi->inflight_ops)) ++ cqspi_wait_idle(cqspi); ++ + spi_unregister_controller(cqspi->host); + cqspi_controller_enable(cqspi, 0); + +diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c +index 78ebdf20c1efa3..4703e2a935684b 100644 +--- a/fs/nfsd/nfsctl.c ++++ b/fs/nfsd/nfsctl.c +@@ -1526,17 +1526,24 @@ static __net_init int nfsd_net_init(struct net *net) + retval = nfsd_stat_counters_init(nn); + if (retval) + goto out_repcache_error; ++ + memset(&nn->nfsd_svcstats, 0, sizeof(nn->nfsd_svcstats)); + nn->nfsd_svcstats.program = &nfsd_program; ++ if (!nfsd_proc_stat_init(net)) { ++ retval = -ENOMEM; ++ goto out_proc_error; ++ } ++ + nn->nfsd_versions = NULL; + nn->nfsd4_minorversions = NULL; + nfsd4_init_leases_net(nn); + get_random_bytes(&nn->siphash_key, sizeof(nn->siphash_key)); + seqlock_init(&nn->writeverf_lock); +- nfsd_proc_stat_init(net); + + return 0; + ++out_proc_error: ++ nfsd_stat_counters_destroy(nn); + out_repcache_error: + nfsd_idmap_shutdown(net); + out_idmap_error: +diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c +index 9f606fa08bd4b8..0a629a18831f19 100644 +--- a/fs/nfsd/stats.c ++++ b/fs/nfsd/stats.c +@@ -115,11 +115,11 @@ void nfsd_stat_counters_destroy(struct nfsd_net *nn) + nfsd_percpu_counters_destroy(nn->counter, NFSD_STATS_COUNTERS_NUM); + } + +-void nfsd_proc_stat_init(struct net *net) ++struct proc_dir_entry *nfsd_proc_stat_init(struct net *net) + { + struct nfsd_net *nn = net_generic(net, nfsd_net_id); + +- svc_proc_register(net, &nn->nfsd_svcstats, &nfsd_proc_ops); ++ return svc_proc_register(net, &nn->nfsd_svcstats, &nfsd_proc_ops); + } + + void nfsd_proc_stat_shutdown(struct net *net) +diff --git a/fs/nfsd/stats.h b/fs/nfsd/stats.h +index d2753e975dfd34..b1f7d21cbcd12c 100644 +--- a/fs/nfsd/stats.h ++++ b/fs/nfsd/stats.h +@@ -15,7 +15,7 @@ void nfsd_percpu_counters_reset(struct percpu_counter *counters, int num); + void nfsd_percpu_counters_destroy(struct percpu_counter *counters, int num); + int nfsd_stat_counters_init(struct nfsd_net *nn); + void nfsd_stat_counters_destroy(struct nfsd_net *nn); +-void nfsd_proc_stat_init(struct net *net); ++struct proc_dir_entry *nfsd_proc_stat_init(struct net *net); + void nfsd_proc_stat_shutdown(struct net *net); + + static inline void nfsd_stats_rc_hits_inc(struct nfsd_net *nn) +diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c +index 58ca7c936393c4..aa39cdce59930b 100644 +--- a/fs/nilfs2/sufile.c ++++ b/fs/nilfs2/sufile.c +@@ -1091,6 +1091,9 @@ int nilfs_sufile_trim_fs(struct inode *sufile, struct fstrim_range *range) + else + end_block = start_block + len - 1; + ++ if (end_block < nilfs->ns_first_data_block) ++ goto out; ++ + segnum = nilfs_get_segnum_of_block(nilfs, start_block); + segnum_end = nilfs_get_segnum_of_block(nilfs, end_block); + +@@ -1188,6 +1191,7 @@ int nilfs_sufile_trim_fs(struct inode *sufile, struct fstrim_range *range) + out_sem: + up_read(&NILFS_MDT(sufile)->mi_sem); + ++out: + range->len = ndiscarded << nilfs->ns_blocksize_bits; + return ret; + } +diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h +index bc8a812ff95f8b..96697c78b3a650 100644 +--- a/fs/smb/client/cached_dir.h ++++ b/fs/smb/client/cached_dir.h +@@ -34,10 +34,10 @@ struct cached_fid { + struct list_head entry; + struct cached_fids *cfids; + const char *path; +- bool has_lease:1; +- bool is_open:1; +- bool on_list:1; +- bool file_all_info_is_valid:1; ++ bool has_lease; ++ bool is_open; ++ bool on_list; ++ bool file_all_info_is_valid; + unsigned long time; /* jiffies of when lease was taken */ + struct kref refcount; + struct cifs_fid fid; +diff --git a/fs/smb/server/server.c b/fs/smb/server/server.c +index 80050b2178980a..598601a4bf92c7 100644 +--- a/fs/smb/server/server.c ++++ b/fs/smb/server/server.c +@@ -126,21 +126,21 @@ static int __process_request(struct ksmbd_work *work, struct ksmbd_conn *conn, + andx_again: + if (command >= conn->max_cmds) { + conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER); +- return SERVER_HANDLER_CONTINUE; ++ return SERVER_HANDLER_ABORT; + } + + cmds = &conn->cmds[command]; + if (!cmds->proc) { + ksmbd_debug(SMB, "*** not implemented yet cmd = %x\n", command); + conn->ops->set_rsp_status(work, STATUS_NOT_IMPLEMENTED); +- return SERVER_HANDLER_CONTINUE; ++ return SERVER_HANDLER_ABORT; + } + + if (work->sess && conn->ops->is_sign_req(work, command)) { + ret = conn->ops->check_sign_req(work); + if (!ret) { + conn->ops->set_rsp_status(work, STATUS_ACCESS_DENIED); +- return SERVER_HANDLER_CONTINUE; ++ return SERVER_HANDLER_ABORT; + } + } + +diff --git a/fs/smb/server/transport_tcp.c b/fs/smb/server/transport_tcp.c +index 08275db6446c2b..d05af46257cf4f 100644 +--- a/fs/smb/server/transport_tcp.c ++++ b/fs/smb/server/transport_tcp.c +@@ -41,6 +41,7 @@ static struct ksmbd_transport_ops ksmbd_tcp_transport_ops; + + static void tcp_stop_kthread(struct task_struct *kthread); + static struct interface *alloc_iface(char *ifname); ++static void ksmbd_tcp_disconnect(struct ksmbd_transport *t); + + #define KSMBD_TRANS(t) (&(t)->transport) + #define TCP_TRANS(t) ((struct tcp_transport *)container_of(t, \ +@@ -219,7 +220,7 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk) + if (IS_ERR(handler)) { + pr_err("cannot start conn thread\n"); + rc = PTR_ERR(handler); +- free_transport(t); ++ ksmbd_tcp_disconnect(KSMBD_TRANS(t)); + } + return rc; + +diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c +index 9f25cfd96f980f..4b805d7f5769f7 100644 +--- a/net/mptcp/pm_netlink.c ++++ b/net/mptcp/pm_netlink.c +@@ -1859,16 +1859,26 @@ static void __reset_counters(struct pm_nl_pernet *pernet) + static int mptcp_nl_cmd_flush_addrs(struct sk_buff *skb, struct genl_info *info) + { + struct pm_nl_pernet *pernet = genl_info_pm_nl(info); +- LIST_HEAD(free_list); ++ struct list_head free_list; + + spin_lock_bh(&pernet->lock); +- list_splice_init(&pernet->local_addr_list, &free_list); ++ free_list = pernet->local_addr_list; ++ INIT_LIST_HEAD_RCU(&pernet->local_addr_list); + __reset_counters(pernet); + pernet->next_id = 1; + bitmap_zero(pernet->id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1); + spin_unlock_bh(&pernet->lock); +- mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list); ++ ++ if (free_list.next == &pernet->local_addr_list) ++ return 0; ++ + synchronize_rcu(); ++ ++ /* Adjust the pointers to free_list instead of pernet->local_addr_list */ ++ free_list.prev->next = &free_list; ++ free_list.next->prev = &free_list; ++ ++ mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list); + __flush_addrs(&free_list); + return 0; + } +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 120d9bd53321ca..a0a5d19fa8506b 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -6615,7 +6615,7 @@ static int nft_setelem_catchall_insert(const struct net *net, + } + } + +- catchall = kmalloc(sizeof(*catchall), GFP_KERNEL); ++ catchall = kmalloc(sizeof(*catchall), GFP_KERNEL_ACCOUNT); + if (!catchall) + return -ENOMEM; + +diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c +index 52cdfee17f73f1..7ca4f0d21fe2a2 100644 +--- a/net/netfilter/nft_compat.c ++++ b/net/netfilter/nft_compat.c +@@ -535,7 +535,7 @@ nft_match_large_init(const struct nft_ctx *ctx, const struct nft_expr *expr, + struct xt_match *m = expr->ops->data; + int ret; + +- priv->info = kmalloc(XT_ALIGN(m->matchsize), GFP_KERNEL); ++ priv->info = kmalloc(XT_ALIGN(m->matchsize), GFP_KERNEL_ACCOUNT); + if (!priv->info) + return -ENOMEM; + +@@ -808,7 +808,7 @@ nft_match_select_ops(const struct nft_ctx *ctx, + goto err; + } + +- ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL); ++ ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL_ACCOUNT); + if (!ops) { + err = -ENOMEM; + goto err; +@@ -898,7 +898,7 @@ nft_target_select_ops(const struct nft_ctx *ctx, + goto err; + } + +- ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL); ++ ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL_ACCOUNT); + if (!ops) { + err = -ENOMEM; + goto err; +diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c +index 5defe6e4fd9820..e3558813799579 100644 +--- a/net/netfilter/nft_log.c ++++ b/net/netfilter/nft_log.c +@@ -163,7 +163,7 @@ static int nft_log_init(const struct nft_ctx *ctx, + + nla = tb[NFTA_LOG_PREFIX]; + if (nla != NULL) { +- priv->prefix = kmalloc(nla_len(nla) + 1, GFP_KERNEL); ++ priv->prefix = kmalloc(nla_len(nla) + 1, GFP_KERNEL_ACCOUNT); + if (priv->prefix == NULL) + return -ENOMEM; + nla_strscpy(priv->prefix, nla, nla_len(nla) + 1); +diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c +index 8c8eb14d647b07..05cd1e6e6a2f61 100644 +--- a/net/netfilter/nft_meta.c ++++ b/net/netfilter/nft_meta.c +@@ -952,7 +952,7 @@ static int nft_secmark_obj_init(const struct nft_ctx *ctx, + if (tb[NFTA_SECMARK_CTX] == NULL) + return -EINVAL; + +- priv->ctx = nla_strdup(tb[NFTA_SECMARK_CTX], GFP_KERNEL); ++ priv->ctx = nla_strdup(tb[NFTA_SECMARK_CTX], GFP_KERNEL_ACCOUNT); + if (!priv->ctx) + return -ENOMEM; + +diff --git a/net/netfilter/nft_numgen.c b/net/netfilter/nft_numgen.c +index 7d29db7c2ac0f0..bd058babfc820c 100644 +--- a/net/netfilter/nft_numgen.c ++++ b/net/netfilter/nft_numgen.c +@@ -66,7 +66,7 @@ static int nft_ng_inc_init(const struct nft_ctx *ctx, + if (priv->offset + priv->modulus - 1 < priv->offset) + return -EOVERFLOW; + +- priv->counter = kmalloc(sizeof(*priv->counter), GFP_KERNEL); ++ priv->counter = kmalloc(sizeof(*priv->counter), GFP_KERNEL_ACCOUNT); + if (!priv->counter) + return -ENOMEM; + +diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c +index ebd0f704c863c3..c3ada6798d4a3f 100644 +--- a/net/netfilter/nft_set_pipapo.c ++++ b/net/netfilter/nft_set_pipapo.c +@@ -610,6 +610,30 @@ static void *nft_pipapo_get(const struct net *net, const struct nft_set *set, + nft_genmask_cur(net), get_jiffies_64()); + } + ++ ++/** ++ * lt_calculate_size() - Get storage size for lookup table with overflow check ++ * @groups: Amount of bit groups ++ * @bb: Number of bits grouped together in lookup table buckets ++ * @bsize: Size of each bucket in lookup table, in longs ++ * ++ * Return: allocation size including alignment overhead, negative on overflow ++ */ ++static ssize_t lt_calculate_size(unsigned int groups, unsigned int bb, ++ unsigned int bsize) ++{ ++ ssize_t ret = groups * NFT_PIPAPO_BUCKETS(bb) * sizeof(long); ++ ++ if (check_mul_overflow(ret, bsize, &ret)) ++ return -1; ++ if (check_add_overflow(ret, NFT_PIPAPO_ALIGN_HEADROOM, &ret)) ++ return -1; ++ if (ret > INT_MAX) ++ return -1; ++ ++ return ret; ++} ++ + /** + * pipapo_resize() - Resize lookup or mapping table, or both + * @f: Field containing lookup and mapping tables +@@ -628,6 +652,7 @@ static int pipapo_resize(struct nft_pipapo_field *f, int old_rules, int rules) + union nft_pipapo_map_bucket *new_mt, *old_mt = f->mt; + size_t new_bucket_size, copy; + int group, bucket; ++ ssize_t lt_size; + + new_bucket_size = DIV_ROUND_UP(rules, BITS_PER_LONG); + #ifdef NFT_PIPAPO_ALIGN +@@ -643,10 +668,11 @@ static int pipapo_resize(struct nft_pipapo_field *f, int old_rules, int rules) + else + copy = new_bucket_size; + +- new_lt = kvzalloc(f->groups * NFT_PIPAPO_BUCKETS(f->bb) * +- new_bucket_size * sizeof(*new_lt) + +- NFT_PIPAPO_ALIGN_HEADROOM, +- GFP_KERNEL); ++ lt_size = lt_calculate_size(f->groups, f->bb, new_bucket_size); ++ if (lt_size < 0) ++ return -ENOMEM; ++ ++ new_lt = kvzalloc(lt_size, GFP_KERNEL_ACCOUNT); + if (!new_lt) + return -ENOMEM; + +@@ -845,7 +871,7 @@ static void pipapo_lt_bits_adjust(struct nft_pipapo_field *f) + { + unsigned long *new_lt; + int groups, bb; +- size_t lt_size; ++ ssize_t lt_size; + + lt_size = f->groups * NFT_PIPAPO_BUCKETS(f->bb) * f->bsize * + sizeof(*f->lt); +@@ -855,15 +881,17 @@ static void pipapo_lt_bits_adjust(struct nft_pipapo_field *f) + groups = f->groups * 2; + bb = NFT_PIPAPO_GROUP_BITS_LARGE_SET; + +- lt_size = groups * NFT_PIPAPO_BUCKETS(bb) * f->bsize * +- sizeof(*f->lt); ++ lt_size = lt_calculate_size(groups, bb, f->bsize); ++ if (lt_size < 0) ++ return; + } else if (f->bb == NFT_PIPAPO_GROUP_BITS_LARGE_SET && + lt_size < NFT_PIPAPO_LT_SIZE_LOW) { + groups = f->groups / 2; + bb = NFT_PIPAPO_GROUP_BITS_SMALL_SET; + +- lt_size = groups * NFT_PIPAPO_BUCKETS(bb) * f->bsize * +- sizeof(*f->lt); ++ lt_size = lt_calculate_size(groups, bb, f->bsize); ++ if (lt_size < 0) ++ return; + + /* Don't increase group width if the resulting lookup table size + * would exceed the upper size threshold for a "small" set. +@@ -874,7 +902,7 @@ static void pipapo_lt_bits_adjust(struct nft_pipapo_field *f) + return; + } + +- new_lt = kvzalloc(lt_size + NFT_PIPAPO_ALIGN_HEADROOM, GFP_KERNEL); ++ new_lt = kvzalloc(lt_size, GFP_KERNEL_ACCOUNT); + if (!new_lt) + return; + +@@ -1150,7 +1178,7 @@ static int pipapo_realloc_scratch(struct nft_pipapo_match *clone, + scratch = kzalloc_node(struct_size(scratch, map, + bsize_max * 2) + + NFT_PIPAPO_ALIGN_HEADROOM, +- GFP_KERNEL, cpu_to_node(i)); ++ GFP_KERNEL_ACCOUNT, cpu_to_node(i)); + if (!scratch) { + /* On failure, there's no need to undo previous + * allocations: this means that some scratch maps have +@@ -1323,7 +1351,7 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old) + struct nft_pipapo_match *new; + int i; + +- new = kmalloc(struct_size(new, f, old->field_count), GFP_KERNEL); ++ new = kmalloc(struct_size(new, f, old->field_count), GFP_KERNEL_ACCOUNT); + if (!new) + return ERR_PTR(-ENOMEM); + +@@ -1347,13 +1375,15 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old) + + for (i = 0; i < old->field_count; i++) { + unsigned long *new_lt; ++ ssize_t lt_size; + + memcpy(dst, src, offsetof(struct nft_pipapo_field, lt)); + +- new_lt = kvzalloc(src->groups * NFT_PIPAPO_BUCKETS(src->bb) * +- src->bsize * sizeof(*dst->lt) + +- NFT_PIPAPO_ALIGN_HEADROOM, +- GFP_KERNEL); ++ lt_size = lt_calculate_size(src->groups, src->bb, src->bsize); ++ if (lt_size < 0) ++ goto out_lt; ++ ++ new_lt = kvzalloc(lt_size, GFP_KERNEL_ACCOUNT); + if (!new_lt) + goto out_lt; + +@@ -1367,7 +1397,7 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old) + if (src->rules > (INT_MAX / sizeof(*src->mt))) + goto out_mt; + +- dst->mt = kvmalloc(src->rules * sizeof(*src->mt), GFP_KERNEL); ++ dst->mt = kvmalloc(src->rules * sizeof(*src->mt), GFP_KERNEL_ACCOUNT); + if (!dst->mt) + goto out_mt; + +diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c +index 3e3ae29dde3359..f77a5bf6991138 100644 +--- a/net/netfilter/nft_tunnel.c ++++ b/net/netfilter/nft_tunnel.c +@@ -503,13 +503,14 @@ static int nft_tunnel_obj_init(const struct nft_ctx *ctx, + return err; + } + +- md = metadata_dst_alloc(priv->opts.len, METADATA_IP_TUNNEL, GFP_KERNEL); ++ md = metadata_dst_alloc(priv->opts.len, METADATA_IP_TUNNEL, ++ GFP_KERNEL_ACCOUNT); + if (!md) + return -ENOMEM; + + memcpy(&md->u.tun_info, &info, sizeof(info)); + #ifdef CONFIG_DST_CACHE +- err = dst_cache_init(&md->u.tun_info.dst_cache, GFP_KERNEL); ++ err = dst_cache_init(&md->u.tun_info.dst_cache, GFP_KERNEL_ACCOUNT); + if (err < 0) { + metadata_dst_free(md); + return err; +diff --git a/tools/testing/selftests/net/mptcp/pm_netlink.sh b/tools/testing/selftests/net/mptcp/pm_netlink.sh +index 3528e730e4d37c..c089d4e06d5999 100755 +--- a/tools/testing/selftests/net/mptcp/pm_netlink.sh ++++ b/tools/testing/selftests/net/mptcp/pm_netlink.sh +@@ -127,6 +127,10 @@ id 8 flags signal 10.0.1.8" "id limit" + ip netns exec $ns1 ./pm_nl_ctl flush + check "ip netns exec $ns1 ./pm_nl_ctl dump" "" "flush addrs" + ++ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.1 flags unknown ++check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags 10.0.1.1" "ignore unknown flags" ++ip netns exec $ns1 ./pm_nl_ctl flush ++ + ip netns exec $ns1 ./pm_nl_ctl limits 9 1 2>/dev/null + check "ip netns exec $ns1 ./pm_nl_ctl limits" "$default_limits" "rcv addrs above hard limit" + +diff --git a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c +index 234c267dd2aad3..f586f1272bd784 100644 +--- a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c ++++ b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c +@@ -29,6 +29,8 @@ + #define IPPROTO_MPTCP 262 + #endif + ++#define MPTCP_PM_ADDR_FLAG_UNKNOWN _BITUL(7) ++ + static void syntax(char *argv[]) + { + fprintf(stderr, "%s add|ann|rem|csf|dsf|get|set|del|flush|dump|events|listen|accept []\n", argv[0]); +@@ -825,6 +827,8 @@ int add_addr(int fd, int pm_family, int argc, char *argv[]) + flags |= MPTCP_PM_ADDR_FLAG_BACKUP; + else if (!strcmp(tok, "fullmesh")) + flags |= MPTCP_PM_ADDR_FLAG_FULLMESH; ++ else if (!strcmp(tok, "unknown")) ++ flags |= MPTCP_PM_ADDR_FLAG_UNKNOWN; + else + error(1, errno, + "unknown flag %s", argv[arg]); +@@ -1030,6 +1034,13 @@ static void print_addr(struct rtattr *attrs, int len) + printf(","); + } + ++ if (flags & MPTCP_PM_ADDR_FLAG_UNKNOWN) { ++ printf("unknown"); ++ flags &= ~MPTCP_PM_ADDR_FLAG_UNKNOWN; ++ if (flags) ++ printf(","); ++ } ++ + /* bump unknown flags, if any */ + if (flags) + printf("0x%x", flags); +diff --git a/tools/testing/vsock/control.c b/tools/testing/vsock/control.c +index d2deb4b15b943c..0066e0324d35c6 100644 +--- a/tools/testing/vsock/control.c ++++ b/tools/testing/vsock/control.c +@@ -27,6 +27,7 @@ + + #include "timeout.h" + #include "control.h" ++#include "util.h" + + static int control_fd = -1; + +@@ -50,7 +51,6 @@ void control_init(const char *control_host, + + for (ai = result; ai; ai = ai->ai_next) { + int fd; +- int val = 1; + + fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (fd < 0) +@@ -65,11 +65,8 @@ void control_init(const char *control_host, + break; + } + +- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, +- &val, sizeof(val)) < 0) { +- perror("setsockopt"); +- exit(EXIT_FAILURE); +- } ++ setsockopt_int_check(fd, SOL_SOCKET, SO_REUSEADDR, 1, ++ "setsockopt SO_REUSEADDR"); + + if (bind(fd, ai->ai_addr, ai->ai_addrlen) < 0) + goto next; +diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c +index 751fe7c6632eac..e67e26636f5796 100644 +--- a/tools/testing/vsock/util.c ++++ b/tools/testing/vsock/util.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -420,3 +421,145 @@ unsigned long hash_djb2(const void *data, size_t len) + + return hash; + } ++ ++/* Set "unsigned long long" socket option and check that it's indeed set */ ++void setsockopt_ull_check(int fd, int level, int optname, ++ unsigned long long val, char const *errmsg) ++{ ++ unsigned long long chkval; ++ socklen_t chklen; ++ int err; ++ ++ err = setsockopt(fd, level, optname, &val, sizeof(val)); ++ if (err) { ++ fprintf(stderr, "setsockopt err: %s (%d)\n", ++ strerror(errno), errno); ++ goto fail; ++ } ++ ++ chkval = ~val; /* just make storage != val */ ++ chklen = sizeof(chkval); ++ ++ err = getsockopt(fd, level, optname, &chkval, &chklen); ++ if (err) { ++ fprintf(stderr, "getsockopt err: %s (%d)\n", ++ strerror(errno), errno); ++ goto fail; ++ } ++ ++ if (chklen != sizeof(chkval)) { ++ fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val), ++ chklen); ++ goto fail; ++ } ++ ++ if (chkval != val) { ++ fprintf(stderr, "value mismatch: set %llu got %llu\n", val, ++ chkval); ++ goto fail; ++ } ++ return; ++fail: ++ fprintf(stderr, "%s val %llu\n", errmsg, val); ++ exit(EXIT_FAILURE); ++; ++} ++ ++/* Set "int" socket option and check that it's indeed set */ ++void setsockopt_int_check(int fd, int level, int optname, int val, ++ char const *errmsg) ++{ ++ int chkval; ++ socklen_t chklen; ++ int err; ++ ++ err = setsockopt(fd, level, optname, &val, sizeof(val)); ++ if (err) { ++ fprintf(stderr, "setsockopt err: %s (%d)\n", ++ strerror(errno), errno); ++ goto fail; ++ } ++ ++ chkval = ~val; /* just make storage != val */ ++ chklen = sizeof(chkval); ++ ++ err = getsockopt(fd, level, optname, &chkval, &chklen); ++ if (err) { ++ fprintf(stderr, "getsockopt err: %s (%d)\n", ++ strerror(errno), errno); ++ goto fail; ++ } ++ ++ if (chklen != sizeof(chkval)) { ++ fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val), ++ chklen); ++ goto fail; ++ } ++ ++ if (chkval != val) { ++ fprintf(stderr, "value mismatch: set %d got %d\n", val, chkval); ++ goto fail; ++ } ++ return; ++fail: ++ fprintf(stderr, "%s val %d\n", errmsg, val); ++ exit(EXIT_FAILURE); ++} ++ ++static void mem_invert(unsigned char *mem, size_t size) ++{ ++ size_t i; ++ ++ for (i = 0; i < size; i++) ++ mem[i] = ~mem[i]; ++} ++ ++/* Set "timeval" socket option and check that it's indeed set */ ++void setsockopt_timeval_check(int fd, int level, int optname, ++ struct timeval val, char const *errmsg) ++{ ++ struct timeval chkval; ++ socklen_t chklen; ++ int err; ++ ++ err = setsockopt(fd, level, optname, &val, sizeof(val)); ++ if (err) { ++ fprintf(stderr, "setsockopt err: %s (%d)\n", ++ strerror(errno), errno); ++ goto fail; ++ } ++ ++ /* just make storage != val */ ++ chkval = val; ++ mem_invert((unsigned char *)&chkval, sizeof(chkval)); ++ chklen = sizeof(chkval); ++ ++ err = getsockopt(fd, level, optname, &chkval, &chklen); ++ if (err) { ++ fprintf(stderr, "getsockopt err: %s (%d)\n", ++ strerror(errno), errno); ++ goto fail; ++ } ++ ++ if (chklen != sizeof(chkval)) { ++ fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val), ++ chklen); ++ goto fail; ++ } ++ ++ if (memcmp(&chkval, &val, sizeof(val)) != 0) { ++ fprintf(stderr, "value mismatch: set %ld:%ld got %ld:%ld\n", ++ val.tv_sec, val.tv_usec, chkval.tv_sec, chkval.tv_usec); ++ goto fail; ++ } ++ return; ++fail: ++ fprintf(stderr, "%s val %ld:%ld\n", errmsg, val.tv_sec, val.tv_usec); ++ exit(EXIT_FAILURE); ++} ++ ++void enable_so_zerocopy_check(int fd) ++{ ++ setsockopt_int_check(fd, SOL_SOCKET, SO_ZEROCOPY, 1, ++ "setsockopt SO_ZEROCOPY"); ++} +diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h +index fb99208a95eab7..a05438851919c7 100644 +--- a/tools/testing/vsock/util.h ++++ b/tools/testing/vsock/util.h +@@ -50,4 +50,11 @@ void list_tests(const struct test_case *test_cases); + void skip_test(struct test_case *test_cases, size_t test_cases_len, + const char *test_id_str); + unsigned long hash_djb2(const void *data, size_t len); ++void setsockopt_ull_check(int fd, int level, int optname, ++ unsigned long long val, char const *errmsg); ++void setsockopt_int_check(int fd, int level, int optname, int val, ++ char const *errmsg); ++void setsockopt_timeval_check(int fd, int level, int optname, ++ struct timeval val, char const *errmsg); ++void enable_so_zerocopy_check(int fd); + #endif /* UTIL_H */ +diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c +index 793d688cd4da6d..01ad8cfa9bde37 100644 +--- a/tools/testing/vsock/vsock_test.c ++++ b/tools/testing/vsock/vsock_test.c +@@ -503,17 +503,13 @@ static void test_seqpacket_msg_bounds_server(const struct test_opts *opts) + + sock_buf_size = SOCK_BUF_SIZE; + +- if (setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE, +- &sock_buf_size, sizeof(sock_buf_size))) { +- perror("setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)"); +- exit(EXIT_FAILURE); +- } ++ setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE, ++ sock_buf_size, ++ "setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)"); + +- if (setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE, +- &sock_buf_size, sizeof(sock_buf_size))) { +- perror("setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)"); +- exit(EXIT_FAILURE); +- } ++ setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE, ++ sock_buf_size, ++ "setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)"); + + /* Ready to receive data. */ + control_writeln("SRVREADY"); +@@ -648,10 +644,8 @@ static void test_seqpacket_timeout_client(const struct test_opts *opts) + tv.tv_sec = RCVTIMEO_TIMEOUT_SEC; + tv.tv_usec = 0; + +- if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv)) == -1) { +- perror("setsockopt(SO_RCVTIMEO)"); +- exit(EXIT_FAILURE); +- } ++ setsockopt_timeval_check(fd, SOL_SOCKET, SO_RCVTIMEO, tv, ++ "setsockopt(SO_RCVTIMEO)"); + + read_enter_ns = current_nsec(); + +@@ -928,11 +922,8 @@ static void test_stream_poll_rcvlowat_client(const struct test_opts *opts) + exit(EXIT_FAILURE); + } + +- if (setsockopt(fd, SOL_SOCKET, SO_RCVLOWAT, +- &lowat_val, sizeof(lowat_val))) { +- perror("setsockopt(SO_RCVLOWAT)"); +- exit(EXIT_FAILURE); +- } ++ setsockopt_int_check(fd, SOL_SOCKET, SO_RCVLOWAT, ++ lowat_val, "setsockopt(SO_RCVLOWAT)"); + + control_expectln("SRVSENT"); + diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.125-126.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.125-126.patch new file mode 100644 index 0000000000..95c59b6314 --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.125-126.patch @@ -0,0 +1,62 @@ +diff --git a/Makefile b/Makefile +index 4a944e80769044..54c385978feed5 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 125 ++SUBLEVEL = 126 + EXTRAVERSION = + NAME = Pinguïn Aangedreven + +diff --git a/drivers/base/base.h b/drivers/base/base.h +index 35e14bebbfb2c2..0b491449b022a1 100644 +--- a/drivers/base/base.h ++++ b/drivers/base/base.h +@@ -165,18 +165,9 @@ void device_set_deferred_probe_reason(const struct device *dev, struct va_format + static inline int driver_match_device(struct device_driver *drv, + struct device *dev) + { +- device_lock_assert(dev); +- + return drv->bus->match ? drv->bus->match(dev, drv) : 1; + } + +-static inline int driver_match_device_locked(struct device_driver *drv, +- struct device *dev) +-{ +- guard(device)(dev); +- return driver_match_device(drv, dev); +-} +- + static inline void dev_sync_state(struct device *dev) + { + if (dev->bus->sync_state) +diff --git a/drivers/base/bus.c b/drivers/base/bus.c +index 27f8442a3aa9dd..b97e13a52c3308 100644 +--- a/drivers/base/bus.c ++++ b/drivers/base/bus.c +@@ -263,7 +263,7 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf, + int err = -ENODEV; + + dev = bus_find_device_by_name(bus, NULL, buf); +- if (dev && driver_match_device_locked(drv, dev)) { ++ if (dev && driver_match_device(drv, dev)) { + err = device_driver_attach(drv, dev); + if (!err) { + /* success */ +diff --git a/drivers/base/dd.c b/drivers/base/dd.c +index 07f1332dd3a440..7e2fb159bb895b 100644 +--- a/drivers/base/dd.c ++++ b/drivers/base/dd.c +@@ -1169,7 +1169,7 @@ static int __driver_attach(struct device *dev, void *data) + * is an error. + */ + +- ret = driver_match_device_locked(drv, dev); ++ ret = driver_match_device(drv, dev); + if (ret == 0) { + /* no match */ + return 0; diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.126-127.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.126-127.patch new file mode 100644 index 0000000000..43ae7e4072 --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.126-127.patch @@ -0,0 +1,2043 @@ +diff --git a/Makefile b/Makefile +index 54c385978feed5..b9c04d8271b94a 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 126 ++SUBLEVEL = 127 + EXTRAVERSION = + NAME = Pinguïn Aangedreven + +diff --git a/arch/loongarch/include/asm/addrspace.h b/arch/loongarch/include/asm/addrspace.h +index b24437e28c6eda..913981b835f4b1 100644 +--- a/arch/loongarch/include/asm/addrspace.h ++++ b/arch/loongarch/include/asm/addrspace.h +@@ -36,6 +36,10 @@ extern unsigned long vm_map_base; + #define UNCACHE_BASE CSR_DMW0_BASE + #endif + ++#ifndef WRITECOMBINE_BASE ++#define WRITECOMBINE_BASE CSR_DMW2_BASE ++#endif ++ + #define DMW_PABITS 48 + #define TO_PHYS_MASK ((1ULL << DMW_PABITS) - 1) + +diff --git a/arch/loongarch/include/asm/io.h b/arch/loongarch/include/asm/io.h +index 4a8adcca329b81..838db690b723a5 100644 +--- a/arch/loongarch/include/asm/io.h ++++ b/arch/loongarch/include/asm/io.h +@@ -30,10 +30,16 @@ extern void __init early_iounmap(void __iomem *addr, unsigned long size); + static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size, + unsigned long prot_val) + { +- if (prot_val & _CACHE_CC) ++ switch (prot_val & _CACHE_MASK) { ++ case _CACHE_CC: + return (void __iomem *)(unsigned long)(CACHE_BASE + offset); +- else ++ case _CACHE_SUC: + return (void __iomem *)(unsigned long)(UNCACHE_BASE + offset); ++ case _CACHE_WUC: ++ return (void __iomem *)(unsigned long)(WRITECOMBINE_BASE + offset); ++ default: ++ return NULL; ++ } + } + + #define ioremap(offset, size) \ +diff --git a/arch/loongarch/include/asm/kasan.h b/arch/loongarch/include/asm/kasan.h +index cb74a47f620e18..7f52bd31b9d4f5 100644 +--- a/arch/loongarch/include/asm/kasan.h ++++ b/arch/loongarch/include/asm/kasan.h +@@ -25,6 +25,7 @@ + /* 64-bit segment value. */ + #define XKPRANGE_UC_SEG (0x8000) + #define XKPRANGE_CC_SEG (0x9000) ++#define XKPRANGE_WC_SEG (0xa000) + #define XKVRANGE_VC_SEG (0xffff) + + /* Cached */ +@@ -41,10 +42,17 @@ + #define XKPRANGE_UC_SHADOW_SIZE (XKPRANGE_UC_SIZE >> KASAN_SHADOW_SCALE_SHIFT) + #define XKPRANGE_UC_SHADOW_END (XKPRANGE_UC_KASAN_OFFSET + XKPRANGE_UC_SHADOW_SIZE) + ++/* WriteCombine */ ++#define XKPRANGE_WC_START WRITECOMBINE_BASE ++#define XKPRANGE_WC_SIZE XRANGE_SIZE ++#define XKPRANGE_WC_KASAN_OFFSET XKPRANGE_UC_SHADOW_END ++#define XKPRANGE_WC_SHADOW_SIZE (XKPRANGE_WC_SIZE >> KASAN_SHADOW_SCALE_SHIFT) ++#define XKPRANGE_WC_SHADOW_END (XKPRANGE_WC_KASAN_OFFSET + XKPRANGE_WC_SHADOW_SIZE) ++ + /* VMALLOC (Cached or UnCached) */ + #define XKVRANGE_VC_START MODULES_VADDR + #define XKVRANGE_VC_SIZE round_up(KFENCE_AREA_END - MODULES_VADDR + 1, PGDIR_SIZE) +-#define XKVRANGE_VC_KASAN_OFFSET XKPRANGE_UC_SHADOW_END ++#define XKVRANGE_VC_KASAN_OFFSET XKPRANGE_WC_SHADOW_END + #define XKVRANGE_VC_SHADOW_SIZE (XKVRANGE_VC_SIZE >> KASAN_SHADOW_SCALE_SHIFT) + #define XKVRANGE_VC_SHADOW_END (XKVRANGE_VC_KASAN_OFFSET + XKVRANGE_VC_SHADOW_SIZE) + +@@ -55,6 +63,7 @@ + + #define XKPRANGE_CC_SHADOW_OFFSET (KASAN_SHADOW_START + XKPRANGE_CC_KASAN_OFFSET) + #define XKPRANGE_UC_SHADOW_OFFSET (KASAN_SHADOW_START + XKPRANGE_UC_KASAN_OFFSET) ++#define XKPRANGE_WC_SHADOW_OFFSET (KASAN_SHADOW_START + XKPRANGE_WC_KASAN_OFFSET) + #define XKVRANGE_VC_SHADOW_OFFSET (KASAN_SHADOW_START + XKVRANGE_VC_KASAN_OFFSET) + + extern bool kasan_early_stage; +diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h +index 2c996da6a5bf57..ce3fc1666868ee 100644 +--- a/arch/loongarch/include/asm/loongarch.h ++++ b/arch/loongarch/include/asm/loongarch.h +@@ -856,7 +856,7 @@ + #define LOONGARCH_CSR_DMWIN2 0x182 /* 64 direct map win2: MEM */ + #define LOONGARCH_CSR_DMWIN3 0x183 /* 64 direct map win3: MEM */ + +-/* Direct Map window 0/1 */ ++/* Direct Map window 0/1/2/3 */ + #define CSR_DMW0_PLV0 _CONST64_(1 << 0) + #define CSR_DMW0_VSEG _CONST64_(0x8000) + #define CSR_DMW0_BASE (CSR_DMW0_VSEG << DMW_PABITS) +@@ -868,6 +868,14 @@ + #define CSR_DMW1_BASE (CSR_DMW1_VSEG << DMW_PABITS) + #define CSR_DMW1_INIT (CSR_DMW1_BASE | CSR_DMW1_MAT | CSR_DMW1_PLV0) + ++#define CSR_DMW2_PLV0 _CONST64_(1 << 0) ++#define CSR_DMW2_MAT _CONST64_(2 << 4) ++#define CSR_DMW2_VSEG _CONST64_(0xa000) ++#define CSR_DMW2_BASE (CSR_DMW2_VSEG << DMW_PABITS) ++#define CSR_DMW2_INIT (CSR_DMW2_BASE | CSR_DMW2_MAT | CSR_DMW2_PLV0) ++ ++#define CSR_DMW3_INIT 0x0 ++ + /* Performance Counter registers */ + #define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */ + #define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */ +diff --git a/arch/loongarch/include/asm/stackframe.h b/arch/loongarch/include/asm/stackframe.h +index efc8c42290d019..35ba862f20252d 100644 +--- a/arch/loongarch/include/asm/stackframe.h ++++ b/arch/loongarch/include/asm/stackframe.h +@@ -37,6 +37,17 @@ + cfi_restore \reg \offset \docfi + .endm + ++ .macro SETUP_DMWINS temp ++ li.d \temp, CSR_DMW0_INIT # WUC, PLV0, 0x8000 xxxx xxxx xxxx ++ csrwr \temp, LOONGARCH_CSR_DMWIN0 ++ li.d \temp, CSR_DMW1_INIT # CAC, PLV0, 0x9000 xxxx xxxx xxxx ++ csrwr \temp, LOONGARCH_CSR_DMWIN1 ++ li.d \temp, CSR_DMW2_INIT # WUC, PLV0, 0xa000 xxxx xxxx xxxx ++ csrwr \temp, LOONGARCH_CSR_DMWIN2 ++ li.d \temp, CSR_DMW3_INIT # 0x0, unused ++ csrwr \temp, LOONGARCH_CSR_DMWIN3 ++ .endm ++ + /* Jump to the runtime virtual address. */ + .macro JUMP_VIRT_ADDR temp1 temp2 + li.d \temp1, CACHE_BASE +diff --git a/arch/loongarch/kernel/head.S b/arch/loongarch/kernel/head.S +index e336fbc4eb9675..841e51144945a6 100644 +--- a/arch/loongarch/kernel/head.S ++++ b/arch/loongarch/kernel/head.S +@@ -44,11 +44,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize); + SYM_CODE_START(kernel_entry) # kernel entry point + + /* Config direct window and set PG */ +- li.d t0, CSR_DMW0_INIT # UC, PLV0, 0x8000 xxxx xxxx xxxx +- csrwr t0, LOONGARCH_CSR_DMWIN0 +- li.d t0, CSR_DMW1_INIT # CA, PLV0, 0x9000 xxxx xxxx xxxx +- csrwr t0, LOONGARCH_CSR_DMWIN1 +- ++ SETUP_DMWINS t0 + JUMP_VIRT_ADDR t0, t1 + + /* Enable PG */ +@@ -119,11 +115,8 @@ SYM_CODE_END(kernel_entry) + * function after setting up the stack and tp registers. + */ + SYM_CODE_START(smpboot_entry) +- li.d t0, CSR_DMW0_INIT # UC, PLV0 +- csrwr t0, LOONGARCH_CSR_DMWIN0 +- li.d t0, CSR_DMW1_INIT # CA, PLV0 +- csrwr t0, LOONGARCH_CSR_DMWIN1 + ++ SETUP_DMWINS t0 + JUMP_VIRT_ADDR t0, t1 + + /* Enable PG */ +diff --git a/arch/loongarch/mm/kasan_init.c b/arch/loongarch/mm/kasan_init.c +index 082cb2a6f1ef24..40aea6c14ab11f 100644 +--- a/arch/loongarch/mm/kasan_init.c ++++ b/arch/loongarch/mm/kasan_init.c +@@ -42,36 +42,43 @@ static pgd_t kasan_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE); + + bool kasan_early_stage = true; + +-void *kasan_mem_to_shadow(const void *addr) ++static void *mem_to_shadow(const void *addr) + { +- if (!kasan_arch_is_ready()) { ++ unsigned long offset = 0; ++ unsigned long maddr = (unsigned long)addr; ++ unsigned long xrange = (maddr >> XRANGE_SHIFT) & 0xffff; ++ ++ if (maddr >= FIXADDR_START) + return (void *)(kasan_early_shadow_page); +- } else { +- unsigned long maddr = (unsigned long)addr; +- unsigned long xrange = (maddr >> XRANGE_SHIFT) & 0xffff; +- unsigned long offset = 0; +- +- if (maddr >= FIXADDR_START) +- return (void *)(kasan_early_shadow_page); +- +- maddr &= XRANGE_SHADOW_MASK; +- switch (xrange) { +- case XKPRANGE_CC_SEG: +- offset = XKPRANGE_CC_SHADOW_OFFSET; +- break; +- case XKPRANGE_UC_SEG: +- offset = XKPRANGE_UC_SHADOW_OFFSET; +- break; +- case XKVRANGE_VC_SEG: +- offset = XKVRANGE_VC_SHADOW_OFFSET; +- break; +- default: +- WARN_ON(1); +- return NULL; +- } + +- return (void *)((maddr >> KASAN_SHADOW_SCALE_SHIFT) + offset); ++ maddr &= XRANGE_SHADOW_MASK; ++ switch (xrange) { ++ case XKPRANGE_CC_SEG: ++ offset = XKPRANGE_CC_SHADOW_OFFSET; ++ break; ++ case XKPRANGE_UC_SEG: ++ offset = XKPRANGE_UC_SHADOW_OFFSET; ++ break; ++ case XKPRANGE_WC_SEG: ++ offset = XKPRANGE_WC_SHADOW_OFFSET; ++ break; ++ case XKVRANGE_VC_SEG: ++ offset = XKVRANGE_VC_SHADOW_OFFSET; ++ break; ++ default: ++ WARN_ON(1); ++ return NULL; + } ++ ++ return (void *)((maddr >> KASAN_SHADOW_SCALE_SHIFT) + offset); ++} ++ ++void *kasan_mem_to_shadow(const void *addr) ++{ ++ if (kasan_arch_is_ready()) ++ return mem_to_shadow(addr); ++ else ++ return (void *)(kasan_early_shadow_page); + } + + const void *kasan_shadow_to_mem(const void *shadow_addr) +@@ -86,6 +93,8 @@ const void *kasan_shadow_to_mem(const void *shadow_addr) + + if (addr >= XKVRANGE_VC_SHADOW_OFFSET) + return (void *)(((addr - XKVRANGE_VC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKVRANGE_VC_START); ++ else if (addr >= XKPRANGE_WC_SHADOW_OFFSET) ++ return (void *)(((addr - XKPRANGE_WC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_WC_START); + else if (addr >= XKPRANGE_UC_SHADOW_OFFSET) + return (void *)(((addr - XKPRANGE_UC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_UC_START); + else if (addr >= XKPRANGE_CC_SHADOW_OFFSET) +@@ -290,10 +299,8 @@ void __init kasan_init(void) + /* Maps everything to a single page of zeroes */ + kasan_pgd_populate(KASAN_SHADOW_START, KASAN_SHADOW_END, NUMA_NO_NODE, true); + +- kasan_populate_early_shadow(kasan_mem_to_shadow((void *)VMALLOC_START), +- kasan_mem_to_shadow((void *)KFENCE_AREA_END)); +- +- kasan_early_stage = false; ++ kasan_populate_early_shadow(mem_to_shadow((void *)VMALLOC_START), ++ mem_to_shadow((void *)KFENCE_AREA_END)); + + /* Populate the linear mapping */ + for_each_mem_range(i, &pa_start, &pa_end) { +@@ -303,13 +310,13 @@ void __init kasan_init(void) + if (start >= end) + break; + +- kasan_map_populate((unsigned long)kasan_mem_to_shadow(start), +- (unsigned long)kasan_mem_to_shadow(end), NUMA_NO_NODE); ++ kasan_map_populate((unsigned long)mem_to_shadow(start), ++ (unsigned long)mem_to_shadow(end), NUMA_NO_NODE); + } + + /* Populate modules mapping */ +- kasan_map_populate((unsigned long)kasan_mem_to_shadow((void *)MODULES_VADDR), +- (unsigned long)kasan_mem_to_shadow((void *)MODULES_END), NUMA_NO_NODE); ++ kasan_map_populate((unsigned long)mem_to_shadow((void *)MODULES_VADDR), ++ (unsigned long)mem_to_shadow((void *)MODULES_END), NUMA_NO_NODE); + /* + * KAsan may reuse the contents of kasan_early_shadow_pte directly, so we + * should make sure that it maps the zero page read-only. +@@ -324,5 +331,6 @@ void __init kasan_init(void) + + /* At this point kasan is fully initialized. Enable error messages */ + init_task.kasan_depth = 0; ++ kasan_early_stage = false; + pr_info("KernelAddressSanitizer initialized.\n"); + } +diff --git a/arch/loongarch/power/suspend_asm.S b/arch/loongarch/power/suspend_asm.S +index e2fc3b4e31f001..c28ad52b7bafba 100644 +--- a/arch/loongarch/power/suspend_asm.S ++++ b/arch/loongarch/power/suspend_asm.S +@@ -73,11 +73,7 @@ SYM_FUNC_START(loongarch_suspend_enter) + * Reload all of the registers and return. + */ + SYM_INNER_LABEL(loongarch_wakeup_start, SYM_L_GLOBAL) +- li.d t0, CSR_DMW0_INIT # UC, PLV0 +- csrwr t0, LOONGARCH_CSR_DMWIN0 +- li.d t0, CSR_DMW1_INIT # CA, PLV0 +- csrwr t0, LOONGARCH_CSR_DMWIN1 +- ++ SETUP_DMWINS t0 + JUMP_VIRT_ADDR t0, t1 + + /* Enable PG */ +diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c +index 03642df2df0bbf..8b421ef0580a78 100644 +--- a/drivers/bus/fsl-mc/fsl-mc-bus.c ++++ b/drivers/bus/fsl-mc/fsl-mc-bus.c +@@ -175,8 +175,8 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + { + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + +- return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor, +- mc_dev->obj_desc.type); ++ return sysfs_emit(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor, ++ mc_dev->obj_desc.type); + } + static DEVICE_ATTR_RO(modalias); + +@@ -201,8 +201,12 @@ static ssize_t driver_override_show(struct device *dev, + struct device_attribute *attr, char *buf) + { + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); ++ ssize_t len; + +- return snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override); ++ device_lock(dev); ++ len = sysfs_emit(buf, "%s\n", mc_dev->driver_override); ++ device_unlock(dev); ++ return len; + } + static DEVICE_ATTR_RW(driver_override); + +diff --git a/drivers/firmware/efi/libstub/loongarch.c b/drivers/firmware/efi/libstub/loongarch.c +index d0ef93551c44f6..3782d0a187d1f5 100644 +--- a/drivers/firmware/efi/libstub/loongarch.c ++++ b/drivers/firmware/efi/libstub/loongarch.c +@@ -74,6 +74,8 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, + /* Config Direct Mapping */ + csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0); + csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1); ++ csr_write64(CSR_DMW2_INIT, LOONGARCH_CSR_DMWIN2); ++ csr_write64(CSR_DMW3_INIT, LOONGARCH_CSR_DMWIN3); + + real_kernel_entry = (void *)kernel_entry_address(kernel_addr, image); + +diff --git a/drivers/gpio/gpio-sprd.c b/drivers/gpio/gpio-sprd.c +index c117c11bfb29a8..192f05a2c19c1c 100644 +--- a/drivers/gpio/gpio-sprd.c ++++ b/drivers/gpio/gpio-sprd.c +@@ -35,7 +35,7 @@ + struct sprd_gpio { + struct gpio_chip chip; + void __iomem *base; +- spinlock_t lock; ++ raw_spinlock_t lock; + int irq; + }; + +@@ -54,7 +54,7 @@ static void sprd_gpio_update(struct gpio_chip *chip, unsigned int offset, + unsigned long flags; + u32 tmp; + +- spin_lock_irqsave(&sprd_gpio->lock, flags); ++ raw_spin_lock_irqsave(&sprd_gpio->lock, flags); + tmp = readl_relaxed(base + reg); + + if (val) +@@ -63,7 +63,7 @@ static void sprd_gpio_update(struct gpio_chip *chip, unsigned int offset, + tmp &= ~BIT(SPRD_GPIO_BIT(offset)); + + writel_relaxed(tmp, base + reg); +- spin_unlock_irqrestore(&sprd_gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&sprd_gpio->lock, flags); + } + + static int sprd_gpio_read(struct gpio_chip *chip, unsigned int offset, u16 reg) +@@ -234,7 +234,7 @@ static int sprd_gpio_probe(struct platform_device *pdev) + if (IS_ERR(sprd_gpio->base)) + return PTR_ERR(sprd_gpio->base); + +- spin_lock_init(&sprd_gpio->lock); ++ raw_spin_lock_init(&sprd_gpio->lock); + + sprd_gpio->chip.label = dev_name(&pdev->dev); + sprd_gpio->chip.ngpio = SPRD_GPIO_NR; +diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c +index 69d4297ae57549..4d4757eac9e5fe 100644 +--- a/drivers/gpio/gpiolib-acpi.c ++++ b/drivers/gpio/gpiolib-acpi.c +@@ -1417,6 +1417,7 @@ static int acpi_gpio_package_count(const union acpi_object *obj) + while (element < end) { + switch (element->type) { + case ACPI_TYPE_LOCAL_REFERENCE: ++ case ACPI_TYPE_STRING: + element += 3; + fallthrough; + case ACPI_TYPE_INTEGER: +diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c +index 58c2ba94e7dd65..2451c9b67024d9 100644 +--- a/drivers/gpu/drm/tegra/hdmi.c ++++ b/drivers/gpu/drm/tegra/hdmi.c +@@ -656,7 +656,7 @@ static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, const void *data, + { + const u8 *ptr = data; + unsigned long offset; +- size_t i, j; ++ size_t i; + u32 value; + + switch (ptr[0]) { +@@ -689,7 +689,7 @@ static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, const void *data, + * - subpack_low: bytes 0 - 3 + * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00) + */ +- for (i = 3, j = 0; i < size; i += 7, j += 8) { ++ for (i = 3; i < size; i += 7) { + size_t rem = size - i, num = min_t(size_t, rem, 4); + + value = tegra_hdmi_subpack(&ptr[i], num); +diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c +index 61b437a84806ed..1b03f8ca80a10b 100644 +--- a/drivers/gpu/drm/tegra/sor.c ++++ b/drivers/gpu/drm/tegra/sor.c +@@ -1861,7 +1861,7 @@ static void tegra_sor_hdmi_write_infopack(struct tegra_sor *sor, + { + const u8 *ptr = data; + unsigned long offset; +- size_t i, j; ++ size_t i; + u32 value; + + switch (ptr[0]) { +@@ -1894,7 +1894,7 @@ static void tegra_sor_hdmi_write_infopack(struct tegra_sor *sor, + * - subpack_low: bytes 0 - 3 + * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00) + */ +- for (i = 3, j = 0; i < size; i += 7, j += 8) { ++ for (i = 3; i < size; i += 7) { + size_t rem = size - i, num = min_t(size_t, rem, 4); + + value = tegra_sor_hdmi_subpack(&ptr[i], num); +diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c +index 54767154de265c..cfbc0240126ef0 100644 +--- a/drivers/net/bareudp.c ++++ b/drivers/net/bareudp.c +@@ -319,7 +319,7 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev, + __be32 saddr; + int err; + +- if (!skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB))) ++ if (skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB))) + return -EINVAL; + + if (!sock) +@@ -385,7 +385,7 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev, + __be16 sport; + int err; + +- if (!skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB))) ++ if (skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB))) + return -EINVAL; + + if (!sock) +diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c +index 27761334e1bff7..33dae09f7fb220 100644 +--- a/drivers/net/geneve.c ++++ b/drivers/net/geneve.c +@@ -927,7 +927,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, + __be16 sport; + int err; + +- if (!skb_vlan_inet_prepare(skb, inner_proto_inherit)) ++ if (skb_vlan_inet_prepare(skb, inner_proto_inherit)) + return -EINVAL; + + sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); +@@ -1026,7 +1026,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, + __be16 sport; + int err; + +- if (!skb_vlan_inet_prepare(skb, inner_proto_inherit)) ++ if (skb_vlan_inet_prepare(skb, inner_proto_inherit)) + return -EINVAL; + + sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); +diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c +index f98e0f027a0542..deb9636b0ecf8f 100644 +--- a/drivers/net/wireguard/device.c ++++ b/drivers/net/wireguard/device.c +@@ -369,7 +369,6 @@ static int wg_newlink(struct net *src_net, struct net_device *dev, + if (ret < 0) + goto err_free_handshake_queue; + +- dev_set_threaded(dev, true); + ret = register_netdevice(dev); + if (ret < 0) + goto err_uninit_ratelimiter; +diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c +index c17dff4bd19b43..c28c3f094496a8 100644 +--- a/drivers/pci/endpoint/pci-ep-cfs.c ++++ b/drivers/pci/endpoint/pci-ep-cfs.c +@@ -23,8 +23,6 @@ struct pci_epf_group { + struct config_group group; + struct config_group primary_epc_group; + struct config_group secondary_epc_group; +- struct config_group *type_group; +- struct delayed_work cfs_work; + struct pci_epf *epf; + int index; + }; +@@ -101,7 +99,7 @@ static struct config_group + secondary_epc_group = &epf_group->secondary_epc_group; + config_group_init_type_name(secondary_epc_group, "secondary", + &pci_secondary_epc_type); +- configfs_register_group(&epf_group->group, secondary_epc_group); ++ configfs_add_default_group(secondary_epc_group, &epf_group->group); + + return secondary_epc_group; + } +@@ -161,7 +159,7 @@ static struct config_group + + config_group_init_type_name(primary_epc_group, "primary", + &pci_primary_epc_type); +- configfs_register_group(&epf_group->group, primary_epc_group); ++ configfs_add_default_group(primary_epc_group, &epf_group->group); + + return primary_epc_group; + } +@@ -562,15 +560,13 @@ static void pci_ep_cfs_add_type_group(struct pci_epf_group *epf_group) + return; + } + +- configfs_register_group(&epf_group->group, group); ++ configfs_add_default_group(group, &epf_group->group); + } + +-static void pci_epf_cfs_work(struct work_struct *work) ++static void pci_epf_cfs_add_sub_groups(struct pci_epf_group *epf_group) + { +- struct pci_epf_group *epf_group; + struct config_group *group; + +- epf_group = container_of(work, struct pci_epf_group, cfs_work.work); + group = pci_ep_cfs_add_primary_group(epf_group); + if (IS_ERR(group)) { + pr_err("failed to create 'primary' EPC interface\n"); +@@ -629,9 +625,7 @@ static struct config_group *pci_epf_make(struct config_group *group, + + kfree(epf_name); + +- INIT_DELAYED_WORK(&epf_group->cfs_work, pci_epf_cfs_work); +- queue_delayed_work(system_wq, &epf_group->cfs_work, +- msecs_to_jiffies(1)); ++ pci_epf_cfs_add_sub_groups(epf_group); + + return &epf_group->group; + +diff --git a/drivers/platform/x86/amd/pmc/pmc-quirks.c b/drivers/platform/x86/amd/pmc/pmc-quirks.c +index a5031339dac8c9..a6006b4ec2cc08 100644 +--- a/drivers/platform/x86/amd/pmc/pmc-quirks.c ++++ b/drivers/platform/x86/amd/pmc/pmc-quirks.c +@@ -296,6 +296,13 @@ static const struct dmi_system_id fwbug_list[] = { + DMI_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"), + } + }, ++ { ++ .ident = "MECHREVO Wujie 15X Pro", ++ .driver_data = &quirk_spurious_8042, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "WUJIE Series-X5SP4NAG"), ++ } ++ }, + {} + }; + +diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c +index 2edaea2492df73..053c8a86d5ece4 100644 +--- a/drivers/platform/x86/classmate-laptop.c ++++ b/drivers/platform/x86/classmate-laptop.c +@@ -208,7 +208,12 @@ static ssize_t cmpc_accel_sensitivity_show_v4(struct device *dev, + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); ++ if (!inputdev) ++ return -ENXIO; ++ + accel = dev_get_drvdata(&inputdev->dev); ++ if (!accel) ++ return -ENXIO; + + return sprintf(buf, "%d\n", accel->sensitivity); + } +@@ -225,7 +230,12 @@ static ssize_t cmpc_accel_sensitivity_store_v4(struct device *dev, + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); ++ if (!inputdev) ++ return -ENXIO; ++ + accel = dev_get_drvdata(&inputdev->dev); ++ if (!accel) ++ return -ENXIO; + + r = kstrtoul(buf, 0, &sensitivity); + if (r) +@@ -257,7 +267,12 @@ static ssize_t cmpc_accel_g_select_show_v4(struct device *dev, + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); ++ if (!inputdev) ++ return -ENXIO; ++ + accel = dev_get_drvdata(&inputdev->dev); ++ if (!accel) ++ return -ENXIO; + + return sprintf(buf, "%d\n", accel->g_select); + } +@@ -274,7 +289,12 @@ static ssize_t cmpc_accel_g_select_store_v4(struct device *dev, + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); ++ if (!inputdev) ++ return -ENXIO; ++ + accel = dev_get_drvdata(&inputdev->dev); ++ if (!accel) ++ return -ENXIO; + + r = kstrtoul(buf, 0, &g_select); + if (r) +@@ -303,6 +323,8 @@ static int cmpc_accel_open_v4(struct input_dev *input) + + acpi = to_acpi_device(input->dev.parent); + accel = dev_get_drvdata(&input->dev); ++ if (!accel) ++ return -ENXIO; + + cmpc_accel_set_sensitivity_v4(acpi->handle, accel->sensitivity); + cmpc_accel_set_g_select_v4(acpi->handle, accel->g_select); +@@ -551,7 +573,12 @@ static ssize_t cmpc_accel_sensitivity_show(struct device *dev, + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); ++ if (!inputdev) ++ return -ENXIO; ++ + accel = dev_get_drvdata(&inputdev->dev); ++ if (!accel) ++ return -ENXIO; + + return sprintf(buf, "%d\n", accel->sensitivity); + } +@@ -568,7 +595,12 @@ static ssize_t cmpc_accel_sensitivity_store(struct device *dev, + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); ++ if (!inputdev) ++ return -ENXIO; ++ + accel = dev_get_drvdata(&inputdev->dev); ++ if (!accel) ++ return -ENXIO; + + r = kstrtoul(buf, 0, &sensitivity); + if (r) +diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c +index 7365286f6d2dc1..ad907c558997a4 100644 +--- a/drivers/platform/x86/panasonic-laptop.c ++++ b/drivers/platform/x86/panasonic-laptop.c +@@ -1077,7 +1077,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device) + PLATFORM_DEVID_NONE, NULL, 0); + if (IS_ERR(pcc->platform)) { + result = PTR_ERR(pcc->platform); +- goto out_backlight; ++ goto out_sysfs; + } + result = device_create_file(&pcc->platform->dev, + &dev_attr_cdpower); +@@ -1093,6 +1093,8 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device) + + out_platform: + platform_device_unregister(pcc->platform); ++out_sysfs: ++ sysfs_remove_group(&device->dev.kobj, &pcc_attr_group); + out_backlight: + backlight_device_unregister(pcc->backlight); + out_input: +diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c +index 10431a67d202bb..f43969ed87bf9e 100644 +--- a/drivers/scsi/qla2xxx/qla_bsg.c ++++ b/drivers/scsi/qla2xxx/qla_bsg.c +@@ -1546,8 +1546,9 @@ qla2x00_update_optrom(struct bsg_job *bsg_job) + ha->optrom_buffer = NULL; + ha->optrom_state = QLA_SWAITING; + mutex_unlock(&ha->optrom_mutex); +- bsg_job_done(bsg_job, bsg_reply->result, +- bsg_reply->reply_payload_rcv_len); ++ if (!rval) ++ bsg_job_done(bsg_job, bsg_reply->result, ++ bsg_reply->reply_payload_rcv_len); + return rval; + } + +@@ -2612,8 +2613,9 @@ qla2x00_manage_host_stats(struct bsg_job *bsg_job) + sizeof(struct ql_vnd_mng_host_stats_resp)); + + bsg_reply->result = DID_OK; +- bsg_job_done(bsg_job, bsg_reply->result, +- bsg_reply->reply_payload_rcv_len); ++ if (!ret) ++ bsg_job_done(bsg_job, bsg_reply->result, ++ bsg_reply->reply_payload_rcv_len); + + return ret; + } +@@ -2702,8 +2704,9 @@ qla2x00_get_host_stats(struct bsg_job *bsg_job) + bsg_job->reply_payload.sg_cnt, + data, response_len); + bsg_reply->result = DID_OK; +- bsg_job_done(bsg_job, bsg_reply->result, +- bsg_reply->reply_payload_rcv_len); ++ if (!ret) ++ bsg_job_done(bsg_job, bsg_reply->result, ++ bsg_reply->reply_payload_rcv_len); + + kfree(data); + host_stat_out: +@@ -2802,8 +2805,9 @@ reply: + bsg_job->reply_payload.sg_cnt, data, + response_len); + bsg_reply->result = DID_OK; +- bsg_job_done(bsg_job, bsg_reply->result, +- bsg_reply->reply_payload_rcv_len); ++ if (!ret) ++ bsg_job_done(bsg_job, bsg_reply->result, ++ bsg_reply->reply_payload_rcv_len); + + tgt_stat_out: + kfree(data); +@@ -2864,8 +2868,9 @@ qla2x00_manage_host_port(struct bsg_job *bsg_job) + bsg_job->reply_payload.sg_cnt, &rsp_data, + sizeof(struct ql_vnd_mng_host_port_resp)); + bsg_reply->result = DID_OK; +- bsg_job_done(bsg_job, bsg_reply->result, +- bsg_reply->reply_payload_rcv_len); ++ if (!ret) ++ bsg_job_done(bsg_job, bsg_reply->result, ++ bsg_reply->reply_payload_rcv_len); + + return ret; + } +@@ -3240,7 +3245,8 @@ int qla2x00_mailbox_passthru(struct bsg_job *bsg_job) + + bsg_job->reply_len = sizeof(*bsg_job->reply); + bsg_reply->result = DID_OK << 16; +- bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); ++ if (!ret) ++ bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); + + kfree(req_data); + +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index 60993836cf91cf..58f34c8d2b84ac 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -1401,12 +1401,16 @@ static const struct usb_device_id option_ids[] = { + .driver_info = NCTRL(0) | RSVD(1) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a0, 0xff), /* Telit FN20C04 (rmnet) */ + .driver_info = RSVD(0) | NCTRL(3) }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a1, 0xff), /* Telit FN20C04 (RNDIS) */ ++ .driver_info = NCTRL(4) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a2, 0xff), /* Telit FN920C04 (MBIM) */ + .driver_info = NCTRL(4) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a3, 0xff), /* Telit FN920C04 (ECM) */ + .driver_info = NCTRL(4) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a4, 0xff), /* Telit FN20C04 (rmnet) */ + .driver_info = RSVD(0) | NCTRL(3) }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a6, 0xff), /* Telit FN920C04 (RNDIS) */ ++ .driver_info = NCTRL(4) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a7, 0xff), /* Telit FN920C04 (MBIM) */ + .driver_info = NCTRL(4) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a8, 0xff), /* Telit FN920C04 (ECM) */ +@@ -1415,6 +1419,8 @@ static const struct usb_device_id option_ids[] = { + .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10aa, 0xff), /* Telit FN920C04 (MBIM) */ + .driver_info = NCTRL(3) | RSVD(4) | RSVD(5) }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10ab, 0xff), /* Telit FN920C04 (RNDIS) */ ++ .driver_info = NCTRL(3) | RSVD(4) | RSVD(5) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b0, 0xff, 0xff, 0x30), /* Telit FE990B (rmnet) */ + .driver_info = NCTRL(5) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b0, 0xff, 0xff, 0x40) }, +diff --git a/drivers/video/fbdev/riva/riva_hw.c b/drivers/video/fbdev/riva/riva_hw.c +index 8b829b7200642f..f292079566cfca 100644 +--- a/drivers/video/fbdev/riva/riva_hw.c ++++ b/drivers/video/fbdev/riva/riva_hw.c +@@ -436,6 +436,9 @@ static char nv3_arb(nv3_fifo_info * res_info, nv3_sim_state * state, nv3_arb_in + vmisses = 2; + eburst_size = state->memory_width * 1; + mburst_size = 32; ++ if (!state->mclk_khz) ++ return (0); ++ + gns = 1000000 * (gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz; + ainfo->by_gfacc = gns*ainfo->gdrain_rate/1000000; + ainfo->wcmocc = 0; +diff --git a/drivers/video/fbdev/smscufx.c b/drivers/video/fbdev/smscufx.c +index 387d18706fecfe..b590763b01089e 100644 +--- a/drivers/video/fbdev/smscufx.c ++++ b/drivers/video/fbdev/smscufx.c +@@ -988,7 +988,6 @@ static int ufx_ops_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) + { + struct ufx_data *dev = info->par; +- struct dloarea *area = NULL; + + if (!atomic_read(&dev->usb_active)) + return 0; +@@ -1003,6 +1002,10 @@ static int ufx_ops_ioctl(struct fb_info *info, unsigned int cmd, + + /* TODO: Help propose a standard fb.h ioctl to report mmap damage */ + if (cmd == UFX_IOCTL_REPORT_DAMAGE) { ++ struct dloarea *area __free(kfree) = kmalloc(sizeof(*area), GFP_KERNEL); ++ if (!area) ++ return -ENOMEM; ++ + /* If we have a damage-aware client, turn fb_defio "off" + * To avoid perf imact of unnecessary page fault handling. + * Done by resetting the delay for this fb_info to a very +@@ -1012,7 +1015,8 @@ static int ufx_ops_ioctl(struct fb_info *info, unsigned int cmd, + if (info->fbdefio) + info->fbdefio->delay = UFX_DEFIO_WRITE_DISABLE; + +- area = (struct dloarea *)arg; ++ if (copy_from_user(area, (u8 __user *)arg, sizeof(*area))) ++ return -EFAULT; + + if (area->x < 0) + area->x = 0; +diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c +index c863e27fd846b3..44f6be3ea11a70 100644 +--- a/fs/f2fs/data.c ++++ b/fs/f2fs/data.c +@@ -358,14 +358,20 @@ static void f2fs_write_end_io(struct bio *bio) + page->index != nid_of_node(page)); + + dec_page_count(sbi, type); ++ ++ /* ++ * we should access sbi before end_page_writeback() to ++ * avoid racing w/ kill_f2fs_super() ++ */ ++ if (type == F2FS_WB_CP_DATA && !get_pages(sbi, type) && ++ wq_has_sleeper(&sbi->cp_wait)) ++ wake_up(&sbi->cp_wait); ++ + if (f2fs_in_warm_node_list(sbi, page)) + f2fs_del_fsync_node_entry(sbi, page); + clear_page_private_gcing(page); + end_page_writeback(page); + } +- if (!get_pages(sbi, F2FS_WB_CP_DATA) && +- wq_has_sleeper(&sbi->cp_wait)) +- wake_up(&sbi->cp_wait); + + bio_put(bio); + } +@@ -3934,6 +3940,7 @@ static int check_swap_activate(struct swap_info_struct *sis, + + while (cur_lblock < last_lblock && cur_lblock < sis->max) { + struct f2fs_map_blocks map; ++ bool last_extent = false; + retry: + cond_resched(); + +@@ -3959,11 +3966,10 @@ retry: + pblock = map.m_pblk; + nr_pblocks = map.m_len; + +- if ((pblock - SM_I(sbi)->main_blkaddr) % blks_per_sec || +- nr_pblocks % blks_per_sec || +- !f2fs_valid_pinned_area(sbi, pblock)) { +- bool last_extent = false; +- ++ if (!last_extent && ++ ((pblock - SM_I(sbi)->main_blkaddr) % blks_per_sec || ++ nr_pblocks % blks_per_sec || ++ !f2fs_valid_pinned_area(sbi, pblock))) { + not_aligned++; + + nr_pblocks = roundup(nr_pblocks, blks_per_sec); +@@ -3984,8 +3990,8 @@ retry: + goto out; + } + +- if (!last_extent) +- goto retry; ++ /* lookup block mapping info after block migration */ ++ goto retry; + } + + if (cur_lblock + nr_pblocks >= sis->max) +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index 9a4eabd11c7340..d7afa8bc0ff8e2 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -1567,6 +1567,7 @@ struct f2fs_sb_info { + + #ifdef CONFIG_BLK_DEV_ZONED + unsigned int blocks_per_blkz; /* F2FS blocks per zone */ ++ unsigned int max_open_zones; /* max open zone resources of the zoned device */ + #endif + + /* for node-related operations */ +diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c +index e9904158241460..8122135bb1fff0 100644 +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -1998,6 +1998,7 @@ int f2fs_gc_range(struct f2fs_sb_info *sbi, + unsigned int segno; + unsigned int gc_secs = dry_run_sections; + ++ stat_inc_gc_call_count(sbi, FOREGROUND); + for (segno = start_seg; segno <= end_seg; segno += SEGS_PER_SEC(sbi)) { + struct gc_inode_list gc_list = { + .ilist = LIST_HEAD_INIT(gc_list.ilist), +diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c +index 1b404937743cf3..133141f10d94da 100644 +--- a/fs/f2fs/node.c ++++ b/fs/f2fs/node.c +@@ -1696,8 +1696,13 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, + goto redirty_out; + } + +- if (atomic && !test_opt(sbi, NOBARRIER) && !f2fs_sb_has_blkzoned(sbi)) +- fio.op_flags |= REQ_PREFLUSH | REQ_FUA; ++ if (atomic) { ++ if (!test_opt(sbi, NOBARRIER) && !f2fs_sb_has_blkzoned(sbi)) ++ fio.op_flags |= REQ_PREFLUSH | REQ_FUA; ++ if (IS_INODE(page)) ++ set_dentry_mark(page, ++ f2fs_need_dentry_mark(sbi, ino_of_node(page))); ++ } + + /* should add to global list before clearing PAGECACHE status */ + if (f2fs_in_warm_node_list(sbi, page)) { +@@ -1852,8 +1857,9 @@ continue_unlock: + if (is_inode_flag_set(inode, + FI_DIRTY_INODE)) + f2fs_update_inode(inode, page); +- set_dentry_mark(page, +- f2fs_need_dentry_mark(sbi, ino)); ++ if (!atomic) ++ set_dentry_mark(page, ++ f2fs_need_dentry_mark(sbi, ino)); + } + /* may be written by other thread */ + if (!PageDirty(page)) +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index dd6cd014fefb03..9bd71d68cd95c2 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -2359,6 +2359,17 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) + if (err) + goto restore_opts; + ++#ifdef CONFIG_BLK_DEV_ZONED ++ if (f2fs_sb_has_blkzoned(sbi) && ++ sbi->max_open_zones < F2FS_OPTION(sbi).active_logs) { ++ f2fs_err(sbi, ++ "zoned: max open zones %u is too small, need at least %u open zones", ++ sbi->max_open_zones, F2FS_OPTION(sbi).active_logs); ++ err = -EINVAL; ++ goto restore_opts; ++ } ++#endif ++ + /* flush outstanding errors before changing fs state */ + flush_work(&sbi->s_error_work); + +@@ -3902,11 +3913,24 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi) + sector_t nr_sectors = bdev_nr_sectors(bdev); + struct f2fs_report_zones_args rep_zone_arg; + u64 zone_sectors; ++ unsigned int max_open_zones; + int ret; + + if (!f2fs_sb_has_blkzoned(sbi)) + return 0; + ++ if (bdev_is_zoned(FDEV(devi).bdev)) { ++ max_open_zones = bdev_max_open_zones(bdev); ++ if (max_open_zones && (max_open_zones < sbi->max_open_zones)) ++ sbi->max_open_zones = max_open_zones; ++ if (sbi->max_open_zones < F2FS_OPTION(sbi).active_logs) { ++ f2fs_err(sbi, ++ "zoned: max open zones %u is too small, need at least %u open zones", ++ sbi->max_open_zones, F2FS_OPTION(sbi).active_logs); ++ return -EINVAL; ++ } ++ } ++ + zone_sectors = bdev_zone_sectors(bdev); + if (sbi->blocks_per_blkz && sbi->blocks_per_blkz != + SECTOR_TO_BLOCK(zone_sectors)) +@@ -4188,6 +4212,9 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi) + + logical_blksize = bdev_logical_block_size(sbi->sb->s_bdev); + sbi->aligned_blksize = true; ++#ifdef CONFIG_BLK_DEV_ZONED ++ sbi->max_open_zones = UINT_MAX; ++#endif + + for (i = 0; i < max_devices; i++) { + if (i == 0) +diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c +index c4b0661888a159..436bbf23f8e7c6 100644 +--- a/fs/f2fs/sysfs.c ++++ b/fs/f2fs/sysfs.c +@@ -58,6 +58,7 @@ struct f2fs_attr { + const char *buf, size_t len); + int struct_type; + int offset; ++ int size; + int id; + }; + +@@ -285,11 +286,30 @@ static ssize_t main_blkaddr_show(struct f2fs_attr *a, + (unsigned long long)MAIN_BLKADDR(sbi)); + } + ++static ssize_t __sbi_show_value(struct f2fs_attr *a, ++ struct f2fs_sb_info *sbi, char *buf, ++ unsigned char *value) ++{ ++ switch (a->size) { ++ case 1: ++ return sysfs_emit(buf, "%u\n", *(u8 *)value); ++ case 2: ++ return sysfs_emit(buf, "%u\n", *(u16 *)value); ++ case 4: ++ return sysfs_emit(buf, "%u\n", *(u32 *)value); ++ case 8: ++ return sysfs_emit(buf, "%llu\n", *(u64 *)value); ++ default: ++ f2fs_bug_on(sbi, 1); ++ return sysfs_emit(buf, ++ "show sysfs node value with wrong type\n"); ++ } ++} ++ + static ssize_t f2fs_sbi_show(struct f2fs_attr *a, + struct f2fs_sb_info *sbi, char *buf) + { + unsigned char *ptr = NULL; +- unsigned int *ui; + + ptr = __struct_ptr(sbi, a->struct_type); + if (!ptr) +@@ -372,9 +392,30 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a, + atomic_read(&sbi->cp_call_count[BACKGROUND])); + #endif + +- ui = (unsigned int *)(ptr + a->offset); ++ return __sbi_show_value(a, sbi, buf, ptr + a->offset); ++} + +- return sysfs_emit(buf, "%u\n", *ui); ++static void __sbi_store_value(struct f2fs_attr *a, ++ struct f2fs_sb_info *sbi, ++ unsigned char *ui, unsigned long value) ++{ ++ switch (a->size) { ++ case 1: ++ *(u8 *)ui = value; ++ break; ++ case 2: ++ *(u16 *)ui = value; ++ break; ++ case 4: ++ *(u32 *)ui = value; ++ break; ++ case 8: ++ *(u64 *)ui = value; ++ break; ++ default: ++ f2fs_bug_on(sbi, 1); ++ f2fs_err(sbi, "store sysfs node value with wrong type"); ++ } + } + + static ssize_t __sbi_store(struct f2fs_attr *a, +@@ -746,7 +787,7 @@ out: + return count; + } + +- *ui = (unsigned int)t; ++ __sbi_store_value(a, sbi, ptr + a->offset, t); + + return count; + } +@@ -860,24 +901,27 @@ static struct f2fs_attr f2fs_attr_sb_##_name = { \ + .id = F2FS_FEATURE_##_feat, \ + } + +-#define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \ ++#define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset, _size) \ + static struct f2fs_attr f2fs_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .show = _show, \ + .store = _store, \ + .struct_type = _struct_type, \ +- .offset = _offset \ ++ .offset = _offset, \ ++ .size = _size \ + } + + #define F2FS_RO_ATTR(struct_type, struct_name, name, elname) \ + F2FS_ATTR_OFFSET(struct_type, name, 0444, \ + f2fs_sbi_show, NULL, \ +- offsetof(struct struct_name, elname)) ++ offsetof(struct struct_name, elname), \ ++ sizeof_field(struct struct_name, elname)) + + #define F2FS_RW_ATTR(struct_type, struct_name, name, elname) \ + F2FS_ATTR_OFFSET(struct_type, name, 0644, \ + f2fs_sbi_show, f2fs_sbi_store, \ +- offsetof(struct struct_name, elname)) ++ offsetof(struct struct_name, elname), \ ++ sizeof_field(struct struct_name, elname)) + + #define F2FS_GENERAL_RO_ATTR(name) \ + static struct f2fs_attr f2fs_attr_##name = __ATTR(name, 0444, name##_show, NULL) +diff --git a/fs/romfs/super.c b/fs/romfs/super.c +index b1bdfbc211c3c0..82975173dcb04e 100644 +--- a/fs/romfs/super.c ++++ b/fs/romfs/super.c +@@ -467,7 +467,10 @@ static int romfs_fill_super(struct super_block *sb, struct fs_context *fc) + + #ifdef CONFIG_BLOCK + if (!sb->s_mtd) { +- sb_set_blocksize(sb, ROMBSIZE); ++ if (!sb_set_blocksize(sb, ROMBSIZE)) { ++ errorf(fc, "romfs: unable to set blocksize\n"); ++ return -EINVAL; ++ } + } else { + sb->s_blocksize = ROMBSIZE; + sb->s_blocksize_bits = blksize_bits(ROMBSIZE); +diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h +index 129a3a75997659..f9eae152bd53a3 100644 +--- a/include/asm-generic/tlb.h ++++ b/include/asm-generic/tlb.h +@@ -46,7 +46,8 @@ + * + * The mmu_gather API consists of: + * +- * - tlb_gather_mmu() / tlb_gather_mmu_fullmm() / tlb_finish_mmu() ++ * - tlb_gather_mmu() / tlb_gather_mmu_fullmm() / tlb_gather_mmu_vma() / ++ * tlb_finish_mmu() + * + * start and finish a mmu_gather + * +@@ -337,6 +338,20 @@ struct mmu_gather { + unsigned int vma_huge : 1; + unsigned int vma_pfn : 1; + ++ /* ++ * Did we unshare (unmap) any shared page tables? For now only ++ * used for hugetlb PMD table sharing. ++ */ ++ unsigned int unshared_tables : 1; ++ ++ /* ++ * Did we unshare any page tables such that they are now exclusive ++ * and could get reused+modified by the new owner? When setting this ++ * flag, "unshared_tables" will be set as well. For now only used ++ * for hugetlb PMD table sharing. ++ */ ++ unsigned int fully_unshared_tables : 1; ++ + unsigned int batch_count; + + #ifndef CONFIG_MMU_GATHER_NO_GATHER +@@ -373,6 +388,7 @@ static inline void __tlb_reset_range(struct mmu_gather *tlb) + tlb->cleared_pmds = 0; + tlb->cleared_puds = 0; + tlb->cleared_p4ds = 0; ++ tlb->unshared_tables = 0; + /* + * Do not reset mmu_gather::vma_* fields here, we do not + * call into tlb_start_vma() again to set them if there is an +@@ -452,7 +468,7 @@ static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb) + * these bits. + */ + if (!(tlb->freed_tables || tlb->cleared_ptes || tlb->cleared_pmds || +- tlb->cleared_puds || tlb->cleared_p4ds)) ++ tlb->cleared_puds || tlb->cleared_p4ds || tlb->unshared_tables)) + return; + + tlb_flush(tlb); +@@ -718,6 +734,63 @@ static inline bool huge_pmd_needs_flush(pmd_t oldpmd, pmd_t newpmd) + } + #endif + ++#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING ++static inline void tlb_unshare_pmd_ptdesc(struct mmu_gather *tlb, struct ptdesc *pt, ++ unsigned long addr) ++{ ++ /* ++ * The caller must make sure that concurrent unsharing + exclusive ++ * reuse is impossible until tlb_flush_unshared_tables() was called. ++ */ ++ VM_WARN_ON_ONCE(!ptdesc_pmd_is_shared(pt)); ++ ptdesc_pmd_pts_dec(pt); ++ ++ /* Clearing a PUD pointing at a PMD table with PMD leaves. */ ++ tlb_flush_pmd_range(tlb, addr & PUD_MASK, PUD_SIZE); ++ ++ /* ++ * If the page table is now exclusively owned, we fully unshared ++ * a page table. ++ */ ++ if (!ptdesc_pmd_is_shared(pt)) ++ tlb->fully_unshared_tables = true; ++ tlb->unshared_tables = true; ++} ++ ++static inline void tlb_flush_unshared_tables(struct mmu_gather *tlb) ++{ ++ /* ++ * As soon as the caller drops locks to allow for reuse of ++ * previously-shared tables, these tables could get modified and ++ * even reused outside of hugetlb context, so we have to make sure that ++ * any page table walkers (incl. TLB, GUP-fast) are aware of that ++ * change. ++ * ++ * Even if we are not fully unsharing a PMD table, we must ++ * flush the TLB for the unsharer now. ++ */ ++ if (tlb->unshared_tables) ++ tlb_flush_mmu_tlbonly(tlb); ++ ++ /* ++ * Similarly, we must make sure that concurrent GUP-fast will not ++ * walk previously-shared page tables that are getting modified+reused ++ * elsewhere. So broadcast an IPI to wait for any concurrent GUP-fast. ++ * ++ * We only perform this when we are the last sharer of a page table, ++ * as the IPI will reach all CPUs: any GUP-fast. ++ * ++ * Note that on configs where tlb_remove_table_sync_one() is a NOP, ++ * the expectation is that the tlb_flush_mmu_tlbonly() would have issued ++ * required IPIs already for us. ++ */ ++ if (tlb->fully_unshared_tables) { ++ tlb_remove_table_sync_one(); ++ tlb->fully_unshared_tables = false; ++ } ++} ++#endif /* CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING */ ++ + #endif /* CONFIG_MMU */ + + #endif /* _ASM_GENERIC__TLB_H */ +diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h +index 8b051b8c40345d..d3aa91007c90a1 100644 +--- a/include/linux/hugetlb.h ++++ b/include/linux/hugetlb.h +@@ -241,8 +241,9 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, + pte_t *huge_pte_offset(struct mm_struct *mm, + unsigned long addr, unsigned long sz); + unsigned long hugetlb_mask_last_page(struct hstate *h); +-int huge_pmd_unshare(struct mm_struct *mm, struct vm_area_struct *vma, +- unsigned long addr, pte_t *ptep); ++int huge_pmd_unshare(struct mmu_gather *tlb, struct vm_area_struct *vma, ++ unsigned long addr, pte_t *ptep); ++void huge_pmd_unshare_flush(struct mmu_gather *tlb, struct vm_area_struct *vma); + void adjust_range_if_pmd_sharing_possible(struct vm_area_struct *vma, + unsigned long *start, unsigned long *end); + +@@ -304,13 +305,17 @@ static inline struct address_space *hugetlb_page_mapping_lock_write( + return NULL; + } + +-static inline int huge_pmd_unshare(struct mm_struct *mm, +- struct vm_area_struct *vma, +- unsigned long addr, pte_t *ptep) ++static inline int huge_pmd_unshare(struct mmu_gather *tlb, ++ struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) + { + return 0; + } + ++static inline void huge_pmd_unshare_flush(struct mmu_gather *tlb, ++ struct vm_area_struct *vma) ++{ ++} ++ + static inline void adjust_range_if_pmd_sharing_possible( + struct vm_area_struct *vma, + unsigned long *start, unsigned long *end) +@@ -1247,7 +1252,7 @@ static inline __init void hugetlb_cma_reserve(int order) + #ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING + static inline bool hugetlb_pmd_shared(pte_t *pte) + { +- return page_count(virt_to_page(pte)) > 1; ++ return ptdesc_pmd_is_shared(virt_to_ptdesc(pte)); + } + #else + static inline bool hugetlb_pmd_shared(pte_t *pte) +diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h +index e77d4a5c0baced..ce3370823f9c7c 100644 +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -492,6 +492,11 @@ static inline int ptdesc_pmd_pts_count(struct ptdesc *ptdesc) + { + return atomic_read(&ptdesc->pt_share_count); + } ++ ++static inline bool ptdesc_pmd_is_shared(struct ptdesc *ptdesc) ++{ ++ return !!ptdesc_pmd_pts_count(ptdesc); ++} + #else + static inline void ptdesc_pmd_pts_init(struct ptdesc *ptdesc) + { +@@ -1172,6 +1177,7 @@ static inline unsigned int mm_cid_size(void) + struct mmu_gather; + extern void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm); + extern void tlb_gather_mmu_fullmm(struct mmu_gather *tlb, struct mm_struct *mm); ++void tlb_gather_mmu_vma(struct mmu_gather *tlb, struct vm_area_struct *vma); + extern void tlb_finish_mmu(struct mmu_gather *tlb); + + struct vm_fault; +diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h +index 3d36794cb1899a..1051af74285c58 100644 +--- a/include/net/ip_tunnels.h ++++ b/include/net/ip_tunnels.h +@@ -362,11 +362,12 @@ static inline bool pskb_inet_may_pull(struct sk_buff *skb) + + /* Variant of pskb_inet_may_pull(). + */ +-static inline bool skb_vlan_inet_prepare(struct sk_buff *skb, +- bool inner_proto_inherit) ++static inline enum skb_drop_reason ++skb_vlan_inet_prepare(struct sk_buff *skb, bool inner_proto_inherit) + { + int nhlen = 0, maclen = inner_proto_inherit ? 0 : ETH_HLEN; + __be16 type = skb->protocol; ++ enum skb_drop_reason reason; + + /* Essentially this is skb_protocol(skb, true) + * And we get MAC len. +@@ -387,11 +388,13 @@ static inline bool skb_vlan_inet_prepare(struct sk_buff *skb, + /* For ETH_P_IPV6/ETH_P_IP we make sure to pull + * a base network header in skb->head. + */ +- if (!pskb_may_pull(skb, maclen + nhlen)) +- return false; ++ reason = pskb_may_pull_reason(skb, maclen + nhlen); ++ if (reason) ++ return reason; + + skb_set_network_header(skb, maclen); +- return true; ++ ++ return SKB_NOT_DROPPED_YET; + } + + static inline int ip_encap_hlen(struct ip_tunnel_encap *e) +diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c +index f61dde0497f397..3c466e74275167 100644 +--- a/kernel/cgroup/cpuset.c ++++ b/kernel/cgroup/cpuset.c +@@ -486,7 +486,7 @@ static inline bool partition_is_populated(struct cpuset *cs, + cs->attach_in_progress) + return true; + if (!excluded_child && !cs->nr_subparts_cpus) +- return cgroup_is_populated(cs->css.cgroup); ++ return cpuset_is_populated(cs); + + rcu_read_lock(); + cpuset_for_each_descendant_pre(cp, pos_css, cs) { +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 532a840a426646..aa0ef3bc4dd650 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -5090,18 +5090,13 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, + break; + } + +- /* +- * If the pagetables are shared don't copy or take references. +- * +- * dst_pte == src_pte is the common case of src/dest sharing. +- * However, src could have 'unshared' and dst shares with +- * another vma. So page_count of ptep page is checked instead +- * to reliably determine whether pte is shared. +- */ +- if (page_count(virt_to_page(dst_pte)) > 1) { ++#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING ++ /* If the pagetables are shared, there is nothing to do */ ++ if (ptdesc_pmd_is_shared(virt_to_ptdesc(dst_pte))) { + addr |= last_addr_mask; + continue; + } ++#endif + + dst_ptl = huge_pte_lock(h, dst, dst_pte); + src_ptl = huge_pte_lockptr(h, src, src_pte); +@@ -5274,7 +5269,7 @@ int move_hugetlb_page_tables(struct vm_area_struct *vma, + unsigned long last_addr_mask; + pte_t *src_pte, *dst_pte; + struct mmu_notifier_range range; +- bool shared_pmd = false; ++ struct mmu_gather tlb; + + mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm, old_addr, + old_end); +@@ -5284,6 +5279,7 @@ int move_hugetlb_page_tables(struct vm_area_struct *vma, + * range. + */ + flush_cache_range(vma, range.start, range.end); ++ tlb_gather_mmu_vma(&tlb, vma); + + mmu_notifier_invalidate_range_start(&range); + last_addr_mask = hugetlb_mask_last_page(h); +@@ -5300,8 +5296,7 @@ int move_hugetlb_page_tables(struct vm_area_struct *vma, + if (huge_pte_none(huge_ptep_get(src_pte))) + continue; + +- if (huge_pmd_unshare(mm, vma, old_addr, src_pte)) { +- shared_pmd = true; ++ if (huge_pmd_unshare(&tlb, vma, old_addr, src_pte)) { + old_addr |= last_addr_mask; + new_addr |= last_addr_mask; + continue; +@@ -5312,15 +5307,16 @@ int move_hugetlb_page_tables(struct vm_area_struct *vma, + break; + + move_huge_pte(vma, old_addr, new_addr, src_pte, dst_pte, sz); ++ tlb_remove_huge_tlb_entry(h, &tlb, src_pte, old_addr); + } + +- if (shared_pmd) +- flush_hugetlb_tlb_range(vma, range.start, range.end); +- else +- flush_hugetlb_tlb_range(vma, old_end - len, old_end); ++ tlb_flush_mmu_tlbonly(&tlb); ++ huge_pmd_unshare_flush(&tlb, vma); ++ + mmu_notifier_invalidate_range_end(&range); + i_mmap_unlock_write(mapping); + hugetlb_vma_unlock_write(vma); ++ tlb_finish_mmu(&tlb); + + return len + old_addr - old_end; + } +@@ -5338,7 +5334,6 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, + struct hstate *h = hstate_vma(vma); + unsigned long sz = huge_page_size(h); + unsigned long last_addr_mask; +- bool force_flush = false; + + WARN_ON(!is_vm_hugetlb_page(vma)); + BUG_ON(start & ~huge_page_mask(h)); +@@ -5361,10 +5356,8 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, + } + + ptl = huge_pte_lock(h, mm, ptep); +- if (huge_pmd_unshare(mm, vma, address, ptep)) { ++ if (huge_pmd_unshare(tlb, vma, address, ptep)) { + spin_unlock(ptl); +- tlb_flush_pmd_range(tlb, address & PUD_MASK, PUD_SIZE); +- force_flush = true; + address |= last_addr_mask; + continue; + } +@@ -5439,21 +5432,7 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, + } + tlb_end_vma(tlb, vma); + +- /* +- * If we unshared PMDs, the TLB flush was not recorded in mmu_gather. We +- * could defer the flush until now, since by holding i_mmap_rwsem we +- * guaranteed that the last refernece would not be dropped. But we must +- * do the flushing before we return, as otherwise i_mmap_rwsem will be +- * dropped and the last reference to the shared PMDs page might be +- * dropped as well. +- * +- * In theory we could defer the freeing of the PMD pages as well, but +- * huge_pmd_unshare() relies on the exact page_count for the PMD page to +- * detect sharing, so we cannot defer the release of the page either. +- * Instead, do flush now. +- */ +- if (force_flush) +- tlb_flush_mmu_tlbonly(tlb); ++ huge_pmd_unshare_flush(tlb, vma); + } + + void __hugetlb_zap_begin(struct vm_area_struct *vma, +@@ -6585,11 +6564,11 @@ long hugetlb_change_protection(struct vm_area_struct *vma, + pte_t pte; + struct hstate *h = hstate_vma(vma); + long pages = 0, psize = huge_page_size(h); +- bool shared_pmd = false; + struct mmu_notifier_range range; + unsigned long last_addr_mask; + bool uffd_wp = cp_flags & MM_CP_UFFD_WP; + bool uffd_wp_resolve = cp_flags & MM_CP_UFFD_WP_RESOLVE; ++ struct mmu_gather tlb; + + /* + * In the case of shared PMDs, the area to flush could be beyond +@@ -6602,6 +6581,7 @@ long hugetlb_change_protection(struct vm_area_struct *vma, + + BUG_ON(address >= end); + flush_cache_range(vma, range.start, range.end); ++ tlb_gather_mmu_vma(&tlb, vma); + + mmu_notifier_invalidate_range_start(&range); + hugetlb_vma_lock_write(vma); +@@ -6626,7 +6606,7 @@ long hugetlb_change_protection(struct vm_area_struct *vma, + } + } + ptl = huge_pte_lock(h, mm, ptep); +- if (huge_pmd_unshare(mm, vma, address, ptep)) { ++ if (huge_pmd_unshare(&tlb, vma, address, ptep)) { + /* + * When uffd-wp is enabled on the vma, unshare + * shouldn't happen at all. Warn about it if it +@@ -6635,7 +6615,6 @@ long hugetlb_change_protection(struct vm_area_struct *vma, + WARN_ON_ONCE(uffd_wp || uffd_wp_resolve); + pages++; + spin_unlock(ptl); +- shared_pmd = true; + address |= last_addr_mask; + continue; + } +@@ -6687,6 +6666,7 @@ long hugetlb_change_protection(struct vm_area_struct *vma, + pte = huge_pte_clear_uffd_wp(pte); + huge_ptep_modify_prot_commit(vma, address, ptep, old_pte, pte); + pages++; ++ tlb_remove_huge_tlb_entry(h, &tlb, ptep, address); + } else { + /* None pte */ + if (unlikely(uffd_wp)) +@@ -6699,17 +6679,9 @@ long hugetlb_change_protection(struct vm_area_struct *vma, + + cond_resched(); + } +- /* +- * Must flush TLB before releasing i_mmap_rwsem: x86's huge_pmd_unshare +- * may have cleared our pud entry and done put_page on the page table: +- * once we release i_mmap_rwsem, another task can do the final put_page +- * and that page table be reused and filled with junk. If we actually +- * did unshare a page of pmds, flush the range corresponding to the pud. +- */ +- if (shared_pmd) +- flush_hugetlb_tlb_range(vma, range.start, range.end); +- else +- flush_hugetlb_tlb_range(vma, start, end); ++ ++ tlb_flush_mmu_tlbonly(&tlb); ++ huge_pmd_unshare_flush(&tlb, vma); + /* + * No need to call mmu_notifier_arch_invalidate_secondary_tlbs() we are + * downgrading page table protection not changing it to point to a new +@@ -6720,6 +6692,7 @@ long hugetlb_change_protection(struct vm_area_struct *vma, + i_mmap_unlock_write(vma->vm_file->f_mapping); + hugetlb_vma_unlock_write(vma); + mmu_notifier_invalidate_range_end(&range); ++ tlb_finish_mmu(&tlb); + + return pages > 0 ? (pages << h->order) : pages; + } +@@ -7057,18 +7030,27 @@ out: + return pte; + } + +-/* +- * unmap huge page backed by shared pte. ++/** ++ * huge_pmd_unshare - Unmap a pmd table if it is shared by multiple users ++ * @tlb: the current mmu_gather. ++ * @vma: the vma covering the pmd table. ++ * @addr: the address we are trying to unshare. ++ * @ptep: pointer into the (pmd) page table. + * +- * Called with page table lock held. ++ * Called with the page table lock held, the i_mmap_rwsem held in write mode ++ * and the hugetlb vma lock held in write mode. + * +- * returns: 1 successfully unmapped a shared pte page +- * 0 the underlying pte page is not shared, or it is the last user ++ * Note: The caller must call huge_pmd_unshare_flush() before dropping the ++ * i_mmap_rwsem. ++ * ++ * Returns: 1 if it was a shared PMD table and it got unmapped, or 0 if it ++ * was not a shared PMD table. + */ +-int huge_pmd_unshare(struct mm_struct *mm, struct vm_area_struct *vma, +- unsigned long addr, pte_t *ptep) ++int huge_pmd_unshare(struct mmu_gather *tlb, struct vm_area_struct *vma, ++ unsigned long addr, pte_t *ptep) + { + unsigned long sz = huge_page_size(hstate_vma(vma)); ++ struct mm_struct *mm = vma->vm_mm; + pgd_t *pgd = pgd_offset(mm, addr); + p4d_t *p4d = p4d_offset(pgd, addr); + pud_t *pud = pud_offset(p4d, addr); +@@ -7077,22 +7059,40 @@ int huge_pmd_unshare(struct mm_struct *mm, struct vm_area_struct *vma, + hugetlb_vma_assert_locked(vma); + if (sz != PMD_SIZE) + return 0; +- if (!ptdesc_pmd_pts_count(virt_to_ptdesc(ptep))) ++ if (!ptdesc_pmd_is_shared(virt_to_ptdesc(ptep))) + return 0; + + pud_clear(pud); +- /* +- * Once our caller drops the rmap lock, some other process might be +- * using this page table as a normal, non-hugetlb page table. +- * Wait for pending gup_fast() in other threads to finish before letting +- * that happen. +- */ +- tlb_remove_table_sync_one(); +- ptdesc_pmd_pts_dec(virt_to_ptdesc(ptep)); ++ ++ tlb_unshare_pmd_ptdesc(tlb, virt_to_ptdesc(ptep), addr); ++ + mm_dec_nr_pmds(mm); + return 1; + } + ++/* ++ * huge_pmd_unshare_flush - Complete a sequence of huge_pmd_unshare() calls ++ * @tlb: the current mmu_gather. ++ * @vma: the vma covering the pmd table. ++ * ++ * Perform necessary TLB flushes or IPI broadcasts to synchronize PMD table ++ * unsharing with concurrent page table walkers. ++ * ++ * This function must be called after a sequence of huge_pmd_unshare() ++ * calls while still holding the i_mmap_rwsem. ++ */ ++void huge_pmd_unshare_flush(struct mmu_gather *tlb, struct vm_area_struct *vma) ++{ ++ /* ++ * We must synchronize page table unsharing such that nobody will ++ * try reusing a previously-shared page table while it might still ++ * be in use by previous sharers (TLB, GUP_fast). ++ */ ++ i_mmap_assert_write_locked(vma->vm_file->f_mapping); ++ ++ tlb_flush_unshared_tables(tlb); ++} ++ + #else /* !CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING */ + + pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -7101,12 +7101,16 @@ pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma, + return NULL; + } + +-int huge_pmd_unshare(struct mm_struct *mm, struct vm_area_struct *vma, +- unsigned long addr, pte_t *ptep) ++int huge_pmd_unshare(struct mmu_gather *tlb, struct vm_area_struct *vma, ++ unsigned long addr, pte_t *ptep) + { + return 0; + } + ++void huge_pmd_unshare_flush(struct mmu_gather *tlb, struct vm_area_struct *vma) ++{ ++} ++ + void adjust_range_if_pmd_sharing_possible(struct vm_area_struct *vma, + unsigned long *start, unsigned long *end) + { +@@ -7339,6 +7343,7 @@ static void hugetlb_unshare_pmds(struct vm_area_struct *vma, + unsigned long sz = huge_page_size(h); + struct mm_struct *mm = vma->vm_mm; + struct mmu_notifier_range range; ++ struct mmu_gather tlb; + unsigned long address; + spinlock_t *ptl; + pte_t *ptep; +@@ -7350,6 +7355,8 @@ static void hugetlb_unshare_pmds(struct vm_area_struct *vma, + return; + + flush_cache_range(vma, start, end); ++ tlb_gather_mmu_vma(&tlb, vma); ++ + /* + * No need to call adjust_range_if_pmd_sharing_possible(), because + * we have already done the PUD_SIZE alignment. +@@ -7368,10 +7375,10 @@ static void hugetlb_unshare_pmds(struct vm_area_struct *vma, + if (!ptep) + continue; + ptl = huge_pte_lock(h, mm, ptep); +- huge_pmd_unshare(mm, vma, address, ptep); ++ huge_pmd_unshare(&tlb, vma, address, ptep); + spin_unlock(ptl); + } +- flush_hugetlb_tlb_range(vma, start, end); ++ huge_pmd_unshare_flush(&tlb, vma); + if (take_locks) { + i_mmap_unlock_write(vma->vm_file->f_mapping); + hugetlb_vma_unlock_write(vma); +@@ -7381,6 +7388,7 @@ static void hugetlb_unshare_pmds(struct vm_area_struct *vma, + * Documentation/mm/mmu_notifier.rst. + */ + mmu_notifier_invalidate_range_end(&range); ++ tlb_finish_mmu(&tlb); + } + + /* +diff --git a/mm/mmu_gather.c b/mm/mmu_gather.c +index 4f559f4ddd2171..156c4d41805bd3 100644 +--- a/mm/mmu_gather.c ++++ b/mm/mmu_gather.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -321,6 +322,7 @@ static void __tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, + tlb->page_size = 0; + #endif + ++ tlb->fully_unshared_tables = 0; + __tlb_reset_range(tlb); + inc_tlb_flush_pending(tlb->mm); + } +@@ -354,6 +356,31 @@ void tlb_gather_mmu_fullmm(struct mmu_gather *tlb, struct mm_struct *mm) + __tlb_gather_mmu(tlb, mm, true); + } + ++/** ++ * tlb_gather_mmu_vma - initialize an mmu_gather structure for operating on a ++ * single VMA ++ * @tlb: the mmu_gather structure to initialize ++ * @vma: the vm_area_struct ++ * ++ * Called to initialize an (on-stack) mmu_gather structure for operating on ++ * a single VMA. In contrast to tlb_gather_mmu(), calling this function will ++ * not require another call to tlb_start_vma(). In contrast to tlb_start_vma(), ++ * this function will *not* call flush_cache_range(). ++ * ++ * For hugetlb VMAs, this function will also initialize the mmu_gather ++ * page_size accordingly, not requiring a separate call to ++ * tlb_change_page_size(). ++ * ++ */ ++void tlb_gather_mmu_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) ++{ ++ tlb_gather_mmu(tlb, vma->vm_mm); ++ tlb_update_vma_flags(tlb, vma); ++ if (is_vm_hugetlb_page(vma)) ++ /* All entries have the same size. */ ++ tlb_change_page_size(tlb, huge_page_size(hstate_vma(vma))); ++} ++ + /** + * tlb_finish_mmu - finish an mmu_gather structure + * @tlb: the mmu_gather structure to finish +@@ -363,6 +390,12 @@ void tlb_gather_mmu_fullmm(struct mmu_gather *tlb, struct mm_struct *mm) + */ + void tlb_finish_mmu(struct mmu_gather *tlb) + { ++ /* ++ * We expect an earlier huge_pmd_unshare_flush() call to sort this out, ++ * due to complicated locking requirements with page table unsharing. ++ */ ++ VM_WARN_ON_ONCE(tlb->fully_unshared_tables); ++ + /* + * If there are parallel threads are doing PTE changes on same range + * under non-exclusive lock (e.g., mmap_lock read-side) but defer TLB +diff --git a/mm/rmap.c b/mm/rmap.c +index b511dd811c30c7..0a88928c410a01 100644 +--- a/mm/rmap.c ++++ b/mm/rmap.c +@@ -76,7 +76,7 @@ + #include + #include + +-#include ++#include + + #define CREATE_TRACE_POINTS + #include +@@ -1568,16 +1568,20 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma, + * if unsuccessful. + */ + if (!anon) { ++ struct mmu_gather tlb; ++ + VM_BUG_ON(!(flags & TTU_RMAP_LOCKED)); + if (!hugetlb_vma_trylock_write(vma)) { + page_vma_mapped_walk_done(&pvmw); + ret = false; + break; + } +- if (huge_pmd_unshare(mm, vma, address, pvmw.pte)) { ++ ++ tlb_gather_mmu_vma(&tlb, vma); ++ if (huge_pmd_unshare(&tlb, vma, address, pvmw.pte)) { + hugetlb_vma_unlock_write(vma); +- flush_tlb_range(vma, +- range.start, range.end); ++ huge_pmd_unshare_flush(&tlb, vma); ++ tlb_finish_mmu(&tlb); + /* + * The PMD table was unmapped, + * consequently unmapping the folio. +@@ -1586,6 +1590,7 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma, + break; + } + hugetlb_vma_unlock_write(vma); ++ tlb_finish_mmu(&tlb); + } + pteval = huge_ptep_clear_flush(vma, address, pvmw.pte); + } else { +@@ -1927,17 +1932,20 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma, + * fail if unsuccessful. + */ + if (!anon) { ++ struct mmu_gather tlb; ++ + VM_BUG_ON(!(flags & TTU_RMAP_LOCKED)); + if (!hugetlb_vma_trylock_write(vma)) { + page_vma_mapped_walk_done(&pvmw); + ret = false; + break; + } +- if (huge_pmd_unshare(mm, vma, address, pvmw.pte)) { +- hugetlb_vma_unlock_write(vma); +- flush_tlb_range(vma, +- range.start, range.end); + ++ tlb_gather_mmu_vma(&tlb, vma); ++ if (huge_pmd_unshare(&tlb, vma, address, pvmw.pte)) { ++ hugetlb_vma_unlock_write(vma); ++ huge_pmd_unshare_flush(&tlb, vma); ++ tlb_finish_mmu(&tlb); + /* + * The PMD table was unmapped, + * consequently unmapping the folio. +@@ -1946,6 +1954,7 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma, + break; + } + hugetlb_vma_unlock_write(vma); ++ tlb_finish_mmu(&tlb); + } + /* Nuke the hugetlb page table entry */ + pteval = huge_ptep_clear_flush(vma, address, pvmw.pte); +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index c60358a4a75728..5b836a91135cc8 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -10650,6 +10650,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1ee7, 0x2078, "HONOR BRB-X M1010", ALC2XX_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1f66, 0x0105, "Ayaneo Portable Game Player", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x2014, 0x800a, "Positivo ARN50", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), ++ SND_PCI_QUIRK(0x2039, 0x0001, "Inspur S14-G1", ALC295_FIXUP_CHROME_BOOK), + SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x2782, 0x0228, "Infinix ZERO BOOK 13", ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13), + SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO), +@@ -11102,6 +11103,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { + {0x12, 0x90a60140}, + {0x19, 0x04a11030}, + {0x21, 0x04211020}), ++ SND_HDA_PIN_QUIRK(0x10ec0274, 0x1d05, "TongFang", ALC274_FIXUP_HP_HEADSET_MIC, ++ {0x17, 0x90170110}, ++ {0x19, 0x03a11030}, ++ {0x21, 0x03211020}), + SND_HDA_PIN_QUIRK(0x10ec0282, 0x1025, "Acer", ALC282_FIXUP_ACER_DISABLE_LINEOUT, + ALC282_STANDARD_PINS, + {0x12, 0x90a609c0}, +diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c +index b0456be5d921a3..b6068d289f5f9d 100644 +--- a/sound/soc/amd/yc/acp6x-mach.c ++++ b/sound/soc/amd/yc/acp6x-mach.c +@@ -535,6 +535,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "15NBC1011"), + } + }, ++ { ++ .driver_data = &acp6x_card, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "ASUS EXPERTBOOK PM1503CDA"), ++ } ++ }, + { + .driver_data = &acp6x_card, + .matches = { +@@ -626,6 +633,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { + DMI_MATCH(DMI_BOARD_NAME, "8BD6"), + } + }, ++ { ++ .driver_data = &acp6x_card, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "HP"), ++ DMI_MATCH(DMI_BOARD_NAME, "8EE4"), ++ } ++ }, + { + .driver_data = &acp6x_card, + .matches = { +diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c +index 7e439c778c6b49..11e28c340a709a 100644 +--- a/sound/soc/codecs/cs35l45.c ++++ b/sound/soc/codecs/cs35l45.c +@@ -316,7 +316,7 @@ static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { + SND_SOC_DAPM_AIF_OUT("ASP_TX2", NULL, 1, CS35L45_ASP_ENABLES1, CS35L45_ASP_TX2_EN_SHIFT, 0), + SND_SOC_DAPM_AIF_OUT("ASP_TX3", NULL, 2, CS35L45_ASP_ENABLES1, CS35L45_ASP_TX3_EN_SHIFT, 0), + SND_SOC_DAPM_AIF_OUT("ASP_TX4", NULL, 3, CS35L45_ASP_ENABLES1, CS35L45_ASP_TX4_EN_SHIFT, 0), +- SND_SOC_DAPM_AIF_OUT("ASP_TX5", NULL, 3, CS35L45_ASP_ENABLES1, CS35L45_ASP_TX5_EN_SHIFT, 0), ++ SND_SOC_DAPM_AIF_OUT("ASP_TX5", NULL, 4, CS35L45_ASP_ENABLES1, CS35L45_ASP_TX5_EN_SHIFT, 0), + + SND_SOC_DAPM_MUX("ASP_TX1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[0]), + SND_SOC_DAPM_MUX("ASP_TX2 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[1]), +diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c +index 6d8455c1bee6d8..f58d55d77693f2 100644 +--- a/sound/soc/codecs/cs42l43-jack.c ++++ b/sound/soc/codecs/cs42l43-jack.c +@@ -496,7 +496,23 @@ void cs42l43_bias_sense_timeout(struct work_struct *work) + pm_runtime_put_autosuspend(priv->dev); + } + +-static void cs42l43_start_load_detect(struct cs42l43_codec *priv) ++static const struct reg_sequence cs42l43_3pole_patch[] = { ++ { 0x4000, 0x00000055 }, ++ { 0x4000, 0x000000AA }, ++ { 0x17420, 0x8500F300 }, ++ { 0x17424, 0x36003E00 }, ++ { 0x4000, 0x00000000 }, ++}; ++ ++static const struct reg_sequence cs42l43_4pole_patch[] = { ++ { 0x4000, 0x00000055 }, ++ { 0x4000, 0x000000AA }, ++ { 0x17420, 0x7800E600 }, ++ { 0x17424, 0x36003800 }, ++ { 0x4000, 0x00000000 }, ++}; ++ ++static void cs42l43_start_load_detect(struct cs42l43_codec *priv, bool mic) + { + struct cs42l43 *cs42l43 = priv->core; + +@@ -520,6 +536,15 @@ static void cs42l43_start_load_detect(struct cs42l43_codec *priv) + dev_err(priv->dev, "Load detect HP power down timed out\n"); + } + ++ if (mic) ++ regmap_multi_reg_write_bypassed(cs42l43->regmap, ++ cs42l43_4pole_patch, ++ ARRAY_SIZE(cs42l43_4pole_patch)); ++ else ++ regmap_multi_reg_write_bypassed(cs42l43->regmap, ++ cs42l43_3pole_patch, ++ ARRAY_SIZE(cs42l43_3pole_patch)); ++ + regmap_update_bits(cs42l43->regmap, CS42L43_BLOCK_EN3, + CS42L43_ADC1_EN_MASK | CS42L43_ADC2_EN_MASK, 0); + regmap_update_bits(cs42l43->regmap, CS42L43_DACCNFG2, CS42L43_HP_HPF_EN_MASK, 0); +@@ -598,7 +623,7 @@ static int cs42l43_run_load_detect(struct cs42l43_codec *priv, bool mic) + + reinit_completion(&priv->load_detect); + +- cs42l43_start_load_detect(priv); ++ cs42l43_start_load_detect(priv, mic); + time_left = wait_for_completion_timeout(&priv->load_detect, + msecs_to_jiffies(CS42L43_LOAD_TIMEOUT_MS)); + cs42l43_stop_load_detect(priv); +@@ -622,11 +647,11 @@ static int cs42l43_run_load_detect(struct cs42l43_codec *priv, bool mic) + } + + switch (val & CS42L43_AMP3_RES_DET_MASK) { +- case 0x0: // low impedance +- case 0x1: // high impedance ++ case 0x0: // < 22 Ohm impedance ++ case 0x1: // < 150 Ohm impedance ++ case 0x2: // < 1000 Ohm impedance + return CS42L43_JACK_HEADPHONE; +- case 0x2: // lineout +- case 0x3: // Open circuit ++ case 0x3: // > 1000 Ohm impedance + return CS42L43_JACK_LINEOUT; + default: + return -EINVAL; +diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c +index 90a0a24c05d845..3a5ab8b5367289 100644 +--- a/sound/soc/fsl/fsl_xcvr.c ++++ b/sound/soc/fsl/fsl_xcvr.c +@@ -206,10 +206,13 @@ static int fsl_xcvr_mode_put(struct snd_kcontrol *kcontrol, + + xcvr->mode = snd_soc_enum_item_to_val(e, item[0]); + ++ down_read(&card->snd_card->controls_rwsem); + fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name, + (xcvr->mode == FSL_XCVR_MODE_ARC)); + fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name, + (xcvr->mode == FSL_XCVR_MODE_EARC)); ++ up_read(&card->snd_card->controls_rwsem); ++ + /* Allow playback for SPDIF only */ + rtd = snd_soc_get_pcm_runtime(card, card->dai_link); + rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count = +diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c +index c9d9381c76796f..02b74ab62ff585 100644 +--- a/sound/soc/intel/boards/sof_es8336.c ++++ b/sound/soc/intel/boards/sof_es8336.c +@@ -332,6 +332,15 @@ static int sof_es8336_quirk_cb(const struct dmi_system_id *id) + * if the topology file is modified as well. + */ + static const struct dmi_system_id sof_es8336_quirk_table[] = { ++ { ++ .callback = sof_es8336_quirk_cb, ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "HUAWEI"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "BOD-WXX9"), ++ }, ++ .driver_data = (void *)(SOF_ES8336_HEADPHONE_GPIO | ++ SOF_ES8336_ENABLE_DMIC) ++ }, + { + .callback = sof_es8336_quirk_cb, + .matches = { diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.127-128.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.127-128.patch new file mode 100644 index 0000000000..b0e4e04227 --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.127-128.patch @@ -0,0 +1,25064 @@ +diff --git a/Documentation/PCI/endpoint/pci-vntb-howto.rst b/Documentation/PCI/endpoint/pci-vntb-howto.rst +index 70d3bc90893f33..949c0d35694c2c 100644 +--- a/Documentation/PCI/endpoint/pci-vntb-howto.rst ++++ b/Documentation/PCI/endpoint/pci-vntb-howto.rst +@@ -52,14 +52,14 @@ pci-epf-vntb device, the following commands can be used:: + # cd /sys/kernel/config/pci_ep/ + # mkdir functions/pci_epf_vntb/func1 + +-The "mkdir func1" above creates the pci-epf-ntb function device that will ++The "mkdir func1" above creates the pci-epf-vntb function device that will + be probed by pci_epf_vntb driver. + + The PCI endpoint framework populates the directory with the following + configurable fields:: + +- # ls functions/pci_epf_ntb/func1 +- baseclass_code deviceid msi_interrupts pci-epf-ntb.0 ++ # ls functions/pci_epf_vntb/func1 ++ baseclass_code deviceid msi_interrupts pci-epf-vntb.0 + progif_code secondary subsys_id vendorid + cache_line_size interrupt_pin msix_interrupts primary + revid subclass_code subsys_vendor_id +@@ -106,13 +106,13 @@ A sample configuration for virtual NTB driver for virtual PCI bus:: + # echo 0x080A > functions/pci_epf_vntb/func1/pci_epf_vntb.0/vntb_pid + # echo 0x10 > functions/pci_epf_vntb/func1/pci_epf_vntb.0/vbus_number + +-Binding pci-epf-ntb Device to EP Controller ++Binding pci-epf-vntb Device to EP Controller + -------------------------------------------- + + NTB function device should be attached to PCI endpoint controllers + connected to the host. + +- # ln -s controllers/5f010000.pcie_ep functions/pci-epf-ntb/func1/primary ++ # ln -s controllers/5f010000.pcie_ep functions/pci_epf_vntb/func1/primary + + Once the above step is completed, the PCI endpoint controllers are ready to + establish a link with the host. +@@ -134,7 +134,7 @@ lspci Output at Host side + ------------------------- + + Note that the devices listed here correspond to the values populated in +-"Creating pci-epf-ntb Device" section above:: ++"Creating pci-epf-vntb Device" section above:: + + # lspci + 00:00.0 PCI bridge: Freescale Semiconductor Inc Device 0000 (rev 01) +@@ -147,7 +147,7 @@ lspci Output at EP Side / Virtual PCI bus + ----------------------------------------- + + Note that the devices listed here correspond to the values populated in +-"Creating pci-epf-ntb Device" section above:: ++"Creating pci-epf-vntb Device" section above:: + + # lspci + 10:00.0 Unassigned class [ffff]: Dawicontrol Computersysteme GmbH Device 1234 (rev ff) +diff --git a/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml +index 4477f84b7acc0e..e44801ddbd2a92 100644 +--- a/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml ++++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml +@@ -18,10 +18,10 @@ properties: + reg: + maxItems: 1 + +- avdd-supply: ++ AVDD-supply: + description: Analog power supply + +- dvdd-supply: ++ DVDD-supply: + description: Digital power supply + + reset-gpios: +@@ -56,7 +56,7 @@ allOf: + properties: + dsd-path: false + +-additionalProperties: false ++unevaluatedProperties: false + + examples: + - | +diff --git a/Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yaml b/Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yaml +index d3d494ae8abfeb..dc8f85f266bf30 100644 +--- a/Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yaml ++++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yaml +@@ -19,10 +19,10 @@ properties: + reg: + maxItems: 1 + +- avdd-supply: ++ AVDD-supply: + description: A 1.8V supply that powers up the AVDD pin. + +- dvdd-supply: ++ DVDD-supply: + description: A 1.2V supply that powers up the DVDD pin. + + reset-gpios: +diff --git a/Documentation/networking/device_drivers/ethernet/marvell/octeon_ep.rst b/Documentation/networking/device_drivers/ethernet/marvell/octeon_ep.rst +index cad96c8d1f97dd..613a818d5db6ec 100644 +--- a/Documentation/networking/device_drivers/ethernet/marvell/octeon_ep.rst ++++ b/Documentation/networking/device_drivers/ethernet/marvell/octeon_ep.rst +@@ -24,6 +24,10 @@ Supported Devices + Currently, this driver support following devices: + * Network controller: Cavium, Inc. Device b200 + * Network controller: Cavium, Inc. Device b400 ++ * Network controller: Cavium, Inc. Device b900 ++ * Network controller: Cavium, Inc. Device ba00 ++ * Network controller: Cavium, Inc. Device bc00 ++ * Network controller: Cavium, Inc. Device bd00 + + Interface Control + ================= +diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst +index a66054d0763a69..531a070df2a6bb 100644 +--- a/Documentation/networking/ip-sysctl.rst ++++ b/Documentation/networking/ip-sysctl.rst +@@ -745,6 +745,13 @@ tcp_comp_sack_nr - INTEGER + + Default : 44 + ++tcp_backlog_ack_defer - BOOLEAN ++ If set, user thread processing socket backlog tries sending ++ one ACK for the whole queue. This helps to avoid potential ++ long latencies at end of a TCP socket syscall. ++ ++ Default : true ++ + tcp_slow_start_after_idle - BOOLEAN + If set, provide RFC2861 behavior and time out the congestion + window after an idle period. An idle period is defined at +@@ -1176,6 +1183,19 @@ tcp_plb_cong_thresh - INTEGER + + Default: 128 + ++tcp_pingpong_thresh - INTEGER ++ The number of estimated data replies sent for estimated incoming data ++ requests that must happen before TCP considers that a connection is a ++ "ping-pong" (request-response) connection for which delayed ++ acknowledgments can provide benefits. ++ ++ This threshold is 1 by default, but some applications may need a higher ++ threshold for optimal performance. ++ ++ Possible Values: 1 - 255 ++ ++ Default: 1 ++ + UDP variables + ============= + +diff --git a/Documentation/trace/events-pci.rst b/Documentation/trace/events-pci.rst +new file mode 100644 +index 00000000000000..03ff4ad30ddfa1 +--- /dev/null ++++ b/Documentation/trace/events-pci.rst +@@ -0,0 +1,74 @@ ++.. SPDX-License-Identifier: GPL-2.0 ++ ++=========================== ++Subsystem Trace Points: PCI ++=========================== ++ ++Overview ++======== ++The PCI tracing system provides tracepoints to monitor critical hardware events ++that can impact system performance and reliability. These events normally show ++up here: ++ ++ /sys/kernel/tracing/events/pci ++ ++Cf. include/trace/events/pci.h for the events definitions. ++ ++Available Tracepoints ++===================== ++ ++pci_hp_event ++------------ ++ ++Monitors PCI hotplug events including card insertion/removal and link ++state changes. ++:: ++ ++ pci_hp_event "%s slot:%s, event:%s\n" ++ ++**Event Types**: ++ ++* ``LINK_UP`` - PCIe link established ++* ``LINK_DOWN`` - PCIe link lost ++* ``CARD_PRESENT`` - Card detected in slot ++* ``CARD_NOT_PRESENT`` - Card removed from slot ++ ++**Example Usage**:: ++ ++ # Enable the tracepoint ++ echo 1 > /sys/kernel/debug/tracing/events/pci/pci_hp_event/enable ++ ++ # Monitor events (the following output is generated when a device is hotplugged) ++ cat /sys/kernel/debug/tracing/trace_pipe ++ irq/51-pciehp-88 [001] ..... 1311.177459: pci_hp_event: 0000:00:02.0 slot:10, event:CARD_PRESENT ++ ++ irq/51-pciehp-88 [001] ..... 1311.177566: pci_hp_event: 0000:00:02.0 slot:10, event:LINK_UP ++ ++pcie_link_event ++--------------- ++ ++Monitors PCIe link speed changes and provides detailed link status information. ++:: ++ ++ pcie_link_event "%s type:%d, reason:%d, cur_bus_speed:%d, max_bus_speed:%d, width:%u, flit_mode:%u, status:%s\n" ++ ++**Parameters**: ++ ++* ``type`` - PCIe device type (4=Root Port, etc.) ++* ``reason`` - Reason for link change: ++ ++ - ``0`` - Link retrain ++ - ``1`` - Bus enumeration ++ - ``2`` - Bandwidth notification enable ++ - ``3`` - Bandwidth notification IRQ ++ - ``4`` - Hotplug event ++ ++ ++**Example Usage**:: ++ ++ # Enable the tracepoint ++ echo 1 > /sys/kernel/debug/tracing/events/pci/pcie_link_event/enable ++ ++ # Monitor events (the following output is generated when a device is hotplugged) ++ cat /sys/kernel/debug/tracing/trace_pipe ++ irq/51-pciehp-88 [001] ..... 381.545386: pcie_link_event: 0000:00:02.0 type:4, reason:4, cur_bus_speed:20, max_bus_speed:23, width:1, flit_mode:0, status:DLLLA +diff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst +index 5092d6c13af5e3..e9bcb9d9f7f3b3 100644 +--- a/Documentation/trace/index.rst ++++ b/Documentation/trace/index.rst +@@ -1,37 +1,104 @@ +-========================== +-Linux Tracing Technologies +-========================== ++================================ ++Linux Tracing Technologies Guide ++================================ ++ ++Tracing in the Linux kernel is a powerful mechanism that allows ++developers and system administrators to analyze and debug system ++behavior. This guide provides documentation on various tracing ++frameworks and tools available in the Linux kernel. ++ ++Introduction to Tracing ++----------------------- ++ ++This section provides an overview of Linux tracing mechanisms ++and debugging approaches. + + .. toctree:: + :maxdepth: 2 + +- ftrace-design ++ debugging ++ tracepoints + tracepoint-analysis ++ ring-buffer-map ++ ++Core Tracing Frameworks ++----------------------- ++ ++The following are the primary tracing frameworks integrated into ++the Linux kernel. ++ ++.. toctree:: ++ :maxdepth: 1 ++ + ftrace ++ ftrace-design + ftrace-uses +- fprobe + kprobes + kprobetrace +- uprobetracer + fprobetrace +- tracepoints ++ fprobe ++ ring-buffer-design ++ ++Event Tracing and Analysis ++-------------------------- ++ ++A detailed explanation of event tracing mechanisms and their ++applications. ++ ++.. toctree:: ++ :maxdepth: 1 ++ + events + events-kmem + events-power + events-nmi + events-msr +- mmiotrace ++ events-pci ++ boottime-trace + histogram + histogram-design +- boottime-trace +- hwlat_detector +- osnoise-tracer +- timerlat-tracer ++ ++Hardware and Performance Tracing ++-------------------------------- ++ ++This section covers tracing features that monitor hardware ++interactions and system performance. ++ ++.. toctree:: ++ :maxdepth: 1 ++ + intel_th +- ring-buffer-design + stm + sys-t + coresight/index +- user_events + rv/index + hisi-ptt ++ mmiotrace ++ hwlat_detector ++ osnoise-tracer ++ timerlat-tracer ++ ++User-Space Tracing ++------------------ ++ ++These tools allow tracing user-space applications and ++interactions. ++ ++.. toctree:: ++ :maxdepth: 1 ++ ++ user_events ++ uprobetracer ++ ++Additional Resources ++-------------------- ++ ++For more details, refer to the respective documentation of each ++tracing tool and framework. ++ ++.. only:: subproject and html ++ ++ Indices ++ ======= ++ ++ * :ref:`genindex` +diff --git a/Documentation/trace/ring-buffer-map.rst b/Documentation/trace/ring-buffer-map.rst +new file mode 100644 +index 00000000000000..8e296bcc0d7f32 +--- /dev/null ++++ b/Documentation/trace/ring-buffer-map.rst +@@ -0,0 +1,106 @@ ++.. SPDX-License-Identifier: GPL-2.0 ++ ++================================== ++Tracefs ring-buffer memory mapping ++================================== ++ ++:Author: Vincent Donnefort ++ ++Overview ++======== ++Tracefs ring-buffer memory map provides an efficient method to stream data ++as no memory copy is necessary. The application mapping the ring-buffer becomes ++then a consumer for that ring-buffer, in a similar fashion to trace_pipe. ++ ++Memory mapping setup ++==================== ++The mapping works with a mmap() of the trace_pipe_raw interface. ++ ++The first system page of the mapping contains ring-buffer statistics and ++description. It is referred to as the meta-page. One of the most important ++fields of the meta-page is the reader. It contains the sub-buffer ID which can ++be safely read by the mapper (see ring-buffer-design.rst). ++ ++The meta-page is followed by all the sub-buffers, ordered by ascending ID. It is ++therefore effortless to know where the reader starts in the mapping: ++ ++.. code-block:: c ++ ++ reader_id = meta->reader->id; ++ reader_offset = meta->meta_page_size + reader_id * meta->subbuf_size; ++ ++When the application is done with the current reader, it can get a new one using ++the trace_pipe_raw ioctl() TRACE_MMAP_IOCTL_GET_READER. This ioctl also updates ++the meta-page fields. ++ ++Limitations ++=========== ++When a mapping is in place on a Tracefs ring-buffer, it is not possible to ++either resize it (either by increasing the entire size of the ring-buffer or ++each subbuf). It is also not possible to use snapshot and causes splice to copy ++the ring buffer data instead of using the copyless swap from the ring buffer. ++ ++Concurrent readers (either another application mapping that ring-buffer or the ++kernel with trace_pipe) are allowed but not recommended. They will compete for ++the ring-buffer and the output is unpredictable, just like concurrent readers on ++trace_pipe would be. ++ ++Example ++======= ++ ++.. code-block:: c ++ ++ #include ++ #include ++ #include ++ #include ++ ++ #include ++ ++ #include ++ #include ++ ++ #define TRACE_PIPE_RAW "/sys/kernel/tracing/per_cpu/cpu0/trace_pipe_raw" ++ ++ int main(void) ++ { ++ int page_size = getpagesize(), fd, reader_id; ++ unsigned long meta_len, data_len; ++ struct trace_buffer_meta *meta; ++ void *map, *reader, *data; ++ ++ fd = open(TRACE_PIPE_RAW, O_RDONLY | O_NONBLOCK); ++ if (fd < 0) ++ exit(EXIT_FAILURE); ++ ++ map = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); ++ if (map == MAP_FAILED) ++ exit(EXIT_FAILURE); ++ ++ meta = (struct trace_buffer_meta *)map; ++ meta_len = meta->meta_page_size; ++ ++ printf("entries: %llu\n", meta->entries); ++ printf("overrun: %llu\n", meta->overrun); ++ printf("read: %llu\n", meta->read); ++ printf("nr_subbufs: %u\n", meta->nr_subbufs); ++ ++ data_len = meta->subbuf_size * meta->nr_subbufs; ++ data = mmap(NULL, data_len, PROT_READ, MAP_SHARED, fd, meta_len); ++ if (data == MAP_FAILED) ++ exit(EXIT_FAILURE); ++ ++ if (ioctl(fd, TRACE_MMAP_IOCTL_GET_READER) < 0) ++ exit(EXIT_FAILURE); ++ ++ reader_id = meta->reader.id; ++ reader = data + meta->subbuf_size * reader_id; ++ ++ printf("Current reader address: %p\n", reader); ++ ++ munmap(data, data_len); ++ munmap(meta, meta_len); ++ close (fd); ++ ++ return 0; ++ } +diff --git a/Makefile b/Makefile +index b9c04d8271b94a..f7157576539da7 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 127 ++SUBLEVEL = 128 + EXTRAVERSION = + NAME = Pinguïn Aangedreven + +@@ -1356,6 +1356,15 @@ ifneq ($(wildcard $(resolve_btfids_O)),) + $(Q)$(MAKE) -sC $(srctree)/tools/bpf/resolve_btfids O=$(resolve_btfids_O) clean + endif + ++PHONY += objtool_clean ++ ++objtool_O = $(abspath $(objtree))/tools/objtool ++ ++objtool_clean: ++ifneq ($(wildcard $(objtool_O)),) ++ $(Q)$(MAKE) -sC $(abs_srctree)/tools/objtool O=$(objtool_O) srctree=$(abs_srctree) clean ++endif ++ + tools/: FORCE + $(Q)mkdir -p $(objtree)/tools + $(Q)$(MAKE) O=$(abspath $(objtree)) subdir=tools -C $(srctree)/tools/ +@@ -1509,7 +1518,7 @@ vmlinuxclean: + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean + $(Q)$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) clean) + +-clean: archclean vmlinuxclean resolve_btfids_clean ++clean: archclean vmlinuxclean resolve_btfids_clean objtool_clean + + # mrproper - Delete all generated files, including .config + # +diff --git a/arch/arm/boot/dts/allwinner/sun5i-a13-utoo-p66.dts b/arch/arm/boot/dts/allwinner/sun5i-a13-utoo-p66.dts +index be486d28d04fae..428cab5a0e906e 100644 +--- a/arch/arm/boot/dts/allwinner/sun5i-a13-utoo-p66.dts ++++ b/arch/arm/boot/dts/allwinner/sun5i-a13-utoo-p66.dts +@@ -102,6 +102,7 @@ + /* The P66 uses a different EINT then the reference design */ + interrupts = <6 9 IRQ_TYPE_EDGE_FALLING>; /* EINT9 (PG9) */ + /* The icn8318 binding expects wake-gpios instead of power-gpios */ ++ /delete-property/ power-gpios; + wake-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */ + touchscreen-size-x = <800>; + touchscreen-size-y = <480>; +diff --git a/arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi b/arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi +index 974410918f35b6..7503074d2877c2 100644 +--- a/arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi ++++ b/arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi +@@ -301,8 +301,9 @@ + mpwm: mpwm@400e8000 { + compatible = "nxp,lpc3220-motor-pwm"; + reg = <0x400e8000 0x78>; ++ clocks = <&clk LPC32XX_CLK_MCPWM>; ++ #pwm-cells = <3>; + status = "disabled"; +- #pwm-cells = <2>; + }; + }; + +diff --git a/arch/arm/kernel/vdso.c b/arch/arm/kernel/vdso.c +index f297d66a8a7624..32b6683b459568 100644 +--- a/arch/arm/kernel/vdso.c ++++ b/arch/arm/kernel/vdso.c +@@ -176,6 +176,7 @@ static void __init patch_vdso(void *ehdr) + vdso_nullpatch_one(&einfo, "__vdso_gettimeofday"); + vdso_nullpatch_one(&einfo, "__vdso_clock_gettime"); + vdso_nullpatch_one(&einfo, "__vdso_clock_gettime64"); ++ vdso_nullpatch_one(&einfo, "__vdso_clock_getres"); + } + } + +diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c +index 79860b23030de3..eb6fc7c61b6e08 100644 +--- a/arch/arm/mach-omap2/control.c ++++ b/arch/arm/mach-omap2/control.c +@@ -732,7 +732,7 @@ int __init omap2_control_base_init(void) + */ + int __init omap_control_init(void) + { +- struct device_node *np, *scm_conf; ++ struct device_node *np, *scm_conf, *clocks_node; + const struct of_device_id *match; + const struct omap_prcm_init_data *data; + int ret; +@@ -753,16 +753,19 @@ int __init omap_control_init(void) + + if (IS_ERR(syscon)) { + ret = PTR_ERR(syscon); +- goto of_node_put; ++ goto err_put_scm_conf; + } + +- if (of_get_child_by_name(scm_conf, "clocks")) { ++ clocks_node = of_get_child_by_name(scm_conf, "clocks"); ++ if (clocks_node) { ++ of_node_put(clocks_node); + ret = omap2_clk_provider_init(scm_conf, + data->index, + syscon, NULL); + if (ret) +- goto of_node_put; ++ goto err_put_scm_conf; + } ++ of_node_put(scm_conf); + } else { + /* No scm_conf found, direct access */ + ret = omap2_clk_provider_init(np, data->index, NULL, +@@ -780,6 +783,9 @@ int __init omap_control_init(void) + + return 0; + ++err_put_scm_conf: ++ if (scm_conf) ++ of_node_put(scm_conf); + of_node_put: + of_node_put(np); + return ret; +diff --git a/arch/arm/mm/physaddr.c b/arch/arm/mm/physaddr.c +index 3f263c840ebc46..1a37ebfacbba96 100644 +--- a/arch/arm/mm/physaddr.c ++++ b/arch/arm/mm/physaddr.c +@@ -38,7 +38,7 @@ static inline bool __virt_addr_valid(unsigned long x) + phys_addr_t __virt_to_phys(unsigned long x) + { + WARN(!__virt_addr_valid(x), +- "virt_to_phys used for non-linear address: %pK (%pS)\n", ++ "virt_to_phys used for non-linear address: %px (%pS)\n", + (void *)x, (void *)x); + + return __virt_to_phys_nodebug(x); +diff --git a/arch/arm64/Kbuild b/arch/arm64/Kbuild +index 5bfbf7d79c99be..d876bc0e542110 100644 +--- a/arch/arm64/Kbuild ++++ b/arch/arm64/Kbuild +@@ -1,4 +1,8 @@ + # SPDX-License-Identifier: GPL-2.0-only ++ ++# Branch profiling isn't noinstr-safe ++subdir-ccflags-$(CONFIG_TRACE_BRANCH_PROFILING) += -DDISABLE_BRANCH_PROFILING ++ + obj-y += kernel/ mm/ net/ + obj-$(CONFIG_KVM) += kvm/ + obj-$(CONFIG_XEN) += xen/ +diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi +index 768d0ed78dbe63..16af71d84a1324 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi +@@ -1894,6 +1894,9 @@ + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_B>; ++ ++ assigned-clocks = <&clkc CLKID_SD_EMMC_B_CLK0>; ++ assigned-clock-rates = <24000000>; + }; + + sd_emmc_c: mmc@7000 { +@@ -1906,6 +1909,9 @@ + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_C>; ++ ++ assigned-clocks = <&clkc CLKID_SD_EMMC_C_CLK0>; ++ assigned-clock-rates = <24000000>; + }; + + usb2_phy1: phy@9020 { +diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi +index 0ff0d090548d0e..c5848363df37ae 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi +@@ -2341,6 +2341,9 @@ + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_A>; ++ ++ assigned-clocks = <&clkc CLKID_SD_EMMC_A_CLK0>; ++ assigned-clock-rates = <24000000>; + }; + + sd_emmc_b: mmc@ffe05000 { +@@ -2353,6 +2356,9 @@ + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_B>; ++ ++ assigned-clocks = <&clkc CLKID_SD_EMMC_B_CLK0>; ++ assigned-clock-rates = <24000000>; + }; + + sd_emmc_c: mmc@ffe07000 { +@@ -2365,6 +2371,9 @@ + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_C>; ++ ++ assigned-clocks = <&clkc CLKID_SD_EMMC_C_CLK0>; ++ assigned-clock-rates = <24000000>; + }; + + usb: usb@ffe09000 { +diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi +index ed00e67e6923a0..851ae89dd17faa 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi +@@ -799,6 +799,9 @@ + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_A>; ++ ++ assigned-clocks = <&clkc CLKID_SD_EMMC_A_CLK0>; ++ assigned-clock-rates = <24000000>; + }; + + &sd_emmc_b { +@@ -807,6 +810,9 @@ + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_B>; ++ ++ assigned-clocks = <&clkc CLKID_SD_EMMC_B_CLK0>; ++ assigned-clock-rates = <24000000>; + }; + + &sd_emmc_c { +@@ -815,6 +821,9 @@ + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_C>; ++ ++ assigned-clocks = <&clkc CLKID_SD_EMMC_C_CLK0>; ++ assigned-clock-rates = <24000000>; + }; + + &simplefb_hdmi { +diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi +index f58d1790de1cb4..f7fafebafd809e 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi +@@ -869,6 +869,9 @@ + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_A>; ++ ++ assigned-clocks = <&clkc CLKID_SD_EMMC_A_CLK0>; ++ assigned-clock-rates = <24000000>; + }; + + &sd_emmc_b { +@@ -877,6 +880,9 @@ + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_B>; ++ ++ assigned-clocks = <&clkc CLKID_SD_EMMC_B_CLK0>; ++ assigned-clock-rates = <24000000>; + }; + + &sd_emmc_c { +@@ -885,6 +891,9 @@ + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_C>; ++ ++ assigned-clocks = <&clkc CLKID_SD_EMMC_C_CLK0>; ++ assigned-clock-rates = <24000000>; + }; + + &simplefb_hdmi { +diff --git a/arch/arm64/boot/dts/apple/t8112-j473.dts b/arch/arm64/boot/dts/apple/t8112-j473.dts +index 06fe257f08be49..4ae1ce919dafc4 100644 +--- a/arch/arm64/boot/dts/apple/t8112-j473.dts ++++ b/arch/arm64/boot/dts/apple/t8112-j473.dts +@@ -21,6 +21,25 @@ + }; + }; + ++/* ++ * Keep the power-domains used for the HDMI port on. ++ */ ++&framebuffer0 { ++ power-domains = <&ps_dispext_cpu0>, <&ps_dptx_ext_phy>; ++}; ++ ++/* ++ * The M2 Mac mini uses dispext for the HDMI output so it's not necessary to ++ * keep disp0 power-domains always-on. ++ */ ++&ps_disp0_sys { ++ /delete-property/ apple,always-on; ++}; ++ ++&ps_disp0_fe { ++ /delete-property/ apple,always-on; ++}; ++ + /* + * Force the bus number assignments so that we can declare some of the + * on-board devices and properties that are populated by the bootloader +diff --git a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts +index 258e90cc16ff3a..5430b62a3b2827 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts ++++ b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts +@@ -810,7 +810,7 @@ + fsl,pins = , + , + , +- ; ++ ; + }; + + pinctrl_hoggpio2: hoggpio2grp { +diff --git a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts +index 53805555dd2d24..a75c6c1928a4a5 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts ++++ b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts +@@ -1724,6 +1724,8 @@ + status = "okay"; + vbus-supply = <&usbc_vbus>; + mode = "otg"; ++ usb-role-switch; ++ role-switch-default-mode = "host"; + }; + + usb3-0 { +diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi +index 0f3f57fb860ec8..74b36cb8bffa8b 100644 +--- a/arch/arm64/boot/dts/qcom/sdm630.dtsi ++++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi +@@ -589,8 +589,8 @@ + }; + + gpu_speed_bin: gpu-speed-bin@41a0 { +- reg = <0x41a2 0x1>; +- bits = <5 7>; ++ reg = <0x41a2 0x2>; ++ bits = <5 8>; + }; + }; + +diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts +index 0a891a0122446c..1164f2cf5bc961 100644 +--- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts ++++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts +@@ -372,6 +372,12 @@ + regulator-initial-mode = ; + }; + ++ vreg_l23a_3p3: ldo23 { ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3312000>; ++ regulator-initial-mode = ; ++ }; ++ + vreg_l24a_3p075: ldo24 { + regulator-min-microvolt = <3088000>; + regulator-max-microvolt = <3088000>; +@@ -852,7 +858,6 @@ + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&qup_spi0_default>; +- cs-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; + + can@0 { + compatible = "microchip,mcp2517fd"; +@@ -1158,6 +1163,7 @@ + vdd-1.8-xo-supply = <&vreg_l7a_1p8>; + vdd-1.3-rfa-supply = <&vreg_l17a_1p3>; + vdd-3.3-ch0-supply = <&vreg_l25a_3p3>; ++ vdd-3.3-ch1-supply = <&vreg_l23a_3p3>; + + qcom,snoc-host-cap-8bit-quirk; + qcom,ath10k-calibration-variant = "Thundercomm_DB845C"; +diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi +index bccc52e01da382..e028b58a30f314 100644 +--- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi ++++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi +@@ -155,7 +155,6 @@ + + gpio = <&tlmm 88 0>; + enable-active-high; +- regulator-boot-on; + }; + }; + +@@ -246,6 +245,7 @@ + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; ++ regulator-boot-on; + }; + + vreg_l14a_1p88: ldo14 { +diff --git a/arch/arm64/boot/dts/qcom/sm6115.dtsi b/arch/arm64/boot/dts/qcom/sm6115.dtsi +index 5c6fcf725473c1..4c6d30404ff132 100644 +--- a/arch/arm64/boot/dts/qcom/sm6115.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm6115.dtsi +@@ -1336,8 +1336,12 @@ + + gpu: gpu@5900000 { + compatible = "qcom,adreno-610.0", "qcom,adreno"; +- reg = <0x0 0x05900000 0x0 0x40000>; +- reg-names = "kgsl_3d0_reg_memory"; ++ reg = <0x0 0x05900000 0x0 0x40000>, ++ <0x0 0x0599e000 0x0 0x1000>, ++ <0x0 0x05961000 0x0 0x800>; ++ reg-names = "kgsl_3d0_reg_memory", ++ "cx_mem", ++ "cx_dbgc"; + + /* There's no (real) GMU, so we have to handle quite a bunch of clocks! */ + clocks = <&gpucc GPU_CC_GX_GFX3D_CLK>, +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +index fb3012a6c9fc30..a1594a436eca63 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +@@ -429,10 +429,6 @@ + status = "okay"; + }; + +-&hdmi_sound { +- status = "okay"; +-}; +- + &i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <4>; +diff --git a/arch/arm64/include/asm/rwonce.h b/arch/arm64/include/asm/rwonce.h +index 56f7b1d4d54b9a..bd5fc880b90908 100644 +--- a/arch/arm64/include/asm/rwonce.h ++++ b/arch/arm64/include/asm/rwonce.h +@@ -62,7 +62,7 @@ + default: \ + atomic = 0; \ + } \ +- atomic ? (typeof(*__x))__u.__val : (*(volatile typeof(__x))__x);\ ++ atomic ? (typeof(*__x))__u.__val : (*(volatile typeof(*__x) *)__x);\ + }) + + #endif /* !BUILD_VDSO */ +diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c +index 2c81e0efaf378e..19518a9da53f8a 100644 +--- a/arch/arm64/kernel/proton-pack.c ++++ b/arch/arm64/kernel/proton-pack.c +@@ -896,6 +896,7 @@ static u8 spectre_bhb_loop_affected(void) + MIDR_ALL_VERSIONS(MIDR_CORTEX_X2), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), ++ MIDR_ALL_VERSIONS(MIDR_HISI_TSV110), + {}, + }; + static const struct midr_range spectre_bhb_k24_list[] = { +diff --git a/arch/arm64/lib/delay.c b/arch/arm64/lib/delay.c +index 5b7890139bc2f8..15a953ac6f0fbf 100644 +--- a/arch/arm64/lib/delay.c ++++ b/arch/arm64/lib/delay.c +@@ -23,9 +23,24 @@ static inline unsigned long xloops_to_cycles(unsigned long xloops) + return (xloops * loops_per_jiffy * HZ) >> 32; + } + ++/* ++ * Force the use of CNTVCT_EL0 in order to have the same base as WFxT. ++ * This avoids some annoying issues when CNTVOFF_EL2 is not reset 0 on a ++ * KVM host running at EL1 until we do a vcpu_put() on the vcpu. When ++ * running at EL2, the effective offset is always 0. ++ * ++ * Note that userspace cannot change the offset behind our back either, ++ * as the vcpu mutex is held as long as KVM_RUN is in progress. ++ */ ++static cycles_t notrace __delay_cycles(void) ++{ ++ guard(preempt_notrace)(); ++ return __arch_counter_get_cntvct_stable(); ++} ++ + void __delay(unsigned long cycles) + { +- cycles_t start = get_cycles(); ++ cycles_t start = __delay_cycles(); + + if (cpus_have_const_cap(ARM64_HAS_WFXT)) { + u64 end = start + cycles; +@@ -35,17 +50,17 @@ void __delay(unsigned long cycles) + * early, use a WFET loop to complete the delay. + */ + wfit(end); +- while ((get_cycles() - start) < cycles) ++ while ((__delay_cycles() - start) < cycles) + wfet(end); + } else if (arch_timer_evtstrm_available()) { + const cycles_t timer_evt_period = + USECS_TO_CYCLES(ARCH_TIMER_EVT_STREAM_PERIOD_US); + +- while ((get_cycles() - start + timer_evt_period) < cycles) ++ while ((__delay_cycles() - start + timer_evt_period) < cycles) + wfe(); + } + +- while ((get_cycles() - start) < cycles) ++ while ((__delay_cycles() - start) < cycles) + cpu_relax(); + } + EXPORT_SYMBOL(__delay); +diff --git a/arch/loongarch/include/asm/topology.h b/arch/loongarch/include/asm/topology.h +index 66128dec0bf6e0..6ff4cdc3d186db 100644 +--- a/arch/loongarch/include/asm/topology.h ++++ b/arch/loongarch/include/asm/topology.h +@@ -11,7 +11,7 @@ + + extern cpumask_t cpus_on_node[]; + +-#define cpumask_of_node(node) (&cpus_on_node[node]) ++#define cpumask_of_node(node) ((node) == NUMA_NO_NODE ? cpu_all_mask : &cpus_on_node[node]) + + struct pci_bus; + extern int pcibus_to_node(struct pci_bus *); +diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c +index 5dfd5d8dfca25f..2e34ece474eece 100644 +--- a/arch/loongarch/kernel/setup.c ++++ b/arch/loongarch/kernel/setup.c +@@ -432,6 +432,7 @@ static void __init arch_mem_init(char **cmdline_p) + PFN_UP(__pa_symbol(&__nosave_end))); + + memblock_dump_all(); ++ memblock_set_bottom_up(false); + + early_memtest(PFN_PHYS(ARCH_PFN_OFFSET), PFN_PHYS(max_low_pfn)); + } +diff --git a/arch/loongarch/kernel/unwind_prologue.c b/arch/loongarch/kernel/unwind_prologue.c +index 929ae240280a5f..c9ee6892d81c7f 100644 +--- a/arch/loongarch/kernel/unwind_prologue.c ++++ b/arch/loongarch/kernel/unwind_prologue.c +@@ -64,7 +64,7 @@ static inline bool scan_handlers(unsigned long entry_offset) + + static inline bool fix_exception(unsigned long pc) + { +-#ifdef CONFIG_NUMA ++#if defined(CONFIG_NUMA) && !defined(CONFIG_PREEMPT_RT) + int cpu; + + for_each_possible_cpu(cpu) { +diff --git a/arch/loongarch/mm/tlb.c b/arch/loongarch/mm/tlb.c +index 526310ec73c7e6..885c9fa447caf6 100644 +--- a/arch/loongarch/mm/tlb.c ++++ b/arch/loongarch/mm/tlb.c +@@ -201,7 +201,7 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep + local_irq_restore(flags); + } + +-static void setup_ptwalker(void) ++static void __no_sanitize_address setup_ptwalker(void) + { + unsigned long pwctl0, pwctl1; + unsigned long pgd_i = 0, pgd_w = 0; +diff --git a/arch/m68k/lib/memmove.c b/arch/m68k/lib/memmove.c +index 6519f7f349f665..e33f00b02e4c0f 100644 +--- a/arch/m68k/lib/memmove.c ++++ b/arch/m68k/lib/memmove.c +@@ -24,6 +24,15 @@ void *memmove(void *dest, const void *src, size_t n) + src = csrc; + n--; + } ++#if defined(CONFIG_M68000) ++ if ((long)src & 1) { ++ char *cdest = dest; ++ const char *csrc = src; ++ for (; n; n--) ++ *cdest++ = *csrc++; ++ return xdest; ++ } ++#endif + if (n > 2 && (long)dest & 2) { + short *sdest = dest; + const short *ssrc = src; +@@ -66,6 +75,15 @@ void *memmove(void *dest, const void *src, size_t n) + src = csrc; + n--; + } ++#if defined(CONFIG_M68000) ++ if ((long)src & 1) { ++ char *cdest = dest; ++ const char *csrc = src; ++ for (; n; n--) ++ *--cdest = *--csrc; ++ return xdest; ++ } ++#endif + if (n > 2 && (long)dest & 2) { + short *sdest = dest; + const short *ssrc = src; +diff --git a/arch/mips/include/asm/mach-loongson64/topology.h b/arch/mips/include/asm/mach-loongson64/topology.h +index 3414a1fd17835e..89bb4deab98a67 100644 +--- a/arch/mips/include/asm/mach-loongson64/topology.h ++++ b/arch/mips/include/asm/mach-loongson64/topology.h +@@ -7,7 +7,7 @@ + #define cpu_to_node(cpu) (cpu_logical_map(cpu) >> 2) + + extern cpumask_t __node_cpumask[]; +-#define cpumask_of_node(node) (&__node_cpumask[node]) ++#define cpumask_of_node(node) ((node) == NUMA_NO_NODE ? cpu_all_mask : &__node_cpumask[node]) + + struct pci_bus; + extern int pcibus_to_node(struct pci_bus *); +diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c +index 6d35d4f7ebe196..55fe0e8295494c 100644 +--- a/arch/mips/kernel/relocate.c ++++ b/arch/mips/kernel/relocate.c +@@ -420,7 +420,20 @@ void *__init relocate_kernel(void) + goto out; + + /* The current thread is now within the relocated image */ ++#ifndef CONFIG_CC_IS_CLANG + __current_thread_info = RELOCATED(&init_thread_union); ++#else ++ /* ++ * LLVM may wrongly restore $gp ($28) in epilog even if it's ++ * intentionally modified. Work around this by using inline ++ * assembly to assign $gp. $gp couldn't be listed as output or ++ * clobber, or LLVM will still restore its original value. ++ * See also LLVM upstream issue ++ * https://github.com/llvm/llvm-project/issues/176546 ++ */ ++ asm volatile("move $28, %0" : : ++ "r" (RELOCATED(&init_thread_union))); ++#endif + + /* Return the new kernel's entry point */ + kernel_entry = RELOCATED(start_kernel); +diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c +index b7f6f782d9a130..ffa4d38ca95df7 100644 +--- a/arch/mips/rb532/devices.c ++++ b/arch/mips/rb532/devices.c +@@ -212,11 +212,12 @@ static struct platform_device rb532_wdt = { + static struct plat_serial8250_port rb532_uart_res[] = { + { + .type = PORT_16550A, +- .membase = (char *)KSEG1ADDR(REGBASE + UART0BASE), ++ .mapbase = REGBASE + UART0BASE, ++ .mapsize = 0x1000, + .irq = UART0_IRQ, + .regshift = 2, + .iotype = UPIO_MEM, +- .flags = UPF_BOOT_AUTOCONF, ++ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, + }, + { + .flags = 0, +diff --git a/arch/openrisc/include/asm/barrier.h b/arch/openrisc/include/asm/barrier.h +index 7538294721bed7..8e592c99090235 100644 +--- a/arch/openrisc/include/asm/barrier.h ++++ b/arch/openrisc/include/asm/barrier.h +@@ -4,6 +4,8 @@ + + #define mb() asm volatile ("l.msync" ::: "memory") + ++#define nop() asm volatile ("l.nop") ++ + #include + + #endif /* __ASM_BARRIER_H */ +diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c +index 8be4558ef33c0e..3cfd81c7e112ec 100644 +--- a/arch/parisc/kernel/drivers.c ++++ b/arch/parisc/kernel/drivers.c +@@ -435,7 +435,7 @@ static struct parisc_device * __init create_tree_node(char id, + dev->dev.dma_mask = &dev->dma_mask; + dev->dev.coherent_dma_mask = dev->dma_mask; + if (device_register(&dev->dev)) { +- kfree(dev); ++ put_device(&dev->dev); + return NULL; + } + +diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c +index ed93bd8c154533..d7b0f233f2cc9e 100644 +--- a/arch/parisc/kernel/process.c ++++ b/arch/parisc/kernel/process.c +@@ -85,6 +85,9 @@ void machine_restart(char *cmd) + #endif + /* set up a new led state on systems shipped with a LED State panel */ + pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN); ++ ++ /* prevent interrupts during reboot */ ++ set_eiem(0); + + /* "Normal" system reset */ + pdc_do_reset(); +diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h +index 514dd056c2c84b..b5709b9aed238f 100644 +--- a/arch/powerpc/include/asm/eeh.h ++++ b/arch/powerpc/include/asm/eeh.h +@@ -289,6 +289,8 @@ void eeh_pe_dev_traverse(struct eeh_pe *root, + void eeh_pe_restore_bars(struct eeh_pe *pe); + const char *eeh_pe_loc_get(struct eeh_pe *pe); + struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe); ++const char *eeh_pe_loc_get_bus(struct pci_bus *bus); ++struct pci_bus *eeh_pe_bus_get_nolock(struct eeh_pe *pe); + + void eeh_show_enabled(void); + int __init eeh_init(struct eeh_ops *ops); +diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h +index ad7e8c5aec3f82..63223b7e520f01 100644 +--- a/arch/powerpc/include/asm/kup.h ++++ b/arch/powerpc/include/asm/kup.h +@@ -134,7 +134,6 @@ static __always_inline void kuap_assert_locked(void) + + static __always_inline void allow_read_from_user(const void __user *from, unsigned long size) + { +- barrier_nospec(); + allow_user_access(NULL, from, size, KUAP_READ); + } + +@@ -146,7 +145,6 @@ static __always_inline void allow_write_to_user(void __user *to, unsigned long s + static __always_inline void allow_read_write_user(void __user *to, const void __user *from, + unsigned long size) + { +- barrier_nospec(); + allow_user_access(to, from, size, KUAP_READ_WRITE); + } + +diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h +index a81bd825087cda..ec7f001d03d017 100644 +--- a/arch/powerpc/include/asm/uaccess.h ++++ b/arch/powerpc/include/asm/uaccess.h +@@ -290,6 +290,7 @@ do { \ + __typeof__(sizeof(*(ptr))) __gu_size = sizeof(*(ptr)); \ + \ + might_fault(); \ ++ barrier_nospec(); \ + allow_read_from_user(__gu_addr, __gu_size); \ + __get_user_size_allowed(__gu_val, __gu_addr, __gu_size, __gu_err); \ + prevent_read_from_user(__gu_addr, __gu_size); \ +@@ -318,6 +319,7 @@ raw_copy_in_user(void __user *to, const void __user *from, unsigned long n) + { + unsigned long ret; + ++ barrier_nospec(); + allow_read_write_user(to, from, n); + ret = __copy_tofrom_user(to, from, n); + prevent_read_write_user(to, from, n); +@@ -404,6 +406,7 @@ static __must_check __always_inline bool user_access_begin(const void __user *pt + + might_fault(); + ++ barrier_nospec(); + allow_read_write_user((void __user *)ptr, ptr, len); + return true; + } +@@ -420,6 +423,7 @@ user_read_access_begin(const void __user *ptr, size_t len) + + might_fault(); + ++ barrier_nospec(); + allow_read_from_user(ptr, len); + return true; + } +diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c +index cc8bedf410ea70..632bf157636ec4 100644 +--- a/arch/powerpc/kernel/eeh_driver.c ++++ b/arch/powerpc/kernel/eeh_driver.c +@@ -846,7 +846,7 @@ void eeh_handle_normal_event(struct eeh_pe *pe) + + pci_lock_rescan_remove(); + +- bus = eeh_pe_bus_get(pe); ++ bus = eeh_pe_bus_get_nolock(pe); + if (!bus) { + pr_err("%s: Cannot find PCI bus for PHB#%x-PE#%x\n", + __func__, pe->phb->global_number, pe->addr); +@@ -877,14 +877,15 @@ void eeh_handle_normal_event(struct eeh_pe *pe) + /* Log the event */ + if (pe->type & EEH_PE_PHB) { + pr_err("EEH: Recovering PHB#%x, location: %s\n", +- pe->phb->global_number, eeh_pe_loc_get(pe)); ++ pe->phb->global_number, eeh_pe_loc_get_bus(bus)); + } else { + struct eeh_pe *phb_pe = eeh_phb_pe_get(pe->phb); + + pr_err("EEH: Recovering PHB#%x-PE#%x\n", + pe->phb->global_number, pe->addr); + pr_err("EEH: PE location: %s, PHB location: %s\n", +- eeh_pe_loc_get(pe), eeh_pe_loc_get(phb_pe)); ++ eeh_pe_loc_get_bus(bus), ++ eeh_pe_loc_get_bus(eeh_pe_bus_get_nolock(phb_pe))); + } + + #ifdef CONFIG_STACKTRACE +@@ -1089,7 +1090,7 @@ recover_failed: + eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true); + eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED); + +- bus = eeh_pe_bus_get(pe); ++ bus = eeh_pe_bus_get_nolock(pe); + if (bus) + pci_hp_remove_devices(bus); + else +@@ -1213,7 +1214,7 @@ void eeh_handle_special_event(void) + (phb_pe->state & EEH_PE_RECOVERING)) + continue; + +- bus = eeh_pe_bus_get(phb_pe); ++ bus = eeh_pe_bus_get_nolock(phb_pe); + if (!bus) { + pr_err("%s: Cannot find PCI bus for " + "PHB#%x-PE#%x\n", +diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c +index 08095aeba5c983..b10fcca5204003 100644 +--- a/arch/powerpc/kernel/eeh_pe.c ++++ b/arch/powerpc/kernel/eeh_pe.c +@@ -812,6 +812,24 @@ void eeh_pe_restore_bars(struct eeh_pe *pe) + const char *eeh_pe_loc_get(struct eeh_pe *pe) + { + struct pci_bus *bus = eeh_pe_bus_get(pe); ++ return eeh_pe_loc_get_bus(bus); ++} ++ ++/** ++ * eeh_pe_loc_get_bus - Retrieve location code binding to the given PCI bus ++ * @bus: PCI bus ++ * ++ * Retrieve the location code associated with the given PCI bus. If the bus ++ * is a root bus, the location code is fetched from the PHB device tree node ++ * or root port. Otherwise, the location code is obtained from the device ++ * tree node of the upstream bridge of the bus. The function walks up the ++ * bus hierarchy if necessary, checking each node for the appropriate ++ * location code property ("ibm,io-base-loc-code" for root buses, ++ * "ibm,slot-location-code" for others). If no location code is found, ++ * returns "N/A". ++ */ ++const char *eeh_pe_loc_get_bus(struct pci_bus *bus) ++{ + struct device_node *dn; + const char *loc = NULL; + +@@ -838,8 +856,9 @@ const char *eeh_pe_loc_get(struct eeh_pe *pe) + } + + /** +- * eeh_pe_bus_get - Retrieve PCI bus according to the given PE ++ * _eeh_pe_bus_get - Retrieve PCI bus according to the given PE + * @pe: EEH PE ++ * @do_lock: Is the caller already held the pci_lock_rescan_remove? + * + * Retrieve the PCI bus according to the given PE. Basically, + * there're 3 types of PEs: PHB/Bus/Device. For PHB PE, the +@@ -847,7 +866,7 @@ const char *eeh_pe_loc_get(struct eeh_pe *pe) + * returned for BUS PE. However, we don't have associated PCI + * bus for DEVICE PE. + */ +-struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) ++static struct pci_bus *_eeh_pe_bus_get(struct eeh_pe *pe, bool do_lock) + { + struct eeh_dev *edev; + struct pci_dev *pdev; +@@ -862,11 +881,58 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) + + /* Retrieve the parent PCI bus of first (top) PCI device */ + edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, entry); +- pci_lock_rescan_remove(); ++ if (do_lock) ++ pci_lock_rescan_remove(); + pdev = eeh_dev_to_pci_dev(edev); + if (pdev) + bus = pdev->bus; +- pci_unlock_rescan_remove(); ++ if (do_lock) ++ pci_unlock_rescan_remove(); + + return bus; + } ++ ++/** ++ * eeh_pe_bus_get - Retrieve PCI bus associated with the given EEH PE, locking ++ * if needed ++ * @pe: Pointer to the EEH PE ++ * ++ * This function is a wrapper around _eeh_pe_bus_get(), which retrieves the PCI ++ * bus associated with the provided EEH PE structure. It acquires the PCI ++ * rescans lock to ensure safe access to shared data during the retrieval ++ * process. This function should be used when the caller requires the PCI bus ++ * while holding the rescan/remove lock, typically during operations that modify ++ * or inspect PCIe device state in a safe manner. ++ * ++ * RETURNS: ++ * A pointer to the PCI bus associated with the EEH PE, or NULL if none found. ++ */ ++ ++struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) ++{ ++ return _eeh_pe_bus_get(pe, true); ++} ++ ++/** ++ * eeh_pe_bus_get_nolock - Retrieve PCI bus associated with the given EEH PE ++ * without locking ++ * @pe: Pointer to the EEH PE ++ * ++ * This function is a variant of _eeh_pe_bus_get() that retrieves the PCI bus ++ * associated with the specified EEH PE without acquiring the ++ * pci_lock_rescan_remove lock. It should only be used when the caller can ++ * guarantee safe access to PE structures without the need for that lock, ++ * typically in contexts where the lock is already held locking is otherwise ++ * managed. ++ * ++ * RETURNS: ++ * pointer to the PCI bus associated with the EEH PE, or NULL if none is found. ++ * ++ * NOTE: ++ * Use this function carefully to avoid race conditions and data corruption. ++ */ ++ ++struct pci_bus *eeh_pe_bus_get_nolock(struct eeh_pe *pe) ++{ ++ return _eeh_pe_bus_get(pe, false); ++} +diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c +index 4e4870031265c7..ab99a3e7f99728 100644 +--- a/arch/powerpc/kernel/smp.c ++++ b/arch/powerpc/kernel/smp.c +@@ -830,6 +830,8 @@ static int parse_thread_groups(struct device_node *dn, + + count = of_property_count_u32_elems(dn, "ibm,thread-groups"); + thread_group_array = kcalloc(count, sizeof(u32), GFP_KERNEL); ++ if (!thread_group_array) ++ return -ENOMEM; + ret = of_property_read_u32_array(dn, "ibm,thread-groups", + thread_group_array, count); + if (ret) +diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig +index e99dae26500d26..3b2625eb34c5a1 100644 +--- a/arch/s390/Kconfig ++++ b/arch/s390/Kconfig +@@ -231,6 +231,7 @@ config S390 + select SPARSE_IRQ + select SWIOTLB + select SYSCTL_EXCEPTION_TRACE ++ select SYSTEM_DATA_VERIFICATION if KEXEC_SIG + select THREAD_INFO_IN_TASK + select TRACE_IRQFLAGS_SUPPORT + select TTY +@@ -254,7 +255,7 @@ config ARCH_SUPPORTS_KEXEC_FILE + def_bool y + + config ARCH_SUPPORTS_KEXEC_SIG +- def_bool MODULE_SIG_FORMAT ++ def_bool y + + config ARCH_SUPPORTS_KEXEC_PURGATORY + def_bool y +diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c +index e52c89739bc9a1..c6cac49f3ae726 100644 +--- a/arch/s390/kernel/perf_cpum_sf.c ++++ b/arch/s390/kernel/perf_cpum_sf.c +@@ -925,7 +925,7 @@ static bool is_callchain_event(struct perf_event *event) + u64 sample_type = event->attr.sample_type; + + return sample_type & (PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | +- PERF_SAMPLE_STACK_USER); ++ PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_STACK_USER); + } + + static int cpumsf_pmu_event_init(struct perf_event *event) +diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c +index 777362cb4ea80b..d4c7c4ef102d8c 100644 +--- a/arch/s390/pci/pci.c ++++ b/arch/s390/pci/pci.c +@@ -206,24 +206,33 @@ int zpci_fmb_disable_device(struct zpci_dev *zdev) + static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len) + { + u64 req = ZPCI_CREATE_REQ(zdev->fh, ZPCI_PCIAS_CFGSPC, len); ++ int rc = -ENODEV; + u64 data; +- int rc; ++ ++ if (!zdev_enabled(zdev)) ++ goto out_err; + + rc = __zpci_load(&data, req, offset); +- if (!rc) { +- data = le64_to_cpu((__force __le64) data); +- data >>= (8 - len) * 8; +- *val = (u32) data; +- } else +- *val = 0xffffffff; ++ if (rc) ++ goto out_err; ++ data = le64_to_cpu((__force __le64)data); ++ data >>= (8 - len) * 8; ++ *val = (u32)data; ++ return 0; ++ ++out_err: ++ PCI_SET_ERROR_RESPONSE(val); + return rc; + } + + static int zpci_cfg_store(struct zpci_dev *zdev, int offset, u32 val, u8 len) + { + u64 req = ZPCI_CREATE_REQ(zdev->fh, ZPCI_PCIAS_CFGSPC, len); ++ int rc = -ENODEV; + u64 data = val; +- int rc; ++ ++ if (!zdev_enabled(zdev)) ++ return rc; + + data <<= (8 - len) * 8; + data = (__force u64) cpu_to_le64(data); +diff --git a/arch/s390/purgatory/Makefile b/arch/s390/purgatory/Makefile +index fe7e71f91711b2..0cbfa716a64a70 100644 +--- a/arch/s390/purgatory/Makefile ++++ b/arch/s390/purgatory/Makefile +@@ -29,6 +29,7 @@ KBUILD_CFLAGS += -fno-stack-protector + KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING + KBUILD_CFLAGS += $(CLANG_FLAGS) + KBUILD_CFLAGS += $(call cc-option,-fno-PIE) ++KBUILD_CFLAGS += $(call cc-option, -Wno-default-const-init-unsafe) + KBUILD_AFLAGS := $(filter-out -DCC_USING_EXPOLINE,$(KBUILD_AFLAGS)) + + # Since we link purgatory with -r unresolved symbols are not checked, so we +diff --git a/arch/sparc/include/uapi/asm/ioctls.h b/arch/sparc/include/uapi/asm/ioctls.h +index 7fd2f5873c9e7a..a8bbdf9877a41a 100644 +--- a/arch/sparc/include/uapi/asm/ioctls.h ++++ b/arch/sparc/include/uapi/asm/ioctls.h +@@ -5,10 +5,10 @@ + #include + + /* Big T */ +-#define TCGETA _IOR('T', 1, struct termio) +-#define TCSETA _IOW('T', 2, struct termio) +-#define TCSETAW _IOW('T', 3, struct termio) +-#define TCSETAF _IOW('T', 4, struct termio) ++#define TCGETA 0x40125401 /* _IOR('T', 1, struct termio) */ ++#define TCSETA 0x80125402 /* _IOW('T', 2, struct termio) */ ++#define TCSETAW 0x80125403 /* _IOW('T', 3, struct termio) */ ++#define TCSETAF 0x80125404 /* _IOW('T', 4, struct termio) */ + #define TCSBRK _IO('T', 5) + #define TCXONC _IO('T', 6) + #define TCFLSH _IO('T', 7) +diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c +index 0442ab00518d3c..7d69877511fac9 100644 +--- a/arch/sparc/kernel/process.c ++++ b/arch/sparc/kernel/process.c +@@ -17,14 +17,18 @@ + + asmlinkage long sparc_fork(struct pt_regs *regs) + { +- unsigned long orig_i1 = regs->u_regs[UREG_I1]; ++ unsigned long orig_i1; + long ret; + struct kernel_clone_args args = { + .exit_signal = SIGCHLD, +- /* Reuse the parent's stack for the child. */ +- .stack = regs->u_regs[UREG_FP], + }; + ++ synchronize_user_stack(); ++ ++ orig_i1 = regs->u_regs[UREG_I1]; ++ /* Reuse the parent's stack for the child. */ ++ args.stack = regs->u_regs[UREG_FP]; ++ + ret = kernel_clone(&args); + + /* If we get an error and potentially restart the system +@@ -40,16 +44,19 @@ asmlinkage long sparc_fork(struct pt_regs *regs) + + asmlinkage long sparc_vfork(struct pt_regs *regs) + { +- unsigned long orig_i1 = regs->u_regs[UREG_I1]; ++ unsigned long orig_i1; + long ret; +- + struct kernel_clone_args args = { + .flags = CLONE_VFORK | CLONE_VM, + .exit_signal = SIGCHLD, +- /* Reuse the parent's stack for the child. */ +- .stack = regs->u_regs[UREG_FP], + }; + ++ synchronize_user_stack(); ++ ++ orig_i1 = regs->u_regs[UREG_I1]; ++ /* Reuse the parent's stack for the child. */ ++ args.stack = regs->u_regs[UREG_FP]; ++ + ret = kernel_clone(&args); + + /* If we get an error and potentially restart the system +@@ -65,15 +72,18 @@ asmlinkage long sparc_vfork(struct pt_regs *regs) + + asmlinkage long sparc_clone(struct pt_regs *regs) + { +- unsigned long orig_i1 = regs->u_regs[UREG_I1]; +- unsigned int flags = lower_32_bits(regs->u_regs[UREG_I0]); ++ unsigned long orig_i1; ++ unsigned int flags; + long ret; ++ struct kernel_clone_args args = {0}; + +- struct kernel_clone_args args = { +- .flags = (flags & ~CSIGNAL), +- .exit_signal = (flags & CSIGNAL), +- .tls = regs->u_regs[UREG_I3], +- }; ++ synchronize_user_stack(); ++ ++ orig_i1 = regs->u_regs[UREG_I1]; ++ flags = lower_32_bits(regs->u_regs[UREG_I0]); ++ args.flags = (flags & ~CSIGNAL); ++ args.exit_signal = (flags & CSIGNAL); ++ args.tls = regs->u_regs[UREG_I3]; + + #ifdef CONFIG_COMPAT + if (test_thread_flag(TIF_32BIT)) { +diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c +index b12bef0ff7bb6f..4b91b41df52070 100644 +--- a/arch/x86/hyperv/hv_vtl.c ++++ b/arch/x86/hyperv/hv_vtl.c +@@ -68,7 +68,7 @@ static void hv_vtl_ap_entry(void) + + static int hv_vtl_bringup_vcpu(u32 target_vp_index, int cpu, u64 eip_ignored) + { +- u64 status; ++ u64 status, rsp, rip; + int ret = 0; + struct hv_enable_vp_vtl *input; + unsigned long irq_flags; +@@ -81,9 +81,11 @@ static int hv_vtl_bringup_vcpu(u32 target_vp_index, int cpu, u64 eip_ignored) + struct desc_struct *gdt; + + struct task_struct *idle = idle_thread_get(cpu); +- u64 rsp = (unsigned long)idle->thread.sp; ++ if (IS_ERR(idle)) ++ return PTR_ERR(idle); + +- u64 rip = (u64)&hv_vtl_ap_entry; ++ rsp = (unsigned long)idle->thread.sp; ++ rip = (u64)&hv_vtl_ap_entry; + + native_store_gdt(&gdt_ptr); + store_idt(&idt_ptr); +diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c +index a61c12c0127097..b1f10084474ad5 100644 +--- a/arch/x86/kernel/kexec-bzimage64.c ++++ b/arch/x86/kernel/kexec-bzimage64.c +@@ -184,6 +184,13 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr, + struct efi_info *current_ei = &boot_params.efi_info; + struct efi_info *ei = ¶ms->efi_info; + ++ if (!params->acpi_rsdp_addr) { ++ if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) ++ params->acpi_rsdp_addr = efi.acpi20; ++ else if (efi.acpi != EFI_INVALID_TABLE_ADDR) ++ params->acpi_rsdp_addr = efi.acpi; ++ } ++ + if (!efi_enabled(EFI_RUNTIME_SERVICES)) + return 0; + +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index eb129277dcdd64..df74f865c9f121 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -372,9 +372,15 @@ int __init ima_free_kexec_buffer(void) + + int __init ima_get_kexec_buffer(void **addr, size_t *size) + { ++ int ret; ++ + if (!ima_kexec_buffer_size) + return -ENOENT; + ++ ret = ima_validate_range(ima_kexec_buffer_phys, ima_kexec_buffer_size); ++ if (ret) ++ return ret; ++ + *addr = __va(ima_kexec_buffer_phys); + *size = ima_kexec_buffer_size; + +diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c +index 97ec7781eb671f..eebfea13228555 100644 +--- a/arch/x86/kvm/svm/nested.c ++++ b/arch/x86/kvm/svm/nested.c +@@ -1758,10 +1758,9 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, + * thus MMU might not be initialized correctly. + * Set it again to fix this. + */ +- + ret = nested_svm_load_cr3(&svm->vcpu, vcpu->arch.cr3, + nested_npt_enabled(svm), false); +- if (WARN_ON_ONCE(ret)) ++ if (ret) + goto out_free; + + svm->nested.force_msr_bitmap_recalc = true; +diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c +index dd4236a6bd94d2..9ddd1ee5f31234 100644 +--- a/arch/x86/kvm/svm/svm.c ++++ b/arch/x86/kvm/svm/svm.c +@@ -2299,12 +2299,13 @@ static int vmload_vmsave_interception(struct kvm_vcpu *vcpu, bool vmload) + + ret = kvm_skip_emulated_instruction(vcpu); + ++ /* KVM always performs VMLOAD/VMSAVE on VMCB01 (see __svm_vcpu_run()) */ + if (vmload) { +- svm_copy_vmloadsave_state(svm->vmcb, vmcb12); ++ svm_copy_vmloadsave_state(svm->vmcb01.ptr, vmcb12); + svm->sysenter_eip_hi = 0; + svm->sysenter_esp_hi = 0; + } else { +- svm_copy_vmloadsave_state(vmcb12, svm->vmcb); ++ svm_copy_vmloadsave_state(vmcb12, svm->vmcb01.ptr); + } + + kvm_vcpu_unmap(vcpu, &map, true); +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 89df215ebf2842..00bbee40dbec2a 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -11437,9 +11437,11 @@ static void __get_sregs2(struct kvm_vcpu *vcpu, struct kvm_sregs2 *sregs2) + return; + + if (is_pae_paging(vcpu)) { ++ kvm_vcpu_srcu_read_lock(vcpu); + for (i = 0 ; i < 4 ; i++) + sregs2->pdptrs[i] = kvm_pdptr_read(vcpu, i); + sregs2->flags |= KVM_SREGS2_FLAGS_PDPTRS_VALID; ++ kvm_vcpu_srcu_read_unlock(vcpu); + } + } + +diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S +index fc46b4dfbd7475..10deae1a30c652 100644 +--- a/arch/x86/platform/pvh/head.S ++++ b/arch/x86/platform/pvh/head.S +@@ -70,10 +70,12 @@ SYM_CODE_START_LOCAL(pvh_start_xen) + + mov $_pa(early_stack_end), %esp + ++#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) + /* Enable PAE mode. */ + mov %cr4, %eax + orl $X86_CR4_PAE, %eax + mov %eax, %cr4 ++#endif + + #ifdef CONFIG_X86_64 + /* Enable Long mode. */ +diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c +index 638de313fc4ed5..03fb16dc0b926e 100644 +--- a/arch/x86/xen/enlighten.c ++++ b/arch/x86/xen/enlighten.c +@@ -480,7 +480,7 @@ int __init arch_xen_unpopulated_init(struct resource **res) + * driver to know how much of the physmap is unpopulated and + * set an accurate initial memory target. + */ +- xen_released_pages += xen_extra_mem[i].n_pfns; ++ xen_unpopulated_pages += xen_extra_mem[i].n_pfns; + /* Zero so region is not also added to the balloon driver. */ + xen_extra_mem[i].n_pfns = 0; + } +diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h +index 6e4c6bd622033b..11fa577af6b488 100644 +--- a/arch/x86/xen/mmu.h ++++ b/arch/x86/xen/mmu.h +@@ -17,10 +17,6 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn); + + void set_pte_mfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags); + +-pte_t xen_ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep); +-void xen_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, +- pte_t *ptep, pte_t pte); +- + unsigned long xen_read_cr2_direct(void); + + extern void xen_init_mmu_ops(void); +diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c +index 88a722954f3f78..23f30ca52816c8 100644 +--- a/arch/x86/xen/mmu_pv.c ++++ b/arch/x86/xen/mmu_pv.c +@@ -173,7 +173,7 @@ static int alloc_discontig_frames(unsigned int order) + * looking at another vcpu's cr3 value, it should use this variable. + */ + DEFINE_PER_CPU(unsigned long, xen_cr3); /* cr3 stored as physaddr */ +-DEFINE_PER_CPU(unsigned long, xen_current_cr3); /* actual vcpu cr3 */ ++static DEFINE_PER_CPU(unsigned long, xen_current_cr3); /* actual vcpu cr3 */ + + static phys_addr_t xen_pt_base, xen_pt_size __initdata; + +@@ -350,16 +350,17 @@ static void xen_set_pte(pte_t *ptep, pte_t pteval) + __xen_set_pte(ptep, pteval); + } + +-pte_t xen_ptep_modify_prot_start(struct vm_area_struct *vma, +- unsigned long addr, pte_t *ptep) ++static pte_t xen_ptep_modify_prot_start(struct vm_area_struct *vma, ++ unsigned long addr, pte_t *ptep) + { + /* Just return the pte as-is. We preserve the bits on commit */ + trace_xen_mmu_ptep_modify_prot_start(vma->vm_mm, addr, ptep, *ptep); + return *ptep; + } + +-void xen_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, +- pte_t *ptep, pte_t pte) ++static void xen_ptep_modify_prot_commit(struct vm_area_struct *vma, ++ unsigned long addr, ++ pte_t *ptep, pte_t pte) + { + struct mmu_update u; + +diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h +index 607f3a42fe3b1b..af418489335cd7 100644 +--- a/arch/x86/xen/xen-ops.h ++++ b/arch/x86/xen/xen-ops.h +@@ -23,7 +23,6 @@ void xen_copy_trap_info(struct trap_info *traps); + + DECLARE_PER_CPU_ALIGNED(struct vcpu_info, xen_vcpu_info); + DECLARE_PER_CPU(unsigned long, xen_cr3); +-DECLARE_PER_CPU(unsigned long, xen_current_cr3); + + extern struct start_info *xen_start_info; + extern struct shared_info xen_dummy_shared_info; +diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c +index c3b5930106b288..e0677043f00de3 100644 +--- a/block/blk-mq-debugfs.c ++++ b/block/blk-mq-debugfs.c +@@ -730,8 +730,10 @@ void blk_mq_debugfs_register_hctxs(struct request_queue *q) + struct blk_mq_hw_ctx *hctx; + unsigned long i; + ++ mutex_lock(&q->debugfs_mutex); + queue_for_each_hw_ctx(q, hctx, i) + blk_mq_debugfs_register_hctx(q, hctx); ++ mutex_unlock(&q->debugfs_mutex); + } + + void blk_mq_debugfs_unregister_hctxs(struct request_queue *q) +diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c +index c0f9cf9768ea9a..5e409f86f07098 100644 +--- a/drivers/acpi/acpi_processor.c ++++ b/drivers/acpi/acpi_processor.c +@@ -39,6 +39,7 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev) + { + u8 value1 = 0; + u8 value2 = 0; ++ struct pci_dev *ide_dev = NULL, *isa_dev = NULL; + + + if (!dev) +@@ -96,12 +97,12 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev) + * each IDE controller's DMA status to make sure we catch all + * DMA activity. + */ +- dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, ++ ide_dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB, + PCI_ANY_ID, PCI_ANY_ID, NULL); +- if (dev) { +- errata.piix4.bmisx = pci_resource_start(dev, 4); +- pci_dev_put(dev); ++ if (ide_dev) { ++ errata.piix4.bmisx = pci_resource_start(ide_dev, 4); ++ pci_dev_put(ide_dev); + } + + /* +@@ -113,24 +114,25 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev) + * disable C3 support if this is enabled, as some legacy + * devices won't operate well if fast DMA is disabled. + */ +- dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, ++ isa_dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_0, + PCI_ANY_ID, PCI_ANY_ID, NULL); +- if (dev) { +- pci_read_config_byte(dev, 0x76, &value1); +- pci_read_config_byte(dev, 0x77, &value2); ++ if (isa_dev) { ++ pci_read_config_byte(isa_dev, 0x76, &value1); ++ pci_read_config_byte(isa_dev, 0x77, &value2); + if ((value1 & 0x80) || (value2 & 0x80)) + errata.piix4.fdma = 1; +- pci_dev_put(dev); ++ pci_dev_put(isa_dev); + } + + break; + } + +- if (errata.piix4.bmisx) +- dev_dbg(&dev->dev, "Bus master activity detection (BM-IDE) erratum enabled\n"); +- if (errata.piix4.fdma) +- dev_dbg(&dev->dev, "Type-F DMA livelock erratum (C3 disabled)\n"); ++ if (ide_dev) ++ dev_dbg(&ide_dev->dev, "Bus master activity detection (BM-IDE) erratum enabled\n"); ++ ++ if (isa_dev) ++ dev_dbg(&isa_dev->dev, "Type-F DMA livelock erratum (C3 disabled)\n"); + + return 0; + } +diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c +index cf53b9535f18e0..7788c27ccf4610 100644 +--- a/drivers/acpi/acpica/evregion.c ++++ b/drivers/acpi/acpica/evregion.c +@@ -163,7 +163,9 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, + return_ACPI_STATUS(AE_NOT_EXIST); + } + +- if (region_obj->region.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) { ++ if (field_obj ++ && region_obj->region.space_id == ++ ACPI_ADR_SPACE_PLATFORM_COMM) { + struct acpi_pcc_info *ctx = + handler_desc->address_space.context; + +diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c +index d3091f619909e8..41758343657ddb 100644 +--- a/drivers/acpi/acpica/exoparg3.c ++++ b/drivers/acpi/acpica/exoparg3.c +@@ -10,6 +10,7 @@ + #include + #include "accommon.h" + #include "acinterp.h" ++#include + #include "acparser.h" + #include "amlcode.h" + +@@ -51,8 +52,7 @@ ACPI_MODULE_NAME("exoparg3") + acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) + { + union acpi_operand_object **operand = &walk_state->operands[0]; +- struct acpi_signal_fatal_info *fatal; +- acpi_status status = AE_OK; ++ struct acpi_signal_fatal_info fatal; + + ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R, + acpi_ps_get_opcode_name(walk_state->opcode)); +@@ -60,28 +60,23 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) + switch (walk_state->opcode) { + case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */ + +- ACPI_DEBUG_PRINT((ACPI_DB_INFO, +- "FatalOp: Type %X Code %X Arg %X " +- "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", +- (u32)operand[0]->integer.value, +- (u32)operand[1]->integer.value, +- (u32)operand[2]->integer.value)); +- +- fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info)); +- if (fatal) { +- fatal->type = (u32) operand[0]->integer.value; +- fatal->code = (u32) operand[1]->integer.value; +- fatal->argument = (u32) operand[2]->integer.value; +- } ++ fatal.type = (u32)operand[0]->integer.value; ++ fatal.code = (u32)operand[1]->integer.value; ++ fatal.argument = (u32)operand[2]->integer.value; + +- /* Always signal the OS! */ ++ ACPI_BIOS_ERROR((AE_INFO, ++ "Fatal ACPI BIOS error (Type 0x%X Code 0x%X Arg 0x%X)\n", ++ fatal.type, fatal.code, fatal.argument)); + +- status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal); ++ /* Always signal the OS! */ + +- /* Might return while OS is shutting down, just continue */ ++ acpi_os_signal(ACPI_SIGNAL_FATAL, &fatal); + +- ACPI_FREE(fatal); +- goto cleanup; ++ /* ++ * Might return while OS is shutting down, so abort the AML execution ++ * by returning an error. ++ */ ++ return_ACPI_STATUS(AE_ERROR); + + case AML_EXTERNAL_OP: + /* +@@ -93,21 +88,16 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) + * wrong if an external opcode ever gets here. + */ + ACPI_ERROR((AE_INFO, "Executed External Op")); +- status = AE_OK; +- goto cleanup; ++ ++ return_ACPI_STATUS(AE_OK); + + default: + + ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X", + walk_state->opcode)); + +- status = AE_AML_BAD_OPCODE; +- goto cleanup; ++ return_ACPI_STATUS(AE_AML_BAD_OPCODE); + } +- +-cleanup: +- +- return_ACPI_STATUS(status); + } + + /******************************************************************************* +diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c +index e768dfd345fb28..9c0d256fc72b11 100644 +--- a/drivers/acpi/apei/ghes.c ++++ b/drivers/acpi/apei/ghes.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -290,6 +291,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic) + error_block_length = GHES_ESTATUS_MAX_SIZE; + } + ghes->estatus = kmalloc(error_block_length, GFP_KERNEL); ++ ghes->estatus_length = error_block_length; + if (!ghes->estatus) { + rc = -ENOMEM; + goto err_unmap_status_addr; +@@ -361,13 +363,15 @@ static int __ghes_check_estatus(struct ghes *ghes, + struct acpi_hest_generic_status *estatus) + { + u32 len = cper_estatus_len(estatus); ++ u32 max_len = min(ghes->generic->error_block_length, ++ ghes->estatus_length); + + if (len < sizeof(*estatus)) { + pr_warn_ratelimited(FW_WARN GHES_PFX "Truncated error status block!\n"); + return -EIO; + } + +- if (len > ghes->generic->error_block_length) { ++ if (!len || len > max_len) { + pr_warn_ratelimited(FW_WARN GHES_PFX "Invalid error status block length!\n"); + return -EIO; + } +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index 16ac219ae6fe51..0bf3861cf79b13 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -347,7 +347,7 @@ static int send_pcc_cmd(int pcc_ss_id, u16 cmd) + end: + if (cmd == CMD_WRITE) { + if (unlikely(ret)) { +- for_each_possible_cpu(i) { ++ for_each_online_cpu(i) { + struct cpc_desc *desc = per_cpu(cpc_desc_ptr, i); + + if (!desc) +@@ -509,7 +509,7 @@ int acpi_get_psd_map(unsigned int cpu, struct cppc_cpudata *cpu_data) + else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY) + cpu_data->shared_type = CPUFREQ_SHARED_TYPE_ANY; + +- for_each_possible_cpu(i) { ++ for_each_online_cpu(i) { + if (i == cpu) + continue; + +diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c +index c2c70139c4f1d9..ff5fcd541e50fb 100644 +--- a/drivers/acpi/power.c ++++ b/drivers/acpi/power.c +@@ -1035,6 +1035,19 @@ static const struct dmi_system_id dmi_leave_unused_power_resources_on[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE Click Mini L9W-B"), + }, + }, ++ { ++ /* ++ * THUNDEROBOT ZERO laptop: Due to its SSDT table bug, power ++ * resource 'PXP' will be shut down on initialization, making ++ * the NVMe #2 and the NVIDIA dGPU both unavailable (they're ++ * both controlled by 'PXP'). ++ */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "THUNDEROBOT"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "ZERO"), ++ } ++ ++ }, + {} + }; + +diff --git a/drivers/android/binder.c b/drivers/android/binder.c +index 43f11f66970b25..73408a5b45b3b0 100644 +--- a/drivers/android/binder.c ++++ b/drivers/android/binder.c +@@ -4211,7 +4211,7 @@ static int binder_thread_write(struct binder_proc *proc, + } + } + binder_debug(BINDER_DEBUG_DEAD_BINDER, +- "%d:%d BC_DEAD_BINDER_DONE %016llx found %pK\n", ++ "%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n", + proc->pid, thread->pid, (u64)cookie, + death); + if (death == NULL) { +diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c +index 34c27223cb7dd2..6a4be6087ae6b1 100644 +--- a/drivers/android/binder_alloc.c ++++ b/drivers/android/binder_alloc.c +@@ -79,7 +79,7 @@ static void binder_insert_free_buffer(struct binder_alloc *alloc, + new_buffer_size = binder_alloc_buffer_size(alloc, new_buffer); + + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "%d: add free buffer, size %zd, at %pK\n", ++ "%d: add free buffer, size %zd, at %p\n", + alloc->pid, new_buffer_size, new_buffer); + + while (*p) { +@@ -474,7 +474,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked( + } + + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n", ++ "%d: binder_alloc_buf size %zd got buffer %p size %zd\n", + alloc->pid, size, buffer, buffer_size); + + has_page_addr = (void __user *) +@@ -646,7 +646,7 @@ static void binder_free_buf_locked(struct binder_alloc *alloc, + ALIGN(buffer->extra_buffers_size, sizeof(void *)); + + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "%d: binder_free_buf %pK size %zd buffer_size %zd\n", ++ "%d: binder_free_buf %p size %zd buffer_size %zd\n", + alloc->pid, buffer, size, buffer_size); + + BUG_ON(buffer->free); +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index d5e713f284b71d..91c6291b01f4e0 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -2318,6 +2318,24 @@ static bool ata_dev_check_adapter(struct ata_device *dev, + return false; + } + ++bool ata_adapter_is_online(struct ata_port *ap) ++{ ++ struct device *dev; ++ ++ if (!ap || !ap->host) ++ return false; ++ ++ dev = ap->host->dev; ++ if (!dev) ++ return false; ++ ++ if (dev_is_pci(dev) && ++ pci_channel_offline(to_pci_dev(dev))) ++ return false; ++ ++ return true; ++} ++ + static int ata_dev_config_ncq(struct ata_device *dev, + char *desc, size_t desc_sz) + { +@@ -5023,6 +5041,12 @@ void ata_qc_issue(struct ata_queued_cmd *qc) + qc->flags |= ATA_QCFLAG_ACTIVE; + ap->qc_active |= 1ULL << qc->tag; + ++ /* Make sure the device is still accessible. */ ++ if (!ata_adapter_is_online(ap)) { ++ qc->err_mask |= AC_ERR_HOST_BUS; ++ goto sys_err; ++ } ++ + /* + * We guarantee to LLDs that they will have at least one + * non-zero sg if the command is a data command. +diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c +index 3263fc13491e1d..fc2c508c41bd42 100644 +--- a/drivers/ata/libata-eh.c ++++ b/drivers/ata/libata-eh.c +@@ -723,7 +723,8 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap) + spin_unlock_irqrestore(ap->lock, flags); + + /* invoke EH, skip if unloading or suspended */ +- if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED))) ++ if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED)) && ++ ata_adapter_is_online(ap)) + ap->ops->error_handler(ap); + else { + /* if unloading, commence suicide */ +diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c +index 8f6a7acf770e4a..300818cb1478a2 100644 +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -1736,6 +1736,42 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) + ata_qc_done(qc); + } + ++static int ata_scsi_qc_issue(struct ata_port *ap, struct ata_queued_cmd *qc) ++{ ++ int ret; ++ ++ if (!ap->ops->qc_defer) ++ goto issue; ++ ++ /* Check if the command needs to be deferred. */ ++ ret = ap->ops->qc_defer(qc); ++ switch (ret) { ++ case 0: ++ break; ++ case ATA_DEFER_LINK: ++ ret = SCSI_MLQUEUE_DEVICE_BUSY; ++ break; ++ case ATA_DEFER_PORT: ++ ret = SCSI_MLQUEUE_HOST_BUSY; ++ break; ++ default: ++ WARN_ON_ONCE(1); ++ ret = SCSI_MLQUEUE_HOST_BUSY; ++ break; ++ } ++ ++ if (ret) { ++ /* Force a requeue of the command to defer its execution. */ ++ ata_qc_free(qc); ++ return ret; ++ } ++ ++issue: ++ ata_qc_issue(qc); ++ ++ return 0; ++} ++ + /** + * ata_scsi_translate - Translate then issue SCSI command to ATA device + * @dev: ATA device to which the command is addressed +@@ -1759,66 +1795,49 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) + * spin_lock_irqsave(host lock) + * + * RETURNS: +- * 0 on success, SCSI_ML_QUEUE_DEVICE_BUSY if the command +- * needs to be deferred. ++ * 0 on success, SCSI_ML_QUEUE_DEVICE_BUSY or SCSI_MLQUEUE_HOST_BUSY if the ++ * command needs to be deferred. + */ + static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, + ata_xlat_func_t xlat_func) + { + struct ata_port *ap = dev->link->ap; + struct ata_queued_cmd *qc; +- int rc; + ++ lockdep_assert_held(ap->lock); ++ ++ /* ++ * ata_scsi_qc_new() calls scsi_done(cmd) in case of failure. So we ++ * have nothing further to do when allocating a qc fails. ++ */ + qc = ata_scsi_qc_new(dev, cmd); + if (!qc) +- goto err_mem; ++ return 0; + + /* data is present; dma-map it */ + if (cmd->sc_data_direction == DMA_FROM_DEVICE || + cmd->sc_data_direction == DMA_TO_DEVICE) { + if (unlikely(scsi_bufflen(cmd) < 1)) { + ata_dev_warn(dev, "WARNING: zero len r/w req\n"); +- goto err_did; ++ cmd->result = (DID_ERROR << 16); ++ goto done; + } + + ata_sg_init(qc, scsi_sglist(cmd), scsi_sg_count(cmd)); +- + qc->dma_dir = cmd->sc_data_direction; + } + + qc->complete_fn = ata_scsi_qc_complete; + + if (xlat_func(qc)) +- goto early_finish; +- +- if (ap->ops->qc_defer) { +- if ((rc = ap->ops->qc_defer(qc))) +- goto defer; +- } ++ goto done; + +- /* select device, send command to hardware */ +- ata_qc_issue(qc); ++ return ata_scsi_qc_issue(ap, qc); + +- return 0; +- +-early_finish: ++done: + ata_qc_free(qc); + scsi_done(cmd); + return 0; +- +-err_did: +- ata_qc_free(qc); +- cmd->result = (DID_ERROR << 16); +- scsi_done(cmd); +-err_mem: +- return 0; +- +-defer: +- ata_qc_free(qc); +- if (rc == ATA_DEFER_LINK) +- return SCSI_MLQUEUE_DEVICE_BUSY; +- else +- return SCSI_MLQUEUE_HOST_BUSY; + } + + struct ata_scsi_args { +@@ -2867,6 +2886,9 @@ ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev) + { + struct ata_device *dev = __ata_scsi_find_dev(ap, scsidev); + ++ if (!ata_adapter_is_online(ap)) ++ return NULL; ++ + if (unlikely(!dev || !ata_dev_enabled(dev))) + return NULL; + +diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h +index 05ac80da8ebc7d..9927d79e55878b 100644 +--- a/drivers/ata/libata.h ++++ b/drivers/ata/libata.h +@@ -75,6 +75,7 @@ extern int atapi_check_dma(struct ata_queued_cmd *qc); + extern void swap_buf_le16(u16 *buf, unsigned int buf_words); + extern bool ata_phys_link_online(struct ata_link *link); + extern bool ata_phys_link_offline(struct ata_link *link); ++bool ata_adapter_is_online(struct ata_port *ap); + extern void ata_dev_init(struct ata_device *dev); + extern void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp); + extern int sata_link_init_spd(struct ata_link *link); +diff --git a/drivers/ata/pata_ftide010.c b/drivers/ata/pata_ftide010.c +index 4d6ef90ccc774b..3e6c82f68ab9dc 100644 +--- a/drivers/ata/pata_ftide010.c ++++ b/drivers/ata/pata_ftide010.c +@@ -122,10 +122,10 @@ static const u8 mwdma_50_active_time[3] = {6, 2, 2}; + static const u8 mwdma_50_recovery_time[3] = {6, 2, 1}; + static const u8 mwdma_66_active_time[3] = {8, 3, 3}; + static const u8 mwdma_66_recovery_time[3] = {8, 2, 1}; +-static const u8 udma_50_setup_time[6] = {3, 3, 2, 2, 1, 1}; ++static const u8 udma_50_setup_time[6] = {3, 3, 2, 2, 1, 9}; + static const u8 udma_50_hold_time[6] = {3, 1, 1, 1, 1, 1}; +-static const u8 udma_66_setup_time[7] = {4, 4, 3, 2, }; +-static const u8 udma_66_hold_time[7] = {}; ++static const u8 udma_66_setup_time[7] = {4, 4, 3, 2, 1, 9, 9}; ++static const u8 udma_66_hold_time[7] = {4, 2, 1, 1, 1, 1, 1}; + + /* + * We set 66 MHz for all MWDMA modes +diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c +index b57faf6dc327ec..ca3051e0023e8f 100644 +--- a/drivers/atm/fore200e.c ++++ b/drivers/atm/fore200e.c +@@ -376,6 +376,10 @@ fore200e_shutdown(struct fore200e* fore200e) + fallthrough; + case FORE200E_STATE_IRQ: + free_irq(fore200e->irq, fore200e->atm_dev); ++#ifdef FORE200E_USE_TASKLET ++ tasklet_kill(&fore200e->tx_tasklet); ++ tasklet_kill(&fore200e->rx_tasklet); ++#endif + + fallthrough; + case FORE200E_STATE_ALLOC_BUF: +diff --git a/drivers/auxdisplay/arm-charlcd.c b/drivers/auxdisplay/arm-charlcd.c +index 0b1c99cca7334f..f418b133ee7525 100644 +--- a/drivers/auxdisplay/arm-charlcd.c ++++ b/drivers/auxdisplay/arm-charlcd.c +@@ -323,7 +323,7 @@ static int __init charlcd_probe(struct platform_device *pdev) + out_no_irq: + iounmap(lcd->virtbase); + out_no_memregion: +- release_mem_region(lcd->phybase, SZ_4K); ++ release_mem_region(lcd->phybase, lcd->physize); + out_no_resource: + kfree(lcd); + return ret; +diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c +index 5a5a9e978e85f3..ddbe9cc91d23da 100644 +--- a/drivers/base/power/wakeirq.c ++++ b/drivers/base/power/wakeirq.c +@@ -83,13 +83,16 @@ EXPORT_SYMBOL_GPL(dev_pm_set_wake_irq); + */ + void dev_pm_clear_wake_irq(struct device *dev) + { +- struct wake_irq *wirq = dev->power.wakeirq; ++ struct wake_irq *wirq; + unsigned long flags; + +- if (!wirq) ++ spin_lock_irqsave(&dev->power.lock, flags); ++ wirq = dev->power.wakeirq; ++ if (!wirq) { ++ spin_unlock_irqrestore(&dev->power.lock, flags); + return; ++ } + +- spin_lock_irqsave(&dev->power.lock, flags); + device_wakeup_detach_irq(dev); + dev->power.wakeirq = NULL; + spin_unlock_irqrestore(&dev->power.lock, flags); +diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c +index a917219feea62d..eae81def0902a0 100644 +--- a/drivers/base/power/wakeup.c ++++ b/drivers/base/power/wakeup.c +@@ -280,9 +280,7 @@ EXPORT_SYMBOL_GPL(wakeup_sources_read_unlock); + */ + struct wakeup_source *wakeup_sources_walk_start(void) + { +- struct list_head *ws_head = &wakeup_sources; +- +- return list_entry_rcu(ws_head->next, struct wakeup_source, entry); ++ return list_first_or_null_rcu(&wakeup_sources, struct wakeup_source, entry); + } + EXPORT_SYMBOL_GPL(wakeup_sources_walk_start); + +diff --git a/drivers/block/rnbd/rnbd-srv.c b/drivers/block/rnbd/rnbd-srv.c +index b67e39a34010b1..ebc0f4c091051f 100644 +--- a/drivers/block/rnbd/rnbd-srv.c ++++ b/drivers/block/rnbd/rnbd-srv.c +@@ -536,6 +536,8 @@ static void rnbd_srv_fill_msg_open_rsp(struct rnbd_msg_open_rsp *rsp, + { + struct block_device *bdev = sess_dev->bdev; + ++ memset(rsp, 0, sizeof(*rsp)); ++ + rsp->hdr.type = cpu_to_le16(RNBD_MSG_OPEN_RSP); + rsp->device_id = cpu_to_le32(sess_dev->device_id); + rsp->nsectors = cpu_to_le64(bdev_nr_sectors(bdev)); +@@ -641,6 +643,7 @@ static void process_msg_sess_info(struct rnbd_srv_session *srv_sess, + + trace_process_msg_sess_info(srv_sess, sess_info_msg); + ++ memset(rsp, 0, sizeof(*rsp)); + rsp->hdr.type = cpu_to_le16(RNBD_MSG_SESS_INFO_RSP); + rsp->ver = srv_sess->ver; + } +diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c +index 44f630a3f610bd..89c1d6ec7adaa8 100644 +--- a/drivers/block/ublk_drv.c ++++ b/drivers/block/ublk_drv.c +@@ -2908,10 +2908,10 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd, + if (issue_flags & IO_URING_F_NONBLOCK) + return -EAGAIN; + +- ublk_ctrl_cmd_dump(cmd); +- + if (!(issue_flags & IO_URING_F_SQE128)) +- goto out; ++ return -EINVAL; ++ ++ ublk_ctrl_cmd_dump(cmd); + + ret = ublk_check_cmd_op(cmd_op); + if (ret) +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index eaeacdadb20232..168e46ce59976a 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -548,6 +548,8 @@ static const struct usb_device_id quirks_table[] = { + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3592), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x13d3, 0x3612), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe122), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + +@@ -719,6 +721,7 @@ static const struct usb_device_id quirks_table[] = { + + /* Additional Realtek 8723BU Bluetooth devices */ + { USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK }, ++ { USB_DEVICE(0x2c0a, 0x8761), .driver_info = BTUSB_REALTEK }, + + /* Additional Realtek 8723DE Bluetooth devices */ + { USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK }, +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c +index 9c6f79d8605329..cdad817e632c61 100644 +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -1959,19 +1959,23 @@ retry: + } + + out: +- if (ret && retries < MAX_INIT_RETRIES) { +- bt_dev_warn(hdev, "Retry BT power ON:%d", retries); ++ if (ret) { + qca_power_shutdown(hu); +- if (hu->serdev) { +- serdev_device_close(hu->serdev); +- ret = serdev_device_open(hu->serdev); +- if (ret) { +- bt_dev_err(hdev, "failed to open port"); +- return ret; ++ ++ if (retries < MAX_INIT_RETRIES) { ++ bt_dev_warn(hdev, "Retry BT power ON:%d", retries); ++ if (hu->serdev) { ++ serdev_device_close(hu->serdev); ++ ret = serdev_device_open(hu->serdev); ++ if (ret) { ++ bt_dev_err(hdev, "failed to open port"); ++ return ret; ++ } + } ++ retries++; ++ goto retry; + } +- retries++; +- goto retry; ++ return ret; + } + + /* Setup bdaddr */ +diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c +index 8b421ef0580a78..56f5c24c367c09 100644 +--- a/drivers/bus/fsl-mc/fsl-mc-bus.c ++++ b/drivers/bus/fsl-mc/fsl-mc-bus.c +@@ -908,11 +908,7 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, + return 0; + + error_cleanup_dev: +- kfree(mc_dev->regions); +- if (mc_bus) +- kfree(mc_bus); +- else +- kfree(mc_dev); ++ put_device(&mc_dev->dev); + + return error; + } +diff --git a/drivers/char/ipmi/ipmi_ipmb.c b/drivers/char/ipmi/ipmi_ipmb.c +index 4e335832fc264e..2b7f6d9aa73996 100644 +--- a/drivers/char/ipmi/ipmi_ipmb.c ++++ b/drivers/char/ipmi/ipmi_ipmb.c +@@ -202,11 +202,16 @@ static int ipmi_ipmb_slave_cb(struct i2c_client *client, + break; + + case I2C_SLAVE_READ_REQUESTED: ++ *val = 0xff; ++ ipmi_ipmb_check_msg_done(iidev); ++ break; ++ + case I2C_SLAVE_STOP: + ipmi_ipmb_check_msg_done(iidev); + break; + + case I2C_SLAVE_READ_PROCESSED: ++ *val = 0xff; + break; + } + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 7b5d4822fa3ae1..c66aecb5616405 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -91,8 +91,7 @@ static ATOMIC_NOTIFIER_HEAD(random_ready_notifier); + /* Control how we warn userspace. */ + static struct ratelimit_state urandom_warning = + RATELIMIT_STATE_INIT_FLAGS("urandom_warning", HZ, 3, RATELIMIT_MSG_ON_RELEASE); +-static int ratelimit_disable __read_mostly = +- IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM); ++static int ratelimit_disable __read_mostly = 0; + module_param_named(ratelimit_disable, ratelimit_disable, int, 0644); + MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression"); + +@@ -163,12 +162,6 @@ int __cold execute_with_initialized_rng(struct notifier_block *nb) + return ret; + } + +-#define warn_unseeded_randomness() \ +- if (IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM) && !crng_ready()) \ +- printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init=%d\n", \ +- __func__, (void *)_RET_IP_, crng_init) +- +- + /********************************************************************* + * + * Fast key erasure RNG, the "crng". +@@ -413,7 +406,6 @@ static void _get_random_bytes(void *buf, size_t len) + */ + void get_random_bytes(void *buf, size_t len) + { +- warn_unseeded_randomness(); + _get_random_bytes(buf, len); + } + EXPORT_SYMBOL(get_random_bytes); +@@ -501,8 +493,6 @@ type get_random_ ##type(void) \ + struct batch_ ##type *batch; \ + unsigned long next_gen; \ + \ +- warn_unseeded_randomness(); \ +- \ + if (!crng_ready()) { \ + _get_random_bytes(&ret, sizeof(ret)); \ + return ret; \ +diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c +index a5b554cd477861..f78c61f4163d57 100644 +--- a/drivers/char/tpm/st33zp24/st33zp24.c ++++ b/drivers/char/tpm/st33zp24/st33zp24.c +@@ -328,8 +328,10 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf, + + for (i = 0; i < len - 1;) { + burstcnt = get_burstcount(chip); +- if (burstcnt < 0) +- return burstcnt; ++ if (burstcnt < 0) { ++ ret = burstcnt; ++ goto out_err; ++ } + size = min_t(int, len - i - 1, burstcnt); + ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_DATA_FIFO, + buf + i, size); +diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c +index 81d8a78dc65528..3675faa4a00c75 100644 +--- a/drivers/char/tpm/tpm_i2c_infineon.c ++++ b/drivers/char/tpm/tpm_i2c_infineon.c +@@ -543,8 +543,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) + burstcnt = get_burstcount(chip); + + /* burstcnt < 0 = TPM is busy */ +- if (burstcnt < 0) +- return burstcnt; ++ if (burstcnt < 0) { ++ rc = burstcnt; ++ goto out_err; ++ } + + if (burstcnt > (len - 1 - count)) + burstcnt = len - 1 - count; +diff --git a/drivers/char/tpm/tpm_tis_i2c_cr50.c b/drivers/char/tpm/tpm_tis_i2c_cr50.c +index e70abd69e1ae30..0f589f301e5bbd 100644 +--- a/drivers/char/tpm/tpm_tis_i2c_cr50.c ++++ b/drivers/char/tpm/tpm_tis_i2c_cr50.c +@@ -713,8 +713,7 @@ static int tpm_cr50_i2c_probe(struct i2c_client *client) + + if (client->irq > 0) { + rc = devm_request_irq(dev, client->irq, tpm_cr50_i2c_int_handler, +- IRQF_TRIGGER_FALLING | IRQF_ONESHOT | +- IRQF_NO_AUTOEN, ++ IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN, + dev->driver->name, chip); + if (rc < 0) { + dev_err(dev, "Failed to probe IRQ %d\n", client->irq); +diff --git a/drivers/char/tpm/tpm_tis_spi_cr50.c b/drivers/char/tpm/tpm_tis_spi_cr50.c +index f4937280e94061..32920b4cecfb44 100644 +--- a/drivers/char/tpm/tpm_tis_spi_cr50.c ++++ b/drivers/char/tpm/tpm_tis_spi_cr50.c +@@ -287,7 +287,7 @@ int cr50_spi_probe(struct spi_device *spi) + if (spi->irq > 0) { + ret = devm_request_irq(&spi->dev, spi->irq, + cr50_spi_irq_handler, +- IRQF_TRIGGER_RISING | IRQF_ONESHOT, ++ IRQF_TRIGGER_RISING, + "cr50_spi", cr50_phy); + if (ret < 0) { + if (ret == -EPROBE_DEFER) +diff --git a/drivers/clk/clk-apple-nco.c b/drivers/clk/clk-apple-nco.c +index 457a48d4894128..c205b7f1dadeb8 100644 +--- a/drivers/clk/clk-apple-nco.c ++++ b/drivers/clk/clk-apple-nco.c +@@ -318,6 +318,7 @@ static int applnco_probe(struct platform_device *pdev) + } + + static const struct of_device_id applnco_ids[] = { ++ { .compatible = "apple,t8103-nco" }, + { .compatible = "apple,nco" }, + { } + }; +diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c +index ba1d1c495bc2bf..644e5a854f2b65 100644 +--- a/drivers/clk/mediatek/clk-mtk.c ++++ b/drivers/clk/mediatek/clk-mtk.c +@@ -497,14 +497,16 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, + + + if (mcd->need_runtime_pm) { +- devm_pm_runtime_enable(&pdev->dev); ++ r = devm_pm_runtime_enable(&pdev->dev); ++ if (r) ++ goto unmap_io; + /* + * Do a pm_runtime_resume_and_get() to workaround a possible + * deadlock between clk_register() and the genpd framework. + */ + r = pm_runtime_resume_and_get(&pdev->dev); + if (r) +- return r; ++ goto unmap_io; + } + + /* Calculate how many clk_hw_onecell_data entries to allocate */ +@@ -618,11 +620,11 @@ unregister_fixed_clks: + free_data: + mtk_free_clk_data(clk_data); + free_base: +- if (mcd->shared_io && base) +- iounmap(base); +- + if (mcd->need_runtime_pm) + pm_runtime_put(&pdev->dev); ++unmap_io: ++ if (mcd->shared_io && base) ++ iounmap(base); + return r; + } + +diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c +index a133013356b645..00eaca92b388a9 100644 +--- a/drivers/clk/meson/gxbb.c ++++ b/drivers/clk/meson/gxbb.c +@@ -318,12 +318,23 @@ static struct clk_regmap gxbb_hdmi_pll = { + }, + }; + ++/* ++ * GXL hdmi OD dividers are POWER_OF_TWO dividers but limited to /4. ++ * A divider value of 3 should map to /8 but instead map /4 so ignore it. ++ */ ++static const struct clk_div_table gxl_hdmi_pll_od_div_table[] = { ++ { .val = 0, .div = 1 }, ++ { .val = 1, .div = 2 }, ++ { .val = 2, .div = 4 }, ++ { /* sentinel */ } ++}; ++ + static struct clk_regmap gxl_hdmi_pll_od = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_HDMI_PLL_CNTL + 8, + .shift = 21, + .width = 2, +- .flags = CLK_DIVIDER_POWER_OF_TWO, ++ .table = gxl_hdmi_pll_od_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdmi_pll_od", +@@ -341,7 +352,7 @@ static struct clk_regmap gxl_hdmi_pll_od2 = { + .offset = HHI_HDMI_PLL_CNTL + 8, + .shift = 23, + .width = 2, +- .flags = CLK_DIVIDER_POWER_OF_TWO, ++ .table = gxl_hdmi_pll_od_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdmi_pll_od2", +@@ -359,7 +370,7 @@ static struct clk_regmap gxl_hdmi_pll = { + .offset = HHI_HDMI_PLL_CNTL + 8, + .shift = 19, + .width = 2, +- .flags = CLK_DIVIDER_POWER_OF_TWO, ++ .table = gxl_hdmi_pll_od_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdmi_pll", +diff --git a/drivers/clk/microchip/clk-core.c b/drivers/clk/microchip/clk-core.c +index 1b4f023cdc8be4..71fbaf8318f22e 100644 +--- a/drivers/clk/microchip/clk-core.c ++++ b/drivers/clk/microchip/clk-core.c +@@ -281,14 +281,13 @@ static u8 roclk_get_parent(struct clk_hw *hw) + + v = (readl(refo->ctrl_reg) >> REFO_SEL_SHIFT) & REFO_SEL_MASK; + +- if (!refo->parent_map) +- return v; +- +- for (i = 0; i < clk_hw_get_num_parents(hw); i++) +- if (refo->parent_map[i] == v) +- return i; ++ if (refo->parent_map) { ++ for (i = 0; i < clk_hw_get_num_parents(hw); i++) ++ if (refo->parent_map[i] == v) ++ return i; ++ } + +- return -EINVAL; ++ return v; + } + + static unsigned long roclk_calc_rate(unsigned long parent_rate, +@@ -823,13 +822,13 @@ static u8 sclk_get_parent(struct clk_hw *hw) + + v = (readl(sclk->mux_reg) >> OSC_CUR_SHIFT) & OSC_CUR_MASK; + +- if (!sclk->parent_map) +- return v; ++ if (sclk->parent_map) { ++ for (i = 0; i < clk_hw_get_num_parents(hw); i++) ++ if (sclk->parent_map[i] == v) ++ return i; ++ } + +- for (i = 0; i < clk_hw_get_num_parents(hw); i++) +- if (sclk->parent_map[i] == v) +- return i; +- return -EINVAL; ++ return v; + } + + static int sclk_set_parent(struct clk_hw *hw, u8 index) +diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c +index fae1c07982aba7..20bb72565f0edb 100644 +--- a/drivers/clk/qcom/clk-rcg2.c ++++ b/drivers/clk/qcom/clk-rcg2.c +@@ -434,7 +434,7 @@ static int clk_rcg2_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) + static int clk_rcg2_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) + { + struct clk_rcg2 *rcg = to_clk_rcg2(hw); +- u32 notn_m, n, m, d, not2d, mask, duty_per, cfg; ++ u32 notn_m, n, m, d, not2d, mask, cfg; + int ret; + + /* Duty-cycle cannot be modified for non-MND RCGs */ +@@ -453,10 +453,8 @@ static int clk_rcg2_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) + + n = (~(notn_m) + m) & mask; + +- duty_per = (duty->num * 100) / duty->den; +- + /* Calculate 2d value */ +- d = DIV_ROUND_CLOSEST(n * duty_per * 2, 100); ++ d = DIV_ROUND_CLOSEST(n * duty->num * 2, duty->den); + + /* + * Check bit widths of 2d. If D is too big reduce duty cycle. +@@ -920,6 +918,7 @@ static int clk_gfx3d_determine_rate(struct clk_hw *hw, + if (req->max_rate < parent_req.max_rate) + parent_req.max_rate = req->max_rate; + ++ parent_req.best_parent_hw = req->best_parent_hw; + ret = __clk_determine_rate(req->best_parent_hw, &parent_req); + if (ret) + return ret; +diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c +index 35bd987f2e52ab..3d6e87872ddc35 100644 +--- a/drivers/clk/qcom/common.c ++++ b/drivers/clk/qcom/common.c +@@ -325,7 +325,7 @@ int qcom_cc_probe_by_index(struct platform_device *pdev, int index, + + base = devm_platform_ioremap_resource(pdev, index); + if (IS_ERR(base)) +- return -ENOMEM; ++ return PTR_ERR(base); + + regmap = devm_regmap_init_mmio(&pdev->dev, base, desc->config); + if (IS_ERR(regmap)) +diff --git a/drivers/clk/qcom/dispcc-sdm845.c b/drivers/clk/qcom/dispcc-sdm845.c +index e792e0b130d333..eae6dcff18da54 100644 +--- a/drivers/clk/qcom/dispcc-sdm845.c ++++ b/drivers/clk/qcom/dispcc-sdm845.c +@@ -280,7 +280,7 @@ static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = { + .name = "disp_cc_mdss_pclk0_clk_src", + .parent_data = disp_cc_parent_data_4, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_4), +- .flags = CLK_SET_RATE_PARENT, ++ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + .ops = &clk_pixel_ops, + }, + }; +@@ -295,7 +295,7 @@ static struct clk_rcg2 disp_cc_mdss_pclk1_clk_src = { + .name = "disp_cc_mdss_pclk1_clk_src", + .parent_data = disp_cc_parent_data_4, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_4), +- .flags = CLK_SET_RATE_PARENT, ++ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + .ops = &clk_pixel_ops, + }, + }; +diff --git a/drivers/clk/qcom/gcc-ipq5018.c b/drivers/clk/qcom/gcc-ipq5018.c +index 915e84db3c97da..292eaa154737f4 100644 +--- a/drivers/clk/qcom/gcc-ipq5018.c ++++ b/drivers/clk/qcom/gcc-ipq5018.c +@@ -1339,6 +1339,7 @@ static struct clk_branch gcc_sleep_clk_src = { + .name = "gcc_sleep_clk_src", + .parent_data = gcc_sleep_clk_data, + .num_parents = ARRAY_SIZE(gcc_sleep_clk_data), ++ .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +diff --git a/drivers/clk/qcom/gcc-msm8917.c b/drivers/clk/qcom/gcc-msm8917.c +index f2dd132e2fb1c1..0be62cb7a62288 100644 +--- a/drivers/clk/qcom/gcc-msm8917.c ++++ b/drivers/clk/qcom/gcc-msm8917.c +@@ -3034,7 +3034,6 @@ static struct gdsc cpp_gdsc = { + .pd = { + .name = "cpp_gdsc", + }, +- .flags = ALWAYS_ON, + .pwrsts = PWRSTS_OFF_ON, + }; + +diff --git a/drivers/clk/qcom/gcc-msm8953.c b/drivers/clk/qcom/gcc-msm8953.c +index e6e2ab1380f20b..1689f088140634 100644 +--- a/drivers/clk/qcom/gcc-msm8953.c ++++ b/drivers/clk/qcom/gcc-msm8953.c +@@ -3946,7 +3946,6 @@ static struct gdsc cpp_gdsc = { + .pd = { + .name = "cpp_gdsc", + }, +- .flags = ALWAYS_ON, + .pwrsts = PWRSTS_OFF_ON, + }; + +diff --git a/drivers/clk/qcom/gcc-qdu1000.c b/drivers/clk/qcom/gcc-qdu1000.c +index 9f42d2601464e7..84643f9ffb02d0 100644 +--- a/drivers/clk/qcom/gcc-qdu1000.c ++++ b/drivers/clk/qcom/gcc-qdu1000.c +@@ -904,7 +904,7 @@ static struct clk_rcg2 gcc_sdcc5_apps_clk_src = { + .name = "gcc_sdcc5_apps_clk_src", + .parent_data = gcc_parent_data_8, + .num_parents = ARRAY_SIZE(gcc_parent_data_8), +- .ops = &clk_rcg2_floor_ops, ++ .ops = &clk_rcg2_shared_floor_ops, + }, + }; + +@@ -923,7 +923,7 @@ static struct clk_rcg2 gcc_sdcc5_ice_core_clk_src = { + .name = "gcc_sdcc5_ice_core_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), +- .ops = &clk_rcg2_floor_ops, ++ .ops = &clk_rcg2_shared_floor_ops, + }, + }; + +diff --git a/drivers/clk/qcom/gcc-sdx75.c b/drivers/clk/qcom/gcc-sdx75.c +index 573af17bd24caa..314bacd03374b5 100644 +--- a/drivers/clk/qcom/gcc-sdx75.c ++++ b/drivers/clk/qcom/gcc-sdx75.c +@@ -1033,7 +1033,7 @@ static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { + .name = "gcc_sdcc1_apps_clk_src", + .parent_data = gcc_parent_data_17, + .num_parents = ARRAY_SIZE(gcc_parent_data_17), +- .ops = &clk_rcg2_floor_ops, ++ .ops = &clk_rcg2_shared_floor_ops, + }, + }; + +@@ -1057,7 +1057,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { + .name = "gcc_sdcc2_apps_clk_src", + .parent_data = gcc_parent_data_18, + .num_parents = ARRAY_SIZE(gcc_parent_data_18), +- .ops = &clk_rcg2_floor_ops, ++ .ops = &clk_rcg2_shared_floor_ops, + }, + }; + +diff --git a/drivers/clk/qcom/gcc-sm8450.c b/drivers/clk/qcom/gcc-sm8450.c +index 4c55df89ddca7d..ef02d1003cb4a4 100644 +--- a/drivers/clk/qcom/gcc-sm8450.c ++++ b/drivers/clk/qcom/gcc-sm8450.c +@@ -936,7 +936,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { + .parent_data = gcc_parent_data_7, + .num_parents = ARRAY_SIZE(gcc_parent_data_7), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_floor_ops, ++ .ops = &clk_rcg2_shared_floor_ops, + }, + }; + +@@ -959,7 +959,7 @@ static struct clk_rcg2 gcc_sdcc4_apps_clk_src = { + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_floor_ops, ++ .ops = &clk_rcg2_shared_floor_ops, + }, + }; + +diff --git a/drivers/clk/qcom/gcc-sm8550.c b/drivers/clk/qcom/gcc-sm8550.c +index b30ece62216f7e..3e5ce6fa680588 100644 +--- a/drivers/clk/qcom/gcc-sm8550.c ++++ b/drivers/clk/qcom/gcc-sm8550.c +@@ -1025,7 +1025,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { + .parent_data = gcc_parent_data_9, + .num_parents = ARRAY_SIZE(gcc_parent_data_9), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_shared_ops, ++ .ops = &clk_rcg2_shared_floor_ops, + }, + }; + +@@ -1048,7 +1048,7 @@ static struct clk_rcg2 gcc_sdcc4_apps_clk_src = { + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_shared_ops, ++ .ops = &clk_rcg2_shared_floor_ops, + }, + }; + +diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c +index 4bba49215c710c..2dea5fb8b858b6 100644 +--- a/drivers/clk/renesas/rzg2l-cpg.c ++++ b/drivers/clk/renesas/rzg2l-cpg.c +@@ -91,8 +91,8 @@ struct sd_mux_hw_data { + + struct rzg2l_pll5_param { + u32 pl5_fracin; ++ u16 pl5_intin; + u8 pl5_refdiv; +- u8 pl5_intin; + u8 pl5_postdiv1; + u8 pl5_postdiv2; + u8 pl5_spread; +@@ -380,8 +380,8 @@ rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param *params, + foutvco_rate = div_u64(mul_u32_u32(EXTAL_FREQ_IN_MEGA_HZ * MEGA, + (params->pl5_intin << 24) + params->pl5_fracin), + params->pl5_refdiv) >> 24; +- foutpostdiv_rate = DIV_ROUND_CLOSEST_ULL(foutvco_rate, +- params->pl5_postdiv1 * params->pl5_postdiv2); ++ foutpostdiv_rate = DIV_ROUND_CLOSEST(foutvco_rate, ++ params->pl5_postdiv1 * params->pl5_postdiv2); + + return foutpostdiv_rate; + } +diff --git a/drivers/clk/tegra/clk-tegra124-emc.c b/drivers/clk/tegra/clk-tegra124-emc.c +index 2a6db043428159..0f6fb776b2298d 100644 +--- a/drivers/clk/tegra/clk-tegra124-emc.c ++++ b/drivers/clk/tegra/clk-tegra124-emc.c +@@ -538,8 +538,10 @@ struct clk *tegra124_clk_register_emc(void __iomem *base, struct device_node *np + tegra->hw.init = &init; + + clk = clk_register(NULL, &tegra->hw); +- if (IS_ERR(clk)) ++ if (IS_ERR(clk)) { ++ kfree(tegra); + return clk; ++ } + + tegra->prev_parent = clk_hw_get_parent_by_index( + &tegra->hw, emc_get_parent(&tegra->hw))->clk; +diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig +index 8208a3d895634b..5b526b74e5deef 100644 +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -236,6 +236,7 @@ config KEYSTONE_TIMER + + config INTEGRATOR_AP_TIMER + bool "Integrator-AP timer driver" if COMPILE_TEST ++ depends on OF + select CLKSRC_MMIO + help + Enables support for the Integrator-AP timer. +diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c +index beffff81c00f3d..3fc6ed9b56300d 100644 +--- a/drivers/clocksource/sh_tmu.c ++++ b/drivers/clocksource/sh_tmu.c +@@ -143,16 +143,6 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_channel *ch, int start) + + static int __sh_tmu_enable(struct sh_tmu_channel *ch) + { +- int ret; +- +- /* enable clock */ +- ret = clk_enable(ch->tmu->clk); +- if (ret) { +- dev_err(&ch->tmu->pdev->dev, "ch%u: cannot enable clock\n", +- ch->index); +- return ret; +- } +- + /* make sure channel is disabled */ + sh_tmu_start_stop_ch(ch, 0); + +@@ -174,7 +164,6 @@ static int sh_tmu_enable(struct sh_tmu_channel *ch) + if (ch->enable_count++ > 0) + return 0; + +- pm_runtime_get_sync(&ch->tmu->pdev->dev); + dev_pm_syscore_device(&ch->tmu->pdev->dev, true); + + return __sh_tmu_enable(ch); +@@ -187,9 +176,6 @@ static void __sh_tmu_disable(struct sh_tmu_channel *ch) + + /* disable interrupts in TMU block */ + sh_tmu_write(ch, TCR, TCR_TPSC_CLK4); +- +- /* stop clock */ +- clk_disable(ch->tmu->clk); + } + + static void sh_tmu_disable(struct sh_tmu_channel *ch) +@@ -203,7 +189,6 @@ static void sh_tmu_disable(struct sh_tmu_channel *ch) + __sh_tmu_disable(ch); + + dev_pm_syscore_device(&ch->tmu->pdev->dev, false); +- pm_runtime_put(&ch->tmu->pdev->dev); + } + + static void sh_tmu_set_next(struct sh_tmu_channel *ch, unsigned long delta, +@@ -552,7 +537,6 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev) + goto err_clk_unprepare; + + tmu->rate = clk_get_rate(tmu->clk) / 4; +- clk_disable(tmu->clk); + + /* Map the memory resource. */ + ret = sh_tmu_map_memory(tmu); +@@ -626,8 +610,6 @@ static int sh_tmu_probe(struct platform_device *pdev) + out: + if (tmu->has_clockevent || tmu->has_clocksource) + pm_runtime_irq_safe(&pdev->dev); +- else +- pm_runtime_idle(&pdev->dev); + + return 0; + } +diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c +index 8b53388280d730..ad4f23e2158be2 100644 +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -158,8 +158,11 @@ static const struct of_device_id blocklist[] __initconst = { + { .compatible = "qcom,sdm845", }, + { .compatible = "qcom,sdx75", }, + { .compatible = "qcom,sm6115", }, ++ { .compatible = "qcom,sm6125", }, ++ { .compatible = "qcom,sm6150", }, + { .compatible = "qcom,sm6350", }, + { .compatible = "qcom,sm6375", }, ++ { .compatible = "qcom,sm7125", }, + { .compatible = "qcom,sm7225", }, + { .compatible = "qcom,sm8150", }, + { .compatible = "qcom,sm8250", }, +diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c +index 6704d610573ad6..aa117f2967fdfc 100644 +--- a/drivers/cpuidle/cpuidle.c ++++ b/drivers/cpuidle/cpuidle.c +@@ -356,6 +356,16 @@ noinstr int cpuidle_enter_state(struct cpuidle_device *dev, + int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, + bool *stop_tick) + { ++ /* ++ * If there is only a single idle state (or none), there is nothing ++ * meaningful for the governor to choose. Skip the governor and ++ * always use state 0 with the tick running. ++ */ ++ if (drv->state_count <= 1) { ++ *stop_tick = false; ++ return 0; ++ } ++ + return cpuidle_curr_governor->select(drv, dev, stop_tick); + } + +diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c +index 27010eee6d1bcd..bedf6c4b8d1b57 100644 +--- a/drivers/cpuidle/governors/menu.c ++++ b/drivers/cpuidle/governors/menu.c +@@ -14,8 +14,6 @@ + #include + #include + #include +-#include +-#include + #include + #include + +@@ -94,16 +92,11 @@ + * state, and thus the less likely a busy CPU will hit such a deep + * C state. + * +- * Two factors are used in determing this multiplier: +- * a value of 10 is added for each point of "per cpu load average" we have. +- * a value of 5 points is added for each process that is waiting for +- * IO on this CPU. +- * (these values are experimentally determined) +- * +- * The load average factor gives a longer term (few seconds) input to the +- * decision, while the iowait value gives a cpu local instantanious input. +- * The iowait factor may look low, but realize that this is also already +- * represented in the system load average. ++ * Currently there is only one value determining the factor: ++ * 10 points are added for each process that is waiting for IO on this CPU. ++ * (This value was experimentally determined.) ++ * Utilization is no longer a factor as it was shown that it never contributed ++ * significantly to the performance multiplier in the first place. + * + */ + +@@ -276,7 +269,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, + + /* Find the shortest expected idle interval. */ + predicted_ns = get_typical_interval(data) * NSEC_PER_USEC; +- if (predicted_ns > RESIDENCY_THRESHOLD_NS) { ++ if (predicted_ns > RESIDENCY_THRESHOLD_NS || tick_nohz_tick_stopped()) { + unsigned int timer_us; + + /* Determine the time till the closest timer. */ +@@ -296,6 +289,16 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, + RESOLUTION * DECAY * NSEC_PER_USEC); + /* Use the lowest expected idle interval to pick the idle state. */ + predicted_ns = min((u64)timer_us * NSEC_PER_USEC, predicted_ns); ++ /* ++ * If the tick is already stopped, the cost of possible short ++ * idle duration misprediction is much higher, because the CPU ++ * may be stuck in a shallow idle state for a long time as a ++ * result of it. In that case, say we might mispredict and use ++ * the known time till the closest timer event for the idle ++ * state selection. ++ */ ++ if (tick_nohz_tick_stopped() && predicted_ns < TICK_NSEC) ++ predicted_ns = data->next_timer_ns; + } else { + /* + * Because the next timer event is not going to be determined +@@ -321,16 +324,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, + return 0; + } + +- /* +- * If the tick is already stopped, the cost of possible short idle +- * duration misprediction is much higher, because the CPU may be stuck +- * in a shallow idle state for a long time as a result of it. In that +- * case, say we might mispredict and use the known time till the closest +- * timer event for the idle state selection. +- */ +- if (tick_nohz_tick_stopped() && predicted_ns < TICK_NSEC) +- predicted_ns = data->next_timer_ns; +- + /* + * Find the idle state with the lowest power while satisfying + * our constraints. +diff --git a/drivers/crypto/cavium/cpt/cptvf_main.c b/drivers/crypto/cavium/cpt/cptvf_main.c +index c246920e6f540c..bccd680c7f7ee4 100644 +--- a/drivers/crypto/cavium/cpt/cptvf_main.c ++++ b/drivers/crypto/cavium/cpt/cptvf_main.c +@@ -180,7 +180,8 @@ static void free_command_queues(struct cpt_vf *cptvf, + + hlist_for_each_entry_safe(chunk, node, &cqinfo->queue[i].chead, + nextchunk) { +- dma_free_coherent(&pdev->dev, chunk->size, ++ dma_free_coherent(&pdev->dev, ++ chunk->size + CPT_NEXT_CHUNK_PTR_SIZE, + chunk->head, + chunk->dma_addr); + chunk->head = NULL; +diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c +index d42d7bc623523d..5f591bce095211 100644 +--- a/drivers/crypto/ccp/psp-dev.c ++++ b/drivers/crypto/ccp/psp-dev.c +@@ -9,6 +9,9 @@ + + #include + #include ++#include ++#include ++#include + + #include "sp-dev.h" + #include "psp-dev.h" +@@ -19,6 +22,62 @@ + + struct psp_device *psp_master; + ++#define PSP_C2PMSG_17_CMDRESP_CMD GENMASK(19, 16) ++ ++static int psp_mailbox_poll(const void __iomem *cmdresp_reg, unsigned int *cmdresp, ++ unsigned int timeout_msecs) ++{ ++ while (true) { ++ *cmdresp = ioread32(cmdresp_reg); ++ if (FIELD_GET(PSP_CMDRESP_RESP, *cmdresp)) ++ return 0; ++ ++ if (!timeout_msecs--) ++ break; ++ ++ usleep_range(1000, 1100); ++ } ++ ++ return -ETIMEDOUT; ++} ++ ++int psp_mailbox_command(struct psp_device *psp, enum psp_cmd cmd, void *cmdbuff, ++ unsigned int timeout_msecs, unsigned int *cmdresp) ++{ ++ void __iomem *cmdresp_reg, *cmdbuff_lo_reg, *cmdbuff_hi_reg; ++ int ret; ++ ++ if (!psp || !psp->vdata || !psp->vdata->cmdresp_reg || ++ !psp->vdata->cmdbuff_addr_lo_reg || !psp->vdata->cmdbuff_addr_hi_reg) ++ return -ENODEV; ++ ++ cmdresp_reg = psp->io_regs + psp->vdata->cmdresp_reg; ++ cmdbuff_lo_reg = psp->io_regs + psp->vdata->cmdbuff_addr_lo_reg; ++ cmdbuff_hi_reg = psp->io_regs + psp->vdata->cmdbuff_addr_hi_reg; ++ ++ mutex_lock(&psp->mailbox_mutex); ++ ++ /* Ensure mailbox is ready for a command */ ++ ret = -EBUSY; ++ if (psp_mailbox_poll(cmdresp_reg, cmdresp, 0)) ++ goto unlock; ++ ++ if (cmdbuff) { ++ iowrite32(lower_32_bits(__psp_pa(cmdbuff)), cmdbuff_lo_reg); ++ iowrite32(upper_32_bits(__psp_pa(cmdbuff)), cmdbuff_hi_reg); ++ } ++ ++ *cmdresp = FIELD_PREP(PSP_C2PMSG_17_CMDRESP_CMD, cmd); ++ iowrite32(*cmdresp, cmdresp_reg); ++ ++ ret = psp_mailbox_poll(cmdresp_reg, cmdresp, timeout_msecs); ++ ++unlock: ++ mutex_unlock(&psp->mailbox_mutex); ++ ++ return ret; ++} ++ + static struct psp_device *psp_alloc_struct(struct sp_device *sp) + { + struct device *dev = sp->dev; +@@ -164,6 +223,7 @@ int psp_dev_init(struct sp_device *sp) + } + + psp->io_regs = sp->io_map; ++ mutex_init(&psp->mailbox_mutex); + + ret = psp_get_capability(psp); + if (ret) +@@ -253,6 +313,17 @@ struct psp_device *psp_get_master_device(void) + return sp ? sp->psp_data : NULL; + } + ++int psp_restore(struct sp_device *sp) ++{ ++ struct psp_device *psp = sp->psp_data; ++ int ret = 0; ++ ++ if (psp->tee_data) ++ ret = tee_restore(psp); ++ ++ return ret; ++} ++ + void psp_pci_init(void) + { + psp_master = psp_get_master_device(); +diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/psp-dev.h +index 8a4de69399c59a..d917657c6085ad 100644 +--- a/drivers/crypto/ccp/psp-dev.h ++++ b/drivers/crypto/ccp/psp-dev.h +@@ -14,6 +14,8 @@ + #include + #include + #include ++#include ++#include + + #include "sp-dev.h" + +@@ -33,6 +35,7 @@ struct psp_device { + struct sp_device *sp; + + void __iomem *io_regs; ++ struct mutex mailbox_mutex; + + psp_irq_handler_t sev_irq_handler; + void *sev_irq_data; +@@ -71,4 +74,19 @@ struct psp_device *psp_get_master_device(void); + #define PSP_SECURITY_HSP_TPM_AVAILABLE BIT(10) + #define PSP_SECURITY_ROM_ARMOR_ENFORCED BIT(11) + ++/** ++ * enum psp_cmd - PSP mailbox commands ++ * @PSP_CMD_TEE_RING_INIT: Initialize TEE ring buffer ++ * @PSP_CMD_TEE_RING_DESTROY: Destroy TEE ring buffer ++ * @PSP_CMD_MAX: Maximum command id ++ */ ++enum psp_cmd { ++ PSP_CMD_TEE_RING_INIT = 1, ++ PSP_CMD_TEE_RING_DESTROY = 2, ++ PSP_CMD_MAX = 15, ++}; ++ ++int psp_mailbox_command(struct psp_device *psp, enum psp_cmd cmd, void *cmdbuff, ++ unsigned int timeout_msecs, unsigned int *cmdresp); ++ + #endif /* __PSP_DEV_H */ +diff --git a/drivers/crypto/ccp/sp-dev.c b/drivers/crypto/ccp/sp-dev.c +index 7eb3e46682860c..ccbe009ad6e580 100644 +--- a/drivers/crypto/ccp/sp-dev.c ++++ b/drivers/crypto/ccp/sp-dev.c +@@ -229,6 +229,18 @@ int sp_resume(struct sp_device *sp) + return 0; + } + ++int sp_restore(struct sp_device *sp) ++{ ++ if (sp->psp_data) { ++ int ret = psp_restore(sp); ++ ++ if (ret) ++ return ret; ++ } ++ ++ return sp_resume(sp); ++} ++ + struct sp_device *sp_get_psp_master_device(void) + { + struct sp_device *i, *ret = NULL; +diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h +index 2329ad524b4945..2efe4a6ef544f1 100644 +--- a/drivers/crypto/ccp/sp-dev.h ++++ b/drivers/crypto/ccp/sp-dev.h +@@ -71,6 +71,9 @@ struct psp_vdata { + const struct sev_vdata *sev; + const struct tee_vdata *tee; + const struct platform_access_vdata *platform_access; ++ const unsigned int cmdresp_reg; ++ const unsigned int cmdbuff_addr_lo_reg; ++ const unsigned int cmdbuff_addr_hi_reg; + const unsigned int feature_reg; + const unsigned int inten_reg; + const unsigned int intsts_reg; +@@ -138,6 +141,7 @@ struct sp_device *sp_get_master(void); + + int sp_suspend(struct sp_device *sp); + int sp_resume(struct sp_device *sp); ++int sp_restore(struct sp_device *sp); + int sp_request_ccp_irq(struct sp_device *sp, irq_handler_t handler, + const char *name, void *data); + void sp_free_ccp_irq(struct sp_device *sp, void *data); +@@ -171,6 +175,7 @@ int psp_dev_init(struct sp_device *sp); + void psp_pci_init(void); + void psp_dev_destroy(struct sp_device *sp); + void psp_pci_exit(void); ++int psp_restore(struct sp_device *sp); + + #else /* !CONFIG_CRYPTO_DEV_SP_PSP */ + +@@ -178,6 +183,7 @@ static inline int psp_dev_init(struct sp_device *sp) { return 0; } + static inline void psp_pci_init(void) { } + static inline void psp_dev_destroy(struct sp_device *sp) { } + static inline void psp_pci_exit(void) { } ++static inline int psp_restore(struct sp_device *sp) { return 0; } + + #endif /* CONFIG_CRYPTO_DEV_SP_PSP */ + +diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c +index b1e60542351a66..86517bb4c19527 100644 +--- a/drivers/crypto/ccp/sp-pci.c ++++ b/drivers/crypto/ccp/sp-pci.c +@@ -407,6 +407,13 @@ static int __maybe_unused sp_pci_resume(struct device *dev) + return sp_resume(sp); + } + ++static int __maybe_unused sp_pci_restore(struct device *dev) ++{ ++ struct sp_device *sp = dev_get_drvdata(dev); ++ ++ return sp_restore(sp); ++} ++ + #ifdef CONFIG_CRYPTO_DEV_SP_PSP + static const struct sev_vdata sevv1 = { + .cmdresp_reg = 0x10580, /* C2PMSG_32 */ +@@ -421,18 +428,12 @@ static const struct sev_vdata sevv2 = { + }; + + static const struct tee_vdata teev1 = { +- .cmdresp_reg = 0x10544, /* C2PMSG_17 */ +- .cmdbuff_addr_lo_reg = 0x10548, /* C2PMSG_18 */ +- .cmdbuff_addr_hi_reg = 0x1054c, /* C2PMSG_19 */ + .ring_wptr_reg = 0x10550, /* C2PMSG_20 */ + .ring_rptr_reg = 0x10554, /* C2PMSG_21 */ + .info_reg = 0x109e8, /* C2PMSG_58 */ + }; + + static const struct tee_vdata teev2 = { +- .cmdresp_reg = 0x10944, /* C2PMSG_17 */ +- .cmdbuff_addr_lo_reg = 0x10948, /* C2PMSG_18 */ +- .cmdbuff_addr_hi_reg = 0x1094c, /* C2PMSG_19 */ + .ring_wptr_reg = 0x10950, /* C2PMSG_20 */ + .ring_rptr_reg = 0x10954, /* C2PMSG_21 */ + }; +@@ -469,6 +470,9 @@ static const struct psp_vdata pspv2 = { + static const struct psp_vdata pspv3 = { + .tee = &teev1, + .platform_access = &pa_v1, ++ .cmdresp_reg = 0x10544, /* C2PMSG_17 */ ++ .cmdbuff_addr_lo_reg = 0x10548, /* C2PMSG_18 */ ++ .cmdbuff_addr_hi_reg = 0x1054c, /* C2PMSG_19 */ + .bootloader_info_reg = 0x109ec, /* C2PMSG_59 */ + .feature_reg = 0x109fc, /* C2PMSG_63 */ + .inten_reg = 0x10690, /* P2CMSG_INTEN */ +@@ -479,6 +483,9 @@ static const struct psp_vdata pspv3 = { + static const struct psp_vdata pspv4 = { + .sev = &sevv2, + .tee = &teev1, ++ .cmdresp_reg = 0x10544, /* C2PMSG_17 */ ++ .cmdbuff_addr_lo_reg = 0x10548, /* C2PMSG_18 */ ++ .cmdbuff_addr_hi_reg = 0x1054c, /* C2PMSG_19 */ + .bootloader_info_reg = 0x109ec, /* C2PMSG_59 */ + .feature_reg = 0x109fc, /* C2PMSG_63 */ + .inten_reg = 0x10690, /* P2CMSG_INTEN */ +@@ -488,6 +495,9 @@ static const struct psp_vdata pspv4 = { + static const struct psp_vdata pspv5 = { + .tee = &teev2, + .platform_access = &pa_v2, ++ .cmdresp_reg = 0x10944, /* C2PMSG_17 */ ++ .cmdbuff_addr_lo_reg = 0x10948, /* C2PMSG_18 */ ++ .cmdbuff_addr_hi_reg = 0x1094c, /* C2PMSG_19 */ + .feature_reg = 0x109fc, /* C2PMSG_63 */ + .inten_reg = 0x10510, /* P2CMSG_INTEN */ + .intsts_reg = 0x10514, /* P2CMSG_INTSTS */ +@@ -496,6 +506,9 @@ static const struct psp_vdata pspv5 = { + static const struct psp_vdata pspv6 = { + .sev = &sevv2, + .tee = &teev2, ++ .cmdresp_reg = 0x10944, /* C2PMSG_17 */ ++ .cmdbuff_addr_lo_reg = 0x10948, /* C2PMSG_18 */ ++ .cmdbuff_addr_hi_reg = 0x1094c, /* C2PMSG_19 */ + .feature_reg = 0x109fc, /* C2PMSG_63 */ + .inten_reg = 0x10510, /* P2CMSG_INTEN */ + .intsts_reg = 0x10514, /* P2CMSG_INTSTS */ +@@ -585,7 +598,14 @@ static const struct pci_device_id sp_pci_table[] = { + }; + MODULE_DEVICE_TABLE(pci, sp_pci_table); + +-static SIMPLE_DEV_PM_OPS(sp_pci_pm_ops, sp_pci_suspend, sp_pci_resume); ++static const struct dev_pm_ops sp_pci_pm_ops = { ++ .suspend = pm_sleep_ptr(sp_pci_suspend), ++ .resume = pm_sleep_ptr(sp_pci_resume), ++ .freeze = pm_sleep_ptr(sp_pci_suspend), ++ .thaw = pm_sleep_ptr(sp_pci_resume), ++ .poweroff = pm_sleep_ptr(sp_pci_suspend), ++ .restore_early = pm_sleep_ptr(sp_pci_restore), ++}; + + static struct pci_driver sp_pci_driver = { + .name = "ccp", +diff --git a/drivers/crypto/ccp/tee-dev.c b/drivers/crypto/ccp/tee-dev.c +index 5560bf8329a127..01d7dcb9cfee19 100644 +--- a/drivers/crypto/ccp/tee-dev.c ++++ b/drivers/crypto/ccp/tee-dev.c +@@ -62,26 +62,6 @@ static void tee_free_ring(struct psp_tee_device *tee) + mutex_destroy(&rb_mgr->mutex); + } + +-static int tee_wait_cmd_poll(struct psp_tee_device *tee, unsigned int timeout, +- unsigned int *reg) +-{ +- /* ~10ms sleep per loop => nloop = timeout * 100 */ +- int nloop = timeout * 100; +- +- while (--nloop) { +- *reg = ioread32(tee->io_regs + tee->vdata->cmdresp_reg); +- if (FIELD_GET(PSP_CMDRESP_RESP, *reg)) +- return 0; +- +- usleep_range(10000, 10100); +- } +- +- dev_err(tee->dev, "tee: command timed out, disabling PSP\n"); +- psp_dead = true; +- +- return -ETIMEDOUT; +-} +- + static + struct tee_init_ring_cmd *tee_alloc_cmd_buffer(struct psp_tee_device *tee) + { +@@ -106,11 +86,34 @@ static inline void tee_free_cmd_buffer(struct tee_init_ring_cmd *cmd) + kfree(cmd); + } + ++static bool tee_send_destroy_cmd(struct psp_tee_device *tee) ++{ ++ unsigned int reg; ++ int ret; ++ ++ ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_DESTROY, NULL, ++ TEE_DEFAULT_CMD_TIMEOUT, ®); ++ if (ret) { ++ dev_err(tee->dev, "tee: ring destroy command timed out, disabling TEE support\n"); ++ psp_dead = true; ++ return false; ++ } ++ ++ if (FIELD_GET(PSP_CMDRESP_STS, reg)) { ++ dev_err(tee->dev, "tee: ring destroy command failed (%#010lx)\n", ++ FIELD_GET(PSP_CMDRESP_STS, reg)); ++ psp_dead = true; ++ return false; ++ } ++ ++ return true; ++} ++ + static int tee_init_ring(struct psp_tee_device *tee) + { + int ring_size = MAX_RING_BUFFER_ENTRIES * sizeof(struct tee_ring_cmd); + struct tee_init_ring_cmd *cmd; +- phys_addr_t cmd_buffer; ++ bool retry = false; + unsigned int reg; + int ret; + +@@ -130,27 +133,32 @@ static int tee_init_ring(struct psp_tee_device *tee) + return -ENOMEM; + } + +- cmd_buffer = __psp_pa((void *)cmd); +- + /* Send command buffer details to Trusted OS by writing to + * CPU-PSP message registers + */ +- +- iowrite32(lower_32_bits(cmd_buffer), +- tee->io_regs + tee->vdata->cmdbuff_addr_lo_reg); +- iowrite32(upper_32_bits(cmd_buffer), +- tee->io_regs + tee->vdata->cmdbuff_addr_hi_reg); +- iowrite32(TEE_RING_INIT_CMD, +- tee->io_regs + tee->vdata->cmdresp_reg); +- +- ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, ®); ++retry_init: ++ ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_INIT, cmd, ++ TEE_DEFAULT_CMD_TIMEOUT, ®); + if (ret) { +- dev_err(tee->dev, "tee: ring init command timed out\n"); ++ dev_err(tee->dev, "tee: ring init command timed out, disabling TEE support\n"); + tee_free_ring(tee); ++ psp_dead = true; + goto free_buf; + } + + if (FIELD_GET(PSP_CMDRESP_STS, reg)) { ++ /* ++ * During the hibernate resume sequence driver may have gotten loaded ++ * but the ring not properly destroyed. If the ring doesn't work, try ++ * to destroy and re-init once. ++ */ ++ if (!retry && FIELD_GET(PSP_CMDRESP_STS, reg) == PSP_TEE_STS_RING_BUSY) { ++ dev_info(tee->dev, "tee: ring init command failed with busy status, retrying\n"); ++ if (tee_send_destroy_cmd(tee)) { ++ retry = true; ++ goto retry_init; ++ } ++ } + dev_err(tee->dev, "tee: ring init command failed (%#010lx)\n", + FIELD_GET(PSP_CMDRESP_STS, reg)); + tee_free_ring(tee); +@@ -165,25 +173,13 @@ free_buf: + + static void tee_destroy_ring(struct psp_tee_device *tee) + { +- unsigned int reg; +- int ret; +- + if (!tee->rb_mgr.ring_start) + return; + + if (psp_dead) + goto free_ring; + +- iowrite32(TEE_RING_DESTROY_CMD, +- tee->io_regs + tee->vdata->cmdresp_reg); +- +- ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, ®); +- if (ret) { +- dev_err(tee->dev, "tee: ring destroy command timed out\n"); +- } else if (FIELD_GET(PSP_CMDRESP_STS, reg)) { +- dev_err(tee->dev, "tee: ring destroy command failed (%#010lx)\n", +- FIELD_GET(PSP_CMDRESP_STS, reg)); +- } ++ tee_send_destroy_cmd(tee); + + free_ring: + tee_free_ring(tee); +@@ -370,7 +366,7 @@ int psp_tee_process_cmd(enum tee_cmd_id cmd_id, void *buf, size_t len, + if (ret) + return ret; + +- ret = tee_wait_cmd_completion(tee, resp, TEE_DEFAULT_TIMEOUT); ++ ret = tee_wait_cmd_completion(tee, resp, TEE_DEFAULT_RING_TIMEOUT); + if (ret) { + resp->flag = CMD_RESPONSE_TIMEDOUT; + return ret; +@@ -395,3 +391,8 @@ int psp_check_tee_status(void) + return 0; + } + EXPORT_SYMBOL(psp_check_tee_status); ++ ++int tee_restore(struct psp_device *psp) ++{ ++ return tee_init_ring(psp->tee_data); ++} +diff --git a/drivers/crypto/ccp/tee-dev.h b/drivers/crypto/ccp/tee-dev.h +index 49d26158b71e31..c23416cb7bb37f 100644 +--- a/drivers/crypto/ccp/tee-dev.h ++++ b/drivers/crypto/ccp/tee-dev.h +@@ -17,21 +17,10 @@ + #include + #include + +-#define TEE_DEFAULT_TIMEOUT 10 ++#define TEE_DEFAULT_CMD_TIMEOUT (10 * MSEC_PER_SEC) ++#define TEE_DEFAULT_RING_TIMEOUT 10 + #define MAX_BUFFER_SIZE 988 + +-/** +- * enum tee_ring_cmd_id - TEE interface commands for ring buffer configuration +- * @TEE_RING_INIT_CMD: Initialize ring buffer +- * @TEE_RING_DESTROY_CMD: Destroy ring buffer +- * @TEE_RING_MAX_CMD: Maximum command id +- */ +-enum tee_ring_cmd_id { +- TEE_RING_INIT_CMD = 0x00010000, +- TEE_RING_DESTROY_CMD = 0x00020000, +- TEE_RING_MAX_CMD = 0x000F0000, +-}; +- + /** + * struct tee_init_ring_cmd - Command to init TEE ring buffer + * @low_addr: bits [31:0] of the physical address of ring buffer +@@ -122,5 +111,6 @@ struct tee_ring_cmd { + + int tee_dev_init(struct psp_device *psp); + void tee_dev_destroy(struct psp_device *psp); ++int tee_restore(struct psp_device *psp); + + #endif /* __TEE_DEV_H__ */ +diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c +index 2c0ca68914e2f2..e09357fea057ca 100644 +--- a/drivers/crypto/hisilicon/qm.c ++++ b/drivers/crypto/hisilicon/qm.c +@@ -633,9 +633,13 @@ static void qm_mb_write(struct hisi_qm *qm, const void *src) + } + + #if IS_ENABLED(CONFIG_ARM64) ++ /* ++ * The dmb oshst instruction ensures that the data in the ++ * mailbox is written before it is sent to the hardware. ++ */ + asm volatile("ldp %0, %1, %3\n" +- "stp %0, %1, %2\n" + "dmb oshst\n" ++ "stp %0, %1, %2\n" + : "=&r" (tmp0), + "=&r" (tmp1), + "+Q" (*((char __iomem *)fun_base)) +diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c +index d6727b8ff582b6..8db3d2990816ea 100644 +--- a/drivers/crypto/hisilicon/sec2/sec_crypto.c ++++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c +@@ -590,10 +590,8 @@ static int sec_ctx_base_init(struct sec_ctx *ctx) + int i, ret; + + ctx->qps = sec_create_qps(); +- if (!ctx->qps) { +- pr_err("Can not create sec qps!\n"); ++ if (!ctx->qps) + return -ENODEV; +- } + + sec = container_of(ctx->qps[0]->qm, struct sec_dev, qm); + ctx->sec = sec; +@@ -632,6 +630,9 @@ static void sec_ctx_base_uninit(struct sec_ctx *ctx) + { + int i; + ++ if (!ctx->qps) ++ return; ++ + for (i = 0; i < ctx->sec->ctx_q_num; i++) + sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]); + +@@ -643,6 +644,9 @@ static int sec_cipher_init(struct sec_ctx *ctx) + { + struct sec_cipher_ctx *c_ctx = &ctx->c_ctx; + ++ if (!ctx->qps) ++ return 0; ++ + c_ctx->c_key = dma_alloc_coherent(ctx->dev, SEC_MAX_KEY_SIZE, + &c_ctx->c_key_dma, GFP_KERNEL); + if (!c_ctx->c_key) +@@ -655,6 +659,9 @@ static void sec_cipher_uninit(struct sec_ctx *ctx) + { + struct sec_cipher_ctx *c_ctx = &ctx->c_ctx; + ++ if (!ctx->qps) ++ return; ++ + memzero_explicit(c_ctx->c_key, SEC_MAX_KEY_SIZE); + dma_free_coherent(ctx->dev, SEC_MAX_KEY_SIZE, + c_ctx->c_key, c_ctx->c_key_dma); +@@ -676,6 +683,9 @@ static void sec_auth_uninit(struct sec_ctx *ctx) + { + struct sec_auth_ctx *a_ctx = &ctx->a_ctx; + ++ if (!ctx->qps) ++ return; ++ + memzero_explicit(a_ctx->a_key, SEC_MAX_AKEY_SIZE); + dma_free_coherent(ctx->dev, SEC_MAX_AKEY_SIZE, + a_ctx->a_key, a_ctx->a_key_dma); +@@ -713,7 +723,7 @@ static int sec_skcipher_init(struct crypto_skcipher *tfm) + } + + ret = sec_ctx_base_init(ctx); +- if (ret) ++ if (ret && ret != -ENODEV) + return ret; + + ret = sec_cipher_init(ctx); +@@ -824,6 +834,9 @@ static int sec_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, + struct device *dev = ctx->dev; + int ret; + ++ if (!ctx->qps) ++ goto set_soft_key; ++ + if (c_mode == SEC_CMODE_XTS) { + ret = xts_verify_key(tfm, key, keylen); + if (ret) { +@@ -854,13 +867,14 @@ static int sec_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, + } + + memcpy(c_ctx->c_key, key, keylen); +- if (c_ctx->fbtfm) { +- ret = crypto_sync_skcipher_setkey(c_ctx->fbtfm, key, keylen); +- if (ret) { +- dev_err(dev, "failed to set fallback skcipher key!\n"); +- return ret; +- } ++ ++set_soft_key: ++ ret = crypto_sync_skcipher_setkey(c_ctx->fbtfm, key, keylen); ++ if (ret) { ++ dev_err(dev, "failed to set fallback skcipher key!\n"); ++ return ret; + } ++ + return 0; + } + +@@ -1139,6 +1153,9 @@ static int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key, + struct crypto_authenc_keys keys; + int ret; + ++ if (!ctx->qps) ++ return sec_aead_fallback_setkey(a_ctx, tfm, key, keylen); ++ + ctx->a_ctx.a_alg = a_alg; + ctx->c_ctx.c_alg = c_alg; + c_ctx->c_mode = c_mode; +@@ -1833,6 +1850,9 @@ static int sec_skcipher_ctx_init(struct crypto_skcipher *tfm) + if (ret) + return ret; + ++ if (!ctx->qps) ++ return 0; ++ + if (ctx->sec->qm.ver < QM_HW_V3) { + ctx->type_supported = SEC_BD_TYPE2; + ctx->req_op = &sec_skcipher_req_ops; +@@ -1841,7 +1861,7 @@ static int sec_skcipher_ctx_init(struct crypto_skcipher *tfm) + ctx->req_op = &sec_skcipher_req_ops_v3; + } + +- return ret; ++ return 0; + } + + static void sec_skcipher_ctx_exit(struct crypto_skcipher *tfm) +@@ -1909,7 +1929,7 @@ static int sec_aead_ctx_init(struct crypto_aead *tfm, const char *hash_name) + int ret; + + ret = sec_aead_init(tfm); +- if (ret) { ++ if (ret && ret != -ENODEV) { + pr_err("hisi_sec2: aead init error!\n"); + return ret; + } +@@ -1951,7 +1971,7 @@ static int sec_aead_xcm_ctx_init(struct crypto_aead *tfm) + int ret; + + ret = sec_aead_init(tfm); +- if (ret) { ++ if (ret && ret != -ENODEV) { + dev_err(ctx->dev, "hisi_sec2: aead xcm init error!\n"); + return ret; + } +@@ -2098,6 +2118,9 @@ static int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt) + bool need_fallback = false; + int ret; + ++ if (!ctx->qps) ++ goto soft_crypto; ++ + if (!sk_req->cryptlen) { + if (ctx->c_ctx.c_mode == SEC_CMODE_XTS) + return -EINVAL; +@@ -2114,9 +2137,12 @@ static int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt) + return -EINVAL; + + if (unlikely(ctx->c_ctx.fallback || need_fallback)) +- return sec_skcipher_soft_crypto(ctx, sk_req, encrypt); ++ goto soft_crypto; + + return ctx->req_op->process(ctx, req); ++ ++soft_crypto: ++ return sec_skcipher_soft_crypto(ctx, sk_req, encrypt); + } + + static int sec_skcipher_encrypt(struct skcipher_request *sk_req) +@@ -2346,6 +2372,9 @@ static int sec_aead_crypto(struct aead_request *a_req, bool encrypt) + bool need_fallback = false; + int ret; + ++ if (!ctx->qps) ++ goto soft_crypto; ++ + req->flag = a_req->base.flags; + req->aead_req.aead_req = a_req; + req->c_req.encrypt = encrypt; +@@ -2355,11 +2384,14 @@ static int sec_aead_crypto(struct aead_request *a_req, bool encrypt) + ret = sec_aead_param_check(ctx, req, &need_fallback); + if (unlikely(ret)) { + if (need_fallback) +- return sec_aead_soft_crypto(ctx, a_req, encrypt); ++ goto soft_crypto; + return -EINVAL; + } + + return ctx->req_op->process(ctx, req); ++ ++soft_crypto: ++ return sec_aead_soft_crypto(ctx, a_req, encrypt); + } + + static int sec_aead_encrypt(struct aead_request *a_req) +diff --git a/drivers/crypto/hisilicon/trng/trng.c b/drivers/crypto/hisilicon/trng/trng.c +index 97e500db0a8259..b2d9b5310b784c 100644 +--- a/drivers/crypto/hisilicon/trng/trng.c ++++ b/drivers/crypto/hisilicon/trng/trng.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0 + /* Copyright (c) 2019 HiSilicon Limited. */ + ++#include + #include + #include + #include +@@ -13,7 +14,6 @@ + #include + #include + #include +-#include + + #define HISI_TRNG_REG 0x00F0 + #define HISI_TRNG_BYTES 4 +@@ -40,6 +40,7 @@ + #define SEED_SHIFT_24 24 + #define SEED_SHIFT_16 16 + #define SEED_SHIFT_8 8 ++#define SW_MAX_RANDOM_BYTES 65520 + + struct hisi_trng_list { + struct mutex lock; +@@ -53,8 +54,10 @@ struct hisi_trng { + struct list_head list; + struct hwrng rng; + u32 ver; +- bool is_used; +- struct mutex mutex; ++ u32 ctx_num; ++ /* The bytes of the random number generated since the last seeding. */ ++ u32 random_bytes; ++ struct mutex lock; + }; + + struct hisi_trng_ctx { +@@ -63,10 +66,14 @@ struct hisi_trng_ctx { + + static atomic_t trng_active_devs; + static struct hisi_trng_list trng_devices; ++static int hisi_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait); + +-static void hisi_trng_set_seed(struct hisi_trng *trng, const u8 *seed) ++static int hisi_trng_set_seed(struct hisi_trng *trng, const u8 *seed) + { + u32 val, seed_reg, i; ++ int ret; ++ ++ writel(0x0, trng->base + SW_DRBG_BLOCKS); + + for (i = 0; i < SW_DRBG_SEED_SIZE; + i += SW_DRBG_SEED_SIZE / SW_DRBG_SEED_REGS_NUM) { +@@ -78,6 +85,20 @@ static void hisi_trng_set_seed(struct hisi_trng *trng, const u8 *seed) + seed_reg = (i >> SW_DRBG_NUM_SHIFT) % SW_DRBG_SEED_REGS_NUM; + writel(val, trng->base + SW_DRBG_SEED(seed_reg)); + } ++ ++ writel(SW_DRBG_BLOCKS_NUM | (0x1 << SW_DRBG_ENABLE_SHIFT), ++ trng->base + SW_DRBG_BLOCKS); ++ writel(0x1, trng->base + SW_DRBG_INIT); ++ ret = readl_relaxed_poll_timeout(trng->base + SW_DRBG_STATUS, ++ val, val & BIT(0), SLEEP_US, TIMEOUT_US); ++ if (ret) { ++ pr_err("failed to init trng(%d)\n", ret); ++ return -EIO; ++ } ++ ++ trng->random_bytes = 0; ++ ++ return 0; + } + + static int hisi_trng_seed(struct crypto_rng *tfm, const u8 *seed, +@@ -85,8 +106,7 @@ static int hisi_trng_seed(struct crypto_rng *tfm, const u8 *seed, + { + struct hisi_trng_ctx *ctx = crypto_rng_ctx(tfm); + struct hisi_trng *trng = ctx->trng; +- u32 val = 0; +- int ret = 0; ++ int ret; + + if (slen < SW_DRBG_SEED_SIZE) { + pr_err("slen(%u) is not matched with trng(%d)\n", slen, +@@ -94,43 +114,45 @@ static int hisi_trng_seed(struct crypto_rng *tfm, const u8 *seed, + return -EINVAL; + } + +- writel(0x0, trng->base + SW_DRBG_BLOCKS); +- hisi_trng_set_seed(trng, seed); ++ mutex_lock(&trng->lock); ++ ret = hisi_trng_set_seed(trng, seed); ++ mutex_unlock(&trng->lock); + +- writel(SW_DRBG_BLOCKS_NUM | (0x1 << SW_DRBG_ENABLE_SHIFT), +- trng->base + SW_DRBG_BLOCKS); +- writel(0x1, trng->base + SW_DRBG_INIT); ++ return ret; ++} + +- ret = readl_relaxed_poll_timeout(trng->base + SW_DRBG_STATUS, +- val, val & BIT(0), SLEEP_US, TIMEOUT_US); +- if (ret) +- pr_err("fail to init trng(%d)\n", ret); ++static int hisi_trng_reseed(struct hisi_trng *trng) ++{ ++ u8 seed[SW_DRBG_SEED_SIZE]; ++ int size; + +- return ret; ++ if (!trng->random_bytes) ++ return 0; ++ ++ size = hisi_trng_read(&trng->rng, seed, SW_DRBG_SEED_SIZE, false); ++ if (size != SW_DRBG_SEED_SIZE) ++ return -EIO; ++ ++ return hisi_trng_set_seed(trng, seed); + } + +-static int hisi_trng_generate(struct crypto_rng *tfm, const u8 *src, +- unsigned int slen, u8 *dstn, unsigned int dlen) ++static int hisi_trng_get_bytes(struct hisi_trng *trng, u8 *dstn, unsigned int dlen) + { +- struct hisi_trng_ctx *ctx = crypto_rng_ctx(tfm); +- struct hisi_trng *trng = ctx->trng; + u32 data[SW_DRBG_DATA_NUM]; + u32 currsize = 0; + u32 val = 0; + int ret; + u32 i; + +- if (dlen > SW_DRBG_BLOCKS_NUM * SW_DRBG_BYTES || dlen == 0) { +- pr_err("dlen(%d) exceeds limit(%d)!\n", dlen, +- SW_DRBG_BLOCKS_NUM * SW_DRBG_BYTES); +- return -EINVAL; +- } ++ ret = hisi_trng_reseed(trng); ++ if (ret) ++ return ret; + + do { + ret = readl_relaxed_poll_timeout(trng->base + SW_DRBG_STATUS, +- val, val & BIT(1), SLEEP_US, TIMEOUT_US); ++ val, val & BIT(1), SLEEP_US, TIMEOUT_US); + if (ret) { +- pr_err("fail to generate random number(%d)!\n", ret); ++ pr_err("failed to generate random number(%d)!\n", ret); + break; + } + +@@ -145,30 +167,57 @@ static int hisi_trng_generate(struct crypto_rng *tfm, const u8 *src, + currsize = dlen; + } + ++ trng->random_bytes += SW_DRBG_BYTES; + writel(0x1, trng->base + SW_DRBG_GEN); + } while (currsize < dlen); + + return ret; + } + ++static int hisi_trng_generate(struct crypto_rng *tfm, const u8 *src, ++ unsigned int slen, u8 *dstn, unsigned int dlen) ++{ ++ struct hisi_trng_ctx *ctx = crypto_rng_ctx(tfm); ++ struct hisi_trng *trng = ctx->trng; ++ unsigned int currsize = 0; ++ unsigned int block_size; ++ int ret; ++ ++ if (!dstn || !dlen) { ++ pr_err("output is error, dlen %u!\n", dlen); ++ return -EINVAL; ++ } ++ ++ do { ++ block_size = min_t(unsigned int, dlen - currsize, SW_MAX_RANDOM_BYTES); ++ mutex_lock(&trng->lock); ++ ret = hisi_trng_get_bytes(trng, dstn + currsize, block_size); ++ mutex_unlock(&trng->lock); ++ if (ret) ++ return ret; ++ currsize += block_size; ++ } while (currsize < dlen); ++ ++ return 0; ++} ++ + static int hisi_trng_init(struct crypto_tfm *tfm) + { + struct hisi_trng_ctx *ctx = crypto_tfm_ctx(tfm); + struct hisi_trng *trng; +- int ret = -EBUSY; ++ u32 ctx_num = ~0; + + mutex_lock(&trng_devices.lock); + list_for_each_entry(trng, &trng_devices.list, list) { +- if (!trng->is_used) { +- trng->is_used = true; ++ if (trng->ctx_num < ctx_num) { ++ ctx_num = trng->ctx_num; + ctx->trng = trng; +- ret = 0; +- break; + } + } ++ ctx->trng->ctx_num++; + mutex_unlock(&trng_devices.lock); + +- return ret; ++ return 0; + } + + static void hisi_trng_exit(struct crypto_tfm *tfm) +@@ -176,7 +225,7 @@ static void hisi_trng_exit(struct crypto_tfm *tfm) + struct hisi_trng_ctx *ctx = crypto_tfm_ctx(tfm); + + mutex_lock(&trng_devices.lock); +- ctx->trng->is_used = false; ++ ctx->trng->ctx_num--; + mutex_unlock(&trng_devices.lock); + } + +@@ -238,7 +287,7 @@ static int hisi_trng_del_from_list(struct hisi_trng *trng) + int ret = -EBUSY; + + mutex_lock(&trng_devices.lock); +- if (!trng->is_used) { ++ if (!trng->ctx_num) { + list_del(&trng->list); + ret = 0; + } +@@ -262,7 +311,9 @@ static int hisi_trng_probe(struct platform_device *pdev) + if (IS_ERR(trng->base)) + return PTR_ERR(trng->base); + +- trng->is_used = false; ++ trng->ctx_num = 0; ++ trng->random_bytes = SW_MAX_RANDOM_BYTES; ++ mutex_init(&trng->lock); + trng->ver = readl(trng->base + HISI_TRNG_VERSION); + if (!trng_devices.is_init) { + INIT_LIST_HEAD(&trng_devices.list); +diff --git a/drivers/crypto/hisilicon/zip/zip_crypto.c b/drivers/crypto/hisilicon/zip/zip_crypto.c +index 6608971d10cdc1..d21ce4094d7dbf 100644 +--- a/drivers/crypto/hisilicon/zip/zip_crypto.c ++++ b/drivers/crypto/hisilicon/zip/zip_crypto.c +@@ -16,36 +16,14 @@ + #define HZIP_OUT_SGE_DATA_OFFSET_M GENMASK(23, 0) + /* hisi_zip_sqe dw9 */ + #define HZIP_REQ_TYPE_M GENMASK(7, 0) +-#define HZIP_ALG_TYPE_ZLIB 0x02 +-#define HZIP_ALG_TYPE_GZIP 0x03 ++#define HZIP_ALG_TYPE_DEFLATE 0x01 + #define HZIP_BUF_TYPE_M GENMASK(11, 8) +-#define HZIP_PBUFFER 0x0 + #define HZIP_SGL 0x1 + +-#define HZIP_ZLIB_HEAD_SIZE 2 +-#define HZIP_GZIP_HEAD_SIZE 10 +- +-#define GZIP_HEAD_FHCRC_BIT BIT(1) +-#define GZIP_HEAD_FEXTRA_BIT BIT(2) +-#define GZIP_HEAD_FNAME_BIT BIT(3) +-#define GZIP_HEAD_FCOMMENT_BIT BIT(4) +- +-#define GZIP_HEAD_FLG_SHIFT 3 +-#define GZIP_HEAD_FEXTRA_SHIFT 10 +-#define GZIP_HEAD_FEXTRA_XLEN 2UL +-#define GZIP_HEAD_FHCRC_SIZE 2 +- +-#define HZIP_GZIP_HEAD_BUF 256 + #define HZIP_ALG_PRIORITY 300 + #define HZIP_SGL_SGE_NR 10 + +-#define HZIP_ALG_ZLIB GENMASK(1, 0) +-#define HZIP_ALG_GZIP GENMASK(3, 2) +- +-static const u8 zlib_head[HZIP_ZLIB_HEAD_SIZE] = {0x78, 0x9c}; +-static const u8 gzip_head[HZIP_GZIP_HEAD_SIZE] = { +- 0x1f, 0x8b, 0x08, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x03 +-}; ++#define HZIP_ALG_DEFLATE GENMASK(5, 4) + + enum hisi_zip_alg_type { + HZIP_ALG_TYPE_COMP = 0, +@@ -58,26 +36,17 @@ enum { + HZIP_CTX_Q_NUM + }; + ++#define GET_REQ_FROM_SQE(sqe) ((u64)(sqe)->dw26 | (u64)(sqe)->dw27 << 32) + #define COMP_NAME_TO_TYPE(alg_name) \ +- (!strcmp((alg_name), "zlib-deflate") ? HZIP_ALG_TYPE_ZLIB : \ +- !strcmp((alg_name), "gzip") ? HZIP_ALG_TYPE_GZIP : 0) \ +- +-#define TO_HEAD_SIZE(req_type) \ +- (((req_type) == HZIP_ALG_TYPE_ZLIB) ? sizeof(zlib_head) : \ +- ((req_type) == HZIP_ALG_TYPE_GZIP) ? sizeof(gzip_head) : 0) \ +- +-#define TO_HEAD(req_type) \ +- (((req_type) == HZIP_ALG_TYPE_ZLIB) ? zlib_head : \ +- ((req_type) == HZIP_ALG_TYPE_GZIP) ? gzip_head : NULL) \ ++ (!strcmp((alg_name), "deflate") ? HZIP_ALG_TYPE_DEFLATE : 0) + + struct hisi_zip_req { + struct acomp_req *req; +- u32 sskip; +- u32 dskip; + struct hisi_acc_hw_sgl *hw_src; + struct hisi_acc_hw_sgl *hw_dst; + dma_addr_t dma_src; + dma_addr_t dma_dst; ++ struct hisi_zip_qp_ctx *qp_ctx; + u16 req_id; + }; + +@@ -104,7 +73,6 @@ struct hisi_zip_sqe_ops { + void (*fill_req_type)(struct hisi_zip_sqe *sqe, u8 req_type); + void (*fill_tag)(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req); + void (*fill_sqe_type)(struct hisi_zip_sqe *sqe, u8 sqe_type); +- u32 (*get_tag)(struct hisi_zip_sqe *sqe); + u32 (*get_status)(struct hisi_zip_sqe *sqe); + u32 (*get_dstlen)(struct hisi_zip_sqe *sqe); + }; +@@ -138,85 +106,8 @@ static u16 sgl_sge_nr = HZIP_SGL_SGE_NR; + module_param_cb(sgl_sge_nr, &sgl_sge_nr_ops, &sgl_sge_nr, 0444); + MODULE_PARM_DESC(sgl_sge_nr, "Number of sge in sgl(1-255)"); + +-static u32 get_extra_field_size(const u8 *start) +-{ +- return *((u16 *)start) + GZIP_HEAD_FEXTRA_XLEN; +-} +- +-static u32 get_name_field_size(const u8 *start) +-{ +- return strlen(start) + 1; +-} +- +-static u32 get_comment_field_size(const u8 *start) +-{ +- return strlen(start) + 1; +-} +- +-static u32 __get_gzip_head_size(const u8 *src) +-{ +- u8 head_flg = *(src + GZIP_HEAD_FLG_SHIFT); +- u32 size = GZIP_HEAD_FEXTRA_SHIFT; +- +- if (head_flg & GZIP_HEAD_FEXTRA_BIT) +- size += get_extra_field_size(src + size); +- if (head_flg & GZIP_HEAD_FNAME_BIT) +- size += get_name_field_size(src + size); +- if (head_flg & GZIP_HEAD_FCOMMENT_BIT) +- size += get_comment_field_size(src + size); +- if (head_flg & GZIP_HEAD_FHCRC_BIT) +- size += GZIP_HEAD_FHCRC_SIZE; +- +- return size; +-} +- +-static u32 __maybe_unused get_gzip_head_size(struct scatterlist *sgl) +-{ +- char buf[HZIP_GZIP_HEAD_BUF]; +- +- sg_copy_to_buffer(sgl, sg_nents(sgl), buf, sizeof(buf)); +- +- return __get_gzip_head_size(buf); +-} +- +-static int add_comp_head(struct scatterlist *dst, u8 req_type) +-{ +- int head_size = TO_HEAD_SIZE(req_type); +- const u8 *head = TO_HEAD(req_type); +- int ret; +- +- ret = sg_copy_from_buffer(dst, sg_nents(dst), head, head_size); +- if (unlikely(ret != head_size)) { +- pr_err("the head size of buffer is wrong (%d)!\n", ret); +- return -ENOMEM; +- } +- +- return head_size; +-} +- +-static int get_comp_head_size(struct acomp_req *acomp_req, u8 req_type) +-{ +- if (unlikely(!acomp_req->src || !acomp_req->slen)) +- return -EINVAL; +- +- if (unlikely(req_type == HZIP_ALG_TYPE_GZIP && +- acomp_req->slen < GZIP_HEAD_FEXTRA_SHIFT)) +- return -EINVAL; +- +- switch (req_type) { +- case HZIP_ALG_TYPE_ZLIB: +- return TO_HEAD_SIZE(HZIP_ALG_TYPE_ZLIB); +- case HZIP_ALG_TYPE_GZIP: +- return TO_HEAD_SIZE(HZIP_ALG_TYPE_GZIP); +- default: +- pr_err("request type does not support!\n"); +- return -EINVAL; +- } +-} +- +-static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req, +- struct hisi_zip_qp_ctx *qp_ctx, +- size_t head_size, bool is_comp) ++static struct hisi_zip_req *hisi_zip_create_req(struct hisi_zip_qp_ctx *qp_ctx, ++ struct acomp_req *req) + { + struct hisi_zip_req_q *req_q = &qp_ctx->req_q; + struct hisi_zip_req *q = req_q->q; +@@ -238,14 +129,7 @@ static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req, + req_cache = q + req_id; + req_cache->req_id = req_id; + req_cache->req = req; +- +- if (is_comp) { +- req_cache->sskip = 0; +- req_cache->dskip = head_size; +- } else { +- req_cache->sskip = head_size; +- req_cache->dskip = 0; +- } ++ req_cache->qp_ctx = qp_ctx; + + return req_cache; + } +@@ -272,10 +156,8 @@ static void hisi_zip_fill_buf_size(struct hisi_zip_sqe *sqe, struct hisi_zip_req + { + struct acomp_req *a_req = req->req; + +- sqe->input_data_length = a_req->slen - req->sskip; +- sqe->dest_avail_out = a_req->dlen - req->dskip; +- sqe->dw7 = FIELD_PREP(HZIP_IN_SGE_DATA_OFFSET_M, req->sskip); +- sqe->dw8 = FIELD_PREP(HZIP_OUT_SGE_DATA_OFFSET_M, req->dskip); ++ sqe->input_data_length = a_req->slen; ++ sqe->dest_avail_out = a_req->dlen; + } + + static void hisi_zip_fill_buf_type(struct hisi_zip_sqe *sqe, u8 buf_type) +@@ -296,14 +178,10 @@ static void hisi_zip_fill_req_type(struct hisi_zip_sqe *sqe, u8 req_type) + sqe->dw9 = val; + } + +-static void hisi_zip_fill_tag_v1(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req) +-{ +- sqe->dw13 = req->req_id; +-} +- +-static void hisi_zip_fill_tag_v2(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req) ++static void hisi_zip_fill_tag(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req) + { +- sqe->dw26 = req->req_id; ++ sqe->dw26 = lower_32_bits((u64)req); ++ sqe->dw27 = upper_32_bits((u64)req); + } + + static void hisi_zip_fill_sqe_type(struct hisi_zip_sqe *sqe, u8 sqe_type) +@@ -330,8 +208,8 @@ static void hisi_zip_fill_sqe(struct hisi_zip_ctx *ctx, struct hisi_zip_sqe *sqe + ops->fill_sqe_type(sqe, ops->sqe_type); + } + +-static int hisi_zip_do_work(struct hisi_zip_req *req, +- struct hisi_zip_qp_ctx *qp_ctx) ++static int hisi_zip_do_work(struct hisi_zip_qp_ctx *qp_ctx, ++ struct hisi_zip_req *req) + { + struct hisi_acc_sgl_pool *pool = qp_ctx->sgl_pool; + struct hisi_zip_dfx *dfx = &qp_ctx->zip_dev->dfx; +@@ -357,7 +235,7 @@ static int hisi_zip_do_work(struct hisi_zip_req *req, + &req->dma_dst); + if (IS_ERR(req->hw_dst)) { + ret = PTR_ERR(req->hw_dst); +- dev_err(dev, "failed to map the dst buffer to hw slg (%d)!\n", ++ dev_err(dev, "failed to map the dst buffer to hw sgl (%d)!\n", + ret); + goto err_unmap_input; + } +@@ -383,16 +261,6 @@ err_unmap_input: + return ret; + } + +-static u32 hisi_zip_get_tag_v1(struct hisi_zip_sqe *sqe) +-{ +- return sqe->dw13; +-} +- +-static u32 hisi_zip_get_tag_v2(struct hisi_zip_sqe *sqe) +-{ +- return sqe->dw26; +-} +- + static u32 hisi_zip_get_status(struct hisi_zip_sqe *sqe) + { + return sqe->dw3 & HZIP_BD_STATUS_M; +@@ -405,17 +273,15 @@ static u32 hisi_zip_get_dstlen(struct hisi_zip_sqe *sqe) + + static void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data) + { +- struct hisi_zip_qp_ctx *qp_ctx = qp->qp_ctx; ++ struct hisi_zip_sqe *sqe = data; ++ struct hisi_zip_req *req = (struct hisi_zip_req *)GET_REQ_FROM_SQE(sqe); ++ struct hisi_zip_qp_ctx *qp_ctx = req->qp_ctx; + const struct hisi_zip_sqe_ops *ops = qp_ctx->ctx->ops; + struct hisi_zip_dfx *dfx = &qp_ctx->zip_dev->dfx; +- struct hisi_zip_req_q *req_q = &qp_ctx->req_q; + struct device *dev = &qp->qm->pdev->dev; +- struct hisi_zip_sqe *sqe = data; +- u32 tag = ops->get_tag(sqe); +- struct hisi_zip_req *req = req_q->q + tag; + struct acomp_req *acomp_req = req->req; +- u32 status, dlen, head_size; + int err = 0; ++ u32 status; + + atomic64_inc(&dfx->recv_cnt); + status = ops->get_status(sqe); +@@ -427,13 +293,10 @@ static void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data) + err = -EIO; + } + +- dlen = ops->get_dstlen(sqe); +- + hisi_acc_sg_buf_unmap(dev, acomp_req->src, req->hw_src); + hisi_acc_sg_buf_unmap(dev, acomp_req->dst, req->hw_dst); + +- head_size = (qp->alg_type == 0) ? TO_HEAD_SIZE(qp->req_type) : 0; +- acomp_req->dlen = dlen + head_size; ++ acomp_req->dlen = ops->get_dstlen(sqe); + + if (acomp_req->base.complete) + acomp_request_complete(acomp_req, err); +@@ -447,22 +310,13 @@ static int hisi_zip_acompress(struct acomp_req *acomp_req) + struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[HZIP_QPC_COMP]; + struct device *dev = &qp_ctx->qp->qm->pdev->dev; + struct hisi_zip_req *req; +- int head_size; + int ret; + +- /* let's output compression head now */ +- head_size = add_comp_head(acomp_req->dst, qp_ctx->qp->req_type); +- if (unlikely(head_size < 0)) { +- dev_err_ratelimited(dev, "failed to add comp head (%d)!\n", +- head_size); +- return head_size; +- } +- +- req = hisi_zip_create_req(acomp_req, qp_ctx, head_size, true); ++ req = hisi_zip_create_req(qp_ctx, acomp_req); + if (IS_ERR(req)) + return PTR_ERR(req); + +- ret = hisi_zip_do_work(req, qp_ctx); ++ ret = hisi_zip_do_work(qp_ctx, req); + if (unlikely(ret != -EINPROGRESS)) { + dev_info_ratelimited(dev, "failed to do compress (%d)!\n", ret); + hisi_zip_remove_req(qp_ctx, req); +@@ -477,20 +331,13 @@ static int hisi_zip_adecompress(struct acomp_req *acomp_req) + struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[HZIP_QPC_DECOMP]; + struct device *dev = &qp_ctx->qp->qm->pdev->dev; + struct hisi_zip_req *req; +- int head_size, ret; +- +- head_size = get_comp_head_size(acomp_req, qp_ctx->qp->req_type); +- if (unlikely(head_size < 0)) { +- dev_err_ratelimited(dev, "failed to get comp head size (%d)!\n", +- head_size); +- return head_size; +- } ++ int ret; + +- req = hisi_zip_create_req(acomp_req, qp_ctx, head_size, false); ++ req = hisi_zip_create_req(qp_ctx, acomp_req); + if (IS_ERR(req)) + return PTR_ERR(req); + +- ret = hisi_zip_do_work(req, qp_ctx); ++ ret = hisi_zip_do_work(qp_ctx, req); + if (unlikely(ret != -EINPROGRESS)) { + dev_info_ratelimited(dev, "failed to do decompress (%d)!\n", + ret); +@@ -527,28 +374,14 @@ static void hisi_zip_release_qp(struct hisi_zip_qp_ctx *qp_ctx) + hisi_qm_free_qps(&qp_ctx->qp, 1); + } + +-static const struct hisi_zip_sqe_ops hisi_zip_ops_v1 = { +- .sqe_type = 0, +- .fill_addr = hisi_zip_fill_addr, +- .fill_buf_size = hisi_zip_fill_buf_size, +- .fill_buf_type = hisi_zip_fill_buf_type, +- .fill_req_type = hisi_zip_fill_req_type, +- .fill_tag = hisi_zip_fill_tag_v1, +- .fill_sqe_type = hisi_zip_fill_sqe_type, +- .get_tag = hisi_zip_get_tag_v1, +- .get_status = hisi_zip_get_status, +- .get_dstlen = hisi_zip_get_dstlen, +-}; +- +-static const struct hisi_zip_sqe_ops hisi_zip_ops_v2 = { ++static const struct hisi_zip_sqe_ops hisi_zip_ops = { + .sqe_type = 0x3, + .fill_addr = hisi_zip_fill_addr, + .fill_buf_size = hisi_zip_fill_buf_size, + .fill_buf_type = hisi_zip_fill_buf_type, + .fill_req_type = hisi_zip_fill_req_type, +- .fill_tag = hisi_zip_fill_tag_v2, ++ .fill_tag = hisi_zip_fill_tag, + .fill_sqe_type = hisi_zip_fill_sqe_type, +- .get_tag = hisi_zip_get_tag_v2, + .get_status = hisi_zip_get_status, + .get_dstlen = hisi_zip_get_dstlen, + }; +@@ -584,10 +417,7 @@ static int hisi_zip_ctx_init(struct hisi_zip_ctx *hisi_zip_ctx, u8 req_type, int + qp_ctx->zip_dev = hisi_zip; + } + +- if (hisi_zip->qm.ver < QM_HW_V3) +- hisi_zip_ctx->ops = &hisi_zip_ops_v1; +- else +- hisi_zip_ctx->ops = &hisi_zip_ops_v2; ++ hisi_zip_ctx->ops = &hisi_zip_ops; + + return 0; + } +@@ -739,101 +569,53 @@ static void hisi_zip_acomp_exit(struct crypto_acomp *tfm) + { + struct hisi_zip_ctx *ctx = crypto_tfm_ctx(&tfm->base); + +- hisi_zip_set_acomp_cb(ctx, NULL); + hisi_zip_release_sgl_pool(ctx); + hisi_zip_release_req_q(ctx); + hisi_zip_ctx_exit(ctx); + } + +-static struct acomp_alg hisi_zip_acomp_zlib = { ++static struct acomp_alg hisi_zip_acomp_deflate = { + .init = hisi_zip_acomp_init, + .exit = hisi_zip_acomp_exit, + .compress = hisi_zip_acompress, + .decompress = hisi_zip_adecompress, + .base = { +- .cra_name = "zlib-deflate", +- .cra_driver_name = "hisi-zlib-acomp", ++ .cra_name = "deflate", ++ .cra_driver_name = "hisi-deflate-acomp", + .cra_module = THIS_MODULE, +- .cra_priority = HZIP_ALG_PRIORITY, ++ .cra_priority = HZIP_ALG_PRIORITY, + .cra_ctxsize = sizeof(struct hisi_zip_ctx), + } + }; + +-static int hisi_zip_register_zlib(struct hisi_qm *qm) ++static int hisi_zip_register_deflate(struct hisi_qm *qm) + { + int ret; + +- if (!hisi_zip_alg_support(qm, HZIP_ALG_ZLIB)) ++ if (!hisi_zip_alg_support(qm, HZIP_ALG_DEFLATE)) + return 0; + +- ret = crypto_register_acomp(&hisi_zip_acomp_zlib); ++ ret = crypto_register_acomp(&hisi_zip_acomp_deflate); + if (ret) +- dev_err(&qm->pdev->dev, "failed to register to zlib (%d)!\n", ret); ++ dev_err(&qm->pdev->dev, "failed to register to deflate (%d)!\n", ret); + + return ret; + } + +-static void hisi_zip_unregister_zlib(struct hisi_qm *qm) ++static void hisi_zip_unregister_deflate(struct hisi_qm *qm) + { +- if (!hisi_zip_alg_support(qm, HZIP_ALG_ZLIB)) ++ if (!hisi_zip_alg_support(qm, HZIP_ALG_DEFLATE)) + return; + +- crypto_unregister_acomp(&hisi_zip_acomp_zlib); +-} +- +-static struct acomp_alg hisi_zip_acomp_gzip = { +- .init = hisi_zip_acomp_init, +- .exit = hisi_zip_acomp_exit, +- .compress = hisi_zip_acompress, +- .decompress = hisi_zip_adecompress, +- .base = { +- .cra_name = "gzip", +- .cra_driver_name = "hisi-gzip-acomp", +- .cra_module = THIS_MODULE, +- .cra_priority = HZIP_ALG_PRIORITY, +- .cra_ctxsize = sizeof(struct hisi_zip_ctx), +- } +-}; +- +-static int hisi_zip_register_gzip(struct hisi_qm *qm) +-{ +- int ret; +- +- if (!hisi_zip_alg_support(qm, HZIP_ALG_GZIP)) +- return 0; +- +- ret = crypto_register_acomp(&hisi_zip_acomp_gzip); +- if (ret) +- dev_err(&qm->pdev->dev, "failed to register to gzip (%d)!\n", ret); +- +- return ret; +-} +- +-static void hisi_zip_unregister_gzip(struct hisi_qm *qm) +-{ +- if (!hisi_zip_alg_support(qm, HZIP_ALG_GZIP)) +- return; +- +- crypto_unregister_acomp(&hisi_zip_acomp_gzip); ++ crypto_unregister_acomp(&hisi_zip_acomp_deflate); + } + + int hisi_zip_register_to_crypto(struct hisi_qm *qm) + { +- int ret = 0; +- +- ret = hisi_zip_register_zlib(qm); +- if (ret) +- return ret; +- +- ret = hisi_zip_register_gzip(qm); +- if (ret) +- hisi_zip_unregister_zlib(qm); +- +- return ret; ++ return hisi_zip_register_deflate(qm); + } + + void hisi_zip_unregister_from_crypto(struct hisi_qm *qm) + { +- hisi_zip_unregister_zlib(qm); +- hisi_zip_unregister_gzip(qm); ++ hisi_zip_unregister_deflate(qm); + } +diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c +index b70aa6032874e1..91212d9584bf54 100644 +--- a/drivers/crypto/hisilicon/zip/zip_main.c ++++ b/drivers/crypto/hisilicon/zip/zip_main.c +@@ -238,8 +238,8 @@ static struct hisi_qm_cap_info zip_basic_cap_info[] = { + {ZIP_CLUSTER_DECOMP_NUM_CAP, 0x313C, 0, GENMASK(7, 0), 0x6, 0x6, 0x3}, + {ZIP_DECOMP_ENABLE_BITMAP, 0x3140, 16, GENMASK(15, 0), 0xFC, 0xFC, 0x1C}, + {ZIP_COMP_ENABLE_BITMAP, 0x3140, 0, GENMASK(15, 0), 0x3, 0x3, 0x3}, +- {ZIP_DRV_ALG_BITMAP, 0x3144, 0, GENMASK(31, 0), 0xF, 0xF, 0xF}, +- {ZIP_DEV_ALG_BITMAP, 0x3148, 0, GENMASK(31, 0), 0xF, 0xF, 0xFF}, ++ {ZIP_DRV_ALG_BITMAP, 0x3144, 0, GENMASK(31, 0), 0x0, 0x0, 0x30}, ++ {ZIP_DEV_ALG_BITMAP, 0x3148, 0, GENMASK(31, 0), 0xF, 0xF, 0x3F}, + {ZIP_CORE1_ALG_BITMAP, 0x314C, 0, GENMASK(31, 0), 0x5, 0x5, 0xD5}, + {ZIP_CORE2_ALG_BITMAP, 0x3150, 0, GENMASK(31, 0), 0x5, 0x5, 0xD5}, + {ZIP_CORE3_ALG_BITMAP, 0x3154, 0, GENMASK(31, 0), 0xA, 0xA, 0x2A}, +diff --git a/drivers/crypto/intel/qat/qat_common/adf_pfvf_pf_proto.c b/drivers/crypto/intel/qat/qat_common/adf_pfvf_pf_proto.c +index 388e58bcbcaf26..4a1ea3e720329c 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_pfvf_pf_proto.c ++++ b/drivers/crypto/intel/qat/qat_common/adf_pfvf_pf_proto.c +@@ -148,6 +148,16 @@ static struct pfvf_message handle_blkmsg_req(struct adf_accel_vf_info *vf_info, + blk_byte = FIELD_GET(ADF_VF2PF_SMALL_BLOCK_BYTE_MASK, req.data); + byte_max = ADF_VF2PF_SMALL_BLOCK_BYTE_MAX; + break; ++ default: ++ dev_err(&GET_DEV(vf_info->accel_dev), ++ "Invalid BlockMsg type 0x%.4x received from VF%u\n", ++ req.type, vf_info->vf_nr); ++ resp.type = ADF_PF2VF_MSGTYPE_BLKMSG_RESP; ++ resp.data = FIELD_PREP(ADF_PF2VF_BLKMSG_RESP_TYPE_MASK, ++ ADF_PF2VF_BLKMSG_RESP_TYPE_ERROR) | ++ FIELD_PREP(ADF_PF2VF_BLKMSG_RESP_DATA_MASK, ++ ADF_PF2VF_UNSPECIFIED_ERROR); ++ return resp; + } + + /* Is this a request for CRC or data? */ +diff --git a/drivers/crypto/marvell/octeontx/otx_cptvf_main.c b/drivers/crypto/marvell/octeontx/otx_cptvf_main.c +index 88a41d1ca5f644..6c0bfb3ea1c9f2 100644 +--- a/drivers/crypto/marvell/octeontx/otx_cptvf_main.c ++++ b/drivers/crypto/marvell/octeontx/otx_cptvf_main.c +@@ -168,7 +168,8 @@ static void free_command_queues(struct otx_cptvf *cptvf, + chunk = list_first_entry(&cqinfo->queue[i].chead, + struct otx_cpt_cmd_chunk, nextchunk); + +- dma_free_coherent(&pdev->dev, chunk->size, ++ dma_free_coherent(&pdev->dev, ++ chunk->size + OTX_CPT_NEXT_CHUNK_PTR_SIZE, + chunk->head, + chunk->dma_addr); + chunk->head = NULL; +diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c +index 36b20b844b109a..f9738c863df0e1 100644 +--- a/drivers/cxl/core/hdm.c ++++ b/drivers/cxl/core/hdm.c +@@ -710,14 +710,13 @@ static int cxl_decoder_commit(struct cxl_decoder *cxld) + writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(id)); + up_read(&cxl_dpa_rwsem); + +- port->commit_end++; + rc = cxld_await_commit(hdm, cxld->id); + if (rc) { + dev_dbg(&port->dev, "%s: error %d committing decoder\n", + dev_name(&cxld->dev), rc); +- cxld->reset(cxld); + return rc; + } ++ port->commit_end++; + cxld->flags |= CXL_DECODER_F_ENABLE; + + return 0; +diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c +index 4f426be2868843..93e00130400df2 100644 +--- a/drivers/dma/dma-axi-dmac.c ++++ b/drivers/dma/dma-axi-dmac.c +@@ -225,6 +225,7 @@ static void axi_dmac_start_transfer(struct axi_dmac_chan *chan) + return; + list_move_tail(&vdesc->node, &chan->active_descs); + desc = to_axi_dmac_desc(vdesc); ++ chan->next_desc = desc; + } + sg = &desc->sg[desc->num_submitted]; + +@@ -242,8 +243,6 @@ static void axi_dmac_start_transfer(struct axi_dmac_chan *chan) + else + chan->next_desc = NULL; + flags |= AXI_DMAC_FLAG_LAST; +- } else { +- chan->next_desc = desc; + } + + sg->id = axi_dmac_read(dmac, AXI_DMAC_REG_TRANSFER_ID); +diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c +index eccbcf67951fbe..34b194759d218e 100644 +--- a/drivers/dma/fsl-edma-main.c ++++ b/drivers/dma/fsl-edma-main.c +@@ -669,7 +669,7 @@ static int fsl_edma_probe(struct platform_device *pdev) + return 0; + } + +-static int fsl_edma_remove(struct platform_device *pdev) ++static void fsl_edma_remove(struct platform_device *pdev) + { + struct device_node *np = pdev->dev.of_node; + struct fsl_edma_engine *fsl_edma = platform_get_drvdata(pdev); +@@ -678,9 +678,6 @@ static int fsl_edma_remove(struct platform_device *pdev) + of_dma_controller_free(np); + dma_async_device_unregister(&fsl_edma->dma_dev); + fsl_edma_cleanup_vchan(&fsl_edma->dma_dev); +- fsl_disable_clocks(fsl_edma, fsl_edma->drvdata->dmamuxs); +- +- return 0; + } + + static int fsl_edma_suspend_late(struct device *dev) +@@ -749,7 +746,7 @@ static struct platform_driver fsl_edma_driver = { + .pm = &fsl_edma_pm_ops, + }, + .probe = fsl_edma_probe, +- .remove = fsl_edma_remove, ++ .remove_new = fsl_edma_remove, + }; + + static int __init fsl_edma_init(void) +diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/mtk-uart-apdma.c +index 06d12ac39144f4..aa42a09fde1a68 100644 +--- a/drivers/dma/mediatek/mtk-uart-apdma.c ++++ b/drivers/dma/mediatek/mtk-uart-apdma.c +@@ -41,7 +41,7 @@ + #define VFF_STOP_CLR_B 0 + #define VFF_EN_CLR_B 0 + #define VFF_INT_EN_CLR_B 0 +-#define VFF_4G_SUPPORT_CLR_B 0 ++#define VFF_ADDR2_CLR_B 0 + + /* + * interrupt trigger level for tx +@@ -72,7 +72,7 @@ + /* TX: the buffer size SW can write. RX: the buffer size HW can write. */ + #define VFF_LEFT_SIZE 0x40 + #define VFF_DEBUG_STATUS 0x50 +-#define VFF_4G_SUPPORT 0x54 ++#define VFF_ADDR2 0x54 + + struct mtk_uart_apdmadev { + struct dma_device ddev; +@@ -149,7 +149,7 @@ static void mtk_uart_apdma_start_tx(struct mtk_chan *c) + mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_TX_INT_CLR_B); + + if (mtkd->support_33bits) +- mtk_uart_apdma_write(c, VFF_4G_SUPPORT, VFF_4G_EN_B); ++ mtk_uart_apdma_write(c, VFF_ADDR2, upper_32_bits(d->addr)); + } + + mtk_uart_apdma_write(c, VFF_EN, VFF_EN_B); +@@ -192,7 +192,7 @@ static void mtk_uart_apdma_start_rx(struct mtk_chan *c) + mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_RX_INT_CLR_B); + + if (mtkd->support_33bits) +- mtk_uart_apdma_write(c, VFF_4G_SUPPORT, VFF_4G_EN_B); ++ mtk_uart_apdma_write(c, VFF_ADDR2, upper_32_bits(d->addr)); + } + + mtk_uart_apdma_write(c, VFF_INT_EN, VFF_RX_INT_EN_B); +@@ -298,7 +298,7 @@ static int mtk_uart_apdma_alloc_chan_resources(struct dma_chan *chan) + } + + if (mtkd->support_33bits) +- mtk_uart_apdma_write(c, VFF_4G_SUPPORT, VFF_4G_SUPPORT_CLR_B); ++ mtk_uart_apdma_write(c, VFF_ADDR2, VFF_ADDR2_CLR_B); + + err_pm: + pm_runtime_put_noidle(mtkd->ddev.dev); +diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c +index f414efdbd809e1..87956563cb1d35 100644 +--- a/drivers/dma/stm32-mdma.c ++++ b/drivers/dma/stm32-mdma.c +@@ -732,7 +732,7 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, + struct stm32_mdma_chan_config *chan_config = &chan->chan_config; + struct scatterlist *sg; + dma_addr_t src_addr, dst_addr; +- u32 m2m_hw_period, ccr, ctcr, ctbr; ++ u32 m2m_hw_period = 0, ccr = 0, ctcr, ctbr; + int i, ret = 0; + + if (chan_config->m2m_hw) +diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c +index 2469efddf54015..6a384bd469528e 100644 +--- a/drivers/dma/sun6i-dma.c ++++ b/drivers/dma/sun6i-dma.c +@@ -582,6 +582,22 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id) + return ret; + } + ++static u32 find_burst_size(const u32 burst_lengths, u32 maxburst) ++{ ++ if (!maxburst) ++ return 1; ++ ++ if (BIT(maxburst) & burst_lengths) ++ return maxburst; ++ ++ /* Hardware only does power-of-two bursts. */ ++ for (u32 burst = rounddown_pow_of_two(maxburst); burst > 0; burst /= 2) ++ if (BIT(burst) & burst_lengths) ++ return burst; ++ ++ return 1; ++} ++ + static int set_config(struct sun6i_dma_dev *sdev, + struct dma_slave_config *sconfig, + enum dma_transfer_direction direction, +@@ -615,15 +631,13 @@ static int set_config(struct sun6i_dma_dev *sdev, + return -EINVAL; + if (!(BIT(dst_addr_width) & sdev->slave.dst_addr_widths)) + return -EINVAL; +- if (!(BIT(src_maxburst) & sdev->cfg->src_burst_lengths)) +- return -EINVAL; +- if (!(BIT(dst_maxburst) & sdev->cfg->dst_burst_lengths)) +- return -EINVAL; + + src_width = convert_buswidth(src_addr_width); + dst_width = convert_buswidth(dst_addr_width); +- dst_burst = convert_burst(dst_maxburst); +- src_burst = convert_burst(src_maxburst); ++ src_burst = find_burst_size(sdev->cfg->src_burst_lengths, src_maxburst); ++ dst_burst = find_burst_size(sdev->cfg->dst_burst_lengths, dst_maxburst); ++ dst_burst = convert_burst(dst_burst); ++ src_burst = convert_burst(src_burst); + + *p_cfg = DMA_CHAN_CFG_SRC_WIDTH(src_width) | + DMA_CHAN_CFG_DST_WIDTH(dst_width); +diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c +index 4f8f87207b67b8..dc1915ffc3cbe2 100644 +--- a/drivers/edac/altera_edac.c ++++ b/drivers/edac/altera_edac.c +@@ -1573,8 +1573,7 @@ static int altr_portb_setup(struct altr_edac_device_dev *device) + goto err_release_group_1; + } + rc = devm_request_irq(&altdev->ddev, altdev->sb_irq, +- prv->ecc_irq_handler, +- IRQF_ONESHOT | IRQF_TRIGGER_HIGH, ++ prv->ecc_irq_handler, IRQF_TRIGGER_HIGH, + ecc_name, altdev); + if (rc) { + edac_printk(KERN_ERR, EDAC_DEVICE, "PortB SBERR IRQ error\n"); +@@ -1597,8 +1596,7 @@ static int altr_portb_setup(struct altr_edac_device_dev *device) + goto err_release_group_1; + } + rc = devm_request_irq(&altdev->ddev, altdev->db_irq, +- prv->ecc_irq_handler, +- IRQF_ONESHOT | IRQF_TRIGGER_HIGH, ++ prv->ecc_irq_handler, IRQF_TRIGGER_HIGH, + ecc_name, altdev); + if (rc) { + edac_printk(KERN_ERR, EDAC_DEVICE, "PortB DBERR IRQ error\n"); +@@ -1981,8 +1979,7 @@ static int altr_edac_a10_device_add(struct altr_arria10_edac *edac, + goto err_release_group1; + } + rc = devm_request_irq(edac->dev, altdev->sb_irq, prv->ecc_irq_handler, +- IRQF_ONESHOT | IRQF_TRIGGER_HIGH, +- ecc_name, altdev); ++ IRQF_TRIGGER_HIGH, ecc_name, altdev); + if (rc) { + edac_printk(KERN_ERR, EDAC_DEVICE, "No SBERR IRQ resource\n"); + goto err_release_group1; +@@ -2004,7 +2001,7 @@ static int altr_edac_a10_device_add(struct altr_arria10_edac *edac, + goto err_release_group1; + } + rc = devm_request_irq(edac->dev, altdev->db_irq, prv->ecc_irq_handler, +- IRQF_ONESHOT | IRQF_TRIGGER_HIGH, ++ IRQF_TRIGGER_HIGH, + ecc_name, altdev); + if (rc) { + edac_printk(KERN_ERR, EDAC_DEVICE, "No DBERR IRQ resource\n"); +diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c +index 4b5a71f8739d90..8c6a291e01f6a4 100644 +--- a/drivers/edac/i5000_edac.c ++++ b/drivers/edac/i5000_edac.c +@@ -1111,6 +1111,7 @@ static void calculate_dimm_size(struct i5000_pvt *pvt) + + n = snprintf(p, space, " "); + p += n; ++ space -= n; + for (branch = 0; branch < MAX_BRANCHES; branch++) { + n = snprintf(p, space, " branch %d | ", branch); + p += n; +diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c +index 49b4499269fb75..68afb3bb8e290e 100644 +--- a/drivers/edac/i5400_edac.c ++++ b/drivers/edac/i5400_edac.c +@@ -1025,13 +1025,13 @@ static void calculate_dimm_size(struct i5400_pvt *pvt) + space -= n; + } + +- space -= n; + edac_dbg(2, "%s\n", mem_buffer); + p = mem_buffer; + space = PAGE_SIZE; + + n = snprintf(p, space, " "); + p += n; ++ space -= n; + for (branch = 0; branch < MAX_BRANCHES; branch++) { + n = snprintf(p, space, " branch %d | ", branch); + p += n; +diff --git a/drivers/firmware/efi/cper-arm.c b/drivers/firmware/efi/cper-arm.c +index 52d18490b59e33..70e1735dfcdd41 100644 +--- a/drivers/firmware/efi/cper-arm.c ++++ b/drivers/firmware/efi/cper-arm.c +@@ -226,7 +226,8 @@ static void cper_print_arm_err_info(const char *pfx, u32 type, + } + + void cper_print_proc_arm(const char *pfx, +- const struct cper_sec_proc_arm *proc) ++ const struct cper_sec_proc_arm *proc, ++ u32 length) + { + int i, len, max_ctx_type; + struct cper_arm_err_info *err_info; +@@ -238,9 +239,12 @@ void cper_print_proc_arm(const char *pfx, + + len = proc->section_length - (sizeof(*proc) + + proc->err_info_num * (sizeof(*err_info))); +- if (len < 0) { +- printk("%ssection length: %d\n", pfx, proc->section_length); +- printk("%ssection length is too small\n", pfx); ++ ++ if (len < 0 || proc->section_length > length) { ++ printk("%ssection length: %d, CPER size: %d\n", ++ pfx, proc->section_length, length); ++ printk("%ssection length is too %s\n", pfx, ++ (len < 0) ? "small" : "big"); + printk("%sfirmware-generated error record is incorrect\n", pfx); + printk("%sERR_INFO_NUM is %d\n", pfx, proc->err_info_num); + return; +diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c +index 74ffaf44d74ce1..9d0f0bf3067ccb 100644 +--- a/drivers/firmware/efi/cper.c ++++ b/drivers/firmware/efi/cper.c +@@ -555,6 +555,11 @@ static void cper_print_fw_err(const char *pfx, + } else { + offset = sizeof(*fw_err); + } ++ if (offset > length) { ++ printk("%s""error section length is too small: offset=%d, length=%d\n", ++ pfx, offset, length); ++ return; ++ } + + buf += offset; + length -= offset; +@@ -635,7 +640,8 @@ cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata + + printk("%ssection_type: ARM processor error\n", newpfx); + if (gdata->error_data_length >= sizeof(*arm_err)) +- cper_print_proc_arm(newpfx, arm_err); ++ cper_print_proc_arm(newpfx, arm_err, ++ gdata->error_data_length); + else + goto err_section_too_small; + #endif +diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c +index 1ab161e00c8679..ef55e3851b3623 100644 +--- a/drivers/firmware/efi/efi.c ++++ b/drivers/firmware/efi/efi.c +@@ -648,13 +648,13 @@ static __init int match_config_table(const efi_guid_t *guid, + + static __init void reserve_unaccepted(struct efi_unaccepted_memory *unaccepted) + { +- phys_addr_t start, size; ++ phys_addr_t start, end; + + start = PAGE_ALIGN_DOWN(efi.unaccepted); +- size = PAGE_ALIGN(sizeof(*unaccepted) + unaccepted->size); ++ end = PAGE_ALIGN(efi.unaccepted + sizeof(*unaccepted) + unaccepted->size); + +- memblock_add(start, size); +- memblock_reserve(start, size); ++ memblock_add(start, end - start); ++ memblock_reserve(start, end - start); + } + + int __init efi_config_parse_tables(const efi_config_table_t *config_tables, +diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c +index dd7a783d53b5f4..f1ced28793d2ad 100644 +--- a/drivers/fpga/dfl.c ++++ b/drivers/fpga/dfl.c +@@ -2029,7 +2029,7 @@ static void __exit dfl_fpga_exit(void) + bus_unregister(&dfl_bus_type); + } + +-module_init(dfl_fpga_init); ++subsys_initcall(dfl_fpga_init); + module_exit(dfl_fpga_exit); + + MODULE_DESCRIPTION("FPGA Device Feature List (DFL) Support"); +diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c +index a6affd83f27578..ed6eae98511794 100644 +--- a/drivers/fpga/of-fpga-region.c ++++ b/drivers/fpga/of-fpga-region.c +@@ -83,7 +83,7 @@ static struct fpga_manager *of_fpga_region_get_mgr(struct device_node *np) + * done with the bridges. + * + * Return: 0 for success (even if there are no bridges specified) +- * or -EBUSY if any of the bridges are in use. ++ * or an error code if any of the bridges are not available. + */ + static int of_fpga_region_get_bridges(struct fpga_region *region) + { +@@ -130,10 +130,10 @@ static int of_fpga_region_get_bridges(struct fpga_region *region) + ®ion->bridge_list); + of_node_put(br); + +- /* If any of the bridges are in use, give up */ +- if (ret == -EBUSY) { ++ /* If any of the bridges are not available, give up */ ++ if (ret) { + fpga_bridges_put(®ion->bridge_list); +- return -EBUSY; ++ return ret; + } + } + +diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c +index 72755fee647847..e69a6ce7be3fbb 100644 +--- a/drivers/gpio/gpio-aspeed-sgpio.c ++++ b/drivers/gpio/gpio-aspeed-sgpio.c +@@ -534,7 +534,7 @@ static const struct of_device_id aspeed_sgpio_of_table[] = { + + MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table); + +-static int __init aspeed_sgpio_probe(struct platform_device *pdev) ++static int aspeed_sgpio_probe(struct platform_device *pdev) + { + u32 nr_gpios, sgpio_freq, sgpio_clk_div, gpio_cnt_regval, pin_mask; + const struct aspeed_sgpio_pdata *pdata; +@@ -629,11 +629,12 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev) + } + + static struct platform_driver aspeed_sgpio_driver = { ++ .probe = aspeed_sgpio_probe, + .driver = { + .name = KBUILD_MODNAME, + .of_match_table = aspeed_sgpio_of_table, + }, + }; + +-module_platform_driver_probe(aspeed_sgpio_driver, aspeed_sgpio_probe); ++module_platform_driver(aspeed_sgpio_driver); + MODULE_DESCRIPTION("Aspeed Serial GPIO Driver"); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +index 8b2f2b921d9de3..7730e56444934f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +@@ -1128,8 +1128,10 @@ static int amdgpu_acpi_enumerate_xcc(void) + if (!dev_info) + ret = amdgpu_acpi_dev_init(&dev_info, xcc_info, bdf); + +- if (ret == -ENOMEM) ++ if (ret == -ENOMEM) { ++ kfree(xcc_info); + return ret; ++ } + + if (!dev_info) { + kfree(xcc_info); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +index 2e492f779b54ce..5c4aa5ff873b6c 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +@@ -2491,6 +2491,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev) + case IP_VERSION(6, 0, 0): + case IP_VERSION(6, 0, 1): + case IP_VERSION(6, 1, 0): ++ case IP_VERSION(6, 1, 1): + adev->hdp.funcs = &hdp_v6_0_funcs; + break; + default: +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +index e9adfc88a54ab1..8175d831abd4d4 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +@@ -65,7 +65,8 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) + DRM_ERROR("Process information: process %s pid %d thread %s pid %d\n", + ti.process_name, ti.tgid, ti.task_name, ti.pid); + +- dma_fence_set_error(&s_job->s_fence->finished, -ETIME); ++ if (dma_fence_get_status(&s_job->s_fence->finished) == 0) ++ dma_fence_set_error(&s_job->s_fence->finished, -ETIME); + + if (amdgpu_device_should_recover_gpu(ring->adev)) { + struct amdgpu_reset_context reset_context; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +index 08886e0ee6428b..2ef87646e6bb14 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +@@ -656,7 +656,7 @@ psp_cmd_submit_buf(struct psp_context *psp, + ras_intr = amdgpu_ras_intr_triggered(); + if (ras_intr) + break; +- usleep_range(10, 100); ++ usleep_range(60, 100); + amdgpu_device_invalidate_hdp(psp->adev, NULL); + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +index 7cba98f8bbdca8..4214bbd7a1a236 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +@@ -2673,7 +2673,7 @@ int amdgpu_ras_init(struct amdgpu_device *adev) + * to handle fatal error */ + r = amdgpu_nbio_ras_sw_init(adev); + if (r) +- return r; ++ goto release_con; + + if (adev->nbio.ras && + adev->nbio.ras->init_ras_controller_interrupt) { +diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +index 18794394c5a052..2505951ad06a09 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +@@ -1862,7 +1862,8 @@ static int vcn_v2_0_start_sriov(struct amdgpu_device *adev) + struct mmsch_v2_0_cmd_end end = { {0} }; + struct mmsch_v2_0_init_header *header; + uint32_t *init_table = adev->virt.mm_table.cpu_addr; +- uint8_t i = 0; ++ ++ /* This path only programs VCN instance 0. */ + + header = (struct mmsch_v2_0_init_header *)init_table; + direct_wt.cmd_header.command_type = MMSCH_COMMAND__DIRECT_REG_WRITE; +@@ -1881,93 +1882,93 @@ static int vcn_v2_0_start_sriov(struct amdgpu_device *adev) + size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.fw->size + 4); + + MMSCH_V2_0_INSERT_DIRECT_RD_MOD_WT( +- SOC15_REG_OFFSET(UVD, i, mmUVD_STATUS), ++ SOC15_REG_OFFSET(UVD, 0, mmUVD_STATUS), + 0xFFFFFFFF, 0x00000004); + + /* mc resume*/ + if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, ++ SOC15_REG_OFFSET(UVD, 0, + mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), + adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_lo); + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, ++ SOC15_REG_OFFSET(UVD, 0, + mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), + adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_hi); + offset = 0; + } else { + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, ++ SOC15_REG_OFFSET(UVD, 0, + mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), + lower_32_bits(adev->vcn.inst->gpu_addr)); + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, ++ SOC15_REG_OFFSET(UVD, 0, + mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), + upper_32_bits(adev->vcn.inst->gpu_addr)); + offset = size; + } + + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_OFFSET0), ++ SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0), + 0); + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_SIZE0), ++ SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_SIZE0), + size); + + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, ++ SOC15_REG_OFFSET(UVD, 0, + mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), + lower_32_bits(adev->vcn.inst->gpu_addr + offset)); + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, ++ SOC15_REG_OFFSET(UVD, 0, + mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), + upper_32_bits(adev->vcn.inst->gpu_addr + offset)); + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_OFFSET1), ++ SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_OFFSET1), + 0); + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_SIZE1), ++ SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_SIZE1), + AMDGPU_VCN_STACK_SIZE); + + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, ++ SOC15_REG_OFFSET(UVD, 0, + mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW), + lower_32_bits(adev->vcn.inst->gpu_addr + offset + + AMDGPU_VCN_STACK_SIZE)); + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, ++ SOC15_REG_OFFSET(UVD, 0, + mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH), + upper_32_bits(adev->vcn.inst->gpu_addr + offset + + AMDGPU_VCN_STACK_SIZE)); + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_OFFSET2), ++ SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_OFFSET2), + 0); + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_SIZE2), ++ SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_SIZE2), + AMDGPU_VCN_CONTEXT_SIZE); + + for (r = 0; r < adev->vcn.num_enc_rings; ++r) { + ring = &adev->vcn.inst->ring_enc[r]; + ring->wptr = 0; + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, mmUVD_RB_BASE_LO), ++ SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_BASE_LO), + lower_32_bits(ring->gpu_addr)); + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, mmUVD_RB_BASE_HI), ++ SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_BASE_HI), + upper_32_bits(ring->gpu_addr)); + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, mmUVD_RB_SIZE), ++ SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_SIZE), + ring->ring_size / 4); + } + + ring = &adev->vcn.inst->ring_dec; + ring->wptr = 0; + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, ++ SOC15_REG_OFFSET(UVD, 0, + mmUVD_LMI_RBC_RB_64BIT_BAR_LOW), + lower_32_bits(ring->gpu_addr)); + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, ++ SOC15_REG_OFFSET(UVD, 0, + mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH), + upper_32_bits(ring->gpu_addr)); + /* force RBC into idle state */ +@@ -1978,7 +1979,7 @@ static int vcn_v2_0_start_sriov(struct amdgpu_device *adev) + tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1); + tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1); + MMSCH_V2_0_INSERT_DIRECT_WT( +- SOC15_REG_OFFSET(UVD, i, mmUVD_RBC_RB_CNTL), tmp); ++ SOC15_REG_OFFSET(UVD, 0, mmUVD_RBC_RB_CNTL), tmp); + + /* add end packet */ + tmp = sizeof(struct mmsch_v2_0_cmd_end); +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_debug.c b/drivers/gpu/drm/amd/amdkfd/kfd_debug.c +index 9c32c64c407fa9..267650dcced9d1 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_debug.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_debug.c +@@ -381,47 +381,45 @@ static int kfd_dbg_get_dev_watch_id(struct kfd_process_device *pdd, int *watch_i + + *watch_id = KFD_DEBUGGER_INVALID_WATCH_POINT_ID; + +- spin_lock(&pdd->dev->kfd->watch_points_lock); ++ spin_lock(&pdd->dev->watch_points_lock); + + for (i = 0; i < MAX_WATCH_ADDRESSES; i++) { + /* device watchpoint in use so skip */ +- if ((pdd->dev->kfd->alloc_watch_ids >> i) & 0x1) ++ if ((pdd->dev->alloc_watch_ids >> i) & 0x1) + continue; + + pdd->alloc_watch_ids |= 0x1 << i; +- pdd->dev->kfd->alloc_watch_ids |= 0x1 << i; ++ pdd->dev->alloc_watch_ids |= 0x1 << i; + *watch_id = i; +- spin_unlock(&pdd->dev->kfd->watch_points_lock); ++ spin_unlock(&pdd->dev->watch_points_lock); + return 0; + } + +- spin_unlock(&pdd->dev->kfd->watch_points_lock); ++ spin_unlock(&pdd->dev->watch_points_lock); + + return -ENOMEM; + } + +-static void kfd_dbg_clear_dev_watch_id(struct kfd_process_device *pdd, int watch_id) ++static void kfd_dbg_clear_dev_watch_id(struct kfd_process_device *pdd, u32 watch_id) + { +- spin_lock(&pdd->dev->kfd->watch_points_lock); ++ spin_lock(&pdd->dev->watch_points_lock); + + /* process owns device watch point so safe to clear */ +- if ((pdd->alloc_watch_ids >> watch_id) & 0x1) { +- pdd->alloc_watch_ids &= ~(0x1 << watch_id); +- pdd->dev->kfd->alloc_watch_ids &= ~(0x1 << watch_id); ++ if (pdd->alloc_watch_ids & BIT(watch_id)) { ++ pdd->alloc_watch_ids &= ~BIT(watch_id); ++ pdd->dev->alloc_watch_ids &= ~BIT(watch_id); + } + +- spin_unlock(&pdd->dev->kfd->watch_points_lock); ++ spin_unlock(&pdd->dev->watch_points_lock); + } + +-static bool kfd_dbg_owns_dev_watch_id(struct kfd_process_device *pdd, int watch_id) ++static bool kfd_dbg_owns_dev_watch_id(struct kfd_process_device *pdd, u32 watch_id) + { + bool owns_watch_id = false; + +- spin_lock(&pdd->dev->kfd->watch_points_lock); +- owns_watch_id = watch_id < MAX_WATCH_ADDRESSES && +- ((pdd->alloc_watch_ids >> watch_id) & 0x1); +- +- spin_unlock(&pdd->dev->kfd->watch_points_lock); ++ spin_lock(&pdd->dev->watch_points_lock); ++ owns_watch_id = pdd->alloc_watch_ids & BIT(watch_id); ++ spin_unlock(&pdd->dev->watch_points_lock); + + return owns_watch_id; + } +@@ -431,6 +429,9 @@ int kfd_dbg_trap_clear_dev_address_watch(struct kfd_process_device *pdd, + { + int r; + ++ if (watch_id >= MAX_WATCH_ADDRESSES) ++ return -EINVAL; ++ + if (!kfd_dbg_owns_dev_watch_id(pdd, watch_id)) + return -EINVAL; + +@@ -468,6 +469,9 @@ int kfd_dbg_trap_set_dev_address_watch(struct kfd_process_device *pdd, + if (r) + return r; + ++ if (*watch_id >= MAX_WATCH_ADDRESSES) ++ return -EINVAL; ++ + if (!pdd->dev->kfd->shared_resources.enable_mes) { + r = debug_lock_and_unmap(pdd->dev->dqm); + if (r) { +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c +index 6af65db4de9479..af50aa9638cab8 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c +@@ -815,13 +815,14 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, + dev_err(kfd_device, "Error initializing KFD node\n"); + goto node_init_error; + } ++ ++ spin_lock_init(&node->watch_points_lock); ++ + kfd->nodes[i] = node; + } + + svm_range_set_max_pages(kfd->adev); + +- spin_lock_init(&kfd->watch_points_lock); +- + kfd->init_complete = true; + dev_info(kfd_device, "added device %x:%x\n", kfd->adev->pdev->vendor, + kfd->adev->pdev->device); +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c +index 2b07c0000df6eb..c98a08c269ae74 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c +@@ -330,6 +330,12 @@ static int kfd_event_page_set(struct kfd_process *p, void *kernel_address, + if (p->signal_page) + return -EBUSY; + ++ if (size < KFD_SIGNAL_EVENT_LIMIT * 8) { ++ pr_err("Event page size %llu is too small, need at least %lu bytes\n", ++ size, (unsigned long)(KFD_SIGNAL_EVENT_LIMIT * 8)); ++ return -EINVAL; ++ } ++ + page = kzalloc(sizeof(*page), GFP_KERNEL); + if (!page) + return -ENOMEM; +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +index f99e3b812ee44b..59575e2424d07d 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +@@ -62,7 +62,7 @@ svm_migrate_gart_map(struct amdgpu_ring *ring, uint64_t npages, + *gart_addr = adev->gmc.gart_start; + + num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8); +- num_bytes = npages * 8; ++ num_bytes = npages * 8 * AMDGPU_GPU_PAGES_IN_CPU_PAGE; + + r = amdgpu_job_alloc_with_ib(adev, &adev->mman.high_pr, + AMDGPU_FENCE_OWNER_UNDEFINED, +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +index b475c2ab9768af..0b69ff5375c528 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +@@ -316,6 +316,10 @@ struct kfd_node { + struct kfd_local_mem_info local_mem_info; + + struct kfd_dev *kfd; ++ ++ /* Track per device allocated watch points */ ++ uint32_t alloc_watch_ids; ++ spinlock_t watch_points_lock; + }; + + struct kfd_dev { +@@ -368,10 +372,6 @@ struct kfd_dev { + struct kfd_node *nodes[MAX_KFD_NODES]; + unsigned int num_nodes; + +- /* Track per device allocated watch points */ +- uint32_t alloc_watch_ids; +- spinlock_t watch_points_lock; +- + /* Kernel doorbells for KFD device */ + struct amdgpu_bo *doorbells; + +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 faef07fdfd3027..26047109726eb4 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -8934,7 +8934,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) + */ + dummy_updates = kzalloc(sizeof(struct dc_surface_update) * MAX_SURFACES, GFP_ATOMIC); + for (j = 0; j < status->plane_count; j++) +- dummy_updates[j].surface = status->plane_states[0]; ++ dummy_updates[j].surface = status->plane_states[j]; + + + mutex_lock(&dm->dc_lock); +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +index d1329f20b7bd4b..746df72405eb43 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +@@ -970,10 +970,15 @@ static void get_min_max_dc_plane_scaling(struct drm_device *dev, + *min_downscale = plane_cap->max_downscale_factor.nv12; + break; + ++ /* All 64 bpp formats have the same fp16 scaling limits */ + case DRM_FORMAT_XRGB16161616F: + case DRM_FORMAT_ARGB16161616F: + case DRM_FORMAT_XBGR16161616F: + case DRM_FORMAT_ABGR16161616F: ++ case DRM_FORMAT_XRGB16161616: ++ case DRM_FORMAT_ARGB16161616: ++ case DRM_FORMAT_XBGR16161616: ++ case DRM_FORMAT_ABGR16161616: + *max_upscale = plane_cap->max_upscale_factor.fp16; + *min_downscale = plane_cap->max_downscale_factor.fp16; + break; +diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c +index 1d052f08aff5e1..f20f0b2be4c7d5 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c +@@ -716,8 +716,7 @@ bool mpc32_program_shaper( + return false; + } + +- if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) +- mpc32_power_on_shaper_3dlut(mpc, mpcc_id, true); ++ mpc32_power_on_shaper_3dlut(mpc, mpcc_id, true); + + current_mode = mpc32_get_shaper_current(mpc, mpcc_id); + +diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c +index caf590caaf2c7b..e759004046938c 100644 +--- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c ++++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c +@@ -3449,6 +3449,11 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev, + max_sclk = 60000; + max_mclk = 80000; + } ++ if ((adev->pdev->device == 0x666f) && ++ (adev->pdev->revision == 0x00)) { ++ max_sclk = 80000; ++ max_mclk = 95000; ++ } + } else if (adev->asic_type == CHIP_OLAND) { + if ((adev->pdev->revision == 0xC7) || + (adev->pdev->revision == 0x80) || +diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +index daa508504f47d6..b35d367b861418 100644 +--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c ++++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +@@ -78,8 +78,6 @@ drm_plane_state_to_atmel_hlcdc_plane_state(struct drm_plane_state *s) + return container_of(s, struct atmel_hlcdc_plane_state, base); + } + +-#define SUBPIXEL_MASK 0xffff +- + static uint32_t rgb_formats[] = { + DRM_FORMAT_C8, + DRM_FORMAT_XRGB4444, +@@ -619,24 +617,15 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, + if (ret || !s->visible) + return ret; + +- hstate->src_x = s->src.x1; +- hstate->src_y = s->src.y1; +- hstate->src_w = drm_rect_width(&s->src); +- hstate->src_h = drm_rect_height(&s->src); ++ hstate->src_x = s->src.x1 >> 16; ++ hstate->src_y = s->src.y1 >> 16; ++ hstate->src_w = drm_rect_width(&s->src) >> 16; ++ hstate->src_h = drm_rect_height(&s->src) >> 16; + hstate->crtc_x = s->dst.x1; + hstate->crtc_y = s->dst.y1; + hstate->crtc_w = drm_rect_width(&s->dst); + hstate->crtc_h = drm_rect_height(&s->dst); + +- if ((hstate->src_x | hstate->src_y | hstate->src_w | hstate->src_h) & +- SUBPIXEL_MASK) +- return -EINVAL; +- +- hstate->src_x >>= 16; +- hstate->src_y >>= 16; +- hstate->src_w >>= 16; +- hstate->src_h >>= 16; +- + hstate->nplanes = fb->format->num_planes; + if (hstate->nplanes > ATMEL_HLCDC_LAYER_MAX_PLANES) + return -EINVAL; +@@ -915,8 +904,7 @@ atmel_hlcdc_plane_atomic_duplicate_state(struct drm_plane *p) + return NULL; + } + +- if (copy->base.fb) +- drm_framebuffer_get(copy->base.fb); ++ __drm_atomic_helper_plane_duplicate_state(p, ©->base); + + return ©->base; + } +@@ -934,8 +922,7 @@ static void atmel_hlcdc_plane_atomic_destroy_state(struct drm_plane *p, + state->dscrs[i]->self); + } + +- if (s->fb) +- drm_framebuffer_put(s->fb); ++ __drm_atomic_helper_plane_destroy_state(s); + + kfree(state); + } +diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c +index 21ff7ef7ce920f..d4a5489d010c4d 100644 +--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c +@@ -4527,7 +4527,8 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, + if (!payload->delete) { + payload->pbn = 0; + payload->delete = true; +- topology_state->payload_mask &= ~BIT(payload->vcpi - 1); ++ if (payload->vcpi > 0) ++ topology_state->payload_mask &= ~BIT(payload->vcpi - 1); + } + + return 0; +diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c +index dfec479830e496..b4ee7d4110f842 100644 +--- a/drivers/gpu/drm/drm_property.c ++++ b/drivers/gpu/drm/drm_property.c +@@ -561,7 +561,7 @@ drm_property_create_blob(struct drm_device *dev, size_t length, + if (!length || length > INT_MAX - sizeof(struct drm_property_blob)) + return ERR_PTR(-EINVAL); + +- blob = kvzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); ++ blob = kvzalloc(sizeof(struct drm_property_blob) + length, GFP_KERNEL_ACCOUNT); + if (!blob) + return ERR_PTR(-ENOMEM); + +diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c b/drivers/gpu/drm/i915/display/intel_acpi.c +index 9df78e7caa2bd7..231b341d968ad0 100644 +--- a/drivers/gpu/drm/i915/display/intel_acpi.c ++++ b/drivers/gpu/drm/i915/display/intel_acpi.c +@@ -93,6 +93,7 @@ static void intel_dsm_platform_mux_info(acpi_handle dhandle) + + if (!pkg->package.count) { + DRM_DEBUG_DRIVER("no connection in _DSM\n"); ++ ACPI_FREE(pkg); + return; + } + +diff --git a/drivers/gpu/drm/i915/intel_wakeref.c b/drivers/gpu/drm/i915/intel_wakeref.c +index 718f2f1b6174d1..a2bffa4a4dd158 100644 +--- a/drivers/gpu/drm/i915/intel_wakeref.c ++++ b/drivers/gpu/drm/i915/intel_wakeref.c +@@ -76,7 +76,7 @@ void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags) + /* Assume we are not in process context and so cannot sleep. */ + if (flags & INTEL_WAKEREF_PUT_ASYNC || !mutex_trylock(&wf->mutex)) { + mod_delayed_work(wf->i915->unordered_wq, &wf->work, +- FIELD_GET(INTEL_WAKEREF_PUT_DELAY, flags)); ++ FIELD_GET(INTEL_WAKEREF_PUT_DELAY_MASK, flags)); + return; + } + +diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h +index ec881b09736896..9923628d706ccd 100644 +--- a/drivers/gpu/drm/i915/intel_wakeref.h ++++ b/drivers/gpu/drm/i915/intel_wakeref.h +@@ -119,17 +119,16 @@ intel_wakeref_get_if_active(struct intel_wakeref *wf) + return atomic_inc_not_zero(&wf->count); + } + +-enum { +- INTEL_WAKEREF_PUT_ASYNC_BIT = 0, +- __INTEL_WAKEREF_PUT_LAST_BIT__ +-}; +- + static inline void + intel_wakeref_might_get(struct intel_wakeref *wf) + { + might_lock(&wf->mutex); + } + ++/* flags for __intel_wakeref_put() and __intel_wakeref_put_last */ ++#define INTEL_WAKEREF_PUT_ASYNC BIT(0) ++#define INTEL_WAKEREF_PUT_DELAY_MASK GENMASK(BITS_PER_LONG - 1, 1) ++ + /** + * __intel_wakeref_put: Release the wakeref + * @wf: the wakeref +@@ -145,9 +144,6 @@ intel_wakeref_might_get(struct intel_wakeref *wf) + */ + static inline void + __intel_wakeref_put(struct intel_wakeref *wf, unsigned long flags) +-#define INTEL_WAKEREF_PUT_ASYNC BIT(INTEL_WAKEREF_PUT_ASYNC_BIT) +-#define INTEL_WAKEREF_PUT_DELAY \ +- GENMASK(BITS_PER_LONG - 1, __INTEL_WAKEREF_PUT_LAST_BIT__) + { + INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0); + if (unlikely(!atomic_add_unless(&wf->count, -1, 1))) +@@ -172,7 +168,7 @@ intel_wakeref_put_delay(struct intel_wakeref *wf, unsigned long delay) + { + __intel_wakeref_put(wf, + INTEL_WAKEREF_PUT_ASYNC | +- FIELD_PREP(INTEL_WAKEREF_PUT_DELAY, delay)); ++ FIELD_PREP(INTEL_WAKEREF_PUT_DELAY_MASK, delay)); + } + + static inline void +diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c +index 535c89ce5d62eb..0410a1657b15e6 100644 +--- a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c ++++ b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c +@@ -77,7 +77,10 @@ static bool a2xx_me_init(struct msm_gpu *gpu) + + /* Vertex and Pixel Shader Start Addresses in instructions + * (3 DWORDS per instruction) */ +- OUT_RING(ring, 0x80000180); ++ if (adreno_is_a225(adreno_gpu)) ++ OUT_RING(ring, 0x80000300); ++ else ++ OUT_RING(ring, 0x80000180); + /* Maximum Contexts */ + OUT_RING(ring, 0x00000001); + /* Write Confirm Interval and The CP will wait the +diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h +index 9195cb996f444b..cbaca4bf2864ac 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h ++++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h +@@ -14,6 +14,7 @@ static const struct dpu_caps sc7280_dpu_caps = { + .has_dim_layer = true, + .has_idle_pc = true, + .max_linewidth = 2400, ++ .has_3d_merge = true, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + }; + +@@ -145,7 +146,7 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = { + .base = 0x6b000, .len = 0, + .features = BIT(DPU_PINGPONG_DITHER), + .sblk = &sc7280_pp_sblk, +- .merge_3d = 0, ++ .merge_3d = MERGE_3D_1, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), + .intr_rdptr = -1, + }, { +@@ -153,12 +154,19 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = { + .base = 0x6c000, .len = 0, + .features = BIT(DPU_PINGPONG_DITHER), + .sblk = &sc7280_pp_sblk, +- .merge_3d = 0, ++ .merge_3d = MERGE_3D_1, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), + .intr_rdptr = -1, + }, + }; + ++static const struct dpu_merge_3d_cfg sc7280_merge_3d[] = { ++ { ++ .name = "merge_3d_1", .id = MERGE_3D_1, ++ .base = 0x4f000, .len = 0x8, ++ }, ++}; ++ + /* NOTE: sc7280 only has one DSC hard slice encoder */ + static const struct dpu_dsc_cfg sc7280_dsc[] = { + { +@@ -265,6 +273,8 @@ const struct dpu_mdss_cfg dpu_sc7280_cfg = { + .mixer = sc7280_lm, + .pingpong_count = ARRAY_SIZE(sc7280_pp), + .pingpong = sc7280_pp, ++ .merge_3d_count = ARRAY_SIZE(sc7280_merge_3d), ++ .merge_3d = sc7280_merge_3d, + .dsc_count = ARRAY_SIZE(sc7280_dsc), + .dsc = sc7280_dsc, + .wb_count = ARRAY_SIZE(sc7280_wb), +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +index 83a804ebf8d7ef..fd2400c4665d27 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +@@ -675,10 +675,11 @@ static int dpu_encoder_phys_cmd_wait_for_commit_done( + if (!dpu_encoder_phys_cmd_is_master(phys_enc)) + return 0; + +- if (phys_enc->hw_ctl->ops.is_started(phys_enc->hw_ctl)) +- return dpu_encoder_phys_cmd_wait_for_tx_complete(phys_enc); ++ if (phys_enc->irq[INTR_IDX_CTL_START] && ++ !phys_enc->hw_ctl->ops.is_started(phys_enc->hw_ctl)) ++ return _dpu_encoder_phys_cmd_wait_for_ctl_start(phys_enc); + +- return _dpu_encoder_phys_cmd_wait_for_ctl_start(phys_enc); ++ return dpu_encoder_phys_cmd_wait_for_tx_complete(phys_enc); + } + + static void dpu_encoder_phys_cmd_handle_post_kickoff( +diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c +index fbf968e3f6d789..c688b4d914819c 100644 +--- a/drivers/gpu/drm/radeon/si_dpm.c ++++ b/drivers/gpu/drm/radeon/si_dpm.c +@@ -2969,6 +2969,11 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, + max_sclk = 60000; + max_mclk = 80000; + } ++ if ((rdev->pdev->device == 0x666f) && ++ (rdev->pdev->revision == 0x00)) { ++ max_sclk = 80000; ++ max_mclk = 95000; ++ } + } else if (rdev->family == CHIP_OLAND) { + if ((rdev->pdev->revision == 0xC7) || + (rdev->pdev->revision == 0x80) || +diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c +index 0e8ea990118844..691a8c8848e405 100644 +--- a/drivers/gpu/drm/v3d/v3d_drv.c ++++ b/drivers/gpu/drm/v3d/v3d_drv.c +@@ -242,6 +242,8 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) + if (ret) + goto clk_disable; + ++ dma_set_max_seg_size(&pdev->dev, UINT_MAX); ++ + v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH); + + ident1 = V3D_READ(V3D_HUB_IDENT1); +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index ffbeb39341e1a4..851ddbc25bedd1 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -328,6 +328,7 @@ config HID_ELECOM + - EX-G Trackballs (M-XT3DRBK, M-XT3URBK) + - DEFT Trackballs (M-DT1DRBK, M-DT1URBK, M-DT2DRBK, M-DT2URBK) + - HUGE Trackballs (M-HT1DRBK, M-HT1URBK) ++ - HUGE Plus Trackball (M-HT1MRBK) + + config HID_ELO + tristate "ELO USB 4000/4500 touchscreen" +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index 2b8021628d3c6a..9dd5c698fefe05 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -340,6 +340,7 @@ static const struct apple_key_translation swapped_fn_leftctrl_keys[] = { + }; + + static const struct apple_non_apple_keyboard non_apple_keyboards[] = { ++ { "SONiX KN85 Keyboard" }, + { "SONiX USB DEVICE" }, + { "SONiX AK870 PRO" }, + { "Keychron" }, +diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c +index f76fec79e89034..9aeb2d2b43a439 100644 +--- a/drivers/hid/hid-elecom.c ++++ b/drivers/hid/hid-elecom.c +@@ -5,6 +5,7 @@ + * - EX-G Trackballs (M-XT3DRBK, M-XT3URBK, M-XT4DRBK) + * - DEFT Trackballs (M-DT1DRBK, M-DT1URBK, M-DT2DRBK, M-DT2URBK) + * - HUGE Trackballs (M-HT1DRBK, M-HT1URBK) ++ * - HUGE Plus Trackball (M-HT1MRBK) + * + * Copyright (c) 2010 Richard Nauber + * Copyright (c) 2016 Yuxuan Shui +@@ -111,12 +112,25 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, + */ + mouse_button_fixup(hdev, rdesc, *rsize, 22, 30, 24, 16, 8); + break; ++ case USB_DEVICE_ID_ELECOM_M_HT1MRBK: ++ case USB_DEVICE_ID_ELECOM_M_HT1MRBK_01AB: ++ case USB_DEVICE_ID_ELECOM_M_HT1MRBK_01AC: ++ /* ++ * Report descriptor format: ++ * 24: button bit count ++ * 28: padding bit count ++ * 22: button report size ++ * 16: button usage maximum ++ */ ++ mouse_button_fixup(hdev, rdesc, *rsize, 24, 28, 22, 16, 8); ++ break; + } + return rdesc; + } + + static const struct hid_device_id elecom_devices[] = { + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1MRBK_01AC) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XGL20DLBK) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK_00FB) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK_018F) }, +@@ -127,6 +141,8 @@ static const struct hid_device_id elecom_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1MRBK) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1MRBK_01AB) }, + { } + }; + MODULE_DEVICE_TABLE(hid, elecom_devices); +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 931746cf363027..a1910e12f7e05f 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -427,6 +427,7 @@ + #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349 0x7349 + #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7 0x73f7 + #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001 ++#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C000 0xc000 + #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002 0xc002 + + #define USB_VENDOR_ID_EDIFIER 0x2d99 +@@ -452,6 +453,9 @@ + #define USB_DEVICE_ID_ELECOM_M_HT1URBK 0x010c + #define USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D 0x010d + #define USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C 0x011c ++#define USB_DEVICE_ID_ELECOM_M_HT1MRBK 0x01aa ++#define USB_DEVICE_ID_ELECOM_M_HT1MRBK_01AB 0x01ab ++#define USB_DEVICE_ID_ELECOM_M_HT1MRBK_01AC 0x01ac + + #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 + #define USB_DEVICE_ID_DREAM_CHEEKY_WN 0x0004 +diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c +index 5a2fe703cf57b0..339a227c457e7a 100644 +--- a/drivers/hid/hid-logitech-hidpp.c ++++ b/drivers/hid/hid-logitech-hidpp.c +@@ -4339,7 +4339,7 @@ static int hidpp_get_report_length(struct hid_device *hdev, int id) + + re = &(hdev->report_enum[HID_OUTPUT_REPORT]); + report = re->report_id_hash[id]; +- if (!report) ++ if (!report || !report->maxfield) + return 0; + + return report->field[0]->report_count + 1; +diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c +index 4fe1e0bc244934..99d0dbf62af378 100644 +--- a/drivers/hid/hid-magicmouse.c ++++ b/drivers/hid/hid-magicmouse.c +@@ -712,6 +712,11 @@ static int magicmouse_input_configured(struct hid_device *hdev, + struct magicmouse_sc *msc = hid_get_drvdata(hdev); + int ret; + ++ if (!msc->input) { ++ hid_err(hdev, "magicmouse setup input failed (no input)"); ++ return -EINVAL; ++ } ++ + ret = magicmouse_setup_input(msc->input, hdev); + if (ret) { + hid_err(hdev, "magicmouse setup input failed (%d)\n", ret); +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index 6d9a85c5fc4097..b6c2cb7153fde3 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -2020,6 +2020,9 @@ static const struct hid_device_id mt_devices[] = { + { .driver_data = MT_CLS_EGALAX_SERIAL, + MT_USB_DEVICE(USB_VENDOR_ID_DWAV, + USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, ++ { .driver_data = MT_CLS_EGALAX_SERIAL, ++ MT_USB_DEVICE(USB_VENDOR_ID_DWAV, ++ USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C000) }, + { .driver_data = MT_CLS_EGALAX, + MT_USB_DEVICE(USB_VENDOR_ID_DWAV, + USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002) }, +diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c +index 93fb07ec31802f..d1a1ddd933abd2 100644 +--- a/drivers/hid/hid-pl.c ++++ b/drivers/hid/hid-pl.c +@@ -194,9 +194,14 @@ static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id) + goto err; + } + +- plff_init(hdev); ++ ret = plff_init(hdev); ++ if (ret) ++ goto stop; + + return 0; ++ ++stop: ++ hid_hw_stop(hdev); + err: + return ret; + } +diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c +index 32f65c45fdc8af..199f76988bae89 100644 +--- a/drivers/hid/hid-playstation.c ++++ b/drivers/hid/hid-playstation.c +@@ -732,7 +732,9 @@ static struct input_dev *ps_gamepad_create(struct hid_device *hdev, + #if IS_ENABLED(CONFIG_PLAYSTATION_FF) + if (play_effect) { + input_set_capability(gamepad, EV_FF, FF_RUMBLE); +- input_ff_create_memless(gamepad, NULL, play_effect); ++ ret = input_ff_create_memless(gamepad, NULL, play_effect); ++ if (ret) ++ return ERR_PTR(ret); + } + #endif + +diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c +index e4e9471d0f1e92..f20d29566b4da7 100644 +--- a/drivers/hid/hid-prodikeys.c ++++ b/drivers/hid/hid-prodikeys.c +@@ -388,6 +388,10 @@ static int pcmidi_handle_report4(struct pcmidi_snd *pm, u8 *data) + bit_mask = (bit_mask << 8) | data[2]; + bit_mask = (bit_mask << 8) | data[3]; + ++ /* robustness in case input_mapping hook does not get called */ ++ if (!pm->input_ep82) ++ return 0; ++ + /* break keys */ + for (bit_index = 0; bit_index < 24; bit_index++) { + if (!((0x01 << bit_index) & bit_mask)) { +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index 1f531626192cdb..7a3e0675d9ba2b 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -415,6 +415,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + #if IS_ENABLED(CONFIG_HID_ELECOM) + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XGL20DLBK) }, ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1MRBK_01AC) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK_00FB) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK_018F) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) }, +@@ -424,6 +425,8 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1MRBK) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1MRBK_01AB) }, + #endif + #if IS_ENABLED(CONFIG_HID_ELO) + { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) }, +diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c +index 27207ec6f7febd..5e3c8be255e873 100644 +--- a/drivers/hwmon/f71882fg.c ++++ b/drivers/hwmon/f71882fg.c +@@ -51,6 +51,7 @@ + #define SIO_F81866_ID 0x1010 /* Chipset ID */ + #define SIO_F71858AD_ID 0x0903 /* Chipset ID */ + #define SIO_F81966_ID 0x1502 /* Chipset ID */ ++#define SIO_F81968_ID 0x1806 /* Chipset ID */ + + #define REGION_LENGTH 8 + #define ADDR_REG_OFFSET 5 +@@ -2571,6 +2572,7 @@ static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data) + break; + case SIO_F81866_ID: + case SIO_F81966_ID: ++ case SIO_F81968_ID: + sio_data->type = f81866a; + break; + default: +@@ -2600,9 +2602,9 @@ static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data) + address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ + + err = address; +- pr_info("Found %s chip at %#x, revision %d\n", ++ pr_info("Found %s chip at %#x, revision %d, devid: %04x\n", + f71882fg_names[sio_data->type], (unsigned int)address, +- (int)superio_inb(sioaddr, SIO_REG_DEVREV)); ++ (int)superio_inb(sioaddr, SIO_REG_DEVREV), devid); + exit: + superio_exit(sioaddr); + return err; +diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c +index 40fff7e95ea1c0..db066b3689187d 100644 +--- a/drivers/hwmon/ibmpex.c ++++ b/drivers/hwmon/ibmpex.c +@@ -282,9 +282,6 @@ static ssize_t ibmpex_high_low_store(struct device *dev, + { + struct ibmpex_bmc_data *data = dev_get_drvdata(dev); + +- if (!data) +- return -ENODEV; +- + ibmpex_reset_high_low_data(data); + + return count; +@@ -517,9 +514,6 @@ static void ibmpex_bmc_delete(struct ibmpex_bmc_data *data) + { + int i, j; + +- hwmon_device_unregister(data->hwmon_dev); +- dev_set_drvdata(data->bmc_device, NULL); +- + device_remove_file(data->bmc_device, + &sensor_dev_attr_reset_high_low.dev_attr); + device_remove_file(data->bmc_device, &sensor_dev_attr_name.dev_attr); +@@ -533,7 +527,8 @@ static void ibmpex_bmc_delete(struct ibmpex_bmc_data *data) + } + + list_del(&data->list); +- ++ dev_set_drvdata(data->bmc_device, NULL); ++ hwmon_device_unregister(data->hwmon_dev); + ipmi_destroy_user(data->user); + kfree(data->sensors); + kfree(data); +diff --git a/drivers/hwmon/nct6775-platform.c b/drivers/hwmon/nct6775-platform.c +index 7e0ac3fcbc0501..b09fd5791db8ef 100644 +--- a/drivers/hwmon/nct6775-platform.c ++++ b/drivers/hwmon/nct6775-platform.c +@@ -1356,6 +1356,7 @@ static const char * const asus_msi_boards[] = { + "Pro WS W680-ACE IPMI", + "Pro WS W790-ACE", + "Pro WS W790E-SAGE SE", ++ "Pro WS WRX90E-SAGE SE", + "ProArt B650-CREATOR", + "ProArt B660-CREATOR D4", + "ProArt B760-CREATOR D4", +diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c +index 116a91d90ac20a..4cef1023f02903 100644 +--- a/drivers/hwtracing/coresight/coresight-etm3x-core.c ++++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c +@@ -814,16 +814,16 @@ static int __init etm_hp_setup(void) + { + int ret; + +- ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ARM_CORESIGHT_STARTING, +- "arm/coresight:starting", +- etm_starting_cpu, etm_dying_cpu); ++ ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING, ++ "arm/coresight:starting", ++ etm_starting_cpu, etm_dying_cpu); + + if (ret) + return ret; + +- ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ONLINE_DYN, +- "arm/coresight:online", +- etm_online_cpu, NULL); ++ ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, ++ "arm/coresight:online", ++ etm_online_cpu, NULL); + + /* HP dyn state ID returned in ret on success */ + if (ret > 0) { +diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c +index 060f70e4d52d77..f74ef65d257d7b 100644 +--- a/drivers/i3c/master.c ++++ b/drivers/i3c/master.c +@@ -586,7 +586,8 @@ static int i3c_set_hotjoin(struct i3c_master_controller *master, bool enable) + else + ret = master->ops->disable_hotjoin(master); + +- master->hotjoin = enable; ++ if (!ret) ++ master->hotjoin = enable; + + i3c_bus_normaluse_unlock(&master->bus); + +@@ -2769,7 +2770,6 @@ int i3c_master_register(struct i3c_master_controller *master, + INIT_LIST_HEAD(&master->boardinfo.i3c); + + device_initialize(&master->dev); +- dev_set_name(&master->dev, "i3c-%d", i3cbus->id); + + master->dev.dma_mask = parent->dma_mask; + master->dev.coherent_dma_mask = parent->coherent_dma_mask; +@@ -2779,6 +2779,8 @@ int i3c_master_register(struct i3c_master_controller *master, + if (ret) + goto err_put_dev; + ++ dev_set_name(&master->dev, "i3c-%d", i3cbus->id); ++ + ret = of_populate_i3c_bus(master); + if (ret) + goto err_put_dev; +diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c +index 030127525672e7..cee2805fccd0f8 100644 +--- a/drivers/i3c/master/dw-i3c-master.c ++++ b/drivers/i3c/master/dw-i3c-master.c +@@ -1483,6 +1483,8 @@ int dw_i3c_common_probe(struct dw_i3c_master *master, + spin_lock_init(&master->xferqueue.lock); + INIT_LIST_HEAD(&master->xferqueue.list); + ++ spin_lock_init(&master->devs_lock); ++ + writel(INTR_ALL, master->regs + INTR_STATUS); + irq = platform_get_irq(pdev, 0); + ret = devm_request_irq(&pdev->dev, irq, +diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c +index 3222b8f56a926f..94792f3559a0f5 100644 +--- a/drivers/i3c/master/svc-i3c-master.c ++++ b/drivers/i3c/master/svc-i3c-master.c +@@ -418,8 +418,8 @@ static void svc_i3c_master_ibi_work(struct work_struct *work) + { + struct svc_i3c_master *master = container_of(work, struct svc_i3c_master, ibi_work); + struct svc_i3c_i2c_dev_data *data; ++ struct i3c_dev_desc *dev = NULL; + unsigned int ibitype, ibiaddr; +- struct i3c_dev_desc *dev; + u32 status, val; + int ret; + +@@ -503,7 +503,7 @@ static void svc_i3c_master_ibi_work(struct work_struct *work) + * for the slave to interrupt again. + */ + if (svc_i3c_master_error(master)) { +- if (master->ibi.tbq_slot) { ++ if (master->ibi.tbq_slot && dev) { + data = i3c_dev_get_master_data(dev); + i3c_generic_ibi_recycle_slot(data->ibi_pool, + master->ibi.tbq_slot); +diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c +index 13439f52d26dba..0eabcd6957979d 100644 +--- a/drivers/iio/accel/bma180.c ++++ b/drivers/iio/accel/bma180.c +@@ -996,8 +996,9 @@ static int bma180_probe(struct i2c_client *client) + } + + ret = devm_request_irq(dev, client->irq, +- iio_trigger_generic_data_rdy_poll, IRQF_TRIGGER_RISING, +- "bma180_event", data->trig); ++ iio_trigger_generic_data_rdy_poll, ++ IRQF_TRIGGER_RISING | IRQF_NO_THREAD, ++ "bma180_event", data->trig); + if (ret) { + dev_err(dev, "unable to request IRQ\n"); + goto err_trigger_free; +diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c +index 87c54e41f6ccd2..2b87f7f5508bbd 100644 +--- a/drivers/iio/accel/sca3000.c ++++ b/drivers/iio/accel/sca3000.c +@@ -1496,7 +1496,11 @@ static int sca3000_probe(struct spi_device *spi) + if (ret) + goto error_free_irq; + +- return iio_device_register(indio_dev); ++ ret = iio_device_register(indio_dev); ++ if (ret) ++ goto error_free_irq; ++ ++ return 0; + + error_free_irq: + if (spi->irq) +diff --git a/drivers/iio/adc/ad7766.c b/drivers/iio/adc/ad7766.c +index 3079a0872947e0..d1d010c1dbf6c8 100644 +--- a/drivers/iio/adc/ad7766.c ++++ b/drivers/iio/adc/ad7766.c +@@ -261,7 +261,7 @@ static int ad7766_probe(struct spi_device *spi) + * don't enable the interrupt to avoid extra load on the system + */ + ret = devm_request_irq(&spi->dev, spi->irq, ad7766_irq, +- IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN, ++ IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN | IRQF_NO_THREAD, + dev_name(&spi->dev), + ad7766->trig); + if (ret < 0) +diff --git a/drivers/iio/gyro/itg3200_buffer.c b/drivers/iio/gyro/itg3200_buffer.c +index 4cfa0d43956053..d1c125a77308ad 100644 +--- a/drivers/iio/gyro/itg3200_buffer.c ++++ b/drivers/iio/gyro/itg3200_buffer.c +@@ -118,11 +118,9 @@ int itg3200_probe_trigger(struct iio_dev *indio_dev) + if (!st->trig) + return -ENOMEM; + +- ret = request_irq(st->i2c->irq, +- &iio_trigger_generic_data_rdy_poll, +- IRQF_TRIGGER_RISING, +- "itg3200_data_rdy", +- st->trig); ++ ret = request_irq(st->i2c->irq, &iio_trigger_generic_data_rdy_poll, ++ IRQF_TRIGGER_RISING | IRQF_NO_THREAD, ++ "itg3200_data_rdy", st->trig); + if (ret) + goto error_free_trig; + +diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c +index 53fb92f0ac7ef9..1127dd9f0df257 100644 +--- a/drivers/iio/gyro/itg3200_core.c ++++ b/drivers/iio/gyro/itg3200_core.c +@@ -93,6 +93,8 @@ static int itg3200_read_raw(struct iio_dev *indio_dev, + case IIO_CHAN_INFO_RAW: + reg = (u8)chan->address; + ret = itg3200_read_reg_s16(indio_dev, reg, val); ++ if (ret) ++ return ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; +diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c +index a791ba3a693a47..de126561f197d8 100644 +--- a/drivers/iio/gyro/mpu3050-core.c ++++ b/drivers/iio/gyro/mpu3050-core.c +@@ -1172,10 +1172,8 @@ int mpu3050_common_probe(struct device *dev, + mpu3050->regs[1].supply = mpu3050_reg_vlogic; + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(mpu3050->regs), + mpu3050->regs); +- if (ret) { +- dev_err(dev, "Cannot get regulators\n"); +- return ret; +- } ++ if (ret) ++ return dev_err_probe(dev, ret, "Cannot get regulators\n"); + + ret = mpu3050_power_up(mpu3050); + if (ret) +diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c +index 77666b780a5c5a..9655214a382762 100644 +--- a/drivers/iio/light/si1145.c ++++ b/drivers/iio/light/si1145.c +@@ -1251,7 +1251,7 @@ static int si1145_probe_trigger(struct iio_dev *indio_dev) + + ret = devm_request_irq(&client->dev, client->irq, + iio_trigger_generic_data_rdy_poll, +- IRQF_TRIGGER_FALLING, ++ IRQF_TRIGGER_FALLING | IRQF_NO_THREAD, + "si1145_irq", + trig); + if (ret < 0) { +diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c +index 3a98d6bae1b203..c1894a26ffd670 100644 +--- a/drivers/iio/magnetometer/ak8975.c ++++ b/drivers/iio/magnetometer/ak8975.c +@@ -542,7 +542,7 @@ static int ak8975_setup_irq(struct ak8975_data *data) + irq = gpiod_to_irq(data->eoc_gpiod); + + rc = devm_request_irq(&client->dev, irq, ak8975_irq_handler, +- IRQF_TRIGGER_RISING | IRQF_ONESHOT, ++ IRQF_TRIGGER_RISING, + dev_name(&client->dev), data); + if (rc < 0) { + dev_err(&client->dev, "irq %d request failed: %d\n", irq, rc); +diff --git a/drivers/iio/pressure/mprls0025pa.c b/drivers/iio/pressure/mprls0025pa.c +index 829c472812e49b..566c21bf3ea0df 100644 +--- a/drivers/iio/pressure/mprls0025pa.c ++++ b/drivers/iio/pressure/mprls0025pa.c +@@ -132,8 +132,8 @@ static const struct iio_chan_spec mpr_channels[] = { + BIT(IIO_CHAN_INFO_OFFSET), + .scan_index = 0, + .scan_type = { +- .sign = 's', +- .realbits = 32, ++ .sign = 'u', ++ .realbits = 24, + .storagebits = 32, + .endianness = IIO_CPU, + }, +diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c +index 77c0b89259911f..cda4fb81174fbd 100644 +--- a/drivers/infiniband/core/cache.c ++++ b/drivers/infiniband/core/cache.c +@@ -927,6 +927,13 @@ static int gid_table_setup_one(struct ib_device *ib_dev) + if (err) + return err; + ++ /* ++ * Mark the device as ready for GID cache updates. This allows netdev ++ * event handlers to update the GID cache even before the device is ++ * fully registered. ++ */ ++ ib_device_enable_gid_updates(ib_dev); ++ + rdma_roce_rescan_device(ib_dev); + + return err; +@@ -1566,7 +1573,8 @@ static void ib_cache_event_task(struct work_struct *_work) + * the cache. + */ + ret = ib_cache_update(work->event.device, work->event.element.port_num, +- work->event.event == IB_EVENT_GID_CHANGE, ++ work->event.event == IB_EVENT_GID_CHANGE || ++ work->event.event == IB_EVENT_CLIENT_REREGISTER, + work->event.event == IB_EVENT_PKEY_CHANGE, + work->enforce_security); + +@@ -1667,6 +1675,12 @@ void ib_cache_release_one(struct ib_device *device) + + void ib_cache_cleanup_one(struct ib_device *device) + { ++ /* ++ * Clear the GID updates mark first to prevent event handlers from ++ * accessing the device while it's being torn down. ++ */ ++ ib_device_disable_gid_updates(device); ++ + /* The cleanup function waits for all in-progress workqueue + * elements and cleans up the GID cache. This function should be + * called after the device was removed from the devices list and +diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h +index f66f48d860ec38..149dacf5b64d83 100644 +--- a/drivers/infiniband/core/core_priv.h ++++ b/drivers/infiniband/core/core_priv.h +@@ -100,6 +100,9 @@ void ib_enum_all_roce_netdevs(roce_netdev_filter filter, + roce_netdev_callback cb, + void *cookie); + ++void ib_device_enable_gid_updates(struct ib_device *device); ++void ib_device_disable_gid_updates(struct ib_device *device); ++ + typedef int (*nldev_callback)(struct ib_device *device, + struct sk_buff *skb, + struct netlink_callback *cb, +diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c +index d5931bb1de41a7..1a241864b7b547 100644 +--- a/drivers/infiniband/core/device.c ++++ b/drivers/infiniband/core/device.c +@@ -93,6 +93,7 @@ static struct workqueue_struct *ib_unreg_wq; + static DEFINE_XARRAY_FLAGS(devices, XA_FLAGS_ALLOC); + static DECLARE_RWSEM(devices_rwsem); + #define DEVICE_REGISTERED XA_MARK_1 ++#define DEVICE_GID_UPDATES XA_MARK_2 + + static u32 highest_client_id; + #define CLIENT_REGISTERED XA_MARK_1 +@@ -2344,11 +2345,42 @@ void ib_enum_all_roce_netdevs(roce_netdev_filter filter, + unsigned long index; + + down_read(&devices_rwsem); +- xa_for_each_marked (&devices, index, dev, DEVICE_REGISTERED) ++ xa_for_each_marked(&devices, index, dev, DEVICE_GID_UPDATES) + ib_enum_roce_netdev(dev, filter, filter_cookie, cb, cookie); + up_read(&devices_rwsem); + } + ++/** ++ * ib_device_enable_gid_updates - Mark device as ready for GID cache updates ++ * @device: Device to mark ++ * ++ * Called after GID table is allocated and initialized. After this mark is set, ++ * netdevice event handlers can update the device's GID cache. This allows ++ * events that arrive during device registration to be processed, avoiding ++ * stale GID entries when netdev properties change during the device ++ * registration process. ++ */ ++void ib_device_enable_gid_updates(struct ib_device *device) ++{ ++ down_write(&devices_rwsem); ++ xa_set_mark(&devices, device->index, DEVICE_GID_UPDATES); ++ up_write(&devices_rwsem); ++} ++ ++/** ++ * ib_device_disable_gid_updates - Clear the GID updates mark ++ * @device: Device to unmark ++ * ++ * Called before GID table cleanup to prevent event handlers from accessing ++ * the device while it's being torn down. ++ */ ++void ib_device_disable_gid_updates(struct ib_device *device) ++{ ++ down_write(&devices_rwsem); ++ xa_clear_mark(&devices, device->index, DEVICE_GID_UPDATES); ++ up_write(&devices_rwsem); ++} ++ + /* + * ib_enum_all_devs - enumerate all ib_devices + * @cb: Callback to call for each found ib_device +diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c +index 8367974b7998b0..2522ff1cc462c7 100644 +--- a/drivers/infiniband/core/rw.c ++++ b/drivers/infiniband/core/rw.c +@@ -651,34 +651,57 @@ unsigned int rdma_rw_mr_factor(struct ib_device *device, u32 port_num, + } + EXPORT_SYMBOL(rdma_rw_mr_factor); + ++/** ++ * rdma_rw_max_send_wr - compute max Send WRs needed for RDMA R/W contexts ++ * @dev: RDMA device ++ * @port_num: port number ++ * @max_rdma_ctxs: number of rdma_rw_ctx structures ++ * @create_flags: QP create flags (pass IB_QP_CREATE_INTEGRITY_EN if ++ * data integrity will be enabled on the QP) ++ * ++ * Returns the total number of Send Queue entries needed for ++ * @max_rdma_ctxs. The result accounts for memory registration and ++ * invalidation work requests when the device requires them. ++ * ++ * ULPs use this to size Send Queues and Send CQs before creating a ++ * Queue Pair. ++ */ ++unsigned int rdma_rw_max_send_wr(struct ib_device *dev, u32 port_num, ++ unsigned int max_rdma_ctxs, u32 create_flags) ++{ ++ unsigned int factor = 1; ++ unsigned int result; ++ ++ if (create_flags & IB_QP_CREATE_INTEGRITY_EN || ++ rdma_rw_can_use_mr(dev, port_num)) ++ factor += 2; /* reg + inv */ ++ ++ if (check_mul_overflow(factor, max_rdma_ctxs, &result)) ++ return UINT_MAX; ++ return result; ++} ++EXPORT_SYMBOL(rdma_rw_max_send_wr); ++ + void rdma_rw_init_qp(struct ib_device *dev, struct ib_qp_init_attr *attr) + { +- u32 factor; ++ unsigned int factor = 1; + + WARN_ON_ONCE(attr->port_num == 0); + + /* +- * Each context needs at least one RDMA READ or WRITE WR. +- * +- * For some hardware we might need more, eventually we should ask the +- * HCA driver for a multiplier here. +- */ +- factor = 1; +- +- /* +- * If the devices needs MRs to perform RDMA READ or WRITE operations, +- * we'll need two additional MRs for the registrations and the +- * invalidation. ++ * If the device uses MRs to perform RDMA READ or WRITE operations, ++ * or if data integrity is enabled, account for registration and ++ * invalidation work requests. + */ + if (attr->create_flags & IB_QP_CREATE_INTEGRITY_EN || + rdma_rw_can_use_mr(dev, attr->port_num)) +- factor += 2; /* inv + reg */ ++ factor += 2; /* reg + inv */ + + attr->cap.max_send_wr += factor * attr->cap.max_rdma_ctxs; + + /* +- * But maybe we were just too high in the sky and the device doesn't +- * even support all we need, and we'll have to live with what we get.. ++ * The device might not support all we need, and we'll have to ++ * live with what we get. + */ + attr->cap.max_send_wr = + min_t(u32, attr->cap.max_send_wr, dev->attrs.max_qp_wr); +diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c +index 39357dc2d229f0..66f5760197479d 100644 +--- a/drivers/infiniband/core/umem_dmabuf.c ++++ b/drivers/infiniband/core/umem_dmabuf.c +@@ -205,13 +205,11 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, + + err = ib_umem_dmabuf_map_pages(umem_dmabuf); + if (err) +- goto err_unpin; ++ goto err_release; + dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv); + + return umem_dmabuf; + +-err_unpin: +- dma_buf_unpin(umem_dmabuf->attach); + err_release: + dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv); + ib_umem_release(&umem_dmabuf->umem); +diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c +index 2ed749f50a29ff..285f251fc014be 100644 +--- a/drivers/infiniband/core/user_mad.c ++++ b/drivers/infiniband/core/user_mad.c +@@ -514,7 +514,8 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, + struct rdma_ah_attr ah_attr; + struct ib_ah *ah; + __be64 *tid; +- int ret, data_len, hdr_len, copy_offset, rmpp_active; ++ int ret, hdr_len, copy_offset, rmpp_active; ++ size_t data_len; + u8 base_version; + + if (count < hdr_size(file) + IB_MGMT_RMPP_HDR) +@@ -588,7 +589,10 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, + } + + base_version = ((struct ib_mad_hdr *)&packet->mad.data)->base_version; +- data_len = count - hdr_size(file) - hdr_len; ++ if (check_sub_overflow(count, hdr_size(file) + hdr_len, &data_len)) { ++ ret = -EINVAL; ++ goto err_ah; ++ } + packet->msg = ib_create_send_mad(agent, + be32_to_cpu(packet->mad.hdr.qpn), + packet->mad.hdr.pkey_index, rmpp_active, +diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c +index 33e2fe0facd529..2e4265ba35b7f3 100644 +--- a/drivers/infiniband/core/uverbs_cmd.c ++++ b/drivers/infiniband/core/uverbs_cmd.c +@@ -2030,7 +2030,10 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs) + if (ret) + return ret; + +- user_wr = kmalloc(cmd.wqe_size, GFP_KERNEL); ++ if (cmd.wqe_size < sizeof(struct ib_uverbs_send_wr)) ++ return -EINVAL; ++ ++ user_wr = kmalloc(cmd.wqe_size, GFP_KERNEL | __GFP_NOWARN); + if (!user_wr) + return -ENOMEM; + +@@ -2220,7 +2223,7 @@ ib_uverbs_unmarshall_recv(struct uverbs_req_iter *iter, u32 wr_count, + if (ret) + return ERR_PTR(ret); + +- user_wr = kmalloc(wqe_size, GFP_KERNEL); ++ user_wr = kmalloc(wqe_size, GFP_KERNEL | __GFP_NOWARN); + if (!user_wr) + return ERR_PTR(-ENOMEM); + +diff --git a/drivers/infiniband/hw/efa/efa_verbs.c b/drivers/infiniband/hw/efa/efa_verbs.c +index 2a5b93ef4b3353..121384fee6696e 100644 +--- a/drivers/infiniband/hw/efa/efa_verbs.c ++++ b/drivers/infiniband/hw/efa/efa_verbs.c +@@ -1567,7 +1567,7 @@ static struct efa_mr *efa_alloc_mr(struct ib_pd *ibpd, int access_flags, + struct efa_mr *mr; + + if (udata && udata->inlen && +- !ib_is_udata_cleared(udata, 0, sizeof(udata->inlen))) { ++ !ib_is_udata_cleared(udata, 0, udata->inlen)) { + ibdev_dbg(&dev->ibdev, + "Incompatible ABI params, udata not cleared\n"); + return ERR_PTR(-EINVAL); +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index f1d4494c7d0082..b50529a652741a 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -3588,6 +3588,23 @@ static void hns_roce_v2_write_cqc(struct hns_roce_dev *hr_dev, + HNS_ROCE_V2_CQ_DEFAULT_INTERVAL); + } + ++static bool left_sw_wc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq) ++{ ++ struct hns_roce_qp *hr_qp; ++ ++ list_for_each_entry(hr_qp, &hr_cq->sq_list, sq_node) { ++ if (hr_qp->sq.head != hr_qp->sq.tail) ++ return true; ++ } ++ ++ list_for_each_entry(hr_qp, &hr_cq->rq_list, rq_node) { ++ if (hr_qp->rq.head != hr_qp->rq.tail) ++ return true; ++ } ++ ++ return false; ++} ++ + static int hns_roce_v2_req_notify_cq(struct ib_cq *ibcq, + enum ib_cq_notify_flags flags) + { +@@ -3596,6 +3613,12 @@ static int hns_roce_v2_req_notify_cq(struct ib_cq *ibcq, + struct hns_roce_v2_db cq_db = {}; + u32 notify_flag; + ++ if (hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN) { ++ if ((flags & IB_CQ_REPORT_MISSED_EVENTS) && ++ left_sw_wc(hr_dev, hr_cq)) ++ return 1; ++ return 0; ++ } + /* + * flags = 0, then notify_flag : next + * flags = 1, then notify flag : solocited +@@ -6604,7 +6627,8 @@ static int hns_roce_v2_init_eq_table(struct hns_roce_dev *hr_dev) + + INIT_WORK(&hr_dev->ecc_work, fmea_ram_ecc_work); + +- hr_dev->irq_workq = alloc_ordered_workqueue("hns_roce_irq_workq", 0); ++ hr_dev->irq_workq = alloc_ordered_workqueue("hns_roce_irq_workq", ++ WQ_MEM_RECLAIM); + if (!hr_dev->irq_workq) { + dev_err(dev, "failed to create irq workqueue.\n"); + ret = -ENOMEM; +diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c +index c997b7cbf2a9e8..81b645c727a17c 100644 +--- a/drivers/infiniband/sw/rxe/rxe_comp.c ++++ b/drivers/infiniband/sw/rxe/rxe_comp.c +@@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t) + + rxe_dbg_qp(qp, "retransmit timer fired\n"); + ++ if (!rxe_get(qp)) ++ return; + spin_lock_irqsave(&qp->state_lock, flags); + if (qp->valid) { + qp->comp.timeout = 1; + rxe_sched_task(&qp->comp.task); + } + spin_unlock_irqrestore(&qp->state_lock, flags); ++ rxe_put(qp); + } + + void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb) +diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c +index 7ff152ffe15b9f..4d550ac0dac5ad 100644 +--- a/drivers/infiniband/sw/rxe/rxe_req.c ++++ b/drivers/infiniband/sw/rxe/rxe_req.c +@@ -103,6 +103,8 @@ void rnr_nak_timer(struct timer_list *t) + + rxe_dbg_qp(qp, "nak timer fired\n"); + ++ if (!rxe_get(qp)) ++ return; + spin_lock_irqsave(&qp->state_lock, flags); + if (qp->valid) { + /* request a send queue retry */ +@@ -111,6 +113,7 @@ void rnr_nak_timer(struct timer_list *t) + rxe_sched_task(&qp->req.task); + } + spin_unlock_irqrestore(&qp->state_lock, flags); ++ rxe_put(qp); + } + + static void req_check_sq_drain_done(struct rxe_qp *qp) +diff --git a/drivers/infiniband/sw/rxe/rxe_srq.c b/drivers/infiniband/sw/rxe/rxe_srq.c +index 2a234f26ac1044..c9a7cd38953d31 100644 +--- a/drivers/infiniband/sw/rxe/rxe_srq.c ++++ b/drivers/infiniband/sw/rxe/rxe_srq.c +@@ -77,9 +77,6 @@ int rxe_srq_from_init(struct rxe_dev *rxe, struct rxe_srq *srq, + goto err_free; + } + +- srq->rq.queue = q; +- init->attr.max_wr = srq->rq.max_wr; +- + if (uresp) { + if (copy_to_user(&uresp->srq_num, &srq->srq_num, + sizeof(uresp->srq_num))) { +@@ -88,6 +85,9 @@ int rxe_srq_from_init(struct rxe_dev *rxe, struct rxe_srq *srq, + } + } + ++ srq->rq.queue = q; ++ init->attr.max_wr = srq->rq.max_wr; ++ + return 0; + + err_free: +diff --git a/drivers/infiniband/sw/siw/siw_qp_rx.c b/drivers/infiniband/sw/siw/siw_qp_rx.c +index 58bbf738e4e599..e2ad2425d57dac 100644 +--- a/drivers/infiniband/sw/siw/siw_qp_rx.c ++++ b/drivers/infiniband/sw/siw/siw_qp_rx.c +@@ -1456,7 +1456,8 @@ int siw_tcp_rx_data(read_descriptor_t *rd_desc, struct sk_buff *skb, + } + if (unlikely(rv != 0 && rv != -EAGAIN)) { + if ((srx->state > SIW_GET_HDR || +- qp->rx_fpdu->more_ddp_segs) && run_completion) ++ (qp->rx_fpdu && qp->rx_fpdu->more_ddp_segs)) && ++ run_completion) + siw_rdmap_complete(qp, rv); + + siw_dbg_qp(qp, "rx error %d, rx state %d\n", rv, +diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c +index eaf911e2ffa9fb..1af2ee8c8ed5ef 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c ++++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c +@@ -1922,7 +1922,7 @@ static int rtrs_rdma_conn_rejected(struct rtrs_clt_con *con, + struct rtrs_path *s = con->c.path; + const struct rtrs_msg_conn_rsp *msg; + const char *rej_msg; +- int status, errno; ++ int status, errno = -ECONNRESET; + u8 data_len; + + status = ev->status; +@@ -1944,7 +1944,7 @@ static int rtrs_rdma_conn_rejected(struct rtrs_clt_con *con, + status, rej_msg); + } + +- return -ECONNRESET; ++ return errno; + } + + void rtrs_clt_close_conns(struct rtrs_clt_path *clt_path, bool wait) +diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c +index 5dbf315630c1a2..2c3c8b32190f8a 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c ++++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c +@@ -205,7 +205,6 @@ static int rdma_write_sg(struct rtrs_srv_op *id) + size_t sg_cnt; + int err, offset; + bool need_inval; +- u32 rkey = 0; + struct ib_reg_wr rwr; + struct ib_sge *plist; + struct ib_sge list; +@@ -237,11 +236,6 @@ static int rdma_write_sg(struct rtrs_srv_op *id) + wr->wr.num_sge = 1; + wr->remote_addr = le64_to_cpu(id->rd_msg->desc[0].addr); + wr->rkey = le32_to_cpu(id->rd_msg->desc[0].key); +- if (rkey == 0) +- rkey = wr->rkey; +- else +- /* Only one key is actually used */ +- WARN_ON_ONCE(rkey != wr->rkey); + + wr->wr.opcode = IB_WR_RDMA_WRITE; + wr->wr.wr_cqe = &io_comp_cqe; +@@ -274,7 +268,7 @@ static int rdma_write_sg(struct rtrs_srv_op *id) + inv_wr.opcode = IB_WR_SEND_WITH_INV; + inv_wr.wr_cqe = &io_comp_cqe; + inv_wr.send_flags = 0; +- inv_wr.ex.invalidate_rkey = rkey; ++ inv_wr.ex.invalidate_rkey = wr->rkey; + } + + imm_wr.wr.next = NULL; +@@ -598,7 +592,7 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_path) + srv_path->mrs_num++) { + struct rtrs_srv_mr *srv_mr = &srv_path->mrs[srv_path->mrs_num]; + struct scatterlist *s; +- int nr, nr_sgt, chunks; ++ int nr, nr_sgt, chunks, ind; + + sgt = &srv_mr->sgt; + chunks = chunks_per_mr * srv_path->mrs_num; +@@ -628,7 +622,7 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_path) + } + nr = ib_map_mr_sg(mr, sgt->sgl, nr_sgt, + NULL, max_chunk_size); +- if (nr != nr_sgt) { ++ if (nr < nr_sgt) { + err = nr < 0 ? nr : -EINVAL; + goto dereg_mr; + } +@@ -644,9 +638,24 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_path) + goto dereg_mr; + } + } +- /* Eventually dma addr for each chunk can be cached */ +- for_each_sg(sgt->sgl, s, nr_sgt, i) +- srv_path->dma_addr[chunks + i] = sg_dma_address(s); ++ ++ /* ++ * Cache DMA addresses by traversing sg entries. If ++ * regions were merged, an inner loop is required to ++ * populate the DMA address array by traversing larger ++ * regions. ++ */ ++ ind = chunks; ++ for_each_sg(sgt->sgl, s, nr_sgt, i) { ++ unsigned int dma_len = sg_dma_len(s); ++ u64 dma_addr = sg_dma_address(s); ++ u64 dma_addr_end = dma_addr + dma_len; ++ ++ do { ++ srv_path->dma_addr[ind++] = dma_addr; ++ dma_addr += max_chunk_size; ++ } while (dma_addr < dma_addr_end); ++ } + + ib_update_fast_reg_key(mr, ib_inc_rkey(mr->rkey)); + srv_mr->mr = mr; +diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c +index 23cfb98fe90a7b..d119a104a34361 100644 +--- a/drivers/iommu/amd/iommu.c ++++ b/drivers/iommu/amd/iommu.c +@@ -941,7 +941,12 @@ static int wait_on_sem(struct amd_iommu *iommu, u64 data) + { + int i = 0; + +- while (*iommu->cmd_sem != data && i < LOOP_TIMEOUT) { ++ /* ++ * cmd_sem holds a monotonically non-decreasing completion sequence ++ * number. ++ */ ++ while ((__s64)(READ_ONCE(*iommu->cmd_sem) - data) < 0 && ++ i < LOOP_TIMEOUT) { + udelay(1); + i += 1; + } +@@ -1210,14 +1215,13 @@ static int iommu_completion_wait(struct amd_iommu *iommu) + raw_spin_lock_irqsave(&iommu->lock, flags); + + ret = __iommu_queue_command_sync(iommu, &cmd, false); ++ raw_spin_unlock_irqrestore(&iommu->lock, flags); ++ + if (ret) +- goto out_unlock; ++ return ret; + + ret = wait_on_sem(iommu, data); + +-out_unlock: +- raw_spin_unlock_irqrestore(&iommu->lock, flags); +- + return ret; + } + +@@ -2879,13 +2883,18 @@ static void iommu_flush_irt_and_complete(struct amd_iommu *iommu, u16 devid) + raw_spin_lock_irqsave(&iommu->lock, flags); + ret = __iommu_queue_command_sync(iommu, &cmd, true); + if (ret) +- goto out; ++ goto out_err; + ret = __iommu_queue_command_sync(iommu, &cmd2, false); + if (ret) +- goto out; ++ goto out_err; ++ raw_spin_unlock_irqrestore(&iommu->lock, flags); ++ + wait_on_sem(iommu, data); +-out: ++ return; ++ ++out_err: + raw_spin_unlock_irqrestore(&iommu->lock, flags); ++ return; + } + + static void set_dte_irq_entry(struct amd_iommu *iommu, u16 devid, +diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +index f2260f45728e79..bb7365b4321989 100644 +--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c ++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +@@ -443,20 +443,26 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu) + */ + static void arm_smmu_cmdq_shared_lock(struct arm_smmu_cmdq *cmdq) + { +- int val; +- + /* +- * We can try to avoid the cmpxchg() loop by simply incrementing the +- * lock counter. When held in exclusive state, the lock counter is set +- * to INT_MIN so these increments won't hurt as the value will remain +- * negative. ++ * When held in exclusive state, the lock counter is set to INT_MIN ++ * so these increments won't hurt as the value will remain negative. ++ * The increment will also signal the exclusive locker that there are ++ * shared waiters. + */ + if (atomic_fetch_inc_relaxed(&cmdq->lock) >= 0) + return; + +- do { +- val = atomic_cond_read_relaxed(&cmdq->lock, VAL >= 0); +- } while (atomic_cmpxchg_relaxed(&cmdq->lock, val, val + 1) != val); ++ /* ++ * Someone else is holding the lock in exclusive state, so wait ++ * for them to finish. Since we already incremented the lock counter, ++ * no exclusive lock can be acquired until we finish. We don't need ++ * the return value since we only care that the exclusive lock is ++ * released (i.e. the lock counter is non-negative). ++ * Once the exclusive locker releases the lock, the sign bit will ++ * be cleared and our increment will make the lock counter positive, ++ * allowing us to proceed. ++ */ ++ atomic_cond_read_relaxed(&cmdq->lock, VAL > 0); + } + + static void arm_smmu_cmdq_shared_unlock(struct arm_smmu_cmdq *cmdq) +@@ -483,9 +489,14 @@ static bool arm_smmu_cmdq_shared_tryunlock(struct arm_smmu_cmdq *cmdq) + __ret; \ + }) + ++/* ++ * Only clear the sign bit when releasing the exclusive lock this will ++ * allow any shared_lock() waiters to proceed without the possibility ++ * of entering the exclusive lock in a tight loop. ++ */ + #define arm_smmu_cmdq_exclusive_unlock_irqrestore(cmdq, flags) \ + ({ \ +- atomic_set_release(&cmdq->lock, 0); \ ++ atomic_fetch_andnot_release(INT_MIN, &cmdq->lock); \ + local_irq_restore(flags); \ + }) + +diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c +index 8faa93cffac45d..99589ac3b96bc6 100644 +--- a/drivers/iommu/intel/pasid.c ++++ b/drivers/iommu/intel/pasid.c +@@ -207,6 +207,9 @@ retry: + if (!entries) + return NULL; + ++ if (!ecap_coherent(info->iommu->ecap)) ++ clflush_cache_range(entries, VTD_PAGE_SIZE); ++ + /* + * The pasid directory table entry won't be freed after + * allocation. No worry about the race with free and +@@ -218,10 +221,8 @@ retry: + free_pgtable_page(entries); + goto retry; + } +- if (!ecap_coherent(info->iommu->ecap)) { +- clflush_cache_range(entries, VTD_PAGE_SIZE); ++ if (!ecap_coherent(info->iommu->ecap)) + clflush_cache_range(&dir[dir_index].val, sizeof(*dir)); +- } + } + + return &entries[index]; +@@ -428,7 +429,7 @@ devtlb_invalidation_with_pasid(struct intel_iommu *iommu, + if (!info || !info->ats_enabled) + return; + +- if (pci_dev_is_disconnected(to_pci_dev(dev))) ++ if (!pci_device_is_present(to_pci_dev(dev))) + return; + + sid = info->bus << 8 | info->devfn; +diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c +index a41c2b13766dc1..9843fe2e5f9eb3 100644 +--- a/drivers/leds/rgb/leds-qcom-lpg.c ++++ b/drivers/leds/rgb/leds-qcom-lpg.c +@@ -221,7 +221,7 @@ static int lpg_lut_store(struct lpg *lpg, struct led_pattern *pattern, + { + unsigned int idx; + u16 val; +- int i; ++ int i, ret; + + idx = bitmap_find_next_zero_area(lpg->lut_bitmap, lpg->lut_size, + 0, len, 0); +@@ -231,8 +231,10 @@ static int lpg_lut_store(struct lpg *lpg, struct led_pattern *pattern, + for (i = 0; i < len; i++) { + val = pattern[i].brightness; + +- regmap_bulk_write(lpg->map, lpg->lut_base + LPG_LUT_REG(idx + i), +- &val, sizeof(val)); ++ ret = regmap_bulk_write(lpg->map, lpg->lut_base + LPG_LUT_REG(idx + i), ++ &val, sizeof(val)); ++ if (ret) ++ return ret; + } + + bitmap_set(lpg->lut_bitmap, idx, len); +diff --git a/drivers/mailbox/bcm-flexrm-mailbox.c b/drivers/mailbox/bcm-flexrm-mailbox.c +index a2b8839d4e7c5e..a1e02efe93ad29 100644 +--- a/drivers/mailbox/bcm-flexrm-mailbox.c ++++ b/drivers/mailbox/bcm-flexrm-mailbox.c +@@ -1173,14 +1173,6 @@ static int flexrm_debugfs_stats_show(struct seq_file *file, void *offset) + + /* ====== FlexRM interrupt handler ===== */ + +-static irqreturn_t flexrm_irq_event(int irq, void *dev_id) +-{ +- /* We only have MSI for completions so just wakeup IRQ thread */ +- /* Ring related errors will be informed via completion descriptors */ +- +- return IRQ_WAKE_THREAD; +-} +- + static irqreturn_t flexrm_irq_thread(int irq, void *dev_id) + { + flexrm_process_completions(dev_id); +@@ -1271,10 +1263,8 @@ static int flexrm_startup(struct mbox_chan *chan) + ret = -ENODEV; + goto fail_free_cmpl_memory; + } +- ret = request_threaded_irq(ring->irq, +- flexrm_irq_event, +- flexrm_irq_thread, +- 0, dev_name(ring->mbox->dev), ring); ++ ret = request_threaded_irq(ring->irq, NULL, flexrm_irq_thread, ++ IRQF_ONESHOT, dev_name(ring->mbox->dev), ring); + if (ret) { + dev_err(ring->mbox->dev, + "failed to request ring%d IRQ\n", ring->num); +diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c +index 3ef4dd8adf5db1..5eef59f00abd51 100644 +--- a/drivers/mailbox/imx-mailbox.c ++++ b/drivers/mailbox/imx-mailbox.c +@@ -113,6 +113,7 @@ struct imx_mu_dcfg { + u32 xRR; /* Receive Register0 */ + u32 xSR[IMX_MU_xSR_MAX]; /* Status Registers */ + u32 xCR[IMX_MU_xCR_MAX]; /* Control Registers */ ++ bool skip_suspend_flag; + }; + + #define IMX_MU_xSR_GIPn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(28 + (3 - (x)))) +@@ -906,6 +907,7 @@ static const struct imx_mu_dcfg imx_mu_cfg_imx7ulp = { + .xRR = 0x40, + .xSR = {0x60, 0x60, 0x60, 0x60}, + .xCR = {0x64, 0x64, 0x64, 0x64, 0x64}, ++ .skip_suspend_flag = true, + }; + + static const struct imx_mu_dcfg imx_mu_cfg_imx8ulp = { +@@ -986,7 +988,8 @@ static int __maybe_unused imx_mu_suspend_noirq(struct device *dev) + priv->xcr[i] = imx_mu_read(priv, priv->dcfg->xCR[i]); + } + +- priv->suspend = true; ++ if (!priv->dcfg->skip_suspend_flag) ++ priv->suspend = true; + + return 0; + } +@@ -1009,7 +1012,8 @@ static int __maybe_unused imx_mu_resume_noirq(struct device *dev) + imx_mu_write(priv, priv->xcr[i], priv->dcfg->xCR[i]); + } + +- priv->suspend = false; ++ if (!priv->dcfg->skip_suspend_flag) ++ priv->suspend = false; + + return 0; + } +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index 2b7d0bc9207263..1d4191cb913804 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -481,7 +481,7 @@ static int pcc_startup(struct mbox_chan *chan) + + if (pchan->plat_irq > 0) { + irqflags = pcc_chan_plat_irq_can_be_shared(pchan) ? +- IRQF_SHARED | IRQF_ONESHOT : 0; ++ IRQF_SHARED : 0; + rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, + irqflags, MBOX_IRQ_NAME, chan); + if (unlikely(rc)) { +diff --git a/drivers/mailbox/sprd-mailbox.c b/drivers/mailbox/sprd-mailbox.c +index 9ae57de77d4d76..109ff60c4ac749 100644 +--- a/drivers/mailbox/sprd-mailbox.c ++++ b/drivers/mailbox/sprd-mailbox.c +@@ -167,6 +167,11 @@ static irqreturn_t sprd_mbox_inbox_isr(int irq, void *data) + return IRQ_NONE; + } + ++ /* Clear FIFO delivery and overflow status first */ ++ writel(fifo_sts & ++ (SPRD_INBOX_FIFO_DELIVER_MASK | SPRD_INBOX_FIFO_OVERLOW_MASK), ++ priv->inbox_base + SPRD_MBOX_FIFO_RST); ++ + while (send_sts) { + id = __ffs(send_sts); + send_sts &= (send_sts - 1); +@@ -182,11 +187,6 @@ static irqreturn_t sprd_mbox_inbox_isr(int irq, void *data) + mbox_chan_txdone(chan, 0); + } + +- /* Clear FIFO delivery and overflow status */ +- writel(fifo_sts & +- (SPRD_INBOX_FIFO_DELIVER_MASK | SPRD_INBOX_FIFO_OVERLOW_MASK), +- priv->inbox_base + SPRD_MBOX_FIFO_RST); +- + /* Clear irq status */ + writel(SPRD_MBOX_IRQ_CLR, priv->inbox_base + SPRD_MBOX_IRQ_STS); + +@@ -244,21 +244,19 @@ static int sprd_mbox_startup(struct mbox_chan *chan) + /* Select outbox FIFO mode and reset the outbox FIFO status */ + writel(0x0, priv->outbox_base + SPRD_MBOX_FIFO_RST); + +- /* Enable inbox FIFO overflow and delivery interrupt */ +- val = readl(priv->inbox_base + SPRD_MBOX_IRQ_MSK); +- val &= ~(SPRD_INBOX_FIFO_OVERFLOW_IRQ | SPRD_INBOX_FIFO_DELIVER_IRQ); ++ /* Enable inbox FIFO delivery interrupt */ ++ val = SPRD_INBOX_FIFO_IRQ_MASK; ++ val &= ~SPRD_INBOX_FIFO_DELIVER_IRQ; + writel(val, priv->inbox_base + SPRD_MBOX_IRQ_MSK); + + /* Enable outbox FIFO not empty interrupt */ +- val = readl(priv->outbox_base + SPRD_MBOX_IRQ_MSK); ++ val = SPRD_OUTBOX_FIFO_IRQ_MASK; + val &= ~SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ; + writel(val, priv->outbox_base + SPRD_MBOX_IRQ_MSK); + + /* Enable supplementary outbox as the fundamental one */ + if (priv->supp_base) { + writel(0x0, priv->supp_base + SPRD_MBOX_FIFO_RST); +- val = readl(priv->supp_base + SPRD_MBOX_IRQ_MSK); +- val &= ~SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ; + writel(val, priv->supp_base + SPRD_MBOX_IRQ_MSK); + } + } +diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c +index c3799757bf4a0c..88f119a0a2ae0d 100644 +--- a/drivers/md/dm-exception-store.c ++++ b/drivers/md/dm-exception-store.c +@@ -116,7 +116,7 @@ int dm_exception_store_type_register(struct dm_exception_store_type *type) + if (!__find_exception_store_type(type->name)) + list_add(&type->list, &_exception_store_types); + else +- r = -EEXIST; ++ r = -EBUSY; + spin_unlock(&_lock); + + return r; +diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c +index 6442d41622eff9..be1bf38654156d 100644 +--- a/drivers/md/dm-integrity.c ++++ b/drivers/md/dm-integrity.c +@@ -2313,7 +2313,7 @@ offload_to_thread: + + new_pos = find_journal_node(ic, dio->range.logical_sector, &next_sector); + if (unlikely(new_pos != NOT_FOUND) || +- unlikely(next_sector < dio->range.logical_sector - dio->range.n_sectors)) { ++ unlikely(next_sector < dio->range.logical_sector + dio->range.n_sectors)) { + remove_range_unlocked(ic, &dio->range); + spin_unlock_irq(&ic->endio_wait.lock); + queue_work(ic->commit_wq, &ic->commit_work); +@@ -3258,14 +3258,27 @@ static void dm_integrity_resume(struct dm_target *ti) + struct dm_integrity_c *ic = ti->private; + __u64 old_provided_data_sectors = le64_to_cpu(ic->sb->provided_data_sectors); + int r; ++ __le32 flags; + + DEBUG_print("resume\n"); + + ic->wrote_to_journal = false; + ++ flags = ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING); ++ r = sync_rw_sb(ic, REQ_OP_READ); ++ if (r) ++ dm_integrity_io_error(ic, "reading superblock", r); ++ if ((ic->sb->flags & flags) != flags) { ++ ic->sb->flags |= flags; ++ r = sync_rw_sb(ic, REQ_OP_WRITE | REQ_FUA); ++ if (unlikely(r)) ++ dm_integrity_io_error(ic, "writing superblock", r); ++ } ++ + if (ic->provided_data_sectors != old_provided_data_sectors) { + if (ic->provided_data_sectors > old_provided_data_sectors && + ic->mode == 'B' && ++ ic->sb->flags & cpu_to_le32(SB_FLAG_DIRTY_BITMAP) && + ic->sb->log2_blocks_per_bitmap_bit == ic->log2_blocks_per_bitmap_bit) { + rw_journal_sectors(ic, REQ_OP_READ, 0, + ic->n_bitmap_blocks * (BITMAP_BLOCK_SIZE >> SECTOR_SHIFT), NULL); +diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c +index f7f9c2100937ba..e215478bcee048 100644 +--- a/drivers/md/dm-log.c ++++ b/drivers/md/dm-log.c +@@ -121,7 +121,7 @@ int dm_dirty_log_type_register(struct dm_dirty_log_type *type) + if (!__find_dirty_log_type(type->name)) + list_add(&type->list, &_log_types); + else +- r = -EEXIST; ++ r = -EBUSY; + spin_unlock(&_lock); + + return r; +diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c +index bea3cda9938e97..9a03658aec202c 100644 +--- a/drivers/md/dm-mpath.c ++++ b/drivers/md/dm-mpath.c +@@ -220,6 +220,7 @@ static struct multipath *alloc_multipath(struct dm_target *ti) + mutex_init(&m->work_mutex); + + m->queue_mode = DM_TYPE_NONE; ++ m->pg_init_delay_msecs = DM_PG_INIT_DELAY_DEFAULT; + + m->ti = ti; + ti->private = m; +@@ -252,7 +253,6 @@ static int alloc_multipath_stage2(struct dm_target *ti, struct multipath *m) + set_bit(MPATHF_QUEUE_IO, &m->flags); + atomic_set(&m->pg_init_in_progress, 0); + atomic_set(&m->pg_init_count, 0); +- m->pg_init_delay_msecs = DM_PG_INIT_DELAY_DEFAULT; + init_waitqueue_head(&m->pg_init_wait); + + return 0; +diff --git a/drivers/md/dm-path-selector.c b/drivers/md/dm-path-selector.c +index 3e4cb81ce512c7..78f98545ca72d0 100644 +--- a/drivers/md/dm-path-selector.c ++++ b/drivers/md/dm-path-selector.c +@@ -107,7 +107,7 @@ int dm_register_path_selector(struct path_selector_type *pst) + + if (__find_path_selector_type(pst->name)) { + kfree(psi); +- r = -EEXIST; ++ r = -EBUSY; + } else + list_add(&psi->list, &_path_selectors); + +diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c +index 499f8cc8a39fbf..29d6ee68d4dfbc 100644 +--- a/drivers/md/dm-rq.c ++++ b/drivers/md/dm-rq.c +@@ -109,14 +109,21 @@ static void end_clone_bio(struct bio *clone) + */ + tio->completed += nr_bytes; + ++ if (!is_last) ++ return; ++ /* ++ * At this moment we know this is the last bio of the cloned request, ++ * and all cloned bios have been released, so reset the clone request's ++ * bio pointer to avoid double free. ++ */ ++ tio->clone->bio = NULL; ++ exit: + /* + * Update the original request. + * Do not use blk_mq_end_request() here, because it may complete + * the original request before the clone, and break the ordering. + */ +- if (is_last) +- exit: +- blk_update_request(tio->orig, BLK_STS_OK, tio->completed); ++ blk_update_request(tio->orig, BLK_STS_OK, tio->completed); + } + + static struct dm_rq_target_io *tio_from_request(struct request *rq) +@@ -278,8 +285,7 @@ static void dm_complete_request(struct request *rq, blk_status_t error) + struct dm_rq_target_io *tio = tio_from_request(rq); + + tio->error = error; +- if (likely(!blk_should_fake_timeout(rq->q))) +- blk_mq_complete_request(rq); ++ blk_mq_complete_request(rq); + } + + /* +diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c +index 27e2992ff24927..4d1f04b40653f9 100644 +--- a/drivers/md/dm-target.c ++++ b/drivers/md/dm-target.c +@@ -88,7 +88,7 @@ int dm_register_target(struct target_type *tt) + if (__find_target_type(tt->name)) { + DMERR("%s: '%s' target already registered", + __func__, tt->name); +- rv = -EEXIST; ++ rv = -EBUSY; + } else { + list_add(&tt->list, &_targets); + } +diff --git a/drivers/md/dm-unstripe.c b/drivers/md/dm-unstripe.c +index e8a9432057dce1..17be483595642c 100644 +--- a/drivers/md/dm-unstripe.c ++++ b/drivers/md/dm-unstripe.c +@@ -117,7 +117,7 @@ static void unstripe_dtr(struct dm_target *ti) + static sector_t map_to_core(struct dm_target *ti, struct bio *bio) + { + struct unstripe_c *uc = ti->private; +- sector_t sector = bio->bi_iter.bi_sector; ++ sector_t sector = dm_target_offset(ti, bio->bi_iter.bi_sector); + sector_t tmp_sector = sector; + + /* Shift us up to the right "row" on the stripe */ +diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c +index 4474352ad3d138..9275053b387b0d 100644 +--- a/drivers/md/dm-verity-fec.c ++++ b/drivers/md/dm-verity-fec.c +@@ -566,9 +566,9 @@ void verity_fec_dtr(struct dm_verity *v) + mempool_exit(&f->output_pool); + kmem_cache_destroy(f->cache); + +- if (f->data_bufio) ++ if (!IS_ERR_OR_NULL(f->data_bufio)) + dm_bufio_client_destroy(f->data_bufio); +- if (f->bufio) ++ if (!IS_ERR_OR_NULL(f->bufio)) + dm_bufio_client_destroy(f->bufio); + + if (f->dev) +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index f0c4c3553c0166..1d03536fded005 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -1363,6 +1363,8 @@ void dm_submit_bio_remap(struct bio *clone, struct bio *tgt_clone) + if (!tgt_clone) + tgt_clone = clone; + ++ bio_clone_blkg_association(tgt_clone, io->orig_bio); ++ + /* + * Account io->origin_bio to DM dev on behalf of target + * that took ownership of IO with DM_MAPIO_SUBMITTED. +diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c +index 1f1991634d0a21..ace28eb81111cf 100644 +--- a/drivers/md/md-bitmap.c ++++ b/drivers/md/md-bitmap.c +@@ -2224,6 +2224,7 @@ int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks, + memcpy(page_address(store.sb_page), + page_address(bitmap->storage.sb_page), + sizeof(bitmap_super_t)); ++ mutex_lock(&bitmap->mddev->bitmap_info.mutex); + spin_lock_irq(&bitmap->counts.lock); + md_bitmap_file_unmap(&bitmap->storage); + bitmap->storage = store; +@@ -2331,7 +2332,7 @@ int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks, + set_page_attr(bitmap, i, BITMAP_PAGE_DIRTY); + } + spin_unlock_irq(&bitmap->counts.lock); +- ++ mutex_unlock(&bitmap->mddev->bitmap_info.mutex); + if (!init) { + md_bitmap_unplug(bitmap); + bitmap->mddev->pers->quiesce(bitmap->mddev, 0); +diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c +index 6a89f6b5d64f98..54f90afbafe967 100644 +--- a/drivers/md/md-cluster.c ++++ b/drivers/md/md-cluster.c +@@ -532,8 +532,13 @@ static void process_metadata_update(struct mddev *mddev, struct cluster_msg *msg + + dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR); + +- /* daemaon thread must exist */ + thread = rcu_dereference_protected(mddev->thread, true); ++ if (!thread) { ++ pr_warn("md-cluster: Received metadata update but MD thread is not ready\n"); ++ dlm_unlock_sync(cinfo->no_new_dev_lockres); ++ return; ++ } ++ + wait_event(thread->wqueue, + (got_lock = mddev_trylock(mddev)) || + test_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state)); +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index a75d090a7fa15a..8546ef98bfa7ed 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -3533,7 +3533,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, + !test_bit(In_sync, &rdev->flags)) + continue; + /* This is where we read from */ +- any_working = 1; + sector = r10_bio->devs[j].addr; + + if (is_badblock(rdev, sector, max_sync, +@@ -3548,6 +3547,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, + continue; + } + } ++ any_working = 1; + bio = r10_bio->devs[0].bio; + bio->bi_next = biolist; + biolist = bio; +diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c +index 9ce5f010de3f84..804fb339f73551 100644 +--- a/drivers/media/dvb-core/dmxdev.c ++++ b/drivers/media/dvb-core/dmxdev.c +@@ -396,11 +396,11 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, + if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) { + ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, + buffer1, buffer1_len, +- buffer_flags); ++ buffer_flags, true); + if (ret == buffer1_len) + ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, + buffer2, buffer2_len, +- buffer_flags); ++ buffer_flags, true); + } else { + ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, + buffer1, buffer1_len); +@@ -451,10 +451,10 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, + + if (dvb_vb2_is_streaming(ctx)) { + ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len, +- buffer_flags); ++ buffer_flags, false); + if (ret == buffer1_len) + ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len, +- buffer_flags); ++ buffer_flags, false); + } else { + if (buffer->error) { + spin_unlock(&dmxdevfilter->dev->lock); +diff --git a/drivers/media/dvb-core/dvb_vb2.c b/drivers/media/dvb-core/dvb_vb2.c +index 909df82fed3329..8950e608a87a41 100644 +--- a/drivers/media/dvb-core/dvb_vb2.c ++++ b/drivers/media/dvb-core/dvb_vb2.c +@@ -252,7 +252,8 @@ int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx) + + int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, + const unsigned char *src, int len, +- enum dmx_buffer_flags *buffer_flags) ++ enum dmx_buffer_flags *buffer_flags, ++ bool flush) + { + unsigned long flags = 0; + void *vbuf = NULL; +@@ -309,7 +310,7 @@ int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, + } + } + +- if (ctx->nonblocking && ctx->buf) { ++ if (flush && ctx->buf) { + vb2_set_plane_payload(&ctx->buf->vb, 0, ll); + vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_DONE); + list_del(&ctx->buf->list); +diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c +index ecb0e7b1f2a5fc..4778ae653ca9dd 100644 +--- a/drivers/media/i2c/adv7180.c ++++ b/drivers/media/i2c/adv7180.c +@@ -471,6 +471,13 @@ static int adv7180_g_frame_interval(struct v4l2_subdev *sd, + fi->interval.denominator = 25; + } + ++ /* ++ * If the de-interlacer is active, the chip produces full video frames ++ * at the field rate. ++ */ ++ if (state->field == V4L2_FIELD_NONE) ++ fi->interval.denominator *= 2; ++ + return 0; + } + +diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c +index 4d31b2bb8f09f6..ae8309bd5e4d52 100644 +--- a/drivers/media/i2c/ccs/ccs-core.c ++++ b/drivers/media/i2c/ccs/ccs-core.c +@@ -2386,7 +2386,7 @@ static void ccs_set_compose_scaler(struct v4l2_subdev *subdev, + * CCS_LIM(sensor, SCALER_N_MIN) / sel->r.height; + max_m = crops[CCS_PAD_SINK]->width + * CCS_LIM(sensor, SCALER_N_MIN) +- / CCS_LIM(sensor, MIN_X_OUTPUT_SIZE); ++ / (CCS_LIM(sensor, MIN_X_OUTPUT_SIZE) ?: 1); + + a = clamp(a, CCS_LIM(sensor, SCALER_M_MIN), + CCS_LIM(sensor, SCALER_M_MAX)); +@@ -3530,7 +3530,21 @@ static int ccs_probe(struct i2c_client *client) + sensor->scale_m = CCS_LIM(sensor, SCALER_N_MIN); + + /* prepare PLL configuration input values */ +- sensor->pll.bus_type = CCS_PLL_BUS_TYPE_CSI2_DPHY; ++ switch (sensor->hwcfg.csi_signalling_mode) { ++ case CCS_CSI_SIGNALING_MODE_CSI_2_CPHY: ++ sensor->pll.bus_type = CCS_PLL_BUS_TYPE_CSI2_CPHY; ++ break; ++ case CCS_CSI_SIGNALING_MODE_CSI_2_DPHY: ++ case SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_CLOCK: ++ case SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_STROBE: ++ sensor->pll.bus_type = CCS_PLL_BUS_TYPE_CSI2_DPHY; ++ break; ++ default: ++ dev_err(&client->dev, "unsupported signalling mode %u\n", ++ sensor->hwcfg.csi_signalling_mode); ++ rval = -EINVAL; ++ goto out_cleanup; ++ } + sensor->pll.csi2.lanes = sensor->hwcfg.lanes; + if (CCS_LIM(sensor, CLOCK_CALCULATION) & + CCS_CLOCK_CALCULATION_LANE_SPEED) { +diff --git a/drivers/media/i2c/ov01a10.c b/drivers/media/i2c/ov01a10.c +index 9afe9bf50334a9..a0e8b1ed0fc93f 100644 +--- a/drivers/media/i2c/ov01a10.c ++++ b/drivers/media/i2c/ov01a10.c +@@ -17,7 +17,7 @@ + #include + + #define OV01A10_LINK_FREQ_400MHZ 400000000ULL +-#define OV01A10_SCLK 40000000LL ++#define OV01A10_SCLK 80000000LL + #define OV01A10_DATA_LANES 1 + + #define OV01A10_REG_CHIP_ID 0x300a +@@ -49,7 +49,7 @@ + /* analog gain controls */ + #define OV01A10_REG_ANALOG_GAIN 0x3508 + #define OV01A10_ANAL_GAIN_MIN 0x100 +-#define OV01A10_ANAL_GAIN_MAX 0xffff ++#define OV01A10_ANAL_GAIN_MAX 0x3fff + #define OV01A10_ANAL_GAIN_STEP 1 + + /* digital gain controls */ +@@ -58,7 +58,7 @@ + #define OV01A10_REG_DIGITAL_GAIN_GR 0x3513 + #define OV01A10_REG_DIGITAL_GAIN_R 0x3516 + #define OV01A10_DGTL_GAIN_MIN 0 +-#define OV01A10_DGTL_GAIN_MAX 0x3ffff ++#define OV01A10_DGTL_GAIN_MAX 0x3fff + #define OV01A10_DGTL_GAIN_STEP 1 + #define OV01A10_DGTL_GAIN_DEFAULT 1024 + +@@ -76,6 +76,15 @@ + #define OV01A10_REG_X_WIN 0x3811 + #define OV01A10_REG_Y_WIN 0x3813 + ++/* ++ * The native ov01a10 bayer-pattern is GBRG, but there was a driver bug enabling ++ * hflip/mirroring by default resulting in BGGR. Because of this bug Intel's ++ * proprietary IPU6 userspace stack expects BGGR. So we report BGGR to not break ++ * userspace and fix things up by shifting the crop window-x coordinate by 1 ++ * when hflip is *disabled*. ++ */ ++#define OV01A10_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR10_1X10 ++ + struct ov01a10_reg { + u16 address; + u8 val; +@@ -186,14 +195,14 @@ static const struct ov01a10_reg sensor_1280x800_setting[] = { + {0x380e, 0x03}, + {0x380f, 0x80}, + {0x3810, 0x00}, +- {0x3811, 0x08}, ++ {0x3811, 0x09}, + {0x3812, 0x00}, + {0x3813, 0x08}, + {0x3814, 0x01}, + {0x3815, 0x01}, + {0x3816, 0x01}, + {0x3817, 0x01}, +- {0x3820, 0xa0}, ++ {0x3820, 0xa8}, + {0x3822, 0x13}, + {0x3832, 0x28}, + {0x3833, 0x10}, +@@ -241,9 +250,8 @@ static const struct ov01a10_reg sensor_1280x800_setting[] = { + static const char * const ov01a10_test_pattern_menu[] = { + "Disabled", + "Color Bar", +- "Top-Bottom Darker Color Bar", +- "Right-Left Darker Color Bar", +- "Color Bar type 4", ++ "Left-Right Darker Color Bar", ++ "Bottom-Top Darker Color Bar", + }; + + static const s64 link_freq_menu_items[] = { +@@ -401,10 +409,8 @@ static int ov01a10_update_digital_gain(struct ov01a10 *ov01a10, u32 d_gain) + + static int ov01a10_test_pattern(struct ov01a10 *ov01a10, u32 pattern) + { +- if (!pattern) +- return 0; +- +- pattern = (pattern - 1) | OV01A10_TEST_PATTERN_ENABLE; ++ if (pattern) ++ pattern |= OV01A10_TEST_PATTERN_ENABLE; + + return ov01a10_write_reg(ov01a10, OV01A10_REG_TEST_PATTERN, 1, pattern); + } +@@ -415,7 +421,7 @@ static int ov01a10_set_hflip(struct ov01a10 *ov01a10, u32 hflip) + int ret; + u32 val, offset; + +- offset = hflip ? 0x9 : 0x8; ++ offset = hflip ? 0x8 : 0x9; + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_X_WIN, 1, offset); + if (ret) + return ret; +@@ -424,8 +430,8 @@ static int ov01a10_set_hflip(struct ov01a10 *ov01a10, u32 hflip) + if (ret) + return ret; + +- val = hflip ? val | FIELD_PREP(OV01A10_HFLIP_MASK, 0x1) : +- val & ~OV01A10_HFLIP_MASK; ++ val = hflip ? val & ~OV01A10_HFLIP_MASK : ++ val | FIELD_PREP(OV01A10_HFLIP_MASK, 0x1); + + return ov01a10_write_reg(ov01a10, OV01A10_REG_FORMAT1, 1, val); + } +@@ -614,7 +620,7 @@ static void ov01a10_update_pad_format(const struct ov01a10_mode *mode, + { + fmt->width = mode->width; + fmt->height = mode->height; +- fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10; ++ fmt->code = OV01A10_MEDIA_BUS_FMT; + fmt->field = V4L2_FIELD_NONE; + fmt->colorspace = V4L2_COLORSPACE_RAW; + } +@@ -800,7 +806,7 @@ static int ov01a10_enum_mbus_code(struct v4l2_subdev *sd, + if (code->index > 0) + return -EINVAL; + +- code->code = MEDIA_BUS_FMT_SBGGR10_1X10; ++ code->code = OV01A10_MEDIA_BUS_FMT; + + return 0; + } +@@ -810,7 +816,7 @@ static int ov01a10_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_size_enum *fse) + { + if (fse->index >= ARRAY_SIZE(supported_modes) || +- fse->code != MEDIA_BUS_FMT_SBGGR10_1X10) ++ fse->code != OV01A10_MEDIA_BUS_FMT) + return -EINVAL; + + fse->min_width = supported_modes[fse->index].width; +@@ -903,6 +909,7 @@ static void ov01a10_remove(struct i2c_client *client) + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_async_unregister_subdev(sd); ++ v4l2_subdev_cleanup(sd); + media_entity_cleanup(&sd->entity); + v4l2_ctrl_handler_free(sd->ctrl_handler); + +@@ -973,6 +980,7 @@ static int ov01a10_probe(struct i2c_client *client) + err_pm_disable: + pm_runtime_disable(dev); + pm_runtime_set_suspended(&client->dev); ++ v4l2_subdev_cleanup(&ov01a10->sd); + + err_media_entity_cleanup: + media_entity_cleanup(&ov01a10->sd.entity); +diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c +index 8de398423b7cb9..b8033fb7aa30e8 100644 +--- a/drivers/media/i2c/ov5647.c ++++ b/drivers/media/i2c/ov5647.c +@@ -69,11 +69,11 @@ + #define OV5647_NATIVE_HEIGHT 1956U + + #define OV5647_PIXEL_ARRAY_LEFT 16U +-#define OV5647_PIXEL_ARRAY_TOP 16U ++#define OV5647_PIXEL_ARRAY_TOP 6U + #define OV5647_PIXEL_ARRAY_WIDTH 2592U + #define OV5647_PIXEL_ARRAY_HEIGHT 1944U + +-#define OV5647_VBLANK_MIN 4 ++#define OV5647_VBLANK_MIN 24 + #define OV5647_VTS_MAX 32767 + + #define OV5647_EXPOSURE_MIN 4 +@@ -509,7 +509,7 @@ static const struct ov5647_mode ov5647_modes[] = { + { + .format = { + .code = MEDIA_BUS_FMT_SBGGR10_1X10, +- .colorspace = V4L2_COLORSPACE_SRGB, ++ .colorspace = V4L2_COLORSPACE_RAW, + .field = V4L2_FIELD_NONE, + .width = 2592, + .height = 1944 +@@ -530,7 +530,7 @@ static const struct ov5647_mode ov5647_modes[] = { + { + .format = { + .code = MEDIA_BUS_FMT_SBGGR10_1X10, +- .colorspace = V4L2_COLORSPACE_SRGB, ++ .colorspace = V4L2_COLORSPACE_RAW, + .field = V4L2_FIELD_NONE, + .width = 1920, + .height = 1080 +@@ -551,7 +551,7 @@ static const struct ov5647_mode ov5647_modes[] = { + { + .format = { + .code = MEDIA_BUS_FMT_SBGGR10_1X10, +- .colorspace = V4L2_COLORSPACE_SRGB, ++ .colorspace = V4L2_COLORSPACE_RAW, + .field = V4L2_FIELD_NONE, + .width = 1296, + .height = 972 +@@ -572,7 +572,7 @@ static const struct ov5647_mode ov5647_modes[] = { + { + .format = { + .code = MEDIA_BUS_FMT_SBGGR10_1X10, +- .colorspace = V4L2_COLORSPACE_SRGB, ++ .colorspace = V4L2_COLORSPACE_RAW, + .field = V4L2_FIELD_NONE, + .width = 640, + .height = 480 +@@ -583,7 +583,7 @@ static const struct ov5647_mode ov5647_modes[] = { + .width = 2560, + .height = 1920, + }, +- .pixel_rate = 55000000, ++ .pixel_rate = 58333000, + .hts = 1852, + .vts = 0x1f8, + .reg_list = ov5647_640x480_10bpp, +@@ -1297,6 +1297,8 @@ static int ov5647_init_controls(struct ov5647 *sensor) + + v4l2_ctrl_handler_init(&sensor->ctrls, 9); + ++ sensor->ctrls.lock = &sensor->lock; ++ + v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops, + V4L2_CID_AUTOGAIN, 0, 1, 1, 0); + +@@ -1430,15 +1432,15 @@ static int ov5647_probe(struct i2c_client *client) + + sensor->mode = OV5647_DEFAULT_MODE; + +- ret = ov5647_init_controls(sensor); +- if (ret) +- goto mutex_destroy; +- + sd = &sensor->sd; + v4l2_i2c_subdev_init(sd, client, &ov5647_subdev_ops); + sd->internal_ops = &ov5647_subdev_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; + ++ ret = ov5647_init_controls(sensor); ++ if (ret) ++ goto mutex_destroy; ++ + sensor->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&sd->entity, 1, &sensor->pad); +diff --git a/drivers/media/i2c/tw9903.c b/drivers/media/i2c/tw9903.c +index 996be3960af3f8..d17f3b9270ef1e 100644 +--- a/drivers/media/i2c/tw9903.c ++++ b/drivers/media/i2c/tw9903.c +@@ -228,6 +228,7 @@ static int tw9903_probe(struct i2c_client *client) + + if (write_regs(sd, initial_registers) < 0) { + v4l2_err(client, "error initializing TW9903\n"); ++ v4l2_ctrl_handler_free(hdl); + return -EINVAL; + } + +diff --git a/drivers/media/i2c/tw9906.c b/drivers/media/i2c/tw9906.c +index 25c625f6d6e488..13cd1b25ef601a 100644 +--- a/drivers/media/i2c/tw9906.c ++++ b/drivers/media/i2c/tw9906.c +@@ -196,6 +196,7 @@ static int tw9906_probe(struct i2c_client *client) + + if (write_regs(sd, initial_registers) < 0) { + v4l2_err(client, "error initializing TW9906\n"); ++ v4l2_ctrl_handler_free(hdl); + return -EINVAL; + } + +diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c +index 25dc8d4dc5b73a..717fc6c9ef21f8 100644 +--- a/drivers/media/pci/cx23885/cx23885-alsa.c ++++ b/drivers/media/pci/cx23885/cx23885-alsa.c +@@ -392,8 +392,10 @@ static int snd_cx23885_hw_params(struct snd_pcm_substream *substream, + + ret = cx23885_risc_databuffer(chip->pci, &buf->risc, buf->sglist, + chip->period_size, chip->num_periods, 1); +- if (ret < 0) ++ if (ret < 0) { ++ cx23885_alsa_dma_unmap(chip); + goto error; ++ } + + /* Loop back to start of program */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC); +diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c +index a42f0c03a7ca86..f463365163b7ec 100644 +--- a/drivers/media/pci/cx25821/cx25821-alsa.c ++++ b/drivers/media/pci/cx25821/cx25821-alsa.c +@@ -535,6 +535,7 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, + chip->period_size, chip->num_periods, 1); + if (ret < 0) { + pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n"); ++ cx25821_alsa_dma_unmap(chip); + goto error; + } + +diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c +index 6627fa9166d301..a7336be444748a 100644 +--- a/drivers/media/pci/cx25821/cx25821-core.c ++++ b/drivers/media/pci/cx25821/cx25821-core.c +@@ -908,6 +908,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) + + if (!dev->lmmio) { + CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n"); ++ release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0)); + cx25821_iounmap(dev); + return -ENOMEM; + } +diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c +index 29fb1311e44349..4e574d8390b4d7 100644 +--- a/drivers/media/pci/cx88/cx88-alsa.c ++++ b/drivers/media/pci/cx88/cx88-alsa.c +@@ -483,8 +483,10 @@ static int snd_cx88_hw_params(struct snd_pcm_substream *substream, + + ret = cx88_risc_databuffer(chip->pci, &buf->risc, buf->sglist, + chip->period_size, chip->num_periods, 1); +- if (ret < 0) ++ if (ret < 0) { ++ cx88_alsa_dma_unmap(chip); + goto error; ++ } + + /* Loop back to start of program */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); +diff --git a/drivers/media/pci/solo6x10/solo6x10-tw28.c b/drivers/media/pci/solo6x10/solo6x10-tw28.c +index 1b7c22a9bc94f1..8f53946c67928f 100644 +--- a/drivers/media/pci/solo6x10/solo6x10-tw28.c ++++ b/drivers/media/pci/solo6x10/solo6x10-tw28.c +@@ -166,7 +166,7 @@ static const u8 tbl_tw2865_pal_template[] = { + 0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0, + }; + +-#define is_tw286x(__solo, __id) (!(__solo->tw2815 & (1 << __id))) ++#define is_tw286x(__solo, __id) (!((__solo)->tw2815 & (1U << (__id)))) + + static u8 tw_readbyte(struct solo_dev *solo_dev, int chip_id, u8 tw6x_off, + u8 tw_off) +@@ -686,6 +686,9 @@ int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, + chip_num = ch / 4; + ch %= 4; + ++ if (chip_num >= TW_NUM_CHIP) ++ return -EINVAL; ++ + if (val > 255 || val < 0) + return -ERANGE; + +@@ -758,6 +761,9 @@ int tw28_get_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, + chip_num = ch / 4; + ch %= 4; + ++ if (chip_num >= TW_NUM_CHIP) ++ return -EINVAL; ++ + switch (ctrl) { + case V4L2_CID_SHARPNESS: + /* Only 286x has sharpness */ +diff --git a/drivers/media/platform/amphion/vdec.c b/drivers/media/platform/amphion/vdec.c +index 4f438eaa7d385a..d7e477f0eb4300 100644 +--- a/drivers/media/platform/amphion/vdec.c ++++ b/drivers/media/platform/amphion/vdec.c +@@ -630,6 +630,7 @@ static int vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd + switch (cmd->cmd) { + case V4L2_DEC_CMD_START: + vdec_cmd_start(inst); ++ vb2_clear_last_buffer_dequeued(v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx)); + break; + case V4L2_DEC_CMD_STOP: + vdec_cmd_stop(inst); +diff --git a/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c b/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c +index 917cdf38f230e7..98540015b1cca6 100644 +--- a/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c ++++ b/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c +@@ -194,11 +194,17 @@ static int mtk_mdp_probe(struct platform_device *pdev) + } + + mdp->vpu_dev = vpu_get_plat_device(pdev); ++ if (!mdp->vpu_dev) { ++ dev_err(&pdev->dev, "Failed to get vpu device\n"); ++ ret = -ENODEV; ++ goto err_vpu_get_dev; ++ } ++ + ret = vpu_wdt_reg_handler(mdp->vpu_dev, mtk_mdp_reset_handler, mdp, + VPU_RST_MDP); + if (ret) { + dev_err(&pdev->dev, "Failed to register reset handler\n"); +- goto err_m2m_register; ++ goto err_reg_handler; + } + + platform_set_drvdata(pdev, mdp); +@@ -206,7 +212,7 @@ static int mtk_mdp_probe(struct platform_device *pdev) + ret = vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(&pdev->dev, "Failed to set vb2 dma mag seg size\n"); +- goto err_m2m_register; ++ goto err_reg_handler; + } + + pm_runtime_enable(dev); +@@ -214,6 +220,12 @@ static int mtk_mdp_probe(struct platform_device *pdev) + + return 0; + ++err_reg_handler: ++ platform_device_put(mdp->vpu_dev); ++ ++err_vpu_get_dev: ++ mtk_mdp_unregister_m2m_device(mdp); ++ + err_m2m_register: + v4l2_device_unregister(&mdp->v4l2_dev); + +@@ -242,6 +254,7 @@ static void mtk_mdp_remove(struct platform_device *pdev) + + pm_runtime_disable(&pdev->dev); + vb2_dma_contig_clear_max_seg_size(&pdev->dev); ++ platform_device_put(mdp->vpu_dev); + mtk_mdp_unregister_m2m_device(mdp); + v4l2_device_unregister(&mdp->v4l2_dev); + +diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c +index e29c9c58f3dac9..fb629a7cd81271 100644 +--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c ++++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c +@@ -475,6 +475,12 @@ static int mtk_vdec_s_ctrl(struct v4l2_ctrl *ctrl) + mtk_v4l2_vdec_err(ctx, "VP9: bit_depth:%d", frame->bit_depth); + return -EINVAL; + } ++ ++ if (!(frame->flags & V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING) || ++ !(frame->flags & V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING)) { ++ mtk_v4l2_vdec_err(ctx, "VP9: only 420 subsampling is supported"); ++ return -EINVAL; ++ } + break; + case V4L2_CID_STATELESS_AV1_SEQUENCE: + seq = (struct v4l2_ctrl_av1_sequence *)hdr_ctrl->p_new.p; +diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c +index eb381fa6e7d14e..ca9d859376d3ea 100644 +--- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c ++++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c +@@ -865,7 +865,7 @@ static void vb2ops_venc_buf_queue(struct vb2_buffer *vb) + static int vb2ops_venc_start_streaming(struct vb2_queue *q, unsigned int count) + { + struct mtk_vcodec_enc_ctx *ctx = vb2_get_drv_priv(q); +- struct venc_enc_param param; ++ struct venc_enc_param param = { }; + int ret; + int i; + +@@ -1021,7 +1021,7 @@ static int mtk_venc_encode_header(void *priv) + int ret; + struct vb2_v4l2_buffer *src_buf, *dst_buf; + struct mtk_vcodec_mem bs_buf; +- struct venc_done_result enc_result; ++ struct venc_done_result enc_result = { }; + + dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); + if (!dst_buf) { +@@ -1142,7 +1142,7 @@ static void mtk_venc_worker(struct work_struct *work) + struct vb2_v4l2_buffer *src_buf, *dst_buf; + struct venc_frm_buf frm_buf; + struct mtk_vcodec_mem bs_buf; +- struct venc_done_result enc_result; ++ struct venc_done_result enc_result = { }; + int ret, i; + + /* check dst_buf, dst_buf may be removed in device_run +diff --git a/drivers/media/platform/qcom/camss/camss-vfe-480.c b/drivers/media/platform/qcom/camss/camss-vfe-480.c +index 8ddb8016434ae9..98d7398db95687 100644 +--- a/drivers/media/platform/qcom/camss/camss-vfe-480.c ++++ b/drivers/media/platform/qcom/camss/camss-vfe-480.c +@@ -223,11 +223,13 @@ static irqreturn_t vfe_isr(int irq, void *dev) + writel_relaxed(status, vfe->base + VFE_BUS_IRQ_CLEAR(0)); + writel_relaxed(1, vfe->base + VFE_BUS_IRQ_CLEAR_GLOBAL); + +- /* Loop through all WMs IRQs */ +- for (i = 0; i < MSM_VFE_IMAGE_MASTERS_NUM; i++) { ++ for (i = 0; i < MAX_VFE_OUTPUT_LINES; i++) { + if (status & BUS_IRQ_MASK_0_RDI_RUP(vfe, i)) + vfe_isr_reg_update(vfe, i); ++ } + ++ /* Loop through all WMs IRQs */ ++ for (i = 0; i < MSM_VFE_IMAGE_MASTERS_NUM; i++) { + if (status & BUS_IRQ_MASK_0_COMP_DONE(vfe, RDI_COMP_GROUP(i))) + vfe_isr_wm_done(vfe, i); + } +diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c +index 8be056210f1d34..f15c3b322fe4aa 100644 +--- a/drivers/media/platform/qcom/venus/vdec.c ++++ b/drivers/media/platform/qcom/venus/vdec.c +@@ -568,7 +568,13 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) + + fdata.buffer_type = HFI_BUFFER_INPUT; + fdata.flags |= HFI_BUFFERFLAG_EOS; +- if (IS_V6(inst->core) && is_fw_rev_or_older(inst->core, 1, 0, 87)) ++ ++ /* Send NULL EOS addr for only IRIS2 (SM8250),for firmware <= 1.0.87. ++ * SC7280 also reports "1.0." parsed as 1.0.0; restricting to IRIS2 ++ * avoids misapplying this quirk and breaking VP9 decode on SC7280. ++ */ ++ ++ if (IS_IRIS2(inst->core) && is_fw_rev_or_older(inst->core, 1, 0, 87)) + fdata.device_addr = 0; + else + fdata.device_addr = 0xdeadb000; +@@ -1433,10 +1439,10 @@ static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type, + inst->drain_active = false; + inst->codec_state = VENUS_DEC_STATE_STOPPED; + } ++ } else { ++ if (!bytesused) ++ state = VB2_BUF_STATE_ERROR; + } +- +- if (!bytesused) +- state = VB2_BUF_STATE_ERROR; + } else { + vbuf->sequence = inst->sequence_out++; + } +diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c +index 3482f7d707b75d..09c20fb2d92eed 100644 +--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c ++++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c +@@ -385,12 +385,6 @@ static void rkisp1_flt_config(struct rkisp1_params *params, + rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_LUM_WEIGHT, + arg->lum_weight); + +- rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_MODE, +- (arg->mode ? RKISP1_CIF_ISP_FLT_MODE_DNR : 0) | +- RKISP1_CIF_ISP_FLT_CHROMA_V_MODE(arg->chr_v_mode) | +- RKISP1_CIF_ISP_FLT_CHROMA_H_MODE(arg->chr_h_mode) | +- RKISP1_CIF_ISP_FLT_GREEN_STAGE1(arg->grn_stage1)); +- + /* avoid to override the old enable value */ + filt_mode = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_FILT_MODE); + filt_mode &= RKISP1_CIF_ISP_FLT_ENA; +diff --git a/drivers/media/platform/ti/omap3isp/isppreview.c b/drivers/media/platform/ti/omap3isp/isppreview.c +index 53aedec7990da1..32e4348e6837a3 100644 +--- a/drivers/media/platform/ti/omap3isp/isppreview.c ++++ b/drivers/media/platform/ti/omap3isp/isppreview.c +@@ -1744,22 +1744,17 @@ static void preview_try_format(struct isp_prev_device *prev, + + switch (pad) { + case PREV_PAD_SINK: +- /* When reading data from the CCDC, the input size has already +- * been mangled by the CCDC output pad so it can be accepted +- * as-is. +- * +- * When reading data from memory, clamp the requested width and +- * height. The TRM doesn't specify a minimum input height, make ++ /* ++ * Clamp the requested width and height. ++ * The TRM doesn't specify a minimum input height, make + * sure we got enough lines to enable the noise filter and color + * filter array interpolation. + */ +- if (prev->input == PREVIEW_INPUT_MEMORY) { +- fmt->width = clamp_t(u32, fmt->width, PREV_MIN_IN_WIDTH, +- preview_max_out_width(prev)); +- fmt->height = clamp_t(u32, fmt->height, +- PREV_MIN_IN_HEIGHT, +- PREV_MAX_IN_HEIGHT); +- } ++ fmt->width = clamp_t(u32, fmt->width, PREV_MIN_IN_WIDTH, ++ preview_max_out_width(prev)); ++ fmt->height = clamp_t(u32, fmt->height, ++ PREV_MIN_IN_HEIGHT, ++ PREV_MAX_IN_HEIGHT); + + fmt->colorspace = V4L2_COLORSPACE_SRGB; + +diff --git a/drivers/media/platform/ti/omap3isp/ispvideo.c b/drivers/media/platform/ti/omap3isp/ispvideo.c +index daca689dc08254..b9e0b6215fa048 100644 +--- a/drivers/media/platform/ti/omap3isp/ispvideo.c ++++ b/drivers/media/platform/ti/omap3isp/ispvideo.c +@@ -148,12 +148,12 @@ static unsigned int isp_video_mbus_to_pix(const struct isp_video *video, + pix->width = mbus->width; + pix->height = mbus->height; + +- for (i = 0; i < ARRAY_SIZE(formats); ++i) { ++ for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) { + if (formats[i].code == mbus->code) + break; + } + +- if (WARN_ON(i == ARRAY_SIZE(formats))) ++ if (WARN_ON(i == ARRAY_SIZE(formats) - 1)) + return 0; + + min_bpl = pix->width * formats[i].bpp; +@@ -191,7 +191,7 @@ static void isp_video_pix_to_mbus(const struct v4l2_pix_format *pix, + /* Skip the last format in the loop so that it will be selected if no + * match is found. + */ +- for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) { ++ for (i = 0; i < ARRAY_SIZE(formats) - 2; ++i) { + if (formats[i].pixelformat == pix->pixelformat) + break; + } +@@ -1288,6 +1288,7 @@ static const struct v4l2_ioctl_ops isp_video_ioctl_ops = { + static int isp_video_open(struct file *file) + { + struct isp_video *video = video_drvdata(file); ++ struct v4l2_mbus_framefmt fmt; + struct isp_video_fh *handle; + struct vb2_queue *queue; + int ret = 0; +@@ -1329,6 +1330,13 @@ static int isp_video_open(struct file *file) + + memset(&handle->format, 0, sizeof(handle->format)); + handle->format.type = video->type; ++ handle->format.fmt.pix.width = 720; ++ handle->format.fmt.pix.height = 480; ++ handle->format.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; ++ handle->format.fmt.pix.field = V4L2_FIELD_NONE; ++ handle->format.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; ++ isp_video_pix_to_mbus(&handle->format.fmt.pix, &fmt); ++ isp_video_mbus_to_pix(video, &fmt, &handle->format.fmt.pix); + handle->timeperframe.denominator = 1; + + handle->video = video; +diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c +index ff78b31728290d..03b9b78d95e88f 100644 +--- a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c ++++ b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c +@@ -72,6 +72,14 @@ + : AV1_DIV_ROUND_UP_POW2((_value_), (_n_))); \ + }) + ++enum rockchip_av1_tx_mode { ++ ROCKCHIP_AV1_TX_MODE_ONLY_4X4 = 0, ++ ROCKCHIP_AV1_TX_MODE_8X8 = 1, ++ ROCKCHIP_AV1_TX_MODE_16x16 = 2, ++ ROCKCHIP_AV1_TX_MODE_32x32 = 3, ++ ROCKCHIP_AV1_TX_MODE_SELECT = 4, ++}; ++ + struct rockchip_av1_film_grain { + u8 scaling_lut_y[256]; + u8 scaling_lut_cb[256]; +@@ -372,12 +380,12 @@ int rockchip_vpu981_av1_dec_init(struct hantro_ctx *ctx) + return -ENOMEM; + av1_dec->global_model.size = GLOBAL_MODEL_SIZE; + +- av1_dec->tile_info.cpu = dma_alloc_coherent(vpu->dev, AV1_MAX_TILES, ++ av1_dec->tile_info.cpu = dma_alloc_coherent(vpu->dev, AV1_TILE_INFO_SIZE, + &av1_dec->tile_info.dma, + GFP_KERNEL); + if (!av1_dec->tile_info.cpu) + return -ENOMEM; +- av1_dec->tile_info.size = AV1_MAX_TILES; ++ av1_dec->tile_info.size = AV1_TILE_INFO_SIZE; + + av1_dec->film_grain.cpu = dma_alloc_coherent(vpu->dev, + ALIGN(sizeof(struct rockchip_av1_film_grain), 2048), +@@ -1397,8 +1405,16 @@ static void rockchip_vpu981_av1_dec_set_cdef(struct hantro_ctx *ctx) + u16 luma_sec_strength = 0; + u32 chroma_pri_strength = 0; + u16 chroma_sec_strength = 0; ++ bool enable_cdef; + int i; + ++ enable_cdef = !(cdef->bits == 0 && ++ cdef->damping_minus_3 == 0 && ++ cdef->y_pri_strength[0] == 0 && ++ cdef->y_sec_strength[0] == 0 && ++ cdef->uv_pri_strength[0] == 0 && ++ cdef->uv_sec_strength[0] == 0); ++ hantro_reg_write(vpu, &av1_enable_cdef, enable_cdef); + hantro_reg_write(vpu, &av1_cdef_bits, cdef->bits); + hantro_reg_write(vpu, &av1_cdef_damping, cdef->damping_minus_3); + +@@ -1928,11 +1944,26 @@ static void rockchip_vpu981_av1_dec_set_reference_frames(struct hantro_ctx *ctx) + rockchip_vpu981_av1_dec_set_other_frames(ctx); + } + ++static int rockchip_vpu981_av1_get_hardware_tx_mode(enum v4l2_av1_tx_mode tx_mode) ++{ ++ switch (tx_mode) { ++ case V4L2_AV1_TX_MODE_ONLY_4X4: ++ return ROCKCHIP_AV1_TX_MODE_ONLY_4X4; ++ case V4L2_AV1_TX_MODE_LARGEST: ++ return ROCKCHIP_AV1_TX_MODE_32x32; ++ case V4L2_AV1_TX_MODE_SELECT: ++ return ROCKCHIP_AV1_TX_MODE_SELECT; ++ } ++ ++ return ROCKCHIP_AV1_TX_MODE_32x32; ++} ++ + static void rockchip_vpu981_av1_dec_set_parameters(struct hantro_ctx *ctx) + { + struct hantro_dev *vpu = ctx->dev; + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; ++ int tx_mode; + + hantro_reg_write(vpu, &av1_skip_mode, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_SKIP_MODE_PRESENT)); +@@ -1954,8 +1985,6 @@ static void rockchip_vpu981_av1_dec_set_parameters(struct hantro_ctx *ctx) + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_SHOW_FRAME)); + hantro_reg_write(vpu, &av1_switchable_motion_mode, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_IS_MOTION_MODE_SWITCHABLE)); +- hantro_reg_write(vpu, &av1_enable_cdef, +- !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF)); + hantro_reg_write(vpu, &av1_allow_masked_compound, + !!(ctrls->sequence->flags + & V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND)); +@@ -1990,7 +2019,7 @@ static void rockchip_vpu981_av1_dec_set_parameters(struct hantro_ctx *ctx) + !!(ctrls->frame->quantization.flags + & V4L2_AV1_QUANTIZATION_FLAG_DELTA_Q_PRESENT)); + +- hantro_reg_write(vpu, &av1_idr_pic_e, !ctrls->frame->frame_type); ++ hantro_reg_write(vpu, &av1_idr_pic_e, IS_INTRA(ctrls->frame->frame_type)); + hantro_reg_write(vpu, &av1_quant_base_qindex, ctrls->frame->quantization.base_q_idx); + hantro_reg_write(vpu, &av1_bit_depth_y_minus8, ctx->bit_depth - 8); + hantro_reg_write(vpu, &av1_bit_depth_c_minus8, ctx->bit_depth - 8); +@@ -2000,7 +2029,9 @@ static void rockchip_vpu981_av1_dec_set_parameters(struct hantro_ctx *ctx) + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_HIGH_PRECISION_MV)); + hantro_reg_write(vpu, &av1_comp_pred_mode, + (ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_REFERENCE_SELECT) ? 2 : 0); +- hantro_reg_write(vpu, &av1_transform_mode, (ctrls->frame->tx_mode == 1) ? 3 : 4); ++ ++ tx_mode = rockchip_vpu981_av1_get_hardware_tx_mode(ctrls->frame->tx_mode); ++ hantro_reg_write(vpu, &av1_transform_mode, tx_mode); + hantro_reg_write(vpu, &av1_max_cb_size, + (ctrls->sequence->flags + & V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK) ? 7 : 6); +diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c +index a35648316aa8d2..05d3c4b5672113 100644 +--- a/drivers/media/radio/radio-keene.c ++++ b/drivers/media/radio/radio-keene.c +@@ -338,7 +338,6 @@ static int usb_keene_probe(struct usb_interface *intf, + if (hdl->error) { + retval = hdl->error; + +- v4l2_ctrl_handler_free(hdl); + goto err_v4l2; + } + retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev); +@@ -384,6 +383,7 @@ static int usb_keene_probe(struct usb_interface *intf, + err_vdev: + v4l2_device_unregister(&radio->v4l2_dev); + err_v4l2: ++ v4l2_ctrl_handler_free(&radio->hdl); + kfree(radio->buffer); + kfree(radio); + err: +diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +index 2de104736f8741..943d56b10251b0 100644 +--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c ++++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +@@ -3709,6 +3709,11 @@ status); + "Failed to submit read-control URB status=%d", + status); + hdw->ctl_read_pend_flag = 0; ++ if (hdw->ctl_write_pend_flag) { ++ usb_unlink_urb(hdw->ctl_write_urb); ++ while (hdw->ctl_write_pend_flag) ++ wait_for_completion(&hdw->ctl_done); ++ } + goto done; + } + } +diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c +index a9f880eb518ad8..ea7d91b19079e0 100644 +--- a/drivers/media/usb/uvc/uvc_video.c ++++ b/drivers/media/usb/uvc/uvc_video.c +@@ -1819,7 +1819,7 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, + npackets = UVC_MAX_PACKETS; + + /* Retry allocations until one succeed. */ +- for (; npackets > 1; npackets /= 2) { ++ for (; npackets > 0; npackets /= 2) { + stream->urb_size = psize * npackets; + + for (i = 0; i < UVC_URBS; ++i) { +@@ -1844,6 +1844,7 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, + uvc_dbg(stream->dev, VIDEO, + "Failed to allocate URB buffers (%u bytes per packet)\n", + psize); ++ stream->urb_size = 0; + return 0; + } + +diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c +index ac4d987bba2556..cf2923dea84b3d 100644 +--- a/drivers/media/v4l2-core/v4l2-async.c ++++ b/drivers/media/v4l2-core/v4l2-async.c +@@ -339,7 +339,6 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_connection *asc) + { +- struct v4l2_async_notifier *subdev_notifier; + bool registered = false; + int ret; + +@@ -385,6 +384,25 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, + dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n", + dev_name(sd->dev), ret); + ++ return 0; ++ ++err_call_unbind: ++ v4l2_async_nf_call_unbind(notifier, sd, asc); ++ list_del(&asc->asc_subdev_entry); ++ ++err_unregister_subdev: ++ if (registered) ++ v4l2_device_unregister_subdev(sd); ++ ++ return ret; ++} ++ ++static int ++v4l2_async_nf_try_subdev_notifier(struct v4l2_async_notifier *notifier, ++ struct v4l2_subdev *sd) ++{ ++ struct v4l2_async_notifier *subdev_notifier; ++ + /* + * See if the sub-device has a notifier. If not, return here. + */ +@@ -400,16 +418,6 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, + subdev_notifier->parent = notifier; + + return v4l2_async_nf_try_all_subdevs(subdev_notifier); +- +-err_call_unbind: +- v4l2_async_nf_call_unbind(notifier, sd, asc); +- list_del(&asc->asc_subdev_entry); +- +-err_unregister_subdev: +- if (registered) +- v4l2_device_unregister_subdev(sd); +- +- return ret; + } + + /* Test all async sub-devices in a notifier for a match. */ +@@ -441,6 +449,10 @@ again: + if (ret < 0) + return ret; + ++ ret = v4l2_async_nf_try_subdev_notifier(notifier, sd); ++ if (ret < 0) ++ return ret; ++ + /* + * v4l2_async_match_notify() may lead to registering a + * new notifier and thus changing the async subdevs +@@ -823,7 +835,11 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd) + ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, + asc); + if (ret) +- goto err_unbind; ++ goto err_unlock; ++ ++ ret = v4l2_async_nf_try_subdev_notifier(notifier, sd); ++ if (ret) ++ goto err_unbind_one; + + ret = v4l2_async_nf_try_complete(notifier); + if (ret) +@@ -847,9 +863,10 @@ err_unbind: + if (subdev_notifier) + v4l2_async_nf_unbind_all_subdevs(subdev_notifier); + +- if (asc) +- v4l2_async_unbind_subdev_one(notifier, asc); ++err_unbind_one: ++ v4l2_async_unbind_subdev_one(notifier, asc); + ++err_unlock: + mutex_unlock(&list_lock); + + return ret; +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 68d71b4b55bd35..cfb22fb7b238bc 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -335,6 +335,17 @@ config MFD_CS47L92 + help + Support for Cirrus Logic CS42L92, CS47L92 and CS47L93 Smart Codecs + ++config MFD_TN48M_CPLD ++ tristate "Delta Networks TN48M switch CPLD driver" ++ depends on I2C ++ depends on ARCH_MVEBU || COMPILE_TEST ++ select MFD_SIMPLE_MFD_I2C ++ help ++ Select this option to enable support for Delta Networks TN48M switch ++ CPLD. It consists of reset and GPIO drivers. CPLD provides GPIOS-s ++ for the SFP slots as well as power supply related information. ++ SFP support depends on the GPIO driver being selected. ++ + config PMIC_DA903X + bool "Dialog Semiconductor DA9030/DA9034 PMIC Support" + depends on I2C=y +@@ -1137,6 +1148,19 @@ config MFD_QCOM_RPM + Say M here if you want to include support for the Qualcomm RPM as a + module. This will build a module called "qcom_rpm". + ++config MFD_SPACEMIT_P1 ++ tristate "SpacemiT P1 PMIC" ++ depends on ARCH_SPACEMIT || COMPILE_TEST ++ depends on I2C ++ select I2C_K1 ++ select MFD_SIMPLE_MFD_I2C ++ help ++ This option supports the I2C-based SpacemiT P1 PMIC, which ++ contains regulators, a power switch, GPIOs, an RTC, and more. ++ This option is selected when any of the supported sub-devices ++ is configured. The basic functionality is implemented by the ++ simple MFD I2C driver. ++ + config MFD_SPMI_PMIC + tristate "Qualcomm SPMI PMICs" + depends on ARCH_QCOM || COMPILE_TEST +diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c +index 19a0adf8ce3dbc..35f516d934c8b5 100644 +--- a/drivers/mfd/arizona-core.c ++++ b/drivers/mfd/arizona-core.c +@@ -1100,7 +1100,7 @@ int arizona_dev_init(struct arizona *arizona) + } else if (val & 0x01) { + ret = wm5102_clear_write_sequencer(arizona); + if (ret) +- return ret; ++ goto err_reset; + } + break; + default: +diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c +index 80fc5c0cac2fb0..be5f2b34e18aeb 100644 +--- a/drivers/mfd/da9052-spi.c ++++ b/drivers/mfd/da9052-spi.c +@@ -37,7 +37,7 @@ static int da9052_spi_probe(struct spi_device *spi) + spi_set_drvdata(spi, da9052); + + config = da9052_regmap_config; +- config.write_flag_mask = 1; ++ config.read_flag_mask = 1; + config.reg_bits = 7; + config.pad_bits = 1; + config.val_bits = 8; +diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c +index 2b85509a90fc29..2b323d1430f522 100644 +--- a/drivers/mfd/mfd-core.c ++++ b/drivers/mfd/mfd-core.c +@@ -22,6 +22,7 @@ + #include + + static LIST_HEAD(mfd_of_node_list); ++static DEFINE_MUTEX(mfd_of_node_mutex); + + struct mfd_of_node_entry { + struct list_head list; +@@ -105,9 +106,11 @@ static int mfd_match_of_node_to_dev(struct platform_device *pdev, + u64 of_node_addr; + + /* Skip if OF node has previously been allocated to a device */ +- list_for_each_entry(of_entry, &mfd_of_node_list, list) +- if (of_entry->np == np) +- return -EAGAIN; ++ scoped_guard(mutex, &mfd_of_node_mutex) { ++ list_for_each_entry(of_entry, &mfd_of_node_list, list) ++ if (of_entry->np == np) ++ return -EAGAIN; ++ } + + if (!cell->use_of_reg) + /* No of_reg defined - allocate first free compatible match */ +@@ -129,7 +132,8 @@ allocate_of_node: + + of_entry->dev = &pdev->dev; + of_entry->np = np; +- list_add_tail(&of_entry->list, &mfd_of_node_list); ++ scoped_guard(mutex, &mfd_of_node_mutex) ++ list_add_tail(&of_entry->list, &mfd_of_node_list); + + pdev->dev.of_node = np; + pdev->dev.fwnode = &np->fwnode; +@@ -286,11 +290,13 @@ fail_res_conflict: + if (cell->swnode) + device_remove_software_node(&pdev->dev); + fail_of_entry: +- list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list) +- if (of_entry->dev == &pdev->dev) { +- list_del(&of_entry->list); +- kfree(of_entry); +- } ++ scoped_guard(mutex, &mfd_of_node_mutex) { ++ list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list) ++ if (of_entry->dev == &pdev->dev) { ++ list_del(&of_entry->list); ++ kfree(of_entry); ++ } ++ } + fail_alias: + regulator_bulk_unregister_supply_alias(&pdev->dev, + cell->parent_supplies, +@@ -360,11 +366,13 @@ static int mfd_remove_devices_fn(struct device *dev, void *data) + if (cell->swnode) + device_remove_software_node(&pdev->dev); + +- list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list) +- if (of_entry->dev == &pdev->dev) { +- list_del(&of_entry->list); +- kfree(of_entry); +- } ++ scoped_guard(mutex, &mfd_of_node_mutex) { ++ list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list) ++ if (of_entry->dev == &pdev->dev) { ++ list_del(&of_entry->list); ++ kfree(of_entry); ++ } ++ } + + regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies, + cell->num_parent_supplies); +diff --git a/drivers/mfd/simple-mfd-i2c.c b/drivers/mfd/simple-mfd-i2c.c +index 6eda79533208a3..908eae338fee00 100644 +--- a/drivers/mfd/simple-mfd-i2c.c ++++ b/drivers/mfd/simple-mfd-i2c.c +@@ -83,11 +83,42 @@ static const struct simple_mfd_data maxim_max5970 = { + .mfd_cell_size = ARRAY_SIZE(max5970_cells), + }; + ++static const struct mfd_cell max77705_sensor_cells[] = { ++ { .name = "max77705-battery" }, ++ { .name = "max77705-hwmon", }, ++}; ++ ++static const struct simple_mfd_data maxim_mon_max77705 = { ++ .mfd_cell = max77705_sensor_cells, ++ .mfd_cell_size = ARRAY_SIZE(max77705_sensor_cells), ++}; ++ ++static const struct regmap_config spacemit_p1_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++}; ++ ++static const struct mfd_cell spacemit_p1_cells[] = { ++ { .name = "spacemit-p1-regulator", }, ++ { .name = "spacemit-p1-rtc", }, ++}; ++ ++static const struct simple_mfd_data spacemit_p1 = { ++ .regmap_config = &spacemit_p1_regmap_config, ++ .mfd_cell = spacemit_p1_cells, ++ .mfd_cell_size = ARRAY_SIZE(spacemit_p1_cells), ++}; ++ + static const struct of_device_id simple_mfd_i2c_of_match[] = { ++ { .compatible = "delta,tn48m-cpld" }, ++ { .compatible = "fsl,ls1028aqds-fpga" }, ++ { .compatible = "fsl,lx2160aqds-fpga" }, + { .compatible = "kontron,sl28cpld" }, +- { .compatible = "silergy,sy7636a", .data = &silergy_sy7636a}, + { .compatible = "maxim,max5970", .data = &maxim_max5970}, + { .compatible = "maxim,max5978", .data = &maxim_max5970}, ++ { .compatible = "maxim,max77705-battery", .data = &maxim_mon_max77705}, ++ { .compatible = "silergy,sy7636a", .data = &silergy_sy7636a}, ++ { .compatible = "spacemit,p1", .data = &spacemit_p1, }, + {} + }; + MODULE_DEVICE_TABLE(of, simple_mfd_i2c_of_match); +diff --git a/drivers/misc/bcm-vk/bcm_vk_msg.c b/drivers/misc/bcm-vk/bcm_vk_msg.c +index e17d81231ea6da..54e25e9bc51b13 100644 +--- a/drivers/misc/bcm-vk/bcm_vk_msg.c ++++ b/drivers/misc/bcm-vk/bcm_vk_msg.c +@@ -1010,6 +1010,9 @@ ssize_t bcm_vk_read(struct file *p_file, + struct device *dev = &vk->pdev->dev; + struct bcm_vk_msg_chan *chan = &vk->to_h_msg_chan; + struct bcm_vk_wkent *entry = NULL, *iter; ++ struct vk_msg_blk tmp_msg; ++ u32 tmp_usr_msg_id; ++ u32 tmp_blks; + u32 q_num; + u32 rsp_length; + +@@ -1034,6 +1037,9 @@ ssize_t bcm_vk_read(struct file *p_file, + entry = iter; + } else { + /* buffer not big enough */ ++ tmp_msg = iter->to_h_msg[0]; ++ tmp_usr_msg_id = iter->usr_msg_id; ++ tmp_blks = iter->to_h_blks; + rc = -EMSGSIZE; + } + goto read_loop_exit; +@@ -1052,14 +1058,12 @@ read_loop_exit: + + bcm_vk_free_wkent(dev, entry); + } else if (rc == -EMSGSIZE) { +- struct vk_msg_blk tmp_msg = entry->to_h_msg[0]; +- + /* + * in this case, return just the first block, so + * that app knows what size it is looking for. + */ +- set_msg_id(&tmp_msg, entry->usr_msg_id); +- tmp_msg.size = entry->to_h_blks - 1; ++ set_msg_id(&tmp_msg, tmp_usr_msg_id); ++ tmp_msg.size = tmp_blks - 1; + if (copy_to_user(buf, &tmp_msg, VK_MSGQ_BLK_SIZE) != 0) { + dev_err(dev, "Error return 1st block in -EMSGSIZE\n"); + rc = -EFAULT; +diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c +index b630625b3024ba..b510d0b5ddfa7b 100644 +--- a/drivers/misc/eeprom/eeprom_93xx46.c ++++ b/drivers/misc/eeprom/eeprom_93xx46.c +@@ -23,6 +23,7 @@ + #define OP_START 0x4 + #define OP_WRITE (OP_START | 0x1) + #define OP_READ (OP_START | 0x2) ++/* The following addresses are offset for the 1K EEPROM variant in 16-bit mode */ + #define ADDR_EWDS 0x00 + #define ADDR_ERAL 0x20 + #define ADDR_EWEN 0x30 +@@ -173,10 +174,7 @@ static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on) + bits = edev->addrlen + 3; + + cmd_addr = OP_START << edev->addrlen; +- if (edev->pdata->flags & EE_ADDR8) +- cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS) << 1; +- else +- cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS); ++ cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS) << (edev->addrlen - 6); + + if (has_quirk_instruction_length(edev)) { + cmd_addr <<= 2; +@@ -320,10 +318,7 @@ static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev) + bits = edev->addrlen + 3; + + cmd_addr = OP_START << edev->addrlen; +- if (edev->pdata->flags & EE_ADDR8) +- cmd_addr |= ADDR_ERAL << 1; +- else +- cmd_addr |= ADDR_ERAL; ++ cmd_addr |= ADDR_ERAL << (edev->addrlen - 6); + + if (has_quirk_instruction_length(edev)) { + cmd_addr <<= 2; +diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c +index 202b4fc064fa39..0831feb58e13db 100644 +--- a/drivers/mtd/nand/raw/cadence-nand-controller.c ++++ b/drivers/mtd/nand/raw/cadence-nand-controller.c +@@ -1018,7 +1018,7 @@ static int cadence_nand_cdma_send(struct cdns_nand_ctrl *cdns_ctrl, + } + + /* Send SDMA command and wait for finish. */ +-static u32 ++static int + cadence_nand_cdma_send_and_wait(struct cdns_nand_ctrl *cdns_ctrl, + u8 thread) + { +diff --git a/drivers/mtd/nand/raw/pl35x-nand-controller.c b/drivers/mtd/nand/raw/pl35x-nand-controller.c +index c506e92a3e457d..eaaaf3319bf863 100644 +--- a/drivers/mtd/nand/raw/pl35x-nand-controller.c ++++ b/drivers/mtd/nand/raw/pl35x-nand-controller.c +@@ -976,6 +976,7 @@ static int pl35x_nand_attach_chip(struct nand_chip *chip) + fallthrough; + case NAND_ECC_ENGINE_TYPE_NONE: + case NAND_ECC_ENGINE_TYPE_SOFT: ++ chip->ecc.write_page_raw = nand_monolithic_write_page_raw; + break; + case NAND_ECC_ENGINE_TYPE_ON_HOST: + ret = pl35x_nand_init_hw_ecc_controller(nfc, chip); +diff --git a/drivers/mtd/parsers/ofpart_core.c b/drivers/mtd/parsers/ofpart_core.c +index e7b8e9d0a91033..3cf75b56d5a2e7 100644 +--- a/drivers/mtd/parsers/ofpart_core.c ++++ b/drivers/mtd/parsers/ofpart_core.c +@@ -77,6 +77,7 @@ static int parse_fixed_partitions(struct mtd_info *master, + of_id = of_match_node(parse_ofpart_match_table, ofpart_node); + if (dedicated && !of_id) { + /* The 'partitions' subnode might be used by another parser */ ++ of_node_put(ofpart_node); + return 0; + } + +@@ -91,12 +92,18 @@ static int parse_fixed_partitions(struct mtd_info *master, + nr_parts++; + } + +- if (nr_parts == 0) ++ if (nr_parts == 0) { ++ if (dedicated) ++ of_node_put(ofpart_node); + return 0; ++ } + + parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); +- if (!parts) ++ if (!parts) { ++ if (dedicated) ++ of_node_put(ofpart_node); + return -ENOMEM; ++ } + + i = 0; + for_each_child_of_node(ofpart_node, pp) { +@@ -175,6 +182,9 @@ static int parse_fixed_partitions(struct mtd_info *master, + if (quirks && quirks->post_parse) + quirks->post_parse(master, parts, nr_parts); + ++ if (dedicated) ++ of_node_put(ofpart_node); ++ + *pparts = parts; + return nr_parts; + +@@ -183,6 +193,8 @@ ofpart_fail: + master->name, pp, mtd_node); + ret = -EINVAL; + ofpart_none: ++ if (dedicated) ++ of_node_put(ofpart_node); + of_node_put(pp); + kfree(parts); + return ret; +diff --git a/drivers/mtd/parsers/tplink_safeloader.c b/drivers/mtd/parsers/tplink_safeloader.c +index 1c689dafca2ae9..3580c79e3277ea 100644 +--- a/drivers/mtd/parsers/tplink_safeloader.c ++++ b/drivers/mtd/parsers/tplink_safeloader.c +@@ -116,6 +116,7 @@ static int mtd_parser_tplink_safeloader_parse(struct mtd_info *mtd, + return idx; + + err_free: ++ kfree(buf); + for (idx -= 1; idx >= 0; idx--) + kfree(parts[idx].name); + err_free_parts: +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 4373e300879d92..836d7fcac71a1d 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -727,26 +727,29 @@ static int bond_update_speed_duplex(struct slave *slave) + struct ethtool_link_ksettings ecmd; + int res; + +- slave->speed = SPEED_UNKNOWN; +- slave->duplex = DUPLEX_UNKNOWN; +- + res = __ethtool_get_link_ksettings(slave_dev, &ecmd); + if (res < 0) +- return 1; ++ goto speed_duplex_unknown; + if (ecmd.base.speed == 0 || ecmd.base.speed == ((__u32)-1)) +- return 1; ++ goto speed_duplex_unknown; + switch (ecmd.base.duplex) { + case DUPLEX_FULL: + case DUPLEX_HALF: + break; + default: +- return 1; ++ goto speed_duplex_unknown; + } + + slave->speed = ecmd.base.speed; + slave->duplex = ecmd.base.duplex; + + return 0; ++ ++speed_duplex_unknown: ++ slave->speed = SPEED_UNKNOWN; ++ slave->duplex = DUPLEX_UNKNOWN; ++ ++ return 1; + } + + const char *bond_slave_link_status(s8 link) +@@ -4398,9 +4401,13 @@ static int bond_close(struct net_device *bond_dev) + + bond_work_cancel_all(bond); + bond->send_peer_notif = 0; ++ WRITE_ONCE(bond->recv_probe, NULL); ++ ++ /* Wait for any in-flight RX handlers */ ++ synchronize_net(); ++ + if (bond_is_lb(bond)) + bond_alb_deinitialize(bond); +- bond->recv_probe = NULL; + + if (bond_uses_primary(bond)) { + rcu_read_lock(); +diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c +index ed3a589def6b1c..699ed0ff461e89 100644 +--- a/drivers/net/caif/caif_serial.c ++++ b/drivers/net/caif/caif_serial.c +@@ -298,6 +298,7 @@ static void ser_release(struct work_struct *work) + { + struct list_head list; + struct ser_device *ser, *tmp; ++ struct tty_struct *tty; + + spin_lock(&ser_lock); + list_replace_init(&ser_release_list, &list); +@@ -306,9 +307,11 @@ static void ser_release(struct work_struct *work) + if (!list_empty(&list)) { + rtnl_lock(); + list_for_each_entry_safe(ser, tmp, &list, node) { ++ tty = ser->tty; + dev_close(ser->dev); + unregister_netdevice(ser->dev); + debugfs_deinit(ser); ++ tty_kref_put(tty); + } + rtnl_unlock(); + } +@@ -369,8 +372,6 @@ static void ldisc_close(struct tty_struct *tty) + { + struct ser_device *ser = tty->disc_data; + +- tty_kref_put(ser->tty); +- + spin_lock(&ser_lock); + list_move(&ser->node, &ser_release_list); + spin_unlock(&ser_lock); +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index 5cbda8ccdbf096..e1df1546a2d6e2 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -756,14 +756,12 @@ static void macb_mac_link_up(struct phylink_config *config, + if (rx_pause) + ctrl |= MACB_BIT(PAE); + +- /* Initialize rings & buffers as clearing MACB_BIT(TE) in link down +- * cleared the pipeline and control registers. +- */ +- macb_init_buffers(bp); +- +- for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) ++ for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { ++ queue->tx_head = 0; ++ queue->tx_tail = 0; + queue_writel(queue, IER, + bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP)); ++ } + } + + macb_or_gem_writel(bp, NCFGR, ctrl); +@@ -2953,6 +2951,7 @@ static int macb_open(struct net_device *dev) + } + + bp->macbgem_ops.mog_init_rings(bp); ++ macb_init_buffers(bp); + + for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { + napi_enable(&queue->napi_rx); +diff --git a/drivers/net/ethernet/ec_bhf.c b/drivers/net/ethernet/ec_bhf.c +index c2c5c589a5e329..6233602d7c5aad 100644 +--- a/drivers/net/ethernet/ec_bhf.c ++++ b/drivers/net/ethernet/ec_bhf.c +@@ -424,7 +424,7 @@ static int ec_bhf_open(struct net_device *net_dev) + + error_rx_free: + dma_free_coherent(dev, priv->rx_buf.alloc_len, priv->rx_buf.alloc, +- priv->rx_buf.alloc_len); ++ priv->rx_buf.alloc_phys); + out: + return err; + } +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +index 37e3224262ed43..2631732ab2164a 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +@@ -2998,6 +2998,13 @@ static int dpaa2_switch_init(struct fsl_mc_device *sw_dev) + goto err_close; + } + ++ if (ethsw->sw_attr.num_ifs >= DPSW_MAX_IF) { ++ dev_err(dev, "DPSW num_ifs %u exceeds max %u\n", ++ ethsw->sw_attr.num_ifs, DPSW_MAX_IF); ++ err = -EINVAL; ++ goto err_close; ++ } ++ + err = dpsw_get_api_version(ethsw->mc_io, 0, + ðsw->major, + ðsw->minor); +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +index 34627de2e311ee..107e692e8c87ae 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +@@ -1048,13 +1048,13 @@ static void hns3_init_tx_spare_buffer(struct hns3_enet_ring *ring) + int order; + + if (!alloc_size) +- return; ++ goto not_init; + + order = get_order(alloc_size); + if (order > MAX_ORDER) { + if (net_ratelimit()) + dev_warn(ring_to_dev(ring), "failed to allocate tx spare buffer, exceed to max order\n"); +- return; ++ goto not_init; + } + + tx_spare = devm_kzalloc(ring_to_dev(ring), sizeof(*tx_spare), +@@ -1092,6 +1092,13 @@ alloc_pages_error: + devm_kfree(ring_to_dev(ring), tx_spare); + devm_kzalloc_error: + ring->tqp->handle->kinfo.tx_spare_buf_size = 0; ++not_init: ++ /* When driver init or reset_init, the ring->tx_spare is always NULL; ++ * but when called from hns3_set_ringparam, it's usually not NULL, and ++ * will be restored if hns3_init_all_ring() failed. So it's safe to set ++ * ring->tx_spare to NULL here. ++ */ ++ ring->tx_spare = NULL; + } + + /* Use hns3_tx_spare_space() to make sure there is enough buffer +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +index 659d6351f26c83..f404a4c10e8f50 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +@@ -727,8 +727,8 @@ struct hclge_fd_tcam_config_3_cmd { + + #define HCLGE_FD_AD_DROP_B 0 + #define HCLGE_FD_AD_DIRECT_QID_B 1 +-#define HCLGE_FD_AD_QID_S 2 +-#define HCLGE_FD_AD_QID_M GENMASK(11, 2) ++#define HCLGE_FD_AD_QID_L_S 2 ++#define HCLGE_FD_AD_QID_L_M GENMASK(11, 2) + #define HCLGE_FD_AD_USE_COUNTER_B 12 + #define HCLGE_FD_AD_COUNTER_NUM_S 13 + #define HCLGE_FD_AD_COUNTER_NUM_M GENMASK(19, 13) +@@ -741,6 +741,7 @@ struct hclge_fd_tcam_config_3_cmd { + #define HCLGE_FD_AD_TC_OVRD_B 16 + #define HCLGE_FD_AD_TC_SIZE_S 17 + #define HCLGE_FD_AD_TC_SIZE_M GENMASK(20, 17) ++#define HCLGE_FD_AD_QID_H_B 21 + + struct hclge_fd_ad_config_cmd { + u8 stage; +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +index 72a5df4e3a3292..04c58928585ca4 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -5606,11 +5606,13 @@ static int hclge_fd_ad_config(struct hclge_dev *hdev, u8 stage, int loc, + hnae3_set_field(ad_data, HCLGE_FD_AD_TC_SIZE_M, + HCLGE_FD_AD_TC_SIZE_S, (u32)action->tc_size); + } ++ hnae3_set_bit(ad_data, HCLGE_FD_AD_QID_H_B, ++ action->queue_id >= HCLGE_TQP_MAX_SIZE_DEV_V2 ? 1 : 0); + ad_data <<= 32; + hnae3_set_bit(ad_data, HCLGE_FD_AD_DROP_B, action->drop_packet); + hnae3_set_bit(ad_data, HCLGE_FD_AD_DIRECT_QID_B, + action->forward_to_direct_queue); +- hnae3_set_field(ad_data, HCLGE_FD_AD_QID_M, HCLGE_FD_AD_QID_S, ++ hnae3_set_field(ad_data, HCLGE_FD_AD_QID_L_M, HCLGE_FD_AD_QID_L_S, + action->queue_id); + hnae3_set_bit(ad_data, HCLGE_FD_AD_USE_COUNTER_B, action->use_counter); + hnae3_set_field(ad_data, HCLGE_FD_AD_COUNTER_NUM_M, +diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c +index 8a0eb51fe9744f..1f233fac9d4e3f 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -74,7 +74,13 @@ static const struct pci_device_id i40e_pci_tbl[] = { + {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4), 0}, + {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T_BC), 0}, + {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_SFP), 0}, +- {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_B), 0}, ++ /* ++ * This ID conflicts with ipw2200, but the devices can be differentiated ++ * because i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200 ++ * devices use PCI_CLASS_NETWORK_OTHER. ++ */ ++ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_10G_B), ++ PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0}, + {PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_X722), 0}, + {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_X722), 0}, + {PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X722), 0}, +diff --git a/drivers/net/ethernet/marvell/octeon_ep/Makefile b/drivers/net/ethernet/marvell/octeon_ep/Makefile +index 2026c8118158c6..02a4a21bc29867 100644 +--- a/drivers/net/ethernet/marvell/octeon_ep/Makefile ++++ b/drivers/net/ethernet/marvell/octeon_ep/Makefile +@@ -6,4 +6,5 @@ + obj-$(CONFIG_OCTEON_EP) += octeon_ep.o + + octeon_ep-y := octep_main.o octep_cn9k_pf.o octep_tx.o octep_rx.o \ +- octep_ethtool.o octep_ctrl_mbox.o octep_ctrl_net.o ++ octep_ethtool.o octep_ctrl_mbox.o octep_ctrl_net.o \ ++ octep_cnxk_pf.o +diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c b/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c +index 90c3a419932d1e..0ed07aad066f4b 100644 +--- a/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c ++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c +@@ -16,9 +16,6 @@ + #define CTRL_MBOX_MAX_PF 128 + #define CTRL_MBOX_SZ ((size_t)(0x400000 / CTRL_MBOX_MAX_PF)) + +-#define FW_HB_INTERVAL_IN_SECS 1 +-#define FW_HB_MISS_COUNT 10 +- + /* Names of Hardware non-queue generic interrupts */ + static char *cn93_non_ioq_msix_names[] = { + "epf_ire_rint", +@@ -250,12 +247,11 @@ static void octep_init_config_cn93_pf(struct octep_device *oct) + link = PCI_DEVFN(PCI_SLOT(oct->pdev->devfn), link); + } + conf->ctrl_mbox_cfg.barmem_addr = (void __iomem *)oct->mmio[2].hw_addr + +- (0x400000ull * 7) + ++ CN93_PEM_BAR4_INDEX_OFFSET + + (link * CTRL_MBOX_SZ); + +- conf->hb_interval = FW_HB_INTERVAL_IN_SECS; +- conf->max_hb_miss_cnt = FW_HB_MISS_COUNT; +- ++ conf->fw_info.hb_interval = OCTEP_DEFAULT_FW_HB_INTERVAL; ++ conf->fw_info.hb_miss_count = OCTEP_DEFAULT_FW_HB_MISS_COUNT; + } + + /* Setup registers for a hardware Tx Queue */ +@@ -306,7 +302,7 @@ static void octep_setup_iq_regs_cn93_pf(struct octep_device *oct, int iq_no) + } + + /* Setup registers for a hardware Rx Queue */ +-static void octep_setup_oq_regs_cn93_pf(struct octep_device *oct, int oq_no) ++static int octep_setup_oq_regs_cn93_pf(struct octep_device *oct, int oq_no) + { + u64 reg_val; + u64 oq_ctl = 0ULL; +@@ -354,6 +350,7 @@ static void octep_setup_oq_regs_cn93_pf(struct octep_device *oct, int oq_no) + reg_val = ((u64)time_threshold << 32) | + CFG_GET_OQ_INTR_PKT(oct->conf); + octep_write_csr64(oct, CN93_SDP_R_OUT_INT_LEVELS(oq_no), reg_val); ++ return 0; + } + + /* Setup registers for a PF mailbox */ +@@ -373,34 +370,40 @@ static void octep_setup_mbox_regs_cn93_pf(struct octep_device *oct, int q_no) + mbox->mbox_read_reg = oct->mmio[0].hw_addr + CN93_SDP_R_MBOX_VF_PF_DATA(q_no); + } + +-/* Process non-ioq interrupts required to keep pf interface running. +- * OEI_RINT is needed for control mailbox +- */ +-static bool octep_poll_non_ioq_interrupts_cn93_pf(struct octep_device *oct) +-{ +- bool handled = false; +- u64 reg0; +- +- /* Check for OEI INTR */ +- reg0 = octep_read_csr64(oct, CN93_SDP_EPF_OEI_RINT); +- if (reg0) { +- dev_info(&oct->pdev->dev, +- "Received OEI_RINT intr: 0x%llx\n", +- reg0); +- octep_write_csr64(oct, CN93_SDP_EPF_OEI_RINT, reg0); +- if (reg0 & CN93_SDP_EPF_OEI_RINT_DATA_BIT_MBOX) ++/* Poll OEI events like heartbeat */ ++static void octep_poll_oei_cn93_pf(struct octep_device *oct) ++{ ++ u64 reg; ++ ++ reg = octep_read_csr64(oct, CN93_SDP_EPF_OEI_RINT); ++ if (reg) { ++ octep_write_csr64(oct, CN93_SDP_EPF_OEI_RINT, reg); ++ if (reg & CN93_SDP_EPF_OEI_RINT_DATA_BIT_MBOX) + queue_work(octep_wq, &oct->ctrl_mbox_task); +- else if (reg0 & CN93_SDP_EPF_OEI_RINT_DATA_BIT_HBEAT) ++ else if (reg & CN93_SDP_EPF_OEI_RINT_DATA_BIT_HBEAT) + atomic_set(&oct->hb_miss_cnt, 0); +- +- handled = true; + } ++} ++ ++/* OEI interrupt handler */ ++static irqreturn_t octep_oei_intr_handler_cn93_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; + +- return handled; ++ octep_poll_oei_cn93_pf(oct); ++ return IRQ_HANDLED; + } + +-/* Interrupts handler for all non-queue generic interrupts. */ +-static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(void *dev) ++/* Process non-ioq interrupts required to keep pf interface running. ++ * OEI_RINT is needed for control mailbox ++ */ ++static void octep_poll_non_ioq_interrupts_cn93_pf(struct octep_device *oct) ++{ ++ octep_poll_oei_cn93_pf(oct); ++} ++ ++/* Interrupt handler for input ring error interrupts. */ ++static irqreturn_t octep_ire_intr_handler_cn93_pf(void *dev) + { + struct octep_device *oct = (struct octep_device *)dev; + struct pci_dev *pdev = oct->pdev; +@@ -425,8 +428,17 @@ static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(void *dev) + reg_val); + } + } +- goto irq_handled; + } ++ return IRQ_HANDLED; ++} ++ ++/* Interrupt handler for output ring error interrupts. */ ++static irqreturn_t octep_ore_intr_handler_cn93_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; ++ u64 reg_val = 0; ++ int i = 0; + + /* Check for ORERR INTR */ + reg_val = octep_read_csr64(oct, CN93_SDP_EPF_ORERR_RINT); +@@ -444,9 +456,16 @@ static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(void *dev) + reg_val); + } + } +- +- goto irq_handled; + } ++ return IRQ_HANDLED; ++} ++ ++/* Interrupt handler for vf input ring error interrupts. */ ++static irqreturn_t octep_vfire_intr_handler_cn93_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; ++ u64 reg_val = 0; + + /* Check for VFIRE INTR */ + reg_val = octep_read_csr64(oct, CN93_SDP_EPF_VFIRE_RINT(0)); +@@ -454,8 +473,16 @@ static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(void *dev) + dev_info(&pdev->dev, + "Received VFIRE_RINT intr: 0x%llx\n", reg_val); + octep_write_csr64(oct, CN93_SDP_EPF_VFIRE_RINT(0), reg_val); +- goto irq_handled; + } ++ return IRQ_HANDLED; ++} ++ ++/* Interrupt handler for vf output ring error interrupts. */ ++static irqreturn_t octep_vfore_intr_handler_cn93_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; ++ u64 reg_val = 0; + + /* Check for VFORE INTR */ + reg_val = octep_read_csr64(oct, CN93_SDP_EPF_VFORE_RINT(0)); +@@ -463,19 +490,30 @@ static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(void *dev) + dev_info(&pdev->dev, + "Received VFORE_RINT intr: 0x%llx\n", reg_val); + octep_write_csr64(oct, CN93_SDP_EPF_VFORE_RINT(0), reg_val); +- goto irq_handled; + } ++ return IRQ_HANDLED; ++} + +- /* Check for MBOX INTR and OEI INTR */ +- if (octep_poll_non_ioq_interrupts_cn93_pf(oct)) +- goto irq_handled; ++/* Interrupt handler for dpi dma related interrupts. */ ++static irqreturn_t octep_dma_intr_handler_cn93_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ u64 reg_val = 0; + + /* Check for DMA INTR */ + reg_val = octep_read_csr64(oct, CN93_SDP_EPF_DMA_RINT); + if (reg_val) { + octep_write_csr64(oct, CN93_SDP_EPF_DMA_RINT, reg_val); +- goto irq_handled; + } ++ return IRQ_HANDLED; ++} ++ ++/* Interrupt handler for dpi dma transaction error interrupts for VFs */ ++static irqreturn_t octep_dma_vf_intr_handler_cn93_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; ++ u64 reg_val = 0; + + /* Check for DMA VF INTR */ + reg_val = octep_read_csr64(oct, CN93_SDP_EPF_DMA_VF_RINT(0)); +@@ -483,8 +521,16 @@ static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(void *dev) + dev_info(&pdev->dev, + "Received DMA_VF_RINT intr: 0x%llx\n", reg_val); + octep_write_csr64(oct, CN93_SDP_EPF_DMA_VF_RINT(0), reg_val); +- goto irq_handled; + } ++ return IRQ_HANDLED; ++} ++ ++/* Interrupt handler for pp transaction error interrupts for VFs */ ++static irqreturn_t octep_pp_vf_intr_handler_cn93_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; ++ u64 reg_val = 0; + + /* Check for PPVF INTR */ + reg_val = octep_read_csr64(oct, CN93_SDP_EPF_PP_VF_RINT(0)); +@@ -492,8 +538,16 @@ static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(void *dev) + dev_info(&pdev->dev, + "Received PP_VF_RINT intr: 0x%llx\n", reg_val); + octep_write_csr64(oct, CN93_SDP_EPF_PP_VF_RINT(0), reg_val); +- goto irq_handled; + } ++ return IRQ_HANDLED; ++} ++ ++/* Interrupt handler for mac related interrupts. */ ++static irqreturn_t octep_misc_intr_handler_cn93_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; ++ u64 reg_val = 0; + + /* Check for MISC INTR */ + reg_val = octep_read_csr64(oct, CN93_SDP_EPF_MISC_RINT); +@@ -501,11 +555,17 @@ static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(void *dev) + dev_info(&pdev->dev, + "Received MISC_RINT intr: 0x%llx\n", reg_val); + octep_write_csr64(oct, CN93_SDP_EPF_MISC_RINT, reg_val); +- goto irq_handled; + } ++ return IRQ_HANDLED; ++} ++ ++/* Interrupts handler for all reserved interrupts. */ ++static irqreturn_t octep_rsvd_intr_handler_cn93_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; + + dev_info(&pdev->dev, "Reserved interrupts raised; Ignore\n"); +-irq_handled: + return IRQ_HANDLED; + } + +@@ -569,27 +629,53 @@ static void octep_enable_interrupts_cn93_pf(struct octep_device *oct) + octep_write_csr64(oct, CN93_SDP_EPF_IRERR_RINT_ENA_W1S, intr_mask); + octep_write_csr64(oct, CN93_SDP_EPF_ORERR_RINT_ENA_W1S, intr_mask); + octep_write_csr64(oct, CN93_SDP_EPF_OEI_RINT_ENA_W1S, -1ULL); ++ ++ octep_write_csr64(oct, CN93_SDP_EPF_VFIRE_RINT_ENA_W1S(0), -1ULL); ++ octep_write_csr64(oct, CN93_SDP_EPF_VFORE_RINT_ENA_W1S(0), -1ULL); ++ + octep_write_csr64(oct, CN93_SDP_EPF_MISC_RINT_ENA_W1S, intr_mask); + octep_write_csr64(oct, CN93_SDP_EPF_DMA_RINT_ENA_W1S, intr_mask); ++ ++ octep_write_csr64(oct, CN93_SDP_EPF_DMA_VF_RINT_ENA_W1S(0), -1ULL); ++ octep_write_csr64(oct, CN93_SDP_EPF_PP_VF_RINT_ENA_W1S(0), -1ULL); + } + + /* Disable all interrupts */ + static void octep_disable_interrupts_cn93_pf(struct octep_device *oct) + { +- u64 intr_mask = 0ULL; ++ u64 reg_val, intr_mask = 0ULL; + int srn, num_rings, i; + + srn = CFG_GET_PORTS_PF_SRN(oct->conf); + num_rings = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); + +- for (i = 0; i < num_rings; i++) +- intr_mask |= (0x1ULL << (srn + i)); ++ for (i = 0; i < num_rings; i++) { ++ intr_mask |= BIT_ULL(srn + i); ++ reg_val = octep_read_csr64(oct, ++ CN93_SDP_R_IN_INT_LEVELS(srn + i)); ++ reg_val &= ~CN93_INT_ENA_BIT; ++ octep_write_csr64(oct, ++ CN93_SDP_R_IN_INT_LEVELS(srn + i), reg_val); ++ ++ reg_val = octep_read_csr64(oct, ++ CN93_SDP_R_OUT_INT_LEVELS(srn + i)); ++ reg_val &= ~CN93_INT_ENA_BIT; ++ octep_write_csr64(oct, ++ CN93_SDP_R_OUT_INT_LEVELS(srn + i), reg_val); ++ } + + octep_write_csr64(oct, CN93_SDP_EPF_IRERR_RINT_ENA_W1C, intr_mask); + octep_write_csr64(oct, CN93_SDP_EPF_ORERR_RINT_ENA_W1C, intr_mask); + octep_write_csr64(oct, CN93_SDP_EPF_OEI_RINT_ENA_W1C, -1ULL); ++ ++ octep_write_csr64(oct, CN93_SDP_EPF_VFIRE_RINT_ENA_W1C(0), -1ULL); ++ octep_write_csr64(oct, CN93_SDP_EPF_VFORE_RINT_ENA_W1C(0), -1ULL); ++ + octep_write_csr64(oct, CN93_SDP_EPF_MISC_RINT_ENA_W1C, intr_mask); + octep_write_csr64(oct, CN93_SDP_EPF_DMA_RINT_ENA_W1C, intr_mask); ++ ++ octep_write_csr64(oct, CN93_SDP_EPF_DMA_VF_RINT_ENA_W1C(0), -1ULL); ++ octep_write_csr64(oct, CN93_SDP_EPF_PP_VF_RINT_ENA_W1C(0), -1ULL); + } + + /* Get new Octeon Read Index: index of descriptor that Octeon reads next. */ +@@ -722,7 +808,16 @@ void octep_device_setup_cn93_pf(struct octep_device *oct) + oct->hw_ops.setup_oq_regs = octep_setup_oq_regs_cn93_pf; + oct->hw_ops.setup_mbox_regs = octep_setup_mbox_regs_cn93_pf; + +- oct->hw_ops.non_ioq_intr_handler = octep_non_ioq_intr_handler_cn93_pf; ++ oct->hw_ops.oei_intr_handler = octep_oei_intr_handler_cn93_pf; ++ oct->hw_ops.ire_intr_handler = octep_ire_intr_handler_cn93_pf; ++ oct->hw_ops.ore_intr_handler = octep_ore_intr_handler_cn93_pf; ++ oct->hw_ops.vfire_intr_handler = octep_vfire_intr_handler_cn93_pf; ++ oct->hw_ops.vfore_intr_handler = octep_vfore_intr_handler_cn93_pf; ++ oct->hw_ops.dma_intr_handler = octep_dma_intr_handler_cn93_pf; ++ oct->hw_ops.dma_vf_intr_handler = octep_dma_vf_intr_handler_cn93_pf; ++ oct->hw_ops.pp_vf_intr_handler = octep_pp_vf_intr_handler_cn93_pf; ++ oct->hw_ops.misc_intr_handler = octep_misc_intr_handler_cn93_pf; ++ oct->hw_ops.rsvd_intr_handler = octep_rsvd_intr_handler_cn93_pf; + oct->hw_ops.ioq_intr_handler = octep_ioq_intr_handler_cn93_pf; + oct->hw_ops.soft_reset = octep_soft_reset_cn93_pf; + oct->hw_ops.reinit_regs = octep_reinit_regs_cn93_pf; +diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c b/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c +new file mode 100644 +index 00000000000000..b1f7bf6e0f5d01 +--- /dev/null ++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c +@@ -0,0 +1,935 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* Marvell Octeon EP (EndPoint) Ethernet Driver ++ * ++ * Copyright (C) 2020 Marvell. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "octep_config.h" ++#include "octep_main.h" ++#include "octep_regs_cnxk_pf.h" ++ ++/* We will support 128 pf's in control mbox */ ++#define CTRL_MBOX_MAX_PF 128 ++#define CTRL_MBOX_SZ ((size_t)(0x400000 / CTRL_MBOX_MAX_PF)) ++ ++/* Names of Hardware non-queue generic interrupts */ ++static char *cnxk_non_ioq_msix_names[] = { ++ "epf_ire_rint", ++ "epf_ore_rint", ++ "epf_vfire_rint", ++ "epf_rsvd0", ++ "epf_vfore_rint", ++ "epf_rsvd1", ++ "epf_mbox_rint", ++ "epf_rsvd2_0", ++ "epf_rsvd2_1", ++ "epf_dma_rint", ++ "epf_dma_vf_rint", ++ "epf_rsvd3", ++ "epf_pp_vf_rint", ++ "epf_rsvd3", ++ "epf_misc_rint", ++ "epf_rsvd5", ++ /* Next 16 are for OEI_RINT */ ++ "epf_oei_rint0", ++ "epf_oei_rint1", ++ "epf_oei_rint2", ++ "epf_oei_rint3", ++ "epf_oei_rint4", ++ "epf_oei_rint5", ++ "epf_oei_rint6", ++ "epf_oei_rint7", ++ "epf_oei_rint8", ++ "epf_oei_rint9", ++ "epf_oei_rint10", ++ "epf_oei_rint11", ++ "epf_oei_rint12", ++ "epf_oei_rint13", ++ "epf_oei_rint14", ++ "epf_oei_rint15", ++ /* IOQ interrupt */ ++ "octeon_ep" ++}; ++ ++/* Dump useful hardware CSRs for debug purpose */ ++static void cnxk_dump_regs(struct octep_device *oct, int qno) ++{ ++ struct device *dev = &oct->pdev->dev; ++ ++ dev_info(dev, "IQ-%d register dump\n", qno); ++ dev_info(dev, "R[%d]_IN_INSTR_DBELL[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_IN_INSTR_DBELL(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_IN_INSTR_DBELL(qno))); ++ dev_info(dev, "R[%d]_IN_CONTROL[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_IN_CONTROL(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_IN_CONTROL(qno))); ++ dev_info(dev, "R[%d]_IN_ENABLE[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_IN_ENABLE(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_IN_ENABLE(qno))); ++ dev_info(dev, "R[%d]_IN_INSTR_BADDR[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_IN_INSTR_BADDR(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_IN_INSTR_BADDR(qno))); ++ dev_info(dev, "R[%d]_IN_INSTR_RSIZE[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_IN_INSTR_RSIZE(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_IN_INSTR_RSIZE(qno))); ++ dev_info(dev, "R[%d]_IN_CNTS[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_IN_CNTS(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_IN_CNTS(qno))); ++ dev_info(dev, "R[%d]_IN_INT_LEVELS[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_IN_INT_LEVELS(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_IN_INT_LEVELS(qno))); ++ dev_info(dev, "R[%d]_IN_PKT_CNT[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_IN_PKT_CNT(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_IN_PKT_CNT(qno))); ++ dev_info(dev, "R[%d]_IN_BYTE_CNT[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_IN_BYTE_CNT(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_IN_BYTE_CNT(qno))); ++ ++ dev_info(dev, "OQ-%d register dump\n", qno); ++ dev_info(dev, "R[%d]_OUT_SLIST_DBELL[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_OUT_SLIST_DBELL(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_OUT_SLIST_DBELL(qno))); ++ dev_info(dev, "R[%d]_OUT_CONTROL[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_OUT_CONTROL(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_OUT_CONTROL(qno))); ++ dev_info(dev, "R[%d]_OUT_ENABLE[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_OUT_ENABLE(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_OUT_ENABLE(qno))); ++ dev_info(dev, "R[%d]_OUT_SLIST_BADDR[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_OUT_SLIST_BADDR(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_OUT_SLIST_BADDR(qno))); ++ dev_info(dev, "R[%d]_OUT_SLIST_RSIZE[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_OUT_SLIST_RSIZE(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_OUT_SLIST_RSIZE(qno))); ++ dev_info(dev, "R[%d]_OUT_CNTS[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_OUT_CNTS(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_OUT_CNTS(qno))); ++ dev_info(dev, "R[%d]_OUT_INT_LEVELS[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_OUT_INT_LEVELS(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_OUT_INT_LEVELS(qno))); ++ dev_info(dev, "R[%d]_OUT_PKT_CNT[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_OUT_PKT_CNT(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_OUT_PKT_CNT(qno))); ++ dev_info(dev, "R[%d]_OUT_BYTE_CNT[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_OUT_BYTE_CNT(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_OUT_BYTE_CNT(qno))); ++ dev_info(dev, "R[%d]_ERR_TYPE[0x%llx]: 0x%016llx\n", ++ qno, CNXK_SDP_R_ERR_TYPE(qno), ++ octep_read_csr64(oct, CNXK_SDP_R_ERR_TYPE(qno))); ++} ++ ++/* Reset Hardware Tx queue */ ++static int cnxk_reset_iq(struct octep_device *oct, int q_no) ++{ ++ struct octep_config *conf = oct->conf; ++ u64 val = 0ULL; ++ ++ dev_dbg(&oct->pdev->dev, "Reset PF IQ-%d\n", q_no); ++ ++ /* Get absolute queue number */ ++ q_no += conf->pf_ring_cfg.srn; ++ ++ /* Disable the Tx/Instruction Ring */ ++ octep_write_csr64(oct, CNXK_SDP_R_IN_ENABLE(q_no), val); ++ ++ /* clear the Instruction Ring packet/byte counts and doorbell CSRs */ ++ octep_write_csr64(oct, CNXK_SDP_R_IN_CNTS(q_no), val); ++ octep_write_csr64(oct, CNXK_SDP_R_IN_INT_LEVELS(q_no), val); ++ octep_write_csr64(oct, CNXK_SDP_R_IN_PKT_CNT(q_no), val); ++ octep_write_csr64(oct, CNXK_SDP_R_IN_BYTE_CNT(q_no), val); ++ octep_write_csr64(oct, CNXK_SDP_R_IN_INSTR_BADDR(q_no), val); ++ octep_write_csr64(oct, CNXK_SDP_R_IN_INSTR_RSIZE(q_no), val); ++ ++ val = 0xFFFFFFFF; ++ octep_write_csr64(oct, CNXK_SDP_R_IN_INSTR_DBELL(q_no), val); ++ ++ return 0; ++} ++ ++/* Reset Hardware Rx queue */ ++static void cnxk_reset_oq(struct octep_device *oct, int q_no) ++{ ++ u64 val = 0ULL; ++ ++ q_no += CFG_GET_PORTS_PF_SRN(oct->conf); ++ ++ /* Disable Output (Rx) Ring */ ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_ENABLE(q_no), val); ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_BADDR(q_no), val); ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_RSIZE(q_no), val); ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_INT_LEVELS(q_no), val); ++ ++ /* Clear count CSRs */ ++ val = octep_read_csr(oct, CNXK_SDP_R_OUT_CNTS(q_no)); ++ octep_write_csr(oct, CNXK_SDP_R_OUT_CNTS(q_no), val); ++ ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_PKT_CNT(q_no), 0xFFFFFFFFFULL); ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_DBELL(q_no), 0xFFFFFFFF); ++} ++ ++/* Reset all hardware Tx/Rx queues */ ++static void octep_reset_io_queues_cnxk_pf(struct octep_device *oct) ++{ ++ struct pci_dev *pdev = oct->pdev; ++ int q; ++ ++ dev_dbg(&pdev->dev, "Reset OCTEP_CNXK PF IO Queues\n"); ++ ++ for (q = 0; q < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); q++) { ++ cnxk_reset_iq(oct, q); ++ cnxk_reset_oq(oct, q); ++ } ++} ++ ++/* Initialize windowed addresses to access some hardware registers */ ++static void octep_setup_pci_window_regs_cnxk_pf(struct octep_device *oct) ++{ ++ u8 __iomem *bar0_pciaddr = oct->mmio[0].hw_addr; ++ ++ oct->pci_win_regs.pci_win_wr_addr = (u8 __iomem *)(bar0_pciaddr + CNXK_SDP_WIN_WR_ADDR64); ++ oct->pci_win_regs.pci_win_rd_addr = (u8 __iomem *)(bar0_pciaddr + CNXK_SDP_WIN_RD_ADDR64); ++ oct->pci_win_regs.pci_win_wr_data = (u8 __iomem *)(bar0_pciaddr + CNXK_SDP_WIN_WR_DATA64); ++ oct->pci_win_regs.pci_win_rd_data = (u8 __iomem *)(bar0_pciaddr + CNXK_SDP_WIN_RD_DATA64); ++} ++ ++/* Configure Hardware mapping: inform hardware which rings belong to PF. */ ++static void octep_configure_ring_mapping_cnxk_pf(struct octep_device *oct) ++{ ++ struct octep_config *conf = oct->conf; ++ struct pci_dev *pdev = oct->pdev; ++ u64 pf_srn = CFG_GET_PORTS_PF_SRN(oct->conf); ++ int q; ++ ++ for (q = 0; q < CFG_GET_PORTS_ACTIVE_IO_RINGS(conf); q++) { ++ u64 regval = 0; ++ ++ if (oct->pcie_port) ++ regval = 8 << CNXK_SDP_FUNC_SEL_EPF_BIT_POS; ++ ++ octep_write_csr64(oct, CNXK_SDP_EPVF_RING(pf_srn + q), regval); ++ ++ regval = octep_read_csr64(oct, CNXK_SDP_EPVF_RING(pf_srn + q)); ++ dev_dbg(&pdev->dev, "Write SDP_EPVF_RING[0x%llx] = 0x%llx\n", ++ CNXK_SDP_EPVF_RING(pf_srn + q), regval); ++ } ++} ++ ++/* Initialize configuration limits and initial active config */ ++static void octep_init_config_cnxk_pf(struct octep_device *oct) ++{ ++ struct octep_config *conf = oct->conf; ++ struct pci_dev *pdev = oct->pdev; ++ u8 link = 0; ++ u64 val; ++ int pos; ++ ++ /* Read ring configuration: ++ * PF ring count, number of VFs and rings per VF supported ++ */ ++ val = octep_read_csr64(oct, CNXK_SDP_EPF_RINFO); ++ dev_info(&pdev->dev, "SDP_EPF_RINFO[0x%x]:0x%llx\n", CNXK_SDP_EPF_RINFO, val); ++ conf->sriov_cfg.max_rings_per_vf = CNXK_SDP_EPF_RINFO_RPVF(val); ++ conf->sriov_cfg.active_rings_per_vf = conf->sriov_cfg.max_rings_per_vf; ++ conf->sriov_cfg.max_vfs = CNXK_SDP_EPF_RINFO_NVFS(val); ++ conf->sriov_cfg.active_vfs = conf->sriov_cfg.max_vfs; ++ conf->sriov_cfg.vf_srn = CNXK_SDP_EPF_RINFO_SRN(val); ++ ++ val = octep_read_csr64(oct, CNXK_SDP_MAC_PF_RING_CTL(oct->pcie_port)); ++ dev_info(&pdev->dev, "SDP_MAC_PF_RING_CTL[%d]:0x%llx\n", oct->pcie_port, val); ++ conf->pf_ring_cfg.srn = CNXK_SDP_MAC_PF_RING_CTL_SRN(val); ++ conf->pf_ring_cfg.max_io_rings = CNXK_SDP_MAC_PF_RING_CTL_RPPF(val); ++ conf->pf_ring_cfg.active_io_rings = conf->pf_ring_cfg.max_io_rings; ++ dev_info(&pdev->dev, "pf_srn=%u rpvf=%u nvfs=%u rppf=%u\n", ++ conf->pf_ring_cfg.srn, conf->sriov_cfg.active_rings_per_vf, ++ conf->sriov_cfg.active_vfs, conf->pf_ring_cfg.active_io_rings); ++ ++ conf->iq.num_descs = OCTEP_IQ_MAX_DESCRIPTORS; ++ conf->iq.instr_type = OCTEP_64BYTE_INSTR; ++ conf->iq.db_min = OCTEP_DB_MIN; ++ conf->iq.intr_threshold = OCTEP_IQ_INTR_THRESHOLD; ++ ++ conf->oq.num_descs = OCTEP_OQ_MAX_DESCRIPTORS; ++ conf->oq.buf_size = OCTEP_OQ_BUF_SIZE; ++ conf->oq.refill_threshold = OCTEP_OQ_REFILL_THRESHOLD; ++ conf->oq.oq_intr_pkt = OCTEP_OQ_INTR_PKT_THRESHOLD; ++ conf->oq.oq_intr_time = OCTEP_OQ_INTR_TIME_THRESHOLD; ++ conf->oq.wmark = OCTEP_OQ_WMARK_MIN; ++ ++ conf->msix_cfg.non_ioq_msix = CNXK_NUM_NON_IOQ_INTR; ++ conf->msix_cfg.ioq_msix = conf->pf_ring_cfg.active_io_rings; ++ conf->msix_cfg.non_ioq_msix_names = cnxk_non_ioq_msix_names; ++ ++ pos = pci_find_ext_capability(oct->pdev, PCI_EXT_CAP_ID_SRIOV); ++ if (pos) { ++ pci_read_config_byte(oct->pdev, ++ pos + PCI_SRIOV_FUNC_LINK, ++ &link); ++ link = PCI_DEVFN(PCI_SLOT(oct->pdev->devfn), link); ++ } ++ conf->ctrl_mbox_cfg.barmem_addr = (void __iomem *)oct->mmio[2].hw_addr + ++ CNXK_PEM_BAR4_INDEX_OFFSET + ++ (link * CTRL_MBOX_SZ); ++ ++ conf->fw_info.hb_interval = OCTEP_DEFAULT_FW_HB_INTERVAL; ++ conf->fw_info.hb_miss_count = OCTEP_DEFAULT_FW_HB_MISS_COUNT; ++} ++ ++/* Setup registers for a hardware Tx Queue */ ++static void octep_setup_iq_regs_cnxk_pf(struct octep_device *oct, int iq_no) ++{ ++ struct octep_iq *iq = oct->iq[iq_no]; ++ u32 reset_instr_cnt; ++ u64 reg_val; ++ ++ iq_no += CFG_GET_PORTS_PF_SRN(oct->conf); ++ reg_val = octep_read_csr64(oct, CNXK_SDP_R_IN_CONTROL(iq_no)); ++ ++ /* wait for IDLE to set to 1 */ ++ if (!(reg_val & CNXK_R_IN_CTL_IDLE)) { ++ do { ++ reg_val = octep_read_csr64(oct, CNXK_SDP_R_IN_CONTROL(iq_no)); ++ } while (!(reg_val & CNXK_R_IN_CTL_IDLE)); ++ } ++ ++ reg_val |= CNXK_R_IN_CTL_RDSIZE; ++ reg_val |= CNXK_R_IN_CTL_IS_64B; ++ reg_val |= CNXK_R_IN_CTL_ESR; ++ octep_write_csr64(oct, CNXK_SDP_R_IN_CONTROL(iq_no), reg_val); ++ ++ /* Write the start of the input queue's ring and its size */ ++ octep_write_csr64(oct, CNXK_SDP_R_IN_INSTR_BADDR(iq_no), ++ iq->desc_ring_dma); ++ octep_write_csr64(oct, CNXK_SDP_R_IN_INSTR_RSIZE(iq_no), ++ iq->max_count); ++ ++ /* Remember the doorbell & instruction count register addr ++ * for this queue ++ */ ++ iq->doorbell_reg = oct->mmio[0].hw_addr + ++ CNXK_SDP_R_IN_INSTR_DBELL(iq_no); ++ iq->inst_cnt_reg = oct->mmio[0].hw_addr + ++ CNXK_SDP_R_IN_CNTS(iq_no); ++ iq->intr_lvl_reg = oct->mmio[0].hw_addr + ++ CNXK_SDP_R_IN_INT_LEVELS(iq_no); ++ ++ /* Store the current instruction counter (used in flush_iq calculation) */ ++ reset_instr_cnt = readl(iq->inst_cnt_reg); ++ writel(reset_instr_cnt, iq->inst_cnt_reg); ++ ++ /* INTR_THRESHOLD is set to max(FFFFFFFF) to disable the INTR */ ++ reg_val = CFG_GET_IQ_INTR_THRESHOLD(oct->conf) & 0xffffffff; ++ octep_write_csr64(oct, CNXK_SDP_R_IN_INT_LEVELS(iq_no), reg_val); ++} ++ ++/* Setup registers for a hardware Rx Queue */ ++static int octep_setup_oq_regs_cnxk_pf(struct octep_device *oct, int oq_no) ++{ ++ struct octep_oq *oq = oct->oq[oq_no]; ++ unsigned long t_out_jiffies; ++ u32 time_threshold = 0; ++ u64 oq_ctl = 0ULL; ++ u64 reg_ba_val; ++ u64 reg_val; ++ ++ oq_no += CFG_GET_PORTS_PF_SRN(oct->conf); ++ reg_val = octep_read_csr64(oct, CNXK_SDP_R_OUT_CONTROL(oq_no)); ++ ++ /* wait for IDLE to set to 1 */ ++ if (!(reg_val & CNXK_R_OUT_CTL_IDLE)) { ++ do { ++ reg_val = octep_read_csr64(oct, CNXK_SDP_R_OUT_CONTROL(oq_no)); ++ } while (!(reg_val & CNXK_R_OUT_CTL_IDLE)); ++ } ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_WMARK(oq_no), oq->max_count); ++ /* Wait for WMARK to get applied */ ++ usleep_range(10, 15); ++ ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_BADDR(oq_no), ++ oq->desc_ring_dma); ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_RSIZE(oq_no), ++ oq->max_count); ++ reg_ba_val = octep_read_csr64(oct, CNXK_SDP_R_OUT_SLIST_BADDR(oq_no)); ++ ++ if (reg_ba_val != oq->desc_ring_dma) { ++ t_out_jiffies = jiffies + 10 * HZ; ++ do { ++ if (reg_ba_val == ULLONG_MAX) ++ return -EFAULT; ++ octep_write_csr64(oct, ++ CNXK_SDP_R_OUT_SLIST_BADDR(oq_no), ++ oq->desc_ring_dma); ++ octep_write_csr64(oct, ++ CNXK_SDP_R_OUT_SLIST_RSIZE(oq_no), ++ oq->max_count); ++ reg_ba_val = ++ octep_read_csr64(oct, ++ CNXK_SDP_R_OUT_SLIST_BADDR(oq_no)); ++ } while ((reg_ba_val != oq->desc_ring_dma) && ++ time_before(jiffies, t_out_jiffies)); ++ ++ if (reg_ba_val != oq->desc_ring_dma) ++ return -EAGAIN; ++ } ++ ++ reg_val &= ~(CNXK_R_OUT_CTL_IMODE); ++ reg_val &= ~(CNXK_R_OUT_CTL_ROR_P); ++ reg_val &= ~(CNXK_R_OUT_CTL_NSR_P); ++ reg_val &= ~(CNXK_R_OUT_CTL_ROR_I); ++ reg_val &= ~(CNXK_R_OUT_CTL_NSR_I); ++ reg_val &= ~(CNXK_R_OUT_CTL_ES_I); ++ reg_val &= ~(CNXK_R_OUT_CTL_ROR_D); ++ reg_val &= ~(CNXK_R_OUT_CTL_NSR_D); ++ reg_val &= ~(CNXK_R_OUT_CTL_ES_D); ++ reg_val |= (CNXK_R_OUT_CTL_ES_P); ++ ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_CONTROL(oq_no), reg_val); ++ ++ oq_ctl = octep_read_csr64(oct, CNXK_SDP_R_OUT_CONTROL(oq_no)); ++ ++ /* Clear the ISIZE and BSIZE (22-0) */ ++ oq_ctl &= ~0x7fffffULL; ++ ++ /* Populate the BSIZE (15-0) */ ++ oq_ctl |= (oq->buffer_size & 0xffff); ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_CONTROL(oq_no), oq_ctl); ++ ++ /* Get the mapped address of the pkt_sent and pkts_credit regs */ ++ oq->pkts_sent_reg = oct->mmio[0].hw_addr + CNXK_SDP_R_OUT_CNTS(oq_no); ++ oq->pkts_credit_reg = oct->mmio[0].hw_addr + ++ CNXK_SDP_R_OUT_SLIST_DBELL(oq_no); ++ ++ time_threshold = CFG_GET_OQ_INTR_TIME(oct->conf); ++ reg_val = ((u64)time_threshold << 32) | ++ CFG_GET_OQ_INTR_PKT(oct->conf); ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_INT_LEVELS(oq_no), reg_val); ++ ++ /* set watermark for backpressure */ ++ reg_val = octep_read_csr64(oct, CNXK_SDP_R_OUT_WMARK(oq_no)); ++ reg_val &= ~0xFFFFFFFFULL; ++ reg_val |= CFG_GET_OQ_WMARK(oct->conf); ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_WMARK(oq_no), reg_val); ++ return 0; ++} ++ ++/* Setup registers for a PF mailbox */ ++static void octep_setup_mbox_regs_cnxk_pf(struct octep_device *oct, int q_no) ++{ ++ struct octep_mbox *mbox = oct->mbox[q_no]; ++ ++ mbox->q_no = q_no; ++ ++ /* PF mbox interrupt reg */ ++ mbox->mbox_int_reg = oct->mmio[0].hw_addr + CNXK_SDP_EPF_MBOX_RINT(0); ++ ++ /* PF to VF DATA reg. PF writes into this reg */ ++ mbox->mbox_write_reg = oct->mmio[0].hw_addr + CNXK_SDP_R_MBOX_PF_VF_DATA(q_no); ++ ++ /* VF to PF DATA reg. PF reads from this reg */ ++ mbox->mbox_read_reg = oct->mmio[0].hw_addr + CNXK_SDP_R_MBOX_VF_PF_DATA(q_no); ++} ++ ++/* Poll OEI events like heartbeat */ ++static void octep_poll_oei_cnxk_pf(struct octep_device *oct) ++{ ++ u64 reg0; ++ ++ /* Check for OEI INTR */ ++ reg0 = octep_read_csr64(oct, CNXK_SDP_EPF_OEI_RINT); ++ if (reg0) { ++ octep_write_csr64(oct, CNXK_SDP_EPF_OEI_RINT, reg0); ++ if (reg0 & CNXK_SDP_EPF_OEI_RINT_DATA_BIT_MBOX) ++ queue_work(octep_wq, &oct->ctrl_mbox_task); ++ if (reg0 & CNXK_SDP_EPF_OEI_RINT_DATA_BIT_HBEAT) ++ atomic_set(&oct->hb_miss_cnt, 0); ++ } ++} ++ ++/* OEI interrupt handler */ ++static irqreturn_t octep_oei_intr_handler_cnxk_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ ++ octep_poll_oei_cnxk_pf(oct); ++ return IRQ_HANDLED; ++} ++ ++/* Process non-ioq interrupts required to keep pf interface running. ++ * OEI_RINT is needed for control mailbox ++ * MBOX_RINT is needed for pfvf mailbox ++ */ ++static void octep_poll_non_ioq_interrupts_cnxk_pf(struct octep_device *oct) ++{ ++ octep_poll_oei_cnxk_pf(oct); ++} ++ ++/* Interrupt handler for input ring error interrupts. */ ++static irqreturn_t octep_ire_intr_handler_cnxk_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; ++ u64 reg_val = 0; ++ int i = 0; ++ ++ /* Check for IRERR INTR */ ++ reg_val = octep_read_csr64(oct, CNXK_SDP_EPF_IRERR_RINT); ++ if (reg_val) { ++ dev_info(&pdev->dev, ++ "received IRERR_RINT intr: 0x%llx\n", reg_val); ++ octep_write_csr64(oct, CNXK_SDP_EPF_IRERR_RINT, reg_val); ++ ++ for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) { ++ reg_val = octep_read_csr64(oct, ++ CNXK_SDP_R_ERR_TYPE(i)); ++ if (reg_val) { ++ dev_info(&pdev->dev, ++ "Received err type on IQ-%d: 0x%llx\n", ++ i, reg_val); ++ octep_write_csr64(oct, CNXK_SDP_R_ERR_TYPE(i), ++ reg_val); ++ } ++ } ++ } ++ return IRQ_HANDLED; ++} ++ ++/* Interrupt handler for output ring error interrupts. */ ++static irqreturn_t octep_ore_intr_handler_cnxk_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; ++ u64 reg_val = 0; ++ int i = 0; ++ ++ /* Check for ORERR INTR */ ++ reg_val = octep_read_csr64(oct, CNXK_SDP_EPF_ORERR_RINT); ++ if (reg_val) { ++ dev_info(&pdev->dev, ++ "Received ORERR_RINT intr: 0x%llx\n", reg_val); ++ octep_write_csr64(oct, CNXK_SDP_EPF_ORERR_RINT, reg_val); ++ for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) { ++ reg_val = octep_read_csr64(oct, CNXK_SDP_R_ERR_TYPE(i)); ++ if (reg_val) { ++ dev_info(&pdev->dev, ++ "Received err type on OQ-%d: 0x%llx\n", ++ i, reg_val); ++ octep_write_csr64(oct, CNXK_SDP_R_ERR_TYPE(i), ++ reg_val); ++ } ++ } ++ } ++ return IRQ_HANDLED; ++} ++ ++/* Interrupt handler for vf input ring error interrupts. */ ++static irqreturn_t octep_vfire_intr_handler_cnxk_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; ++ u64 reg_val = 0; ++ ++ /* Check for VFIRE INTR */ ++ reg_val = octep_read_csr64(oct, CNXK_SDP_EPF_VFIRE_RINT(0)); ++ if (reg_val) { ++ dev_info(&pdev->dev, ++ "Received VFIRE_RINT intr: 0x%llx\n", reg_val); ++ octep_write_csr64(oct, CNXK_SDP_EPF_VFIRE_RINT(0), reg_val); ++ } ++ return IRQ_HANDLED; ++} ++ ++/* Interrupt handler for vf output ring error interrupts. */ ++static irqreturn_t octep_vfore_intr_handler_cnxk_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; ++ u64 reg_val = 0; ++ ++ /* Check for VFORE INTR */ ++ reg_val = octep_read_csr64(oct, CNXK_SDP_EPF_VFORE_RINT(0)); ++ if (reg_val) { ++ dev_info(&pdev->dev, ++ "Received VFORE_RINT intr: 0x%llx\n", reg_val); ++ octep_write_csr64(oct, CNXK_SDP_EPF_VFORE_RINT(0), reg_val); ++ } ++ return IRQ_HANDLED; ++} ++ ++/* Interrupt handler for dpi dma related interrupts. */ ++static irqreturn_t octep_dma_intr_handler_cnxk_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ u64 reg_val = 0; ++ ++ /* Check for DMA INTR */ ++ reg_val = octep_read_csr64(oct, CNXK_SDP_EPF_DMA_RINT); ++ if (reg_val) ++ octep_write_csr64(oct, CNXK_SDP_EPF_DMA_RINT, reg_val); ++ ++ return IRQ_HANDLED; ++} ++ ++/* Interrupt handler for dpi dma transaction error interrupts for VFs */ ++static irqreturn_t octep_dma_vf_intr_handler_cnxk_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; ++ u64 reg_val = 0; ++ ++ /* Check for DMA VF INTR */ ++ reg_val = octep_read_csr64(oct, CNXK_SDP_EPF_DMA_VF_RINT(0)); ++ if (reg_val) { ++ dev_info(&pdev->dev, ++ "Received DMA_VF_RINT intr: 0x%llx\n", reg_val); ++ octep_write_csr64(oct, CNXK_SDP_EPF_DMA_VF_RINT(0), reg_val); ++ } ++ return IRQ_HANDLED; ++} ++ ++/* Interrupt handler for pp transaction error interrupts for VFs */ ++static irqreturn_t octep_pp_vf_intr_handler_cnxk_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; ++ u64 reg_val = 0; ++ ++ /* Check for PPVF INTR */ ++ reg_val = octep_read_csr64(oct, CNXK_SDP_EPF_PP_VF_RINT(0)); ++ if (reg_val) { ++ dev_info(&pdev->dev, ++ "Received PP_VF_RINT intr: 0x%llx\n", reg_val); ++ octep_write_csr64(oct, CNXK_SDP_EPF_PP_VF_RINT(0), reg_val); ++ } ++ return IRQ_HANDLED; ++} ++ ++/* Interrupt handler for mac related interrupts. */ ++static irqreturn_t octep_misc_intr_handler_cnxk_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; ++ u64 reg_val = 0; ++ ++ /* Check for MISC INTR */ ++ reg_val = octep_read_csr64(oct, CNXK_SDP_EPF_MISC_RINT); ++ if (reg_val) { ++ dev_info(&pdev->dev, ++ "Received MISC_RINT intr: 0x%llx\n", reg_val); ++ octep_write_csr64(oct, CNXK_SDP_EPF_MISC_RINT, reg_val); ++ } ++ return IRQ_HANDLED; ++} ++ ++/* Interrupts handler for all reserved interrupts. */ ++static irqreturn_t octep_rsvd_intr_handler_cnxk_pf(void *dev) ++{ ++ struct octep_device *oct = (struct octep_device *)dev; ++ struct pci_dev *pdev = oct->pdev; ++ ++ dev_info(&pdev->dev, "Reserved interrupts raised; Ignore\n"); ++ return IRQ_HANDLED; ++} ++ ++/* Tx/Rx queue interrupt handler */ ++static irqreturn_t octep_ioq_intr_handler_cnxk_pf(void *data) ++{ ++ struct octep_ioq_vector *vector = (struct octep_ioq_vector *)data; ++ struct octep_oq *oq = vector->oq; ++ ++ napi_schedule_irqoff(oq->napi); ++ return IRQ_HANDLED; ++} ++ ++/* soft reset */ ++static int octep_soft_reset_cnxk_pf(struct octep_device *oct) ++{ ++ dev_info(&oct->pdev->dev, "CNXKXX: Doing soft reset\n"); ++ ++ octep_write_csr64(oct, CNXK_SDP_WIN_WR_MASK_REG, 0xFF); ++ ++ /* Firmware status CSR is supposed to be cleared by ++ * core domain reset, but due to a hw bug, it is not. ++ * Set it to RUNNING right before reset so that it is not ++ * left in READY (1) state after a reset. This is required ++ * in addition to the early setting to handle the case where ++ * the OcteonTX is unexpectedly reset, reboots, and then ++ * the module is removed. ++ */ ++ OCTEP_PCI_WIN_WRITE(oct, CNXK_PEMX_PFX_CSX_PFCFGX(0, 0, CNXK_PCIEEP_VSECST_CTL), ++ FW_STATUS_RUNNING); ++ ++ /* Set chip domain reset bit */ ++ OCTEP_PCI_WIN_WRITE(oct, CNXK_RST_CHIP_DOMAIN_W1S, 1); ++ /* Wait till Octeon resets. */ ++ mdelay(10); ++ /* restore the reset value */ ++ octep_write_csr64(oct, CNXK_SDP_WIN_WR_MASK_REG, 0xFF); ++ ++ return 0; ++} ++ ++/* Re-initialize Octeon hardware registers */ ++static void octep_reinit_regs_cnxk_pf(struct octep_device *oct) ++{ ++ u32 i; ++ ++ for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) ++ oct->hw_ops.setup_iq_regs(oct, i); ++ ++ for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) ++ oct->hw_ops.setup_oq_regs(oct, i); ++ ++ oct->hw_ops.enable_interrupts(oct); ++ oct->hw_ops.enable_io_queues(oct); ++ ++ for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) ++ writel(oct->oq[i]->max_count, oct->oq[i]->pkts_credit_reg); ++} ++ ++/* Enable all interrupts */ ++static void octep_enable_interrupts_cnxk_pf(struct octep_device *oct) ++{ ++ u64 intr_mask = 0ULL; ++ int srn, num_rings, i; ++ ++ srn = CFG_GET_PORTS_PF_SRN(oct->conf); ++ num_rings = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); ++ ++ for (i = 0; i < num_rings; i++) ++ intr_mask |= (0x1ULL << (srn + i)); ++ ++ octep_write_csr64(oct, CNXK_SDP_EPF_IRERR_RINT_ENA_W1S, intr_mask); ++ octep_write_csr64(oct, CNXK_SDP_EPF_ORERR_RINT_ENA_W1S, intr_mask); ++ octep_write_csr64(oct, CNXK_SDP_EPF_OEI_RINT_ENA_W1S, -1ULL); ++ ++ octep_write_csr64(oct, CNXK_SDP_EPF_VFIRE_RINT_ENA_W1S(0), -1ULL); ++ octep_write_csr64(oct, CNXK_SDP_EPF_VFORE_RINT_ENA_W1S(0), -1ULL); ++ ++ octep_write_csr64(oct, CNXK_SDP_EPF_MISC_RINT_ENA_W1S, intr_mask); ++ octep_write_csr64(oct, CNXK_SDP_EPF_DMA_RINT_ENA_W1S, intr_mask); ++ ++ octep_write_csr64(oct, CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1S(0), -1ULL); ++ octep_write_csr64(oct, CNXK_SDP_EPF_PP_VF_RINT_ENA_W1S(0), -1ULL); ++} ++ ++/* Disable all interrupts */ ++static void octep_disable_interrupts_cnxk_pf(struct octep_device *oct) ++{ ++ u64 reg_val, intr_mask = 0ULL; ++ int srn, num_rings, i; ++ ++ srn = CFG_GET_PORTS_PF_SRN(oct->conf); ++ num_rings = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); ++ ++ for (i = 0; i < num_rings; i++) { ++ intr_mask |= BIT_ULL(srn + i); ++ reg_val = octep_read_csr64(oct, ++ CNXK_SDP_R_IN_INT_LEVELS(srn + i)); ++ reg_val &= ~CNXK_INT_ENA_BIT; ++ octep_write_csr64(oct, ++ CNXK_SDP_R_IN_INT_LEVELS(srn + i), reg_val); ++ ++ reg_val = octep_read_csr64(oct, ++ CNXK_SDP_R_OUT_INT_LEVELS(srn + i)); ++ reg_val &= ~CNXK_INT_ENA_BIT; ++ octep_write_csr64(oct, ++ CNXK_SDP_R_OUT_INT_LEVELS(srn + i), reg_val); ++ } ++ ++ octep_write_csr64(oct, CNXK_SDP_EPF_IRERR_RINT_ENA_W1C, intr_mask); ++ octep_write_csr64(oct, CNXK_SDP_EPF_ORERR_RINT_ENA_W1C, intr_mask); ++ octep_write_csr64(oct, CNXK_SDP_EPF_OEI_RINT_ENA_W1C, -1ULL); ++ ++ octep_write_csr64(oct, CNXK_SDP_EPF_VFIRE_RINT_ENA_W1C(0), -1ULL); ++ octep_write_csr64(oct, CNXK_SDP_EPF_VFORE_RINT_ENA_W1C(0), -1ULL); ++ ++ octep_write_csr64(oct, CNXK_SDP_EPF_MISC_RINT_ENA_W1C, intr_mask); ++ octep_write_csr64(oct, CNXK_SDP_EPF_DMA_RINT_ENA_W1C, intr_mask); ++ ++ octep_write_csr64(oct, CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1C(0), -1ULL); ++ octep_write_csr64(oct, CNXK_SDP_EPF_PP_VF_RINT_ENA_W1C(0), -1ULL); ++} ++ ++/* Get new Octeon Read Index: index of descriptor that Octeon reads next. */ ++static u32 octep_update_iq_read_index_cnxk_pf(struct octep_iq *iq) ++{ ++ u32 pkt_in_done = readl(iq->inst_cnt_reg); ++ u32 last_done, new_idx; ++ ++ last_done = pkt_in_done - iq->pkt_in_done; ++ iq->pkt_in_done = pkt_in_done; ++ ++ new_idx = (iq->octep_read_index + last_done) % iq->max_count; ++ ++ return new_idx; ++} ++ ++/* Enable a hardware Tx Queue */ ++static void octep_enable_iq_cnxk_pf(struct octep_device *oct, int iq_no) ++{ ++ u64 loop = HZ; ++ u64 reg_val; ++ ++ iq_no += CFG_GET_PORTS_PF_SRN(oct->conf); ++ ++ octep_write_csr64(oct, CNXK_SDP_R_IN_INSTR_DBELL(iq_no), 0xFFFFFFFF); ++ ++ while (octep_read_csr64(oct, CNXK_SDP_R_IN_INSTR_DBELL(iq_no)) && ++ loop--) { ++ schedule_timeout_interruptible(1); ++ } ++ ++ reg_val = octep_read_csr64(oct, CNXK_SDP_R_IN_INT_LEVELS(iq_no)); ++ reg_val |= (0x1ULL << 62); ++ octep_write_csr64(oct, CNXK_SDP_R_IN_INT_LEVELS(iq_no), reg_val); ++ ++ reg_val = octep_read_csr64(oct, CNXK_SDP_R_IN_ENABLE(iq_no)); ++ reg_val |= 0x1ULL; ++ octep_write_csr64(oct, CNXK_SDP_R_IN_ENABLE(iq_no), reg_val); ++} ++ ++/* Enable a hardware Rx Queue */ ++static void octep_enable_oq_cnxk_pf(struct octep_device *oct, int oq_no) ++{ ++ u64 reg_val = 0ULL; ++ ++ oq_no += CFG_GET_PORTS_PF_SRN(oct->conf); ++ ++ reg_val = octep_read_csr64(oct, CNXK_SDP_R_OUT_INT_LEVELS(oq_no)); ++ reg_val |= (0x1ULL << 62); ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_INT_LEVELS(oq_no), reg_val); ++ ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_DBELL(oq_no), 0xFFFFFFFF); ++ ++ reg_val = octep_read_csr64(oct, CNXK_SDP_R_OUT_ENABLE(oq_no)); ++ reg_val |= 0x1ULL; ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_ENABLE(oq_no), reg_val); ++} ++ ++/* Enable all hardware Tx/Rx Queues assined to PF */ ++static void octep_enable_io_queues_cnxk_pf(struct octep_device *oct) ++{ ++ u8 q; ++ ++ for (q = 0; q < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); q++) { ++ octep_enable_iq_cnxk_pf(oct, q); ++ octep_enable_oq_cnxk_pf(oct, q); ++ } ++} ++ ++/* Disable a hardware Tx Queue assined to PF */ ++static void octep_disable_iq_cnxk_pf(struct octep_device *oct, int iq_no) ++{ ++ u64 reg_val = 0ULL; ++ ++ iq_no += CFG_GET_PORTS_PF_SRN(oct->conf); ++ ++ reg_val = octep_read_csr64(oct, CNXK_SDP_R_IN_ENABLE(iq_no)); ++ reg_val &= ~0x1ULL; ++ octep_write_csr64(oct, CNXK_SDP_R_IN_ENABLE(iq_no), reg_val); ++} ++ ++/* Disable a hardware Rx Queue assined to PF */ ++static void octep_disable_oq_cnxk_pf(struct octep_device *oct, int oq_no) ++{ ++ u64 reg_val = 0ULL; ++ ++ oq_no += CFG_GET_PORTS_PF_SRN(oct->conf); ++ reg_val = octep_read_csr64(oct, CNXK_SDP_R_OUT_ENABLE(oq_no)); ++ reg_val &= ~0x1ULL; ++ octep_write_csr64(oct, CNXK_SDP_R_OUT_ENABLE(oq_no), reg_val); ++} ++ ++/* Disable all hardware Tx/Rx Queues assined to PF */ ++static void octep_disable_io_queues_cnxk_pf(struct octep_device *oct) ++{ ++ int q = 0; ++ ++ for (q = 0; q < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); q++) { ++ octep_disable_iq_cnxk_pf(oct, q); ++ octep_disable_oq_cnxk_pf(oct, q); ++ } ++} ++ ++/* Dump hardware registers (including Tx/Rx queues) for debugging. */ ++static void octep_dump_registers_cnxk_pf(struct octep_device *oct) ++{ ++ u8 srn, num_rings, q; ++ ++ srn = CFG_GET_PORTS_PF_SRN(oct->conf); ++ num_rings = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); ++ ++ for (q = srn; q < srn + num_rings; q++) ++ cnxk_dump_regs(oct, q); ++} ++ ++/** ++ * octep_device_setup_cnxk_pf() - Setup Octeon device. ++ * ++ * @oct: Octeon device private data structure. ++ * ++ * - initialize hardware operations. ++ * - get target side pcie port number for the device. ++ * - setup window access to hardware registers. ++ * - set initial configuration and max limits. ++ * - setup hardware mapping of rings to the PF device. ++ */ ++void octep_device_setup_cnxk_pf(struct octep_device *oct) ++{ ++ oct->hw_ops.setup_iq_regs = octep_setup_iq_regs_cnxk_pf; ++ oct->hw_ops.setup_oq_regs = octep_setup_oq_regs_cnxk_pf; ++ oct->hw_ops.setup_mbox_regs = octep_setup_mbox_regs_cnxk_pf; ++ ++ oct->hw_ops.oei_intr_handler = octep_oei_intr_handler_cnxk_pf; ++ oct->hw_ops.ire_intr_handler = octep_ire_intr_handler_cnxk_pf; ++ oct->hw_ops.ore_intr_handler = octep_ore_intr_handler_cnxk_pf; ++ oct->hw_ops.vfire_intr_handler = octep_vfire_intr_handler_cnxk_pf; ++ oct->hw_ops.vfore_intr_handler = octep_vfore_intr_handler_cnxk_pf; ++ oct->hw_ops.dma_intr_handler = octep_dma_intr_handler_cnxk_pf; ++ oct->hw_ops.dma_vf_intr_handler = octep_dma_vf_intr_handler_cnxk_pf; ++ oct->hw_ops.pp_vf_intr_handler = octep_pp_vf_intr_handler_cnxk_pf; ++ oct->hw_ops.misc_intr_handler = octep_misc_intr_handler_cnxk_pf; ++ oct->hw_ops.rsvd_intr_handler = octep_rsvd_intr_handler_cnxk_pf; ++ oct->hw_ops.ioq_intr_handler = octep_ioq_intr_handler_cnxk_pf; ++ oct->hw_ops.soft_reset = octep_soft_reset_cnxk_pf; ++ oct->hw_ops.reinit_regs = octep_reinit_regs_cnxk_pf; ++ ++ oct->hw_ops.enable_interrupts = octep_enable_interrupts_cnxk_pf; ++ oct->hw_ops.disable_interrupts = octep_disable_interrupts_cnxk_pf; ++ oct->hw_ops.poll_non_ioq_interrupts = octep_poll_non_ioq_interrupts_cnxk_pf; ++ ++ oct->hw_ops.update_iq_read_idx = octep_update_iq_read_index_cnxk_pf; ++ ++ oct->hw_ops.enable_iq = octep_enable_iq_cnxk_pf; ++ oct->hw_ops.enable_oq = octep_enable_oq_cnxk_pf; ++ oct->hw_ops.enable_io_queues = octep_enable_io_queues_cnxk_pf; ++ ++ oct->hw_ops.disable_iq = octep_disable_iq_cnxk_pf; ++ oct->hw_ops.disable_oq = octep_disable_oq_cnxk_pf; ++ oct->hw_ops.disable_io_queues = octep_disable_io_queues_cnxk_pf; ++ oct->hw_ops.reset_io_queues = octep_reset_io_queues_cnxk_pf; ++ ++ oct->hw_ops.dump_registers = octep_dump_registers_cnxk_pf; ++ ++ octep_setup_pci_window_regs_cnxk_pf(oct); ++ ++ oct->pcie_port = octep_read_csr64(oct, CNXK_SDP_MAC_NUMBER) & 0xff; ++ dev_info(&oct->pdev->dev, ++ "Octeon device using PCIE Port %d\n", oct->pcie_port); ++ ++ octep_init_config_cnxk_pf(oct); ++ octep_configure_ring_mapping_cnxk_pf(oct); ++ ++ /* Firmware status CSR is supposed to be cleared by ++ * core domain reset, but due to IPBUPEM-38842, it is not. ++ * Set it to RUNNING early in boot, so that unexpected resets ++ * leave it in a state that is not READY (1). ++ */ ++ OCTEP_PCI_WIN_WRITE(oct, CNXK_PEMX_PFX_CSX_PFCFGX(0, 0, CNXK_PCIEEP_VSECST_CTL), ++ FW_STATUS_RUNNING); ++} +diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_config.h b/drivers/net/ethernet/marvell/octeon_ep/octep_config.h +index df7cd39d9fce13..ecc29479314109 100644 +--- a/drivers/net/ethernet/marvell/octeon_ep/octep_config.h ++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_config.h +@@ -19,6 +19,9 @@ + /* Packet threshold for Tx queue interrupt */ + #define OCTEP_IQ_INTR_THRESHOLD 0x0 + ++/* Minimum watermark for backpressure */ ++#define OCTEP_OQ_WMARK_MIN 256 ++ + /* Rx Queue: maximum descriptors per ring */ + #define OCTEP_OQ_MAX_DESCRIPTORS 1024 + +@@ -49,6 +52,11 @@ + /* Default MTU */ + #define OCTEP_DEFAULT_MTU 1500 + ++/* pf heartbeat interval in milliseconds */ ++#define OCTEP_DEFAULT_FW_HB_INTERVAL 1000 ++/* pf heartbeat miss count */ ++#define OCTEP_DEFAULT_FW_HB_MISS_COUNT 20 ++ + /* Macros to get octeon config params */ + #define CFG_GET_IQ_CFG(cfg) ((cfg)->iq) + #define CFG_GET_IQ_NUM_DESC(cfg) ((cfg)->iq.num_descs) +@@ -63,6 +71,7 @@ + #define CFG_GET_OQ_REFILL_THRESHOLD(cfg) ((cfg)->oq.refill_threshold) + #define CFG_GET_OQ_INTR_PKT(cfg) ((cfg)->oq.oq_intr_pkt) + #define CFG_GET_OQ_INTR_TIME(cfg) ((cfg)->oq.oq_intr_time) ++#define CFG_GET_OQ_WMARK(cfg) ((cfg)->oq.wmark) + + #define CFG_GET_PORTS_MAX_IO_RINGS(cfg) ((cfg)->pf_ring_cfg.max_io_rings) + #define CFG_GET_PORTS_ACTIVE_IO_RINGS(cfg) ((cfg)->pf_ring_cfg.active_io_rings) +@@ -132,6 +141,12 @@ struct octep_oq_config { + * default. The time is specified in microseconds. + */ + u32 oq_intr_time; ++ ++ /* Water mark for backpressure. ++ * Output queue sends backpressure signal to source when ++ * free buffer count falls below wmark. ++ */ ++ u32 wmark; + }; + + /* Tx/Rx configuration */ +@@ -181,6 +196,16 @@ struct octep_ctrl_mbox_config { + void __iomem *barmem_addr; + }; + ++/* Info from firmware */ ++struct octep_fw_info { ++ /* interface pkind */ ++ u16 pkind; ++ /* heartbeat interval in milliseconds */ ++ u16 hb_interval; ++ /* heartbeat miss count */ ++ u16 hb_miss_count; ++}; ++ + /* Data Structure to hold configuration limits and active config */ + struct octep_config { + /* Input Queue attributes. */ +@@ -201,10 +226,7 @@ struct octep_config { + /* ctrl mbox config */ + struct octep_ctrl_mbox_config ctrl_mbox_cfg; + +- /* Configured maximum heartbeat miss count */ +- u32 max_hb_miss_cnt; +- +- /* Configured firmware heartbeat interval in secs */ +- u32 hb_interval; ++ /* fw info */ ++ struct octep_fw_info fw_info; + }; + #endif /* _OCTEP_CONFIG_H_ */ +diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c +index 17bfd5cdf46201..0594607a258545 100644 +--- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c ++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c +@@ -26,7 +26,7 @@ static atomic_t ctrl_net_msg_id; + + /* Control plane version in which OCTEP_CTRL_NET_H2F_CMD was added */ + static const u32 octep_ctrl_net_h2f_cmd_versions[OCTEP_CTRL_NET_H2F_CMD_MAX] = { +- [OCTEP_CTRL_NET_H2F_CMD_INVALID ... OCTEP_CTRL_NET_H2F_CMD_LINK_INFO] = ++ [OCTEP_CTRL_NET_H2F_CMD_INVALID ... OCTEP_CTRL_NET_H2F_CMD_GET_INFO] = + OCTEP_CP_VERSION(1, 0, 0) + }; + +@@ -353,6 +353,28 @@ void octep_ctrl_net_recv_fw_messages(struct octep_device *oct) + } + } + ++int octep_ctrl_net_get_info(struct octep_device *oct, int vfid, ++ struct octep_fw_info *info) ++{ ++ struct octep_ctrl_net_wait_data d = {0}; ++ struct octep_ctrl_net_h2f_resp *resp; ++ struct octep_ctrl_net_h2f_req *req; ++ int err; ++ ++ req = &d.data.req; ++ init_send_req(&d.msg, req, 0, vfid); ++ req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_GET_INFO; ++ req->link_info.cmd = OCTEP_CTRL_NET_CMD_GET; ++ err = octep_send_mbox_req(oct, &d, true); ++ if (err < 0) ++ return err; ++ ++ resp = &d.data.resp; ++ memcpy(info, &resp->info.fw_info, sizeof(struct octep_fw_info)); ++ ++ return 0; ++} ++ + int octep_ctrl_net_uninit(struct octep_device *oct) + { + struct octep_ctrl_net_wait_data *pos, *n; +diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h +index 1c2ef4ee31d91e..b330f370131be7 100644 +--- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h ++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h +@@ -41,6 +41,7 @@ enum octep_ctrl_net_h2f_cmd { + OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS, + OCTEP_CTRL_NET_H2F_CMD_RX_STATE, + OCTEP_CTRL_NET_H2F_CMD_LINK_INFO, ++ OCTEP_CTRL_NET_H2F_CMD_GET_INFO, + OCTEP_CTRL_NET_H2F_CMD_MAX + }; + +@@ -161,6 +162,11 @@ struct octep_ctrl_net_h2f_resp_cmd_state { + u16 state; + }; + ++/* get info request */ ++struct octep_ctrl_net_h2f_resp_cmd_get_info { ++ struct octep_fw_info fw_info; ++}; ++ + /* Host to fw response data */ + struct octep_ctrl_net_h2f_resp { + union octep_ctrl_net_resp_hdr hdr; +@@ -171,6 +177,7 @@ struct octep_ctrl_net_h2f_resp { + struct octep_ctrl_net_h2f_resp_cmd_state link; + struct octep_ctrl_net_h2f_resp_cmd_state rx; + struct octep_ctrl_net_link_info link_info; ++ struct octep_ctrl_net_h2f_resp_cmd_get_info info; + }; + } __packed; + +@@ -330,6 +337,17 @@ int octep_ctrl_net_set_link_info(struct octep_device *oct, + */ + void octep_ctrl_net_recv_fw_messages(struct octep_device *oct); + ++/** Get info from firmware. ++ * ++ * @param oct: non-null pointer to struct octep_device. ++ * @param vfid: Index of virtual function. ++ * @param info: non-null pointer to struct octep_fw_info. ++ * ++ * return value: 0 on success, -errno on failure. ++ */ ++int octep_ctrl_net_get_info(struct octep_device *oct, int vfid, ++ struct octep_fw_info *info); ++ + /** Uninitialize data for ctrl net. + * + * @param oct: non-null pointer to struct octep_device. +diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c +index c385084546639d..db24c290a90796 100644 +--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c ++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c +@@ -24,6 +24,10 @@ struct workqueue_struct *octep_wq; + static const struct pci_device_id octep_pci_id_tbl[] = { + {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CN93_PF)}, + {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CNF95N_PF)}, ++ {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CN10KA_PF)}, ++ {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CNF10KA_PF)}, ++ {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CNF10KB_PF)}, ++ {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CN10KB_PF)}, + {0, }, + }; + MODULE_DEVICE_TABLE(pci, octep_pci_id_tbl); +@@ -155,18 +159,153 @@ static void octep_disable_msix(struct octep_device *oct) + } + + /** +- * octep_non_ioq_intr_handler() - common handler for all generic interrupts. ++ * octep_oei_intr_handler() - common handler for output endpoint interrupts. + * + * @irq: Interrupt number. + * @data: interrupt data. + * +- * this is common handler for all non-queue (generic) interrupts. ++ * this is common handler for all output endpoint interrupts. ++ */ ++static irqreturn_t octep_oei_intr_handler(int irq, void *data) ++{ ++ struct octep_device *oct = data; ++ ++ return oct->hw_ops.oei_intr_handler(oct); ++} ++ ++/** ++ * octep_ire_intr_handler() - common handler for input ring error interrupts. ++ * ++ * @irq: Interrupt number. ++ * @data: interrupt data. ++ * ++ * this is common handler for input ring error interrupts. ++ */ ++static irqreturn_t octep_ire_intr_handler(int irq, void *data) ++{ ++ struct octep_device *oct = data; ++ ++ return oct->hw_ops.ire_intr_handler(oct); ++} ++ ++/** ++ * octep_ore_intr_handler() - common handler for output ring error interrupts. ++ * ++ * @irq: Interrupt number. ++ * @data: interrupt data. ++ * ++ * this is common handler for output ring error interrupts. ++ */ ++static irqreturn_t octep_ore_intr_handler(int irq, void *data) ++{ ++ struct octep_device *oct = data; ++ ++ return oct->hw_ops.ore_intr_handler(oct); ++} ++ ++/** ++ * octep_vfire_intr_handler() - common handler for vf input ring error interrupts. ++ * ++ * @irq: Interrupt number. ++ * @data: interrupt data. ++ * ++ * this is common handler for vf input ring error interrupts. ++ */ ++static irqreturn_t octep_vfire_intr_handler(int irq, void *data) ++{ ++ struct octep_device *oct = data; ++ ++ return oct->hw_ops.vfire_intr_handler(oct); ++} ++ ++/** ++ * octep_vfore_intr_handler() - common handler for vf output ring error interrupts. ++ * ++ * @irq: Interrupt number. ++ * @data: interrupt data. ++ * ++ * this is common handler for vf output ring error interrupts. ++ */ ++static irqreturn_t octep_vfore_intr_handler(int irq, void *data) ++{ ++ struct octep_device *oct = data; ++ ++ return oct->hw_ops.vfore_intr_handler(oct); ++} ++ ++/** ++ * octep_dma_intr_handler() - common handler for dpi dma related interrupts. ++ * ++ * @irq: Interrupt number. ++ * @data: interrupt data. ++ * ++ * this is common handler for dpi dma related interrupts. ++ */ ++static irqreturn_t octep_dma_intr_handler(int irq, void *data) ++{ ++ struct octep_device *oct = data; ++ ++ return oct->hw_ops.dma_intr_handler(oct); ++} ++ ++/** ++ * octep_dma_vf_intr_handler() - common handler for dpi dma transaction error interrupts for VFs. ++ * ++ * @irq: Interrupt number. ++ * @data: interrupt data. ++ * ++ * this is common handler for dpi dma transaction error interrupts for VFs. ++ */ ++static irqreturn_t octep_dma_vf_intr_handler(int irq, void *data) ++{ ++ struct octep_device *oct = data; ++ ++ return oct->hw_ops.dma_vf_intr_handler(oct); ++} ++ ++/** ++ * octep_pp_vf_intr_handler() - common handler for pp transaction error interrupts for VFs. ++ * ++ * @irq: Interrupt number. ++ * @data: interrupt data. ++ * ++ * this is common handler for pp transaction error interrupts for VFs. ++ */ ++static irqreturn_t octep_pp_vf_intr_handler(int irq, void *data) ++{ ++ struct octep_device *oct = data; ++ ++ return oct->hw_ops.pp_vf_intr_handler(oct); ++} ++ ++/** ++ * octep_misc_intr_handler() - common handler for mac related interrupts. ++ * ++ * @irq: Interrupt number. ++ * @data: interrupt data. ++ * ++ * this is common handler for mac related interrupts. + */ +-static irqreturn_t octep_non_ioq_intr_handler(int irq, void *data) ++static irqreturn_t octep_misc_intr_handler(int irq, void *data) + { + struct octep_device *oct = data; + +- return oct->hw_ops.non_ioq_intr_handler(oct); ++ return oct->hw_ops.misc_intr_handler(oct); ++} ++ ++/** ++ * octep_rsvd_intr_handler() - common handler for reserved interrupts (future use). ++ * ++ * @irq: Interrupt number. ++ * @data: interrupt data. ++ * ++ * this is common handler for all reserved interrupts. ++ */ ++static irqreturn_t octep_rsvd_intr_handler(int irq, void *data) ++{ ++ struct octep_device *oct = data; ++ ++ return oct->hw_ops.rsvd_intr_handler(oct); + } + + /** +@@ -222,9 +361,57 @@ static int octep_request_irqs(struct octep_device *oct) + + snprintf(irq_name, OCTEP_MSIX_NAME_SIZE, + "%s-%s", netdev->name, non_ioq_msix_names[i]); +- ret = request_irq(msix_entry->vector, +- octep_non_ioq_intr_handler, 0, +- irq_name, oct); ++ if (!strncmp(non_ioq_msix_names[i], "epf_oei_rint", ++ strlen("epf_oei_rint"))) { ++ ret = request_irq(msix_entry->vector, ++ octep_oei_intr_handler, 0, ++ irq_name, oct); ++ } else if (!strncmp(non_ioq_msix_names[i], "epf_ire_rint", ++ strlen("epf_ire_rint"))) { ++ ret = request_irq(msix_entry->vector, ++ octep_ire_intr_handler, 0, ++ irq_name, oct); ++ } else if (!strncmp(non_ioq_msix_names[i], "epf_ore_rint", ++ strlen("epf_ore_rint"))) { ++ ret = request_irq(msix_entry->vector, ++ octep_ore_intr_handler, 0, ++ irq_name, oct); ++ } else if (!strncmp(non_ioq_msix_names[i], "epf_vfire_rint", ++ strlen("epf_vfire_rint"))) { ++ ret = request_irq(msix_entry->vector, ++ octep_vfire_intr_handler, 0, ++ irq_name, oct); ++ } else if (!strncmp(non_ioq_msix_names[i], "epf_vfore_rint", ++ strlen("epf_vfore_rint"))) { ++ ret = request_irq(msix_entry->vector, ++ octep_vfore_intr_handler, 0, ++ irq_name, oct); ++ } else if (!strncmp(non_ioq_msix_names[i], "epf_dma_rint", ++ strlen("epf_dma_rint"))) { ++ ret = request_irq(msix_entry->vector, ++ octep_dma_intr_handler, 0, ++ irq_name, oct); ++ } else if (!strncmp(non_ioq_msix_names[i], "epf_dma_vf_rint", ++ strlen("epf_dma_vf_rint"))) { ++ ret = request_irq(msix_entry->vector, ++ octep_dma_vf_intr_handler, 0, ++ irq_name, oct); ++ } else if (!strncmp(non_ioq_msix_names[i], "epf_pp_vf_rint", ++ strlen("epf_pp_vf_rint"))) { ++ ret = request_irq(msix_entry->vector, ++ octep_pp_vf_intr_handler, 0, ++ irq_name, oct); ++ } else if (!strncmp(non_ioq_msix_names[i], "epf_misc_rint", ++ strlen("epf_misc_rint"))) { ++ ret = request_irq(msix_entry->vector, ++ octep_misc_intr_handler, 0, ++ irq_name, oct); ++ } else { ++ ret = request_irq(msix_entry->vector, ++ octep_rsvd_intr_handler, 0, ++ irq_name, oct); ++ } ++ + if (ret) { + netdev_err(netdev, + "request_irq failed for %s; err=%d", +@@ -907,9 +1094,9 @@ static void octep_hb_timeout_task(struct work_struct *work) + int miss_cnt; + + miss_cnt = atomic_inc_return(&oct->hb_miss_cnt); +- if (miss_cnt < oct->conf->max_hb_miss_cnt) { ++ if (miss_cnt < oct->conf->fw_info.hb_miss_count) { + queue_delayed_work(octep_wq, &oct->hb_task, +- msecs_to_jiffies(oct->conf->hb_interval * 1000)); ++ msecs_to_jiffies(oct->conf->fw_info.hb_interval)); + return; + } + +@@ -943,6 +1130,14 @@ static const char *octep_devid_to_str(struct octep_device *oct) + return "CN93XX"; + case OCTEP_PCI_DEVICE_ID_CNF95N_PF: + return "CNF95N"; ++ case OCTEP_PCI_DEVICE_ID_CN10KA_PF: ++ return "CN10KA"; ++ case OCTEP_PCI_DEVICE_ID_CNF10KA_PF: ++ return "CNF10KA"; ++ case OCTEP_PCI_DEVICE_ID_CNF10KB_PF: ++ return "CNF10KB"; ++ case OCTEP_PCI_DEVICE_ID_CN10KB_PF: ++ return "CN10KB"; + default: + return "Unsupported"; + } +@@ -988,6 +1183,14 @@ int octep_device_setup(struct octep_device *oct) + OCTEP_MINOR_REV(oct)); + octep_device_setup_cn93_pf(oct); + break; ++ case OCTEP_PCI_DEVICE_ID_CNF10KA_PF: ++ case OCTEP_PCI_DEVICE_ID_CN10KA_PF: ++ case OCTEP_PCI_DEVICE_ID_CNF10KB_PF: ++ case OCTEP_PCI_DEVICE_ID_CN10KB_PF: ++ dev_info(&pdev->dev, "Setting up OCTEON %s PF PASS%d.%d\n", ++ octep_devid_to_str(oct), OCTEP_MAJOR_REV(oct), OCTEP_MINOR_REV(oct)); ++ octep_device_setup_cnxk_pf(oct); ++ break; + default: + dev_err(&pdev->dev, + "%s: unsupported device\n", __func__); +@@ -1002,8 +1205,7 @@ int octep_device_setup(struct octep_device *oct) + + atomic_set(&oct->hb_miss_cnt, 0); + INIT_DELAYED_WORK(&oct->hb_task, octep_hb_timeout_task); +- queue_delayed_work(octep_wq, &oct->hb_task, +- msecs_to_jiffies(oct->conf->hb_interval * 1000)); ++ + return 0; + + unsupported_dev: +@@ -1133,6 +1335,15 @@ static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + dev_err(&pdev->dev, "Device setup failed\n"); + goto err_octep_config; + } ++ ++ octep_ctrl_net_get_info(octep_dev, OCTEP_CTRL_NET_INVALID_VFID, ++ &octep_dev->conf->fw_info); ++ dev_info(&octep_dev->pdev->dev, "Heartbeat interval %u msecs Heartbeat miss count %u\n", ++ octep_dev->conf->fw_info.hb_interval, ++ octep_dev->conf->fw_info.hb_miss_count); ++ queue_delayed_work(octep_wq, &octep_dev->hb_task, ++ msecs_to_jiffies(octep_dev->conf->fw_info.hb_interval)); ++ + INIT_WORK(&octep_dev->tx_timeout_task, octep_tx_timeout_task); + INIT_WORK(&octep_dev->ctrl_mbox_task, octep_ctrl_mbox_task); + INIT_DELAYED_WORK(&octep_dev->intr_poll_task, octep_intr_poll_task); +diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h +index e0907a7191330e..ce92a201278948 100644 +--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h ++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h +@@ -23,6 +23,11 @@ + + #define OCTEP_PCI_DEVICE_ID_CNF95N_PF 0xB400 //95N PF + ++#define OCTEP_PCI_DEVICE_ID_CN10KA_PF 0xB900 //CN10KA PF ++#define OCTEP_PCI_DEVICE_ID_CNF10KA_PF 0xBA00 //CNF10KA PF ++#define OCTEP_PCI_DEVICE_ID_CNF10KB_PF 0xBC00 //CNF10KB PF ++#define OCTEP_PCI_DEVICE_ID_CN10KB_PF 0xBD00 //CN10KB PF ++ + #define OCTEP_MAX_QUEUES 63 + #define OCTEP_MAX_IQ OCTEP_MAX_QUEUES + #define OCTEP_MAX_OQ OCTEP_MAX_QUEUES +@@ -62,10 +67,19 @@ struct octep_pci_win_regs { + + struct octep_hw_ops { + void (*setup_iq_regs)(struct octep_device *oct, int q); +- void (*setup_oq_regs)(struct octep_device *oct, int q); ++ int (*setup_oq_regs)(struct octep_device *oct, int q); + void (*setup_mbox_regs)(struct octep_device *oct, int mbox); + +- irqreturn_t (*non_ioq_intr_handler)(void *ioq_vector); ++ irqreturn_t (*oei_intr_handler)(void *ioq_vector); ++ irqreturn_t (*ire_intr_handler)(void *ioq_vector); ++ irqreturn_t (*ore_intr_handler)(void *ioq_vector); ++ irqreturn_t (*vfire_intr_handler)(void *ioq_vector); ++ irqreturn_t (*vfore_intr_handler)(void *ioq_vector); ++ irqreturn_t (*dma_intr_handler)(void *ioq_vector); ++ irqreturn_t (*dma_vf_intr_handler)(void *ioq_vector); ++ irqreturn_t (*pp_vf_intr_handler)(void *ioq_vector); ++ irqreturn_t (*misc_intr_handler)(void *ioq_vector); ++ irqreturn_t (*rsvd_intr_handler)(void *ioq_vector); + irqreturn_t (*ioq_intr_handler)(void *ioq_vector); + int (*soft_reset)(struct octep_device *oct); + void (*reinit_regs)(struct octep_device *oct); +@@ -73,7 +87,7 @@ struct octep_hw_ops { + + void (*enable_interrupts)(struct octep_device *oct); + void (*disable_interrupts)(struct octep_device *oct); +- bool (*poll_non_ioq_interrupts)(struct octep_device *oct); ++ void (*poll_non_ioq_interrupts)(struct octep_device *oct); + + void (*enable_io_queues)(struct octep_device *oct); + void (*disable_io_queues)(struct octep_device *oct); +@@ -368,6 +382,7 @@ int octep_setup_oqs(struct octep_device *oct); + void octep_free_oqs(struct octep_device *oct); + void octep_oq_dbell_init(struct octep_device *oct); + void octep_device_setup_cn93_pf(struct octep_device *oct); ++void octep_device_setup_cnxk_pf(struct octep_device *oct); + int octep_iq_process_completions(struct octep_iq *iq, u16 budget); + int octep_oq_process_rx(struct octep_oq *oq, int budget); + void octep_set_ethtool_ops(struct net_device *netdev); +diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h b/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h +index b25c3093dc7b4e..9ecfbabe3b9c5b 100644 +--- a/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h ++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h +@@ -370,4 +370,9 @@ + /* bit 1 for firmware heartbeat interrupt */ + #define CN93_SDP_EPF_OEI_RINT_DATA_BIT_HBEAT BIT_ULL(1) + ++#define CN93_PEM_BAR4_INDEX 7 ++#define CN93_PEM_BAR4_INDEX_SIZE 0x400000ULL ++#define CN93_PEM_BAR4_INDEX_OFFSET (CN93_PEM_BAR4_INDEX * CN93_PEM_BAR4_INDEX_SIZE) ++#define CN93_INT_ENA_BIT BIT_ULL(62) ++ + #endif /* _OCTEP_REGS_CN9K_PF_H_ */ +diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cnxk_pf.h b/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cnxk_pf.h +new file mode 100644 +index 00000000000000..f0b3937002b624 +--- /dev/null ++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cnxk_pf.h +@@ -0,0 +1,404 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* Marvell Octeon EP (EndPoint) Ethernet Driver ++ * ++ * Copyright (C) 2020 Marvell. ++ * ++ */ ++ ++#ifndef _OCTEP_REGS_CNXK_PF_H_ ++#define _OCTEP_REGS_CNXK_PF_H_ ++ ++/* ############################ RST ######################### */ ++#define CNXK_RST_BOOT 0x000087E006001600ULL ++#define CNXK_RST_CHIP_DOMAIN_W1S 0x000087E006001810ULL ++#define CNXK_RST_CORE_DOMAIN_W1S 0x000087E006001820ULL ++#define CNXK_RST_CORE_DOMAIN_W1C 0x000087E006001828ULL ++ ++#define CNXK_CONFIG_XPANSION_BAR 0x38 ++#define CNXK_CONFIG_PCIE_CAP 0x70 ++#define CNXK_CONFIG_PCIE_DEVCAP 0x74 ++#define CNXK_CONFIG_PCIE_DEVCTL 0x78 ++#define CNXK_CONFIG_PCIE_LINKCAP 0x7C ++#define CNXK_CONFIG_PCIE_LINKCTL 0x80 ++#define CNXK_CONFIG_PCIE_SLOTCAP 0x84 ++#define CNXK_CONFIG_PCIE_SLOTCTL 0x88 ++ ++#define CNXK_PCIE_SRIOV_FDL 0x188 /* 0x98 */ ++#define CNXK_PCIE_SRIOV_FDL_BIT_POS 0x10 ++#define CNXK_PCIE_SRIOV_FDL_MASK 0xFF ++ ++#define CNXK_CONFIG_PCIE_FLTMSK 0x720 ++ ++/* ################# Offsets of RING, EPF, MAC ######################### */ ++#define CNXK_RING_OFFSET (0x1ULL << 17) ++#define CNXK_EPF_OFFSET (0x1ULL << 25) ++#define CNXK_MAC_OFFSET (0x1ULL << 4) ++#define CNXK_BIT_ARRAY_OFFSET (0x1ULL << 4) ++#define CNXK_EPVF_RING_OFFSET (0x1ULL << 4) ++ ++/* ################# Scratch Registers ######################### */ ++#define CNXK_SDP_EPF_SCRATCH 0x209E0 ++ ++/* ################# Window Registers ######################### */ ++#define CNXK_SDP_WIN_WR_ADDR64 0x20000 ++#define CNXK_SDP_WIN_RD_ADDR64 0x20010 ++#define CNXK_SDP_WIN_WR_DATA64 0x20020 ++#define CNXK_SDP_WIN_WR_MASK_REG 0x20030 ++#define CNXK_SDP_WIN_RD_DATA64 0x20040 ++ ++#define CNXK_SDP_MAC_NUMBER 0x2C100 ++ ++/* ################# Global Previliged registers ######################### */ ++#define CNXK_SDP_EPF_RINFO 0x209F0 ++ ++#define CNXK_SDP_EPF_RINFO_SRN(val) ((val) & 0x7F) ++#define CNXK_SDP_EPF_RINFO_RPVF(val) (((val) >> 32) & 0xF) ++#define CNXK_SDP_EPF_RINFO_NVFS(val) (((val) >> 48) & 0x7F) ++ ++/* SDP Function select */ ++#define CNXK_SDP_FUNC_SEL_EPF_BIT_POS 7 ++#define CNXK_SDP_FUNC_SEL_FUNC_BIT_POS 0 ++ ++/* ##### RING IN (Into device from PCI: Tx Ring) REGISTERS #### */ ++#define CNXK_SDP_R_IN_CONTROL_START 0x10000 ++#define CNXK_SDP_R_IN_ENABLE_START 0x10010 ++#define CNXK_SDP_R_IN_INSTR_BADDR_START 0x10020 ++#define CNXK_SDP_R_IN_INSTR_RSIZE_START 0x10030 ++#define CNXK_SDP_R_IN_INSTR_DBELL_START 0x10040 ++#define CNXK_SDP_R_IN_CNTS_START 0x10050 ++#define CNXK_SDP_R_IN_INT_LEVELS_START 0x10060 ++#define CNXK_SDP_R_IN_PKT_CNT_START 0x10080 ++#define CNXK_SDP_R_IN_BYTE_CNT_START 0x10090 ++ ++#define CNXK_SDP_R_IN_CONTROL(ring) \ ++ (CNXK_SDP_R_IN_CONTROL_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_IN_ENABLE(ring) \ ++ (CNXK_SDP_R_IN_ENABLE_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_IN_INSTR_BADDR(ring) \ ++ (CNXK_SDP_R_IN_INSTR_BADDR_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_IN_INSTR_RSIZE(ring) \ ++ (CNXK_SDP_R_IN_INSTR_RSIZE_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_IN_INSTR_DBELL(ring) \ ++ (CNXK_SDP_R_IN_INSTR_DBELL_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_IN_CNTS(ring) \ ++ (CNXK_SDP_R_IN_CNTS_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_IN_INT_LEVELS(ring) \ ++ (CNXK_SDP_R_IN_INT_LEVELS_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_IN_PKT_CNT(ring) \ ++ (CNXK_SDP_R_IN_PKT_CNT_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_IN_BYTE_CNT(ring) \ ++ (CNXK_SDP_R_IN_BYTE_CNT_START + ((ring) * CNXK_RING_OFFSET)) ++ ++/* Rings per Virtual Function */ ++#define CNXK_R_IN_CTL_RPVF_MASK (0xF) ++#define CNXK_R_IN_CTL_RPVF_POS (48) ++ ++/* Number of instructions to be read in one MAC read request. ++ * setting to Max value(4) ++ */ ++#define CNXK_R_IN_CTL_IDLE (0x1ULL << 28) ++#define CNXK_R_IN_CTL_RDSIZE (0x3ULL << 25) ++#define CNXK_R_IN_CTL_IS_64B (0x1ULL << 24) ++#define CNXK_R_IN_CTL_D_NSR (0x1ULL << 8) ++#define CNXK_R_IN_CTL_D_ESR (0x1ULL << 6) ++#define CNXK_R_IN_CTL_D_ROR (0x1ULL << 5) ++#define CNXK_R_IN_CTL_NSR (0x1ULL << 3) ++#define CNXK_R_IN_CTL_ESR (0x1ULL << 1) ++#define CNXK_R_IN_CTL_ROR (0x1ULL << 0) ++ ++#define CNXK_R_IN_CTL_MASK (CNXK_R_IN_CTL_RDSIZE | CNXK_R_IN_CTL_IS_64B) ++ ++/* ##### RING OUT (out from device to PCI host: Rx Ring) REGISTERS #### */ ++#define CNXK_SDP_R_OUT_CNTS_START 0x10100 ++#define CNXK_SDP_R_OUT_INT_LEVELS_START 0x10110 ++#define CNXK_SDP_R_OUT_SLIST_BADDR_START 0x10120 ++#define CNXK_SDP_R_OUT_SLIST_RSIZE_START 0x10130 ++#define CNXK_SDP_R_OUT_SLIST_DBELL_START 0x10140 ++#define CNXK_SDP_R_OUT_CONTROL_START 0x10150 ++#define CNXK_SDP_R_OUT_WMARK_START 0x10160 ++#define CNXK_SDP_R_OUT_ENABLE_START 0x10170 ++#define CNXK_SDP_R_OUT_PKT_CNT_START 0x10180 ++#define CNXK_SDP_R_OUT_BYTE_CNT_START 0x10190 ++ ++#define CNXK_SDP_R_OUT_CONTROL(ring) \ ++ (CNXK_SDP_R_OUT_CONTROL_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_OUT_ENABLE(ring) \ ++ (CNXK_SDP_R_OUT_ENABLE_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_OUT_SLIST_BADDR(ring) \ ++ (CNXK_SDP_R_OUT_SLIST_BADDR_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_OUT_SLIST_RSIZE(ring) \ ++ (CNXK_SDP_R_OUT_SLIST_RSIZE_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_OUT_SLIST_DBELL(ring) \ ++ (CNXK_SDP_R_OUT_SLIST_DBELL_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_OUT_WMARK(ring) \ ++ (CNXK_SDP_R_OUT_WMARK_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_OUT_CNTS(ring) \ ++ (CNXK_SDP_R_OUT_CNTS_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_OUT_INT_LEVELS(ring) \ ++ (CNXK_SDP_R_OUT_INT_LEVELS_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_OUT_PKT_CNT(ring) \ ++ (CNXK_SDP_R_OUT_PKT_CNT_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_OUT_BYTE_CNT(ring) \ ++ (CNXK_SDP_R_OUT_BYTE_CNT_START + ((ring) * CNXK_RING_OFFSET)) ++ ++/*------------------ R_OUT Masks ----------------*/ ++#define CNXK_R_OUT_INT_LEVELS_BMODE BIT_ULL(63) ++#define CNXK_R_OUT_INT_LEVELS_TIMET (32) ++ ++#define CNXK_R_OUT_CTL_IDLE BIT_ULL(40) ++#define CNXK_R_OUT_CTL_ES_I BIT_ULL(34) ++#define CNXK_R_OUT_CTL_NSR_I BIT_ULL(33) ++#define CNXK_R_OUT_CTL_ROR_I BIT_ULL(32) ++#define CNXK_R_OUT_CTL_ES_D BIT_ULL(30) ++#define CNXK_R_OUT_CTL_NSR_D BIT_ULL(29) ++#define CNXK_R_OUT_CTL_ROR_D BIT_ULL(28) ++#define CNXK_R_OUT_CTL_ES_P BIT_ULL(26) ++#define CNXK_R_OUT_CTL_NSR_P BIT_ULL(25) ++#define CNXK_R_OUT_CTL_ROR_P BIT_ULL(24) ++#define CNXK_R_OUT_CTL_IMODE BIT_ULL(23) ++ ++/* ############### Interrupt Moderation Registers ############### */ ++#define CNXK_SDP_R_IN_INT_MDRT_CTL0_START 0x10280 ++#define CNXK_SDP_R_IN_INT_MDRT_CTL1_START 0x102A0 ++#define CNXK_SDP_R_IN_INT_MDRT_DBG_START 0x102C0 ++ ++#define CNXK_SDP_R_OUT_INT_MDRT_CTL0_START 0x10380 ++#define CNXK_SDP_R_OUT_INT_MDRT_CTL1_START 0x103A0 ++#define CNXK_SDP_R_OUT_INT_MDRT_DBG_START 0x103C0 ++ ++#define CNXK_SDP_R_OUT_CNTS_ISM_START 0x10510 ++#define CNXK_SDP_R_IN_CNTS_ISM_START 0x10520 ++ ++#define CNXK_SDP_R_IN_INT_MDRT_CTL0(ring) \ ++ (CNXK_SDP_R_IN_INT_MDRT_CTL0_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_IN_INT_MDRT_CTL1(ring) \ ++ (CNXK_SDP_R_IN_INT_MDRT_CTL1_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_IN_INT_MDRT_DBG(ring) \ ++ (CNXK_SDP_R_IN_INT_MDRT_DBG_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_OUT_INT_MDRT_CTL0(ring) \ ++ (CNXK_SDP_R_OUT_INT_MDRT_CTL0_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_OUT_INT_MDRT_CTL1(ring) \ ++ (CNXK_SDP_R_OUT_INT_MDRT_CTL1_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_OUT_INT_MDRT_DBG(ring) \ ++ (CNXK_SDP_R_OUT_INT_MDRT_DBG_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_OUT_CNTS_ISM(ring) \ ++ (CNXK_SDP_R_OUT_CNTS_ISM_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_IN_CNTS_ISM(ring) \ ++ (CNXK_SDP_R_IN_CNTS_ISM_START + ((ring) * CNXK_RING_OFFSET)) ++ ++/* ##################### Mail Box Registers ########################## */ ++/* INT register for VF. when a MBOX write from PF happed to a VF, ++ * corresponding bit will be set in this register as well as in ++ * PF_VF_INT register. ++ * ++ * This is a RO register, the int can be cleared by writing 1 to PF_VF_INT ++ */ ++/* Basically first 3 are from PF to VF. The last one is data from VF to PF */ ++#define CNXK_SDP_R_MBOX_PF_VF_DATA_START 0x10210 ++#define CNXK_SDP_R_MBOX_PF_VF_INT_START 0x10220 ++#define CNXK_SDP_R_MBOX_VF_PF_DATA_START 0x10230 ++ ++#define CNXK_SDP_R_MBOX_PF_VF_DATA(ring) \ ++ (CNXK_SDP_R_MBOX_PF_VF_DATA_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_MBOX_PF_VF_INT(ring) \ ++ (CNXK_SDP_R_MBOX_PF_VF_INT_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_MBOX_VF_PF_DATA(ring) \ ++ (CNXK_SDP_R_MBOX_VF_PF_DATA_START + ((ring) * CNXK_RING_OFFSET)) ++ ++/* ##################### Interrupt Registers ########################## */ ++#define CNXK_SDP_R_ERR_TYPE_START 0x10400 ++ ++#define CNXK_SDP_R_ERR_TYPE(ring) \ ++ (CNXK_SDP_R_ERR_TYPE_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_MBOX_ISM_START 0x10500 ++#define CNXK_SDP_R_OUT_CNTS_ISM_START 0x10510 ++#define CNXK_SDP_R_IN_CNTS_ISM_START 0x10520 ++ ++#define CNXK_SDP_R_MBOX_ISM(ring) \ ++ (CNXK_SDP_R_MBOX_ISM_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_OUT_CNTS_ISM(ring) \ ++ (CNXK_SDP_R_OUT_CNTS_ISM_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_R_IN_CNTS_ISM(ring) \ ++ (CNXK_SDP_R_IN_CNTS_ISM_START + ((ring) * CNXK_RING_OFFSET)) ++ ++#define CNXK_SDP_EPF_MBOX_RINT_START 0x20100 ++#define CNXK_SDP_EPF_MBOX_RINT_W1S_START 0x20120 ++#define CNXK_SDP_EPF_MBOX_RINT_ENA_W1C_START 0x20140 ++#define CNXK_SDP_EPF_MBOX_RINT_ENA_W1S_START 0x20160 ++ ++#define CNXK_SDP_EPF_VFIRE_RINT_START 0x20180 ++#define CNXK_SDP_EPF_VFIRE_RINT_W1S_START 0x201A0 ++#define CNXK_SDP_EPF_VFIRE_RINT_ENA_W1C_START 0x201C0 ++#define CNXK_SDP_EPF_VFIRE_RINT_ENA_W1S_START 0x201E0 ++ ++#define CNXK_SDP_EPF_IRERR_RINT 0x20200 ++#define CNXK_SDP_EPF_IRERR_RINT_W1S 0x20210 ++#define CNXK_SDP_EPF_IRERR_RINT_ENA_W1C 0x20220 ++#define CNXK_SDP_EPF_IRERR_RINT_ENA_W1S 0x20230 ++ ++#define CNXK_SDP_EPF_VFORE_RINT_START 0x20240 ++#define CNXK_SDP_EPF_VFORE_RINT_W1S_START 0x20260 ++#define CNXK_SDP_EPF_VFORE_RINT_ENA_W1C_START 0x20280 ++#define CNXK_SDP_EPF_VFORE_RINT_ENA_W1S_START 0x202A0 ++ ++#define CNXK_SDP_EPF_ORERR_RINT 0x20320 ++#define CNXK_SDP_EPF_ORERR_RINT_W1S 0x20330 ++#define CNXK_SDP_EPF_ORERR_RINT_ENA_W1C 0x20340 ++#define CNXK_SDP_EPF_ORERR_RINT_ENA_W1S 0x20350 ++ ++#define CNXK_SDP_EPF_OEI_RINT 0x20400 ++#define CNXK_SDP_EPF_OEI_RINT_W1S 0x20500 ++#define CNXK_SDP_EPF_OEI_RINT_ENA_W1C 0x20600 ++#define CNXK_SDP_EPF_OEI_RINT_ENA_W1S 0x20700 ++ ++#define CNXK_SDP_EPF_DMA_RINT 0x20800 ++#define CNXK_SDP_EPF_DMA_RINT_W1S 0x20810 ++#define CNXK_SDP_EPF_DMA_RINT_ENA_W1C 0x20820 ++#define CNXK_SDP_EPF_DMA_RINT_ENA_W1S 0x20830 ++ ++#define CNXK_SDP_EPF_DMA_INT_LEVEL_START 0x20840 ++#define CNXK_SDP_EPF_DMA_CNT_START 0x20860 ++#define CNXK_SDP_EPF_DMA_TIM_START 0x20880 ++ ++#define CNXK_SDP_EPF_MISC_RINT 0x208A0 ++#define CNXK_SDP_EPF_MISC_RINT_W1S 0x208B0 ++#define CNXK_SDP_EPF_MISC_RINT_ENA_W1C 0x208C0 ++#define CNXK_SDP_EPF_MISC_RINT_ENA_W1S 0x208D0 ++ ++#define CNXK_SDP_EPF_DMA_VF_RINT_START 0x208E0 ++#define CNXK_SDP_EPF_DMA_VF_RINT_W1S_START 0x20900 ++#define CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1C_START 0x20920 ++#define CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1S_START 0x20940 ++ ++#define CNXK_SDP_EPF_PP_VF_RINT_START 0x20960 ++#define CNXK_SDP_EPF_PP_VF_RINT_W1S_START 0x20980 ++#define CNXK_SDP_EPF_PP_VF_RINT_ENA_W1C_START 0x209A0 ++#define CNXK_SDP_EPF_PP_VF_RINT_ENA_W1S_START 0x209C0 ++ ++#define CNXK_SDP_EPF_MBOX_RINT(index) \ ++ (CNXK_SDP_EPF_MBOX_RINT_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_MBOX_RINT_W1S(index) \ ++ (CNXK_SDP_EPF_MBOX_RINT_W1S_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_MBOX_RINT_ENA_W1C(index) \ ++ (CNXK_SDP_EPF_MBOX_RINT_ENA_W1C_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_MBOX_RINT_ENA_W1S(index) \ ++ (CNXK_SDP_EPF_MBOX_RINT_ENA_W1S_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) ++ ++#define CNXK_SDP_EPF_VFIRE_RINT(index) \ ++ (CNXK_SDP_EPF_VFIRE_RINT_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_VFIRE_RINT_W1S(index) \ ++ (CNXK_SDP_EPF_VFIRE_RINT_W1S_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_VFIRE_RINT_ENA_W1C(index) \ ++ (CNXK_SDP_EPF_VFIRE_RINT_ENA_W1C_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_VFIRE_RINT_ENA_W1S(index) \ ++ (CNXK_SDP_EPF_VFIRE_RINT_ENA_W1S_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) ++ ++#define CNXK_SDP_EPF_VFORE_RINT(index) \ ++ (CNXK_SDP_EPF_VFORE_RINT_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_VFORE_RINT_W1S(index) \ ++ (CNXK_SDP_EPF_VFORE_RINT_W1S_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_VFORE_RINT_ENA_W1C(index) \ ++ (CNXK_SDP_EPF_VFORE_RINT_ENA_W1C_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_VFORE_RINT_ENA_W1S(index) \ ++ (CNXK_SDP_EPF_VFORE_RINT_ENA_W1S_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) ++ ++#define CNXK_SDP_EPF_DMA_VF_RINT(index) \ ++ (CNXK_SDP_EPF_DMA_VF_RINT_START + ((index) + CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_DMA_VF_RINT_W1S(index) \ ++ (CNXK_SDP_EPF_DMA_VF_RINT_W1S_START + ((index) + CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1C(index) \ ++ (CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1C_START + ((index) + CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1S(index) \ ++ (CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1S_START + ((index) + CNXK_BIT_ARRAY_OFFSET)) ++ ++#define CNXK_SDP_EPF_PP_VF_RINT(index) \ ++ (CNXK_SDP_EPF_PP_VF_RINT_START + ((index) + CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_PP_VF_RINT_W1S(index) \ ++ (CNXK_SDP_EPF_PP_VF_RINT_W1S_START + ((index) + CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_PP_VF_RINT_ENA_W1C(index) \ ++ (CNXK_SDP_EPF_PP_VF_RINT_ENA_W1C_START + ((index) + CNXK_BIT_ARRAY_OFFSET)) ++#define CNXK_SDP_EPF_PP_VF_RINT_ENA_W1S(index) \ ++ (CNXK_SDP_EPF_PP_VF_RINT_ENA_W1S_START + ((index) + CNXK_BIT_ARRAY_OFFSET)) ++ ++/*------------------ Interrupt Masks ----------------*/ ++#define CNXK_INTR_R_SEND_ISM BIT_ULL(63) ++#define CNXK_INTR_R_OUT_INT BIT_ULL(62) ++#define CNXK_INTR_R_IN_INT BIT_ULL(61) ++#define CNXK_INTR_R_MBOX_INT BIT_ULL(60) ++#define CNXK_INTR_R_RESEND BIT_ULL(59) ++#define CNXK_INTR_R_CLR_TIM BIT_ULL(58) ++ ++/* ####################### Ring Mapping Registers ################################## */ ++#define CNXK_SDP_EPVF_RING_START 0x26000 ++#define CNXK_SDP_IN_RING_TB_MAP_START 0x28000 ++#define CNXK_SDP_IN_RATE_LIMIT_START 0x2A000 ++#define CNXK_SDP_MAC_PF_RING_CTL_START 0x2C000 ++ ++#define CNXK_SDP_EPVF_RING(ring) \ ++ (CNXK_SDP_EPVF_RING_START + ((ring) * CNXK_EPVF_RING_OFFSET)) ++#define CNXK_SDP_IN_RING_TB_MAP(ring) \ ++ (CNXK_SDP_N_RING_TB_MAP_START + ((ring) * CNXK_EPVF_RING_OFFSET)) ++#define CNXK_SDP_IN_RATE_LIMIT(ring) \ ++ (CNXK_SDP_IN_RATE_LIMIT_START + ((ring) * CNXK_EPVF_RING_OFFSET)) ++#define CNXK_SDP_MAC_PF_RING_CTL(mac) \ ++ (CNXK_SDP_MAC_PF_RING_CTL_START + ((mac) * CNXK_MAC_OFFSET)) ++ ++#define CNXK_SDP_MAC_PF_RING_CTL_NPFS(val) ((val) & 0x3) ++#define CNXK_SDP_MAC_PF_RING_CTL_SRN(val) (((val) >> 8) & 0x7F) ++#define CNXK_SDP_MAC_PF_RING_CTL_RPPF(val) (((val) >> 16) & 0x3F) ++ ++/* Number of non-queue interrupts in CNXKxx */ ++#define CNXK_NUM_NON_IOQ_INTR 32 ++ ++/* bit 0 for control mbox interrupt */ ++#define CNXK_SDP_EPF_OEI_RINT_DATA_BIT_MBOX BIT_ULL(0) ++/* bit 1 for firmware heartbeat interrupt */ ++#define CNXK_SDP_EPF_OEI_RINT_DATA_BIT_HBEAT BIT_ULL(1) ++#define FW_STATUS_RUNNING 2ULL ++#define CNXK_PEMX_PFX_CSX_PFCFGX(pem, pf, offset) ({ typeof(offset) _off = (offset); \ ++ ((0x8e0000008000 | \ ++ (uint64_t)(pem) << 36 \ ++ | (pf) << 18 \ ++ | ((_off >> 16) & 1) << 16 \ ++ | (_off >> 3) << 3) \ ++ + (((_off >> 2) & 1) << 2)); \ ++ }) ++ ++/* Register defines for use with CNXK_PEMX_PFX_CSX_PFCFGX */ ++#define CNXK_PCIEEP_VSECST_CTL 0x418 ++ ++#define CNXK_PEM_BAR4_INDEX 7 ++#define CNXK_PEM_BAR4_INDEX_SIZE 0x400000ULL ++#define CNXK_PEM_BAR4_INDEX_OFFSET (CNXK_PEM_BAR4_INDEX * CNXK_PEM_BAR4_INDEX_SIZE) ++#define CNXK_INT_ENA_BIT BIT_ULL(62) ++ ++#endif /* _OCTEP_REGS_CNXK_PF_H_ */ +diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c +index c7f4e3c058b7fa..60afb6bf2f6792 100644 +--- a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c ++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c +@@ -12,6 +12,8 @@ + #include "octep_config.h" + #include "octep_main.h" + ++static void octep_oq_free_ring_buffers(struct octep_oq *oq); ++ + static void octep_oq_reset_indices(struct octep_oq *oq) + { + oq->host_read_idx = 0; +@@ -169,11 +171,15 @@ static int octep_setup_oq(struct octep_device *oct, int q_no) + goto oq_fill_buff_err; + + octep_oq_reset_indices(oq); +- oct->hw_ops.setup_oq_regs(oct, q_no); ++ if (oct->hw_ops.setup_oq_regs(oct, q_no)) ++ goto oq_setup_err; ++ + oct->num_oqs++; + + return 0; + ++oq_setup_err: ++ octep_oq_free_ring_buffers(oq); + oq_fill_buff_err: + vfree(oq->buff_info); + oq->buff_info = NULL; +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +index 729d1833a829a5..278dc1aabd4b41 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +@@ -1793,6 +1793,8 @@ static int cgx_lmac_exit(struct cgx *cgx) + cgx->mac_ops->mac_pause_frm_config(cgx, lmac->lmac_id, false); + cgx_configure_interrupt(cgx, lmac, lmac->lmac_id, true); + kfree(lmac->mac_to_index_bmap.bmap); ++ rvu_free_bitmap(&lmac->rx_fc_pfvf_bmap); ++ rvu_free_bitmap(&lmac->tx_fc_pfvf_bmap); + kfree(lmac->name); + kfree(lmac); + } +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +index 846049b6c4d60c..a7fcea9b1ee7e0 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +@@ -3444,11 +3444,22 @@ static void rvu_remove(struct pci_dev *pdev) + devm_kfree(&pdev->dev, rvu); + } + ++static void rvu_shutdown(struct pci_dev *pdev) ++{ ++ struct rvu *rvu = pci_get_drvdata(pdev); ++ ++ if (!rvu) ++ return; ++ ++ rvu_clear_rvum_blk_revid(rvu); ++} ++ + static struct pci_driver rvu_driver = { + .name = DRV_NAME, + .id_table = rvu_id_table, + .probe = rvu_probe, + .remove = rvu_remove, ++ .shutdown = rvu_shutdown, + }; + + static int __init rvu_init_module(void) +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +index 29487518ca6724..0703b0d8df783e 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +@@ -4509,12 +4509,18 @@ static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw) + /* Set chan/link to backpressure TL3 instead of TL2 */ + rvu_write64(rvu, blkaddr, NIX_AF_PSE_CHANNEL_LEVEL, 0x01); + +- /* Disable SQ manager's sticky mode operation (set TM6 = 0) ++ /* Disable SQ manager's sticky mode operation (set TM6 = 0, TM11 = 0) + * This sticky mode is known to cause SQ stalls when multiple +- * SQs are mapped to same SMQ and transmitting pkts at a time. ++ * SQs are mapped to same SMQ and transmitting pkts simultaneously. ++ * NIX PSE may deadlock when there are any sticky to non-sticky ++ * transmission. Hence disable it (TM5 = 0). + */ + cfg = rvu_read64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS); +- cfg &= ~BIT_ULL(15); ++ cfg &= ~(BIT_ULL(15) | BIT_ULL(14) | BIT_ULL(23)); ++ /* NIX may drop credits when condition clocks are turned off. ++ * Hence enable control flow clk (set TM9 = 1). ++ */ ++ cfg |= BIT_ULL(21); + rvu_write64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS, cfg); + + ltdefs = rvu->kpu.lt_def; +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +index 00ef6d201b973a..9b8a6046e6dff0 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +@@ -1070,32 +1070,35 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf, + rvu_write64(rvu, blkaddr, + NPC_AF_MCAMEX_BANKX_ACTION(index, bank), *(u64 *)&action); + +- /* update the VF flow rule action with the VF default entry action */ +- if (mcam_index < 0) +- npc_update_vf_flow_entry(rvu, mcam, blkaddr, pcifunc, +- *(u64 *)&action); +- + /* update the action change in default rule */ + pfvf = rvu_get_pfvf(rvu, pcifunc); + if (pfvf->def_ucast_rule) + pfvf->def_ucast_rule->rx_action = action; + +- index = npc_get_nixlf_mcam_index(mcam, pcifunc, +- nixlf, NIXLF_PROMISC_ENTRY); ++ if (mcam_index < 0) { ++ /* update the VF flow rule action with the VF default ++ * entry action ++ */ ++ npc_update_vf_flow_entry(rvu, mcam, blkaddr, pcifunc, ++ *(u64 *)&action); + +- /* If PF's promiscuous entry is enabled, +- * Set RSS action for that entry as well +- */ +- npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index, blkaddr, +- alg_idx); ++ index = npc_get_nixlf_mcam_index(mcam, pcifunc, ++ nixlf, NIXLF_PROMISC_ENTRY); + +- index = npc_get_nixlf_mcam_index(mcam, pcifunc, +- nixlf, NIXLF_ALLMULTI_ENTRY); +- /* If PF's allmulti entry is enabled, +- * Set RSS action for that entry as well +- */ +- npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index, blkaddr, +- alg_idx); ++ /* If PF's promiscuous entry is enabled, ++ * Set RSS action for that entry as well ++ */ ++ npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index, ++ blkaddr, alg_idx); ++ ++ index = npc_get_nixlf_mcam_index(mcam, pcifunc, ++ nixlf, NIXLF_ALLMULTI_ENTRY); ++ /* If PF's allmulti entry is enabled, ++ * Set RSS action for that entry as well ++ */ ++ npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index, ++ blkaddr, alg_idx); ++ } + } + + void npc_enadis_default_mce_entry(struct rvu *rvu, u16 pcifunc, +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +index b4194ec2a1f2d0..784130b4b08655 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +@@ -3097,6 +3097,7 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id) + return 0; + + err_pf_sriov_init: ++ otx2_unregister_dl(pf); + otx2_shutdown_tc(pf); + err_mcam_flow_del: + otx2_mcam_flow_del(pf); +diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c +index 1b43704baceb52..2bb77e2389701e 100644 +--- a/drivers/net/ethernet/marvell/skge.c ++++ b/drivers/net/ethernet/marvell/skge.c +@@ -78,7 +78,6 @@ static const struct pci_device_id skge_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x4320) }, /* SK-98xx V2.0 */ + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, /* D-Link DGE-530T (rev.B) */ + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4c00) }, /* D-Link DGE-530T */ +- { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302) }, /* D-Link DGE-530T Rev C1 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, /* Marvell Yukon 88E8001/8003/8010 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ + { PCI_DEVICE(PCI_VENDOR_ID_CNET, 0x434E) }, /* CNet PowerG-2000 */ +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c +index a2fc937d54617c..172862a70c70d2 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c +@@ -193,7 +193,9 @@ static int mlx5_sriov_enable(struct pci_dev *pdev, int num_vfs) + err = pci_enable_sriov(pdev, num_vfs); + if (err) { + mlx5_core_warn(dev, "pci_enable_sriov failed : %d\n", err); ++ devl_lock(devlink); + mlx5_device_disable_sriov(dev, num_vfs, true, true); ++ devl_unlock(devlink); + } + return err; + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c +index 7e36e1062139ea..ebe81c5aa61155 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c +@@ -664,8 +664,8 @@ static int dr_dump_domain_all(struct seq_file *file, struct mlx5dr_domain *dmn) + struct mlx5dr_table *tbl; + int ret; + +- mutex_lock(&dmn->dump_info.dbg_mutex); + mlx5dr_domain_lock(dmn); ++ mutex_lock(&dmn->dump_info.dbg_mutex); + + ret = dr_dump_domain(file, dmn); + if (ret < 0) +@@ -678,8 +678,8 @@ static int dr_dump_domain_all(struct seq_file *file, struct mlx5dr_domain *dmn) + } + + unlock_mutex: +- mlx5dr_domain_unlock(dmn); + mutex_unlock(&dmn->dump_info.dbg_mutex); ++ mlx5dr_domain_unlock(dmn); + return ret; + } + +diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c b/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c +index 5a932460db5819..6b2dbfbeef377b 100644 +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c +@@ -562,7 +562,7 @@ static int sparx5_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) + static struct ptp_clock_info sparx5_ptp_clock_info = { + .owner = THIS_MODULE, + .name = "sparx5 ptp", +- .max_adj = 200000, ++ .max_adj = 10000000, + .gettime64 = sparx5_ptp_gettime64, + .settime64 = sparx5_ptp_settime64, + .adjtime = sparx5_ptp_adjtime, +diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_qos.h b/drivers/net/ethernet/microchip/sparx5/sparx5_qos.h +index ced35033a6c5dd..b1c6c5c6f16caf 100644 +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_qos.h ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_qos.h +@@ -35,7 +35,7 @@ + #define SPX5_SE_BURST_UNIT 4096 + + /* Dwrr */ +-#define SPX5_DWRR_COST_MAX 63 ++#define SPX5_DWRR_COST_MAX 31 + + struct sparx5_shaper { + u32 mode; +diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c +index 21a87a3fc5562d..b516b4e1ed974b 100644 +--- a/drivers/net/ethernet/mscc/ocelot_net.c ++++ b/drivers/net/ethernet/mscc/ocelot_net.c +@@ -551,44 +551,81 @@ static int ocelot_port_stop(struct net_device *dev) + return 0; + } + +-static netdev_tx_t ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev) ++static bool ocelot_xmit_timestamp(struct ocelot *ocelot, int port, ++ struct sk_buff *skb, u32 *rew_op) + { +- struct ocelot_port_private *priv = netdev_priv(dev); +- struct ocelot_port *ocelot_port = &priv->port; +- struct ocelot *ocelot = ocelot_port->ocelot; +- int port = priv->port.index; +- u32 rew_op = 0; +- +- if (!static_branch_unlikely(&ocelot_fdma_enabled) && +- !ocelot_can_inject(ocelot, 0)) +- return NETDEV_TX_BUSY; +- +- /* Check if timestamping is needed */ + if (ocelot->ptp && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { + struct sk_buff *clone = NULL; + + if (ocelot_port_txtstamp_request(ocelot, port, skb, &clone)) { + kfree_skb(skb); +- return NETDEV_TX_OK; ++ return false; + } + + if (clone) + OCELOT_SKB_CB(skb)->clone = clone; + +- rew_op = ocelot_ptp_rew_op(skb); ++ *rew_op = ocelot_ptp_rew_op(skb); + } + +- if (static_branch_unlikely(&ocelot_fdma_enabled)) { +- ocelot_fdma_inject_frame(ocelot, port, rew_op, skb, dev); +- } else { +- ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb); ++ return true; ++} ++ ++static netdev_tx_t ocelot_port_xmit_fdma(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct ocelot_port_private *priv = netdev_priv(dev); ++ struct ocelot_port *ocelot_port = &priv->port; ++ struct ocelot *ocelot = ocelot_port->ocelot; ++ int port = priv->port.index; ++ u32 rew_op = 0; ++ ++ if (!ocelot_xmit_timestamp(ocelot, port, skb, &rew_op)) ++ return NETDEV_TX_OK; ++ ++ ocelot_fdma_inject_frame(ocelot, port, rew_op, skb, dev); ++ ++ return NETDEV_TX_OK; ++} + +- consume_skb(skb); ++static netdev_tx_t ocelot_port_xmit_inj(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct ocelot_port_private *priv = netdev_priv(dev); ++ struct ocelot_port *ocelot_port = &priv->port; ++ struct ocelot *ocelot = ocelot_port->ocelot; ++ int port = priv->port.index; ++ u32 rew_op = 0; ++ ++ ocelot_lock_inj_grp(ocelot, 0); ++ ++ if (!ocelot_can_inject(ocelot, 0)) { ++ ocelot_unlock_inj_grp(ocelot, 0); ++ return NETDEV_TX_BUSY; + } + ++ if (!ocelot_xmit_timestamp(ocelot, port, skb, &rew_op)) { ++ ocelot_unlock_inj_grp(ocelot, 0); ++ return NETDEV_TX_OK; ++ } ++ ++ ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb); ++ ++ ocelot_unlock_inj_grp(ocelot, 0); ++ ++ consume_skb(skb); ++ + return NETDEV_TX_OK; + } + ++static netdev_tx_t ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ if (static_branch_unlikely(&ocelot_fdma_enabled)) ++ return ocelot_port_xmit_fdma(skb, dev); ++ ++ return ocelot_port_xmit_inj(skb, dev); ++} ++ + enum ocelot_action_type { + OCELOT_MACT_LEARN, + OCELOT_MACT_FORGET, +diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +index 7b7e1c5b00f472..f3b1605f6adc9a 100644 +--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c ++++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +@@ -688,6 +688,9 @@ static int myri10ge_get_firmware_capabilities(struct myri10ge_priv *mgp) + + /* probe for IPv6 TSO support */ + mgp->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; ++ cmd.data0 = 0, ++ cmd.data1 = 0, ++ cmd.data2 = 0, + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE, + &cmd, 0); + if (status == 0) { +@@ -806,6 +809,7 @@ static int myri10ge_update_mac_address(struct myri10ge_priv *mgp, + | (addr[2] << 8) | addr[3]); + + cmd.data1 = ((addr[4] << 8) | (addr[5])); ++ cmd.data2 = 0; + + status = myri10ge_send_cmd(mgp, MXGEFW_SET_MAC_ADDRESS, &cmd, 0); + return status; +@@ -817,6 +821,9 @@ static int myri10ge_change_pause(struct myri10ge_priv *mgp, int pause) + int status, ctl; + + ctl = pause ? MXGEFW_ENABLE_FLOW_CONTROL : MXGEFW_DISABLE_FLOW_CONTROL; ++ cmd.data0 = 0, ++ cmd.data1 = 0, ++ cmd.data2 = 0, + status = myri10ge_send_cmd(mgp, ctl, &cmd, 0); + + if (status) { +@@ -834,6 +841,9 @@ myri10ge_change_promisc(struct myri10ge_priv *mgp, int promisc, int atomic) + int status, ctl; + + ctl = promisc ? MXGEFW_ENABLE_PROMISC : MXGEFW_DISABLE_PROMISC; ++ cmd.data0 = 0; ++ cmd.data1 = 0; ++ cmd.data2 = 0; + status = myri10ge_send_cmd(mgp, ctl, &cmd, atomic); + if (status) + netdev_err(mgp->dev, "Failed to set promisc mode\n"); +@@ -1946,6 +1956,8 @@ static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss) + /* get ring sizes */ + slice = ss - mgp->ss; + cmd.data0 = slice; ++ cmd.data1 = 0; ++ cmd.data2 = 0; + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd, 0); + tx_ring_size = cmd.data0; + cmd.data0 = slice; +@@ -2238,12 +2250,16 @@ static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice) + status = 0; + if (slice == 0 || (mgp->dev->real_num_tx_queues > 1)) { + cmd.data0 = slice; ++ cmd.data1 = 0; ++ cmd.data2 = 0; + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, + &cmd, 0); + ss->tx.lanai = (struct mcp_kreq_ether_send __iomem *) + (mgp->sram + cmd.data0); + } + cmd.data0 = slice; ++ cmd.data1 = 0; ++ cmd.data2 = 0; + status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET, + &cmd, 0); + ss->rx_small.lanai = (struct mcp_kreq_ether_recv __iomem *) +@@ -2312,6 +2328,7 @@ static int myri10ge_open(struct net_device *dev) + if (mgp->num_slices > 1) { + cmd.data0 = mgp->num_slices; + cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE; ++ cmd.data2 = 0; + if (mgp->dev->real_num_tx_queues > 1) + cmd.data1 |= MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES; + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES, +@@ -2414,6 +2431,8 @@ static int myri10ge_open(struct net_device *dev) + + /* now give firmware buffers sizes, and MTU */ + cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN; ++ cmd.data1 = 0; ++ cmd.data2 = 0; + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_MTU, &cmd, 0); + cmd.data0 = mgp->small_bytes; + status |= +@@ -2472,7 +2491,6 @@ abort_with_nothing: + static int myri10ge_close(struct net_device *dev) + { + struct myri10ge_priv *mgp = netdev_priv(dev); +- struct myri10ge_cmd cmd; + int status, old_down_cnt; + int i; + +@@ -2491,8 +2509,13 @@ static int myri10ge_close(struct net_device *dev) + + netif_tx_stop_all_queues(dev); + if (mgp->rebooted == 0) { ++ struct myri10ge_cmd cmd; ++ + old_down_cnt = mgp->down_cnt; + mb(); ++ cmd.data0 = 0; ++ cmd.data1 = 0; ++ cmd.data2 = 0; + status = + myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0); + if (status) +@@ -2956,6 +2979,9 @@ static void myri10ge_set_multicast_list(struct net_device *dev) + + /* Disable multicast filtering */ + ++ cmd.data0 = 0; ++ cmd.data1 = 0; ++ cmd.data2 = 0; + err = myri10ge_send_cmd(mgp, MXGEFW_ENABLE_ALLMULTI, &cmd, 1); + if (err != 0) { + netdev_err(dev, "Failed MXGEFW_ENABLE_ALLMULTI, error status: %d\n", +diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c +index d76e63f57ff1ec..b07dd56b0c76d2 100644 +--- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c ++++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c +@@ -222,9 +222,10 @@ static int ionic_get_link_ksettings(struct net_device *netdev, + /* This means there's no module plugged in */ + break; + default: +- dev_info(lif->ionic->dev, "unknown xcvr type pid=%d / 0x%x\n", +- idev->port_info->status.xcvr.pid, +- idev->port_info->status.xcvr.pid); ++ dev_dbg_ratelimited(lif->ionic->dev, ++ "unknown xcvr type pid=%d / 0x%x\n", ++ idev->port_info->status.xcvr.pid, ++ idev->port_info->status.xcvr.pid); + break; + } + +diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c +index b983b9c23be68a..61ca7377b612c1 100644 +--- a/drivers/net/ethernet/sun/sunhme.c ++++ b/drivers/net/ethernet/sun/sunhme.c +@@ -2551,6 +2551,9 @@ static int happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe) + goto err_out_clear_quattro; + } + ++ /* BIGMAC may have bogus sizes */ ++ if ((op->resource[3].end - op->resource[3].start) >= BMAC_REG_SIZE) ++ op->resource[3].end = op->resource[3].start + BMAC_REG_SIZE - 1; + hp->bigmacregs = devm_platform_ioremap_resource(op, 3); + if (IS_ERR(hp->bigmacregs)) { + dev_err(&op->dev, "Cannot map BIGMAC registers.\n"); +diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c +index 1c1d4806c119b8..1f98044b3666ff 100644 +--- a/drivers/net/ethernet/ti/cpsw_new.c ++++ b/drivers/net/ethernet/ti/cpsw_new.c +@@ -1967,7 +1967,7 @@ static int cpsw_probe(struct platform_device *pdev) + /* setup netdevs */ + ret = cpsw_create_ports(cpsw); + if (ret) +- goto clean_unregister_netdev; ++ goto clean_cpts; + + /* Grab RX and TX IRQs. Note that we also have RX_THRESHOLD and + * MISC IRQs which are always kept disabled with this driver so +@@ -1981,14 +1981,14 @@ static int cpsw_probe(struct platform_device *pdev) + 0, dev_name(dev), cpsw); + if (ret < 0) { + dev_err(dev, "error attaching irq (%d)\n", ret); +- goto clean_unregister_netdev; ++ goto clean_cpts; + } + + ret = devm_request_irq(dev, cpsw->irqs_table[1], cpsw_tx_interrupt, + 0, dev_name(dev), cpsw); + if (ret < 0) { + dev_err(dev, "error attaching irq (%d)\n", ret); +- goto clean_unregister_netdev; ++ goto clean_cpts; + } + + if (!cpsw->cpts) +@@ -1998,7 +1998,7 @@ static int cpsw_probe(struct platform_device *pdev) + 0, dev_name(&pdev->dev), cpsw); + if (ret < 0) { + dev_err(dev, "error attaching misc irq (%d)\n", ret); +- goto clean_unregister_netdev; ++ goto clean_cpts; + } + + /* Enable misc CPTS evnt_pend IRQ */ +@@ -2007,7 +2007,7 @@ static int cpsw_probe(struct platform_device *pdev) + skip_cpts: + ret = cpsw_register_notifiers(cpsw); + if (ret) +- goto clean_unregister_netdev; ++ goto clean_cpts; + + ret = cpsw_register_devlink(cpsw); + if (ret) +@@ -2029,8 +2029,6 @@ skip_cpts: + + clean_unregister_notifiers: + cpsw_unregister_notifiers(cpsw); +-clean_unregister_netdev: +- cpsw_unregister_ports(cpsw); + clean_cpts: + cpts_release(cpsw->cpts); + cpdma_ctlr_destroy(cpsw->dma); +diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c +index 3b0c5f177447bf..aa6d30dd35c383 100644 +--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c ++++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c +@@ -386,28 +386,29 @@ static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb) + __raw_writel(TX_SNAPSHOT_LOCKED, ®s->channel[ch].ch_event); + } + +-static int hwtstamp_set(struct net_device *netdev, struct ifreq *ifr) ++static int ixp4xx_hwtstamp_set(struct net_device *netdev, ++ struct kernel_hwtstamp_config *cfg, ++ struct netlink_ext_ack *extack) + { +- struct hwtstamp_config cfg; + struct ixp46x_ts_regs *regs; + struct port *port = netdev_priv(netdev); + int ret; + int ch; + +- if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) +- return -EFAULT; ++ if (!netif_running(netdev)) ++ return -EINVAL; + + ret = ixp46x_ptp_find(&port->timesync_regs, &port->phc_index); + if (ret) +- return ret; ++ return -EOPNOTSUPP; + + ch = PORT2CHANNEL(port); + regs = port->timesync_regs; + +- if (cfg.tx_type != HWTSTAMP_TX_OFF && cfg.tx_type != HWTSTAMP_TX_ON) ++ if (cfg->tx_type != HWTSTAMP_TX_OFF && cfg->tx_type != HWTSTAMP_TX_ON) + return -ERANGE; + +- switch (cfg.rx_filter) { ++ switch (cfg->rx_filter) { + case HWTSTAMP_FILTER_NONE: + port->hwts_rx_en = 0; + break; +@@ -423,39 +424,45 @@ static int hwtstamp_set(struct net_device *netdev, struct ifreq *ifr) + return -ERANGE; + } + +- port->hwts_tx_en = cfg.tx_type == HWTSTAMP_TX_ON; ++ port->hwts_tx_en = cfg->tx_type == HWTSTAMP_TX_ON; + + /* Clear out any old time stamps. */ + __raw_writel(TX_SNAPSHOT_LOCKED | RX_SNAPSHOT_LOCKED, + ®s->channel[ch].ch_event); + +- return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; ++ return 0; + } + +-static int hwtstamp_get(struct net_device *netdev, struct ifreq *ifr) ++static int ixp4xx_hwtstamp_get(struct net_device *netdev, ++ struct kernel_hwtstamp_config *cfg) + { +- struct hwtstamp_config cfg; + struct port *port = netdev_priv(netdev); + +- cfg.flags = 0; +- cfg.tx_type = port->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; ++ if (!cpu_is_ixp46x()) ++ return -EOPNOTSUPP; ++ ++ if (!netif_running(netdev)) ++ return -EINVAL; ++ ++ cfg->flags = 0; ++ cfg->tx_type = port->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; + + switch (port->hwts_rx_en) { + case 0: +- cfg.rx_filter = HWTSTAMP_FILTER_NONE; ++ cfg->rx_filter = HWTSTAMP_FILTER_NONE; + break; + case PTP_SLAVE_MODE: +- cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; ++ cfg->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; + break; + case PTP_MASTER_MODE: +- cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; ++ cfg->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; + break; + default: + WARN_ON_ONCE(1); + return -ERANGE; + } + +- return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; ++ return 0; + } + + static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location, +@@ -977,21 +984,6 @@ static void eth_set_mcast_list(struct net_device *dev) + } + + +-static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd) +-{ +- if (!netif_running(dev)) +- return -EINVAL; +- +- if (cpu_is_ixp46x()) { +- if (cmd == SIOCSHWTSTAMP) +- return hwtstamp_set(dev, req); +- if (cmd == SIOCGHWTSTAMP) +- return hwtstamp_get(dev, req); +- } +- +- return phy_mii_ioctl(dev->phydev, req, cmd); +-} +- + /* ethtool support */ + + static void ixp4xx_get_drvinfo(struct net_device *dev, +@@ -1376,9 +1368,11 @@ static const struct net_device_ops ixp4xx_netdev_ops = { + .ndo_stop = eth_close, + .ndo_start_xmit = eth_xmit, + .ndo_set_rx_mode = eth_set_mcast_list, +- .ndo_eth_ioctl = eth_ioctl, ++ .ndo_eth_ioctl = phy_do_ioctl_running, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, ++ .ndo_hwtstamp_get = ixp4xx_hwtstamp_get, ++ .ndo_hwtstamp_set = ixp4xx_hwtstamp_set, + }; + + static struct eth_plat_info *ixp4xx_of_get_platdata(struct device *dev) +diff --git a/drivers/net/ethernet/xscale/ptp_ixp46x.c b/drivers/net/ethernet/xscale/ptp_ixp46x.c +index 94203eb46e6b02..93c64db22a696c 100644 +--- a/drivers/net/ethernet/xscale/ptp_ixp46x.c ++++ b/drivers/net/ethernet/xscale/ptp_ixp46x.c +@@ -232,6 +232,9 @@ static struct ixp_clock ixp_clock; + + int ixp46x_ptp_find(struct ixp46x_ts_regs *__iomem *regs, int *phc_index) + { ++ if (!cpu_is_ixp46x()) ++ return -ENODEV; ++ + *regs = ixp_clock.regs; + *phc_index = ptp_clock_index(ixp_clock.ptp_clock); + +diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c +index fea7352e2a470c..4e28fcbf13c74d 100644 +--- a/drivers/net/macvlan.c ++++ b/drivers/net/macvlan.c +@@ -1577,6 +1577,11 @@ destroy_macvlan_port: + if (create) + macvlan_port_destroy(port->dev); + } ++ /* @dev might have been made visible before an error was detected. ++ * Make sure to observe an RCU grace period before our caller ++ * (rtnl_newlink()) frees it. ++ */ ++ synchronize_net(); + return err; + } + EXPORT_SYMBOL_GPL(macvlan_common_newlink); +diff --git a/drivers/net/mctp/mctp-i2c.c b/drivers/net/mctp/mctp-i2c.c +index fbe8483a07b589..c8c2c5dc46eb79 100644 +--- a/drivers/net/mctp/mctp-i2c.c ++++ b/drivers/net/mctp/mctp-i2c.c +@@ -243,6 +243,12 @@ static int mctp_i2c_slave_cb(struct i2c_client *client, + return 0; + + switch (event) { ++ case I2C_SLAVE_READ_REQUESTED: ++ case I2C_SLAVE_READ_PROCESSED: ++ /* MCTP I2C transport only uses writes */ ++ midev->rx_pos = 0; ++ *val = 0xff; ++ break; + case I2C_SLAVE_WRITE_RECEIVED: + if (midev->rx_pos < MCTP_I2C_BUFSZ) { + midev->rx_buffer[midev->rx_pos] = *val; +@@ -280,6 +286,9 @@ static int mctp_i2c_recv(struct mctp_i2c_dev *midev) + size_t recvlen; + int status; + ++ if (midev->rx_pos == 0) ++ return 0; ++ + /* + 1 for the PEC */ + if (midev->rx_pos < MCTP_I2C_MINLEN + 1) { + ndev->stats.rx_length_errors++; +diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig +index 3fd7dccf0f9c98..fe9e8483e8c59c 100644 +--- a/drivers/net/usb/Kconfig ++++ b/drivers/net/usb/Kconfig +@@ -320,7 +320,6 @@ config USB_NET_DM9601 + config USB_NET_SR9700 + tristate "CoreChip-sz SR9700 based USB 1.1 10/100 ethernet devices" + depends on USB_USBNET +- select CRC32 + help + This option adds support for CoreChip-sz SR9700 based USB 1.1 + 10/100 Ethernet adapters. +diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c +index ff439ef535ac9b..98346cb4ece01e 100644 +--- a/drivers/net/usb/catc.c ++++ b/drivers/net/usb/catc.c +@@ -64,6 +64,16 @@ static const char driver_name[] = "catc"; + #define CTRL_QUEUE 16 /* Max control requests in flight (power of two) */ + #define RX_PKT_SZ 1600 /* Max size of receive packet for F5U011 */ + ++/* ++ * USB endpoints. ++ */ ++ ++enum catc_usb_ep { ++ CATC_USB_EP_CONTROL = 0, ++ CATC_USB_EP_BULK = 1, ++ CATC_USB_EP_INT_IN = 2, ++}; ++ + /* + * Control requests. + */ +@@ -772,6 +782,13 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id + u8 broadcast[ETH_ALEN]; + u8 *macbuf; + int pktsz, ret = -ENOMEM; ++ static const u8 bulk_ep_addr[] = { ++ CATC_USB_EP_BULK | USB_DIR_OUT, ++ CATC_USB_EP_BULK | USB_DIR_IN, ++ 0}; ++ static const u8 int_ep_addr[] = { ++ CATC_USB_EP_INT_IN | USB_DIR_IN, ++ 0}; + + macbuf = kmalloc(ETH_ALEN, GFP_KERNEL); + if (!macbuf) +@@ -784,6 +801,14 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id + goto fail_mem; + } + ++ /* Verify that all required endpoints are present */ ++ if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) || ++ !usb_check_int_endpoints(intf, int_ep_addr)) { ++ dev_err(dev, "Missing or invalid endpoints\n"); ++ ret = -ENODEV; ++ goto fail_mem; ++ } ++ + netdev = alloc_etherdev(sizeof(struct catc)); + if (!netdev) + goto fail_mem; +@@ -828,14 +853,14 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id + usb_fill_control_urb(catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0), + NULL, NULL, 0, catc_ctrl_done, catc); + +- usb_fill_bulk_urb(catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, 1), +- NULL, 0, catc_tx_done, catc); ++ usb_fill_bulk_urb(catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, CATC_USB_EP_BULK), ++ NULL, 0, catc_tx_done, catc); + +- usb_fill_bulk_urb(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1), +- catc->rx_buf, pktsz, catc_rx_done, catc); ++ usb_fill_bulk_urb(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, CATC_USB_EP_BULK), ++ catc->rx_buf, pktsz, catc_rx_done, catc); + +- usb_fill_int_urb(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2), +- catc->irq_buf, 2, catc_irq_done, catc, 1); ++ usb_fill_int_urb(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, CATC_USB_EP_INT_IN), ++ catc->irq_buf, 2, catc_irq_done, catc, 1); + + if (!catc->is_f5u011) { + u32 *buf; +diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c +index c9efb7df892ec5..e01d14f6c36677 100644 +--- a/drivers/net/usb/kaweth.c ++++ b/drivers/net/usb/kaweth.c +@@ -765,7 +765,6 @@ static void kaweth_set_rx_mode(struct net_device *net) + + netdev_dbg(net, "Setting Rx mode to %d\n", packet_filter_bitmap); + +- netif_stop_queue(net); + + if (net->flags & IFF_PROMISC) { + packet_filter_bitmap |= KAWETH_PACKET_FILTER_PROMISCUOUS; +@@ -775,7 +774,6 @@ static void kaweth_set_rx_mode(struct net_device *net) + } + + kaweth->packet_filter_bitmap = packet_filter_bitmap; +- netif_wake_queue(net); + } + + /**************************************************************** +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index 121f1c15c67936..4a6377ac316090 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -2106,8 +2106,6 @@ static int lan78xx_mdio_init(struct lan78xx_net *dev) + dev->mdiobus->phy_mask = ~(1 << 1); + break; + case ID_REV_CHIP_ID_7801_: +- /* scan thru PHYAD[2..0] */ +- dev->mdiobus->phy_mask = ~(0xFF); + break; + } + +diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c +index c514483134f05f..0f16a133c75d13 100644 +--- a/drivers/net/usb/pegasus.c ++++ b/drivers/net/usb/pegasus.c +@@ -31,6 +31,17 @@ static const char driver_name[] = "pegasus"; + BMSR_100FULL | BMSR_ANEGCAPABLE) + #define CARRIER_CHECK_DELAY (2 * HZ) + ++/* ++ * USB endpoints. ++ */ ++ ++enum pegasus_usb_ep { ++ PEGASUS_USB_EP_CONTROL = 0, ++ PEGASUS_USB_EP_BULK_IN = 1, ++ PEGASUS_USB_EP_BULK_OUT = 2, ++ PEGASUS_USB_EP_INT_IN = 3, ++}; ++ + static bool loopback; + static bool mii_mode; + static char *devid; +@@ -545,7 +556,7 @@ static void read_bulk_callback(struct urb *urb) + goto tl_sched; + goon: + usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, +- usb_rcvbulkpipe(pegasus->usb, 1), ++ usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN), + pegasus->rx_skb->data, PEGASUS_MTU, + read_bulk_callback, pegasus); + rx_status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC); +@@ -585,7 +596,7 @@ static void rx_fixup(struct tasklet_struct *t) + return; + } + usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, +- usb_rcvbulkpipe(pegasus->usb, 1), ++ usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN), + pegasus->rx_skb->data, PEGASUS_MTU, + read_bulk_callback, pegasus); + try_again: +@@ -713,7 +724,7 @@ static netdev_tx_t pegasus_start_xmit(struct sk_buff *skb, + ((__le16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16); + skb_copy_from_linear_data(skb, pegasus->tx_buff + 2, skb->len); + usb_fill_bulk_urb(pegasus->tx_urb, pegasus->usb, +- usb_sndbulkpipe(pegasus->usb, 2), ++ usb_sndbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_OUT), + pegasus->tx_buff, count, + write_bulk_callback, pegasus); + if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) { +@@ -840,7 +851,7 @@ static int pegasus_open(struct net_device *net) + set_registers(pegasus, EthID, 6, net->dev_addr); + + usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, +- usb_rcvbulkpipe(pegasus->usb, 1), ++ usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN), + pegasus->rx_skb->data, PEGASUS_MTU, + read_bulk_callback, pegasus); + if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) { +@@ -851,7 +862,7 @@ static int pegasus_open(struct net_device *net) + } + + usb_fill_int_urb(pegasus->intr_urb, pegasus->usb, +- usb_rcvintpipe(pegasus->usb, 3), ++ usb_rcvintpipe(pegasus->usb, PEGASUS_USB_EP_INT_IN), + pegasus->intr_buff, sizeof(pegasus->intr_buff), + intr_callback, pegasus, pegasus->intr_interval); + if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) { +@@ -1136,10 +1147,24 @@ static int pegasus_probe(struct usb_interface *intf, + pegasus_t *pegasus; + int dev_index = id - pegasus_ids; + int res = -ENOMEM; ++ static const u8 bulk_ep_addr[] = { ++ PEGASUS_USB_EP_BULK_IN | USB_DIR_IN, ++ PEGASUS_USB_EP_BULK_OUT | USB_DIR_OUT, ++ 0}; ++ static const u8 int_ep_addr[] = { ++ PEGASUS_USB_EP_INT_IN | USB_DIR_IN, ++ 0}; + + if (pegasus_blacklisted(dev)) + return -ENODEV; + ++ /* Verify that all required endpoints are present */ ++ if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) || ++ !usb_check_int_endpoints(intf, int_ep_addr)) { ++ dev_err(&intf->dev, "Missing or invalid endpoints\n"); ++ return -ENODEV; ++ } ++ + net = alloc_etherdev(sizeof(struct pegasus)); + if (!net) + goto out; +diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c +index 386376ceeda25d..a2e3f9583def78 100644 +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -2445,6 +2445,8 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg) + ret = usb_submit_urb(agg->urb, GFP_ATOMIC); + if (ret < 0) + usb_autopm_put_interface_async(tp->intf); ++ else ++ netif_trans_update(tp->netdev); + + out_tx_fill: + return ret; +diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c +index 213b4817cfdf6d..e4d7bcd0d99c23 100644 +--- a/drivers/net/usb/sr9700.c ++++ b/drivers/net/usb/sr9700.c +@@ -18,7 +18,6 @@ + #include + #include + #include +-#include + #include + + #include "sr9700.h" +@@ -265,31 +264,15 @@ static const struct ethtool_ops sr9700_ethtool_ops = { + static void sr9700_set_multicast(struct net_device *netdev) + { + struct usbnet *dev = netdev_priv(netdev); +- /* We use the 20 byte dev->data for our 8 byte filter buffer +- * to avoid allocating memory that is tricky to free later +- */ +- u8 *hashes = (u8 *)&dev->data; + /* rx_ctl setting : enable, disable_long, disable_crc */ + u8 rx_ctl = RCR_RXEN | RCR_DIS_CRC | RCR_DIS_LONG; + +- memset(hashes, 0x00, SR_MCAST_SIZE); +- /* broadcast address */ +- hashes[SR_MCAST_SIZE - 1] |= SR_MCAST_ADDR_FLAG; +- if (netdev->flags & IFF_PROMISC) { ++ if (netdev->flags & IFF_PROMISC) + rx_ctl |= RCR_PRMSC; +- } else if (netdev->flags & IFF_ALLMULTI || +- netdev_mc_count(netdev) > SR_MCAST_MAX) { +- rx_ctl |= RCR_RUNT; +- } else if (!netdev_mc_empty(netdev)) { +- struct netdev_hw_addr *ha; +- +- netdev_for_each_mc_addr(ha, netdev) { +- u32 crc = ether_crc(ETH_ALEN, ha->addr) >> 26; +- hashes[crc >> 3] |= 1 << (crc & 0x7); +- } +- } ++ else if (netdev->flags & IFF_ALLMULTI || !netdev_mc_empty(netdev)) ++ /* The chip has no multicast filter */ ++ rx_ctl |= RCR_ALL; + +- sr_write_async(dev, SR_MAR, SR_MCAST_SIZE, hashes); + sr_write_reg_async(dev, SR_RCR, rx_ctl); + } + +diff --git a/drivers/net/usb/sr9700.h b/drivers/net/usb/sr9700.h +index ea2b4de621c867..c479908f7d823d 100644 +--- a/drivers/net/usb/sr9700.h ++++ b/drivers/net/usb/sr9700.h +@@ -104,9 +104,7 @@ + #define WCR_LINKEN (1 << 5) + /* Physical Address Reg */ + #define SR_PAR 0x10 /* 0x10 ~ 0x15 6 bytes for PAR */ +-/* Multicast Address Reg */ +-#define SR_MAR 0x16 /* 0x16 ~ 0x1D 8 bytes for MAR */ +-/* 0x1e unused */ ++/* 0x16 --> 0x1E unused */ + /* Phy Reset Reg */ + #define SR_PRR 0x1F + #define PRR_PHY_RST (1 << 0) +@@ -161,9 +159,6 @@ + /* parameters */ + #define SR_SHARE_TIMEOUT 1000 + #define SR_EEPROM_LEN 256 +-#define SR_MCAST_SIZE 8 +-#define SR_MCAST_ADDR_FLAG 0x80 +-#define SR_MCAST_MAX 64 + #define SR_TX_OVERHEAD 2 /* 2bytes header */ + #define SR_RX_OVERHEAD 7 /* 3bytes header + 4crc tail */ + +diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c +index 5b01642ca44e05..6b2d1e63855e8b 100644 +--- a/drivers/net/wan/farsync.c ++++ b/drivers/net/wan/farsync.c +@@ -2550,6 +2550,8 @@ fst_remove_one(struct pci_dev *pdev) + + fst_disable_intr(card); + free_irq(card->irq, card); ++ tasklet_kill(&fst_tx_task); ++ tasklet_kill(&fst_int_task); + + iounmap(card->ctlmem); + iounmap(card->mem); +diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c +index fd50bb313b9244..7176055cb38a5d 100644 +--- a/drivers/net/wan/fsl_ucc_hdlc.c ++++ b/drivers/net/wan/fsl_ucc_hdlc.c +@@ -790,18 +790,14 @@ static void uhdlc_memclean(struct ucc_hdlc_private *priv) + + if (priv->rx_buffer) { + dma_free_coherent(priv->dev, +- RX_BD_RING_LEN * MAX_RX_BUF_LENGTH, ++ (RX_BD_RING_LEN + TX_BD_RING_LEN) * MAX_RX_BUF_LENGTH, + priv->rx_buffer, priv->dma_rx_addr); + priv->rx_buffer = NULL; + priv->dma_rx_addr = 0; +- } + +- if (priv->tx_buffer) { +- dma_free_coherent(priv->dev, +- TX_BD_RING_LEN * MAX_RX_BUF_LENGTH, +- priv->tx_buffer, priv->dma_tx_addr); + priv->tx_buffer = NULL; + priv->dma_tx_addr = 0; ++ + } + } + +diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c +index 850d999615a2c3..7d0a522e5402ef 100644 +--- a/drivers/net/wireless/ath/ath10k/sdio.c ++++ b/drivers/net/wireless/ath/ath10k/sdio.c +@@ -2486,7 +2486,11 @@ void ath10k_sdio_fw_crashed_dump(struct ath10k *ar) + if (fast_dump) + ath10k_bmi_start(ar); + ++ mutex_lock(&ar->dump_mutex); ++ ++ spin_lock_bh(&ar->data_lock); + ar->stats.fw_crash_counter++; ++ spin_unlock_bh(&ar->data_lock); + + ath10k_sdio_disable_intrs(ar); + +@@ -2504,6 +2508,8 @@ void ath10k_sdio_fw_crashed_dump(struct ath10k *ar) + + ath10k_sdio_enable_intrs(ar); + ++ mutex_unlock(&ar->dump_mutex); ++ + ath10k_core_start_recovery(ar); + } + +diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c +index c7c96d210061d1..ee41f45b3426c0 100644 +--- a/drivers/net/wireless/ath/ath10k/wmi.c ++++ b/drivers/net/wireless/ath/ath10k/wmi.c +@@ -5283,8 +5283,6 @@ ath10k_wmi_event_peer_sta_ps_state_chg(struct ath10k *ar, struct sk_buff *skb) + struct ath10k_sta *arsta; + u8 peer_addr[ETH_ALEN]; + +- lockdep_assert_held(&ar->data_lock); +- + ev = (struct wmi_peer_sta_ps_state_chg_event *)skb->data; + ether_addr_copy(peer_addr, ev->peer_macaddr.addr); + +@@ -5299,7 +5297,9 @@ ath10k_wmi_event_peer_sta_ps_state_chg(struct ath10k *ar, struct sk_buff *skb) + } + + arsta = (struct ath10k_sta *)sta->drv_priv; ++ spin_lock_bh(&ar->data_lock); + arsta->peer_ps_state = __le32_to_cpu(ev->peer_ps_state); ++ spin_unlock_bh(&ar->data_lock); + + exit: + rcu_read_unlock(); +diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c +index 355424baeedde2..9eb8887f84e7e4 100644 +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -789,6 +789,34 @@ static const struct dmi_system_id ath11k_pm_quirk_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "21F9"), + }, + }, ++ { ++ .driver_data = (void *)ATH11K_PM_WOW, ++ .matches = { /* Z13 G1 */ ++ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "21D2"), ++ }, ++ }, ++ { ++ .driver_data = (void *)ATH11K_PM_WOW, ++ .matches = { /* Z13 G1 */ ++ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "21D3"), ++ }, ++ }, ++ { ++ .driver_data = (void *)ATH11K_PM_WOW, ++ .matches = { /* Z16 G1 */ ++ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "21D4"), ++ }, ++ }, ++ { ++ .driver_data = (void *)ATH11K_PM_WOW, ++ .matches = { /* Z16 G1 */ ++ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "21D5"), ++ }, ++ }, + {} + }; + +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 7e400a0e0eb111..fe920ecd25baf2 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -3804,7 +3804,7 @@ static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc, + + pref = soc->wmi_ab.preferred_hw_mode; + +- if (ath12k_hw_mode_pri_map[mode] < ath12k_hw_mode_pri_map[pref]) { ++ if (ath12k_hw_mode_pri_map[mode] <= ath12k_hw_mode_pri_map[pref]) { + svc_rdy_ext->pref_hw_mode_caps = *hw_mode_caps; + soc->wmi_ab.preferred_hw_mode = mode; + } +diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c +index 820100cac49150..76e67870f38519 100644 +--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c ++++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c +@@ -11384,7 +11384,13 @@ static const struct pci_device_id card_ids[] = { + {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2754, 0, 0, 0}, + {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2761, 0, 0, 0}, + {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2762, 0, 0, 0}, +- {PCI_VDEVICE(INTEL, 0x104f), 0}, ++ /* ++ * This ID conflicts with i40e, but the devices can be differentiated ++ * because i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200 ++ * devices use PCI_CLASS_NETWORK_OTHER. ++ */ ++ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x104f), ++ PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0}, + {PCI_VDEVICE(INTEL, 0x4220), 0}, /* BG */ + {PCI_VDEVICE(INTEL, 0x4221), 0}, /* BG */ + {PCI_VDEVICE(INTEL, 0x4223), 0}, /* ABG */ +diff --git a/drivers/net/wireless/intel/iwlegacy/3945-mac.c b/drivers/net/wireless/intel/iwlegacy/3945-mac.c +index 9eaf5ec133f9ef..5d61cebbdc400b 100644 +--- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c ++++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c +@@ -3262,7 +3262,9 @@ il3945_store_measurement(struct device *d, struct device_attribute *attr, + + D_INFO("Invoking measurement of type %d on " "channel %d (for '%s')\n", + type, params.channel, buf); ++ mutex_lock(&il->mutex); + il3945_get_measurement(il, ¶ms, type); ++ mutex_unlock(&il->mutex); + + return count; + } +diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c +index 75118e24061911..b345fa22563415 100644 +--- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c ++++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c +@@ -4612,7 +4612,9 @@ il4965_store_tx_power(struct device *d, struct device_attribute *attr, + if (ret) + IL_INFO("%s is not in decimal form.\n", buf); + else { ++ mutex_lock(&il->mutex); + ret = il_set_tx_power(il, val, false); ++ mutex_unlock(&il->mutex); + if (ret) + IL_ERR("failed setting tx power (0x%08x).\n", ret); + else +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +index 9c97691e603844..60472c89fca380 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +@@ -1722,6 +1722,20 @@ void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm, + + mvmvif = iwl_mvm_vif_from_mac80211(vif); + ++ /* ++ * len_low should be 2 + n*13 (where n is the number of descriptors. ++ * 13 is the size of a NoA descriptor). We can have either one or two ++ * descriptors. ++ */ ++ if (IWL_FW_CHECK(mvm, notif->noa_active && ++ notif->noa_attr.len_low != 2 + ++ sizeof(struct ieee80211_p2p_noa_desc) && ++ notif->noa_attr.len_low != 2 + ++ sizeof(struct ieee80211_p2p_noa_desc) * 2, ++ "Invalid noa_attr.len_low (%d)\n", ++ notif->noa_attr.len_low)) ++ return; ++ + new_data = kzalloc(sizeof(*new_data), GFP_KERNEL); + if (!new_data) + return; +diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c +index 2240b4db8c0366..d98c81539ba53b 100644 +--- a/drivers/net/wireless/marvell/libertas/if_usb.c ++++ b/drivers/net/wireless/marvell/libertas/if_usb.c +@@ -426,6 +426,8 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb + goto tx_ret; + } + ++ usb_kill_urb(cardp->tx_urb); ++ + usb_fill_bulk_urb(cardp->tx_urb, cardp->udev, + usb_sndbulkpipe(cardp->udev, + cardp->ep_out), +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index c7396ae9256b9b..9a4c23163fba4c 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -710,10 +710,10 @@ void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel) + } + EXPORT_SYMBOL(rtw_set_rx_freq_band); + +-void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period) ++void rtw_set_dtim_period(struct rtw_dev *rtwdev, u8 dtim_period) + { + rtw_write32_set(rtwdev, REG_TCR, BIT_TCR_UPDATE_TIMIE); +- rtw_write8(rtwdev, REG_DTIM_COUNTER_ROOT, dtim_period - 1); ++ rtw_write8(rtwdev, REG_DTIM_COUNTER_ROOT, dtim_period ? dtim_period - 1 : 0); + } + + void rtw_update_channel(struct rtw_dev *rtwdev, u8 center_channel, +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index c42ef8294d59e4..6e0e1c9c28f707 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -2154,7 +2154,7 @@ enum nl80211_band rtw_hw_to_nl80211_band(enum rtw_supported_band hw_band) + } + + void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel); +-void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period); ++void rtw_set_dtim_period(struct rtw_dev *rtwdev, u8 dtim_period); + void rtw_get_channel_params(struct cfg80211_chan_def *chandef, + struct rtw_channel_params *ch_param); + bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c +index a019f4085e7389..1f5af09aed99fa 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c +@@ -37,6 +37,8 @@ static const struct usb_device_id rtw_8821cu_id_table[] = { + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */ + { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd811, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0105, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Mercusys */ + {}, + }; + MODULE_DEVICE_TABLE(usb, rtw_8821cu_id_table); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +index 99318a82b43f4b..e792d7c8669910 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +@@ -1044,7 +1044,8 @@ static int rtw8822b_set_antenna(struct rtw_dev *rtwdev, + hal->antenna_tx = antenna_tx; + hal->antenna_rx = antenna_rx; + +- rtw8822b_config_trx_mode(rtwdev, antenna_tx, antenna_rx, false); ++ if (test_bit(RTW_FLAG_POWERON, rtwdev->flags)) ++ rtw8822b_config_trx_mode(rtwdev, antenna_tx, antenna_rx, false); + + return 0; + } +diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c +index 33b2543ee4d230..1ac5d021893d38 100644 +--- a/drivers/net/wireless/realtek/rtw89/pci.c ++++ b/drivers/net/wireless/realtek/rtw89/pci.c +@@ -3856,6 +3856,7 @@ static int __maybe_unused rtw89_pci_resume(struct device *dev) + rtw89_write32_clr(rtwdev, R_AX_PCIE_PS_CTRL_V1, + B_AX_SEL_REQ_ENTR_L1); + } ++ rtw89_pci_hci_ldo(rtwdev); + rtw89_pci_l2_hci_ldo(rtwdev); + rtw89_pci_filter_out(rtwdev); + rtw89_pci_link_cfg(rtwdev); +diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c +index aa9efca0402539..f558df21a2fd00 100644 +--- a/drivers/net/wireless/realtek/rtw89/wow.c ++++ b/drivers/net/wireless/realtek/rtw89/wow.c +@@ -100,6 +100,10 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev) + reason = rtw89_read8(rtwdev, wow_reason_reg); + + switch (reason) { ++ case RTW89_WOW_RSN_RX_DISASSOC: ++ wakeup.disconnect = true; ++ rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx disassoc\n"); ++ break; + case RTW89_WOW_RSN_RX_DEAUTH: + wakeup.disconnect = true; + rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx deauth\n"); +diff --git a/drivers/net/wireless/realtek/rtw89/wow.h b/drivers/net/wireless/realtek/rtw89/wow.h +index a2f7b2e3cdb4dd..fd85772ccb04ed 100644 +--- a/drivers/net/wireless/realtek/rtw89/wow.h ++++ b/drivers/net/wireless/realtek/rtw89/wow.h +@@ -8,6 +8,7 @@ + enum rtw89_wake_reason { + RTW89_WOW_RSN_RX_PTK_REKEY = 0x1, + RTW89_WOW_RSN_RX_GTK_REKEY = 0x2, ++ RTW89_WOW_RSN_RX_DISASSOC = 0x4, + RTW89_WOW_RSN_RX_DEAUTH = 0x8, + RTW89_WOW_RSN_DISCONNECT = 0x10, + RTW89_WOW_RSN_RX_MAGIC_PKT = 0x21, +diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c +index a78a25b872409a..61b547aab286a2 100644 +--- a/drivers/net/xen-netback/xenbus.c ++++ b/drivers/net/xen-netback/xenbus.c +@@ -735,10 +735,11 @@ static void connect(struct backend_info *be) + */ + requested_num_queues = xenbus_read_unsigned(dev->otherend, + "multi-queue-num-queues", 1); +- if (requested_num_queues > xenvif_max_queues) { ++ if (requested_num_queues > xenvif_max_queues || ++ requested_num_queues == 0) { + /* buggy or malicious guest */ + xenbus_dev_fatal(dev, -EINVAL, +- "guest requested %u queues, exceeding the maximum of %u.", ++ "guest requested %u queues, but valid range is 1 - %u.", + requested_num_queues, xenvif_max_queues); + return; + } +diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c +index 3ae4b41c59ac3d..edf5514795fd08 100644 +--- a/drivers/nfc/nxp-nci/i2c.c ++++ b/drivers/nfc/nxp-nci/i2c.c +@@ -305,7 +305,7 @@ static int nxp_nci_i2c_probe(struct i2c_client *client) + + r = request_threaded_irq(client->irq, NULL, + nxp_nci_i2c_irq_thread_fn, +- IRQF_TRIGGER_RISING | IRQF_ONESHOT, ++ IRQF_ONESHOT, + NXP_NCI_I2C_DRIVER_NAME, phy); + if (r < 0) + nfc_err(&client->dev, "Unable to register IRQ handler\n"); +diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c +index b5f93f07e22a4d..7f23f10ef64e47 100644 +--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c ++++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c +@@ -1202,7 +1202,8 @@ static void switchtec_ntb_init_mw(struct switchtec_ntb *sndev) + sndev->mmio_self_ctrl); + + sndev->nr_lut_mw = ioread16(&sndev->mmio_self_ctrl->lut_table_entries); +- sndev->nr_lut_mw = rounddown_pow_of_two(sndev->nr_lut_mw); ++ if (sndev->nr_lut_mw) ++ sndev->nr_lut_mw = rounddown_pow_of_two(sndev->nr_lut_mw); + + dev_dbg(&sndev->stdev->dev, "MWs: %d direct, %d lut\n", + sndev->nr_direct_mw, sndev->nr_lut_mw); +@@ -1212,7 +1213,8 @@ static void switchtec_ntb_init_mw(struct switchtec_ntb *sndev) + + sndev->peer_nr_lut_mw = + ioread16(&sndev->mmio_peer_ctrl->lut_table_entries); +- sndev->peer_nr_lut_mw = rounddown_pow_of_two(sndev->peer_nr_lut_mw); ++ if (sndev->peer_nr_lut_mw) ++ sndev->peer_nr_lut_mw = rounddown_pow_of_two(sndev->peer_nr_lut_mw); + + dev_dbg(&sndev->stdev->dev, "Peer MWs: %d direct, %d lut\n", + sndev->peer_nr_direct_mw, sndev->peer_nr_lut_mw); +@@ -1314,6 +1316,12 @@ static void switchtec_ntb_init_shared(struct switchtec_ntb *sndev) + for (i = 0; i < sndev->nr_lut_mw; i++) { + int idx = sndev->nr_direct_mw + i; + ++ if (idx >= MAX_MWS) { ++ dev_err(&sndev->stdev->dev, ++ "Total number of MW cannot be bigger than %d", MAX_MWS); ++ break; ++ } ++ + sndev->self_shared->mw_sizes[idx] = LUT_SIZE; + } + } +diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c +index 76cc5b49a5f1ee..0087c23655c7a4 100644 +--- a/drivers/ntb/ntb_transport.c ++++ b/drivers/ntb/ntb_transport.c +@@ -1227,9 +1227,9 @@ static int ntb_transport_init_queue(struct ntb_transport_ctx *nt, + qp->tx_max_entry = tx_size / qp->tx_max_frame; + + if (nt->debugfs_node_dir) { +- char debugfs_name[4]; ++ char debugfs_name[8]; + +- snprintf(debugfs_name, 4, "qp%d", qp_num); ++ snprintf(debugfs_name, sizeof(debugfs_name), "qp%d", qp_num); + qp->debugfs_dir = debugfs_create_dir(debugfs_name, + nt->debugfs_node_dir); + +diff --git a/drivers/nvdimm/nd_virtio.c b/drivers/nvdimm/nd_virtio.c +index 839f10ca56eac9..e5a7b031da2d6f 100644 +--- a/drivers/nvdimm/nd_virtio.c ++++ b/drivers/nvdimm/nd_virtio.c +@@ -44,6 +44,8 @@ static int virtio_pmem_flush(struct nd_region *nd_region) + unsigned long flags; + int err, err1; + ++ guard(mutex)(&vpmem->flush_lock); ++ + /* + * Don't bother to submit the request to the device if the device is + * not activated. +@@ -53,7 +55,6 @@ static int virtio_pmem_flush(struct nd_region *nd_region) + return -EIO; + } + +- might_sleep(); + req_data = kmalloc(sizeof(*req_data), GFP_KERNEL); + if (!req_data) + return -ENOMEM; +diff --git a/drivers/nvdimm/virtio_pmem.c b/drivers/nvdimm/virtio_pmem.c +index a92eb172f0e7eb..4eebb2ec3cf978 100644 +--- a/drivers/nvdimm/virtio_pmem.c ++++ b/drivers/nvdimm/virtio_pmem.c +@@ -49,6 +49,7 @@ static int virtio_pmem_probe(struct virtio_device *vdev) + goto out_err; + } + ++ mutex_init(&vpmem->flush_lock); + vpmem->vdev = vdev; + vdev->priv = vpmem; + err = init_vq(vpmem); +diff --git a/drivers/nvdimm/virtio_pmem.h b/drivers/nvdimm/virtio_pmem.h +index 0dddefe594c46a..f72cf17f9518fb 100644 +--- a/drivers/nvdimm/virtio_pmem.h ++++ b/drivers/nvdimm/virtio_pmem.h +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + + struct virtio_pmem_request { +@@ -35,6 +36,9 @@ struct virtio_pmem { + /* Virtio pmem request queue */ + struct virtqueue *req_vq; + ++ /* Serialize flush requests to the device. */ ++ struct mutex flush_lock; ++ + /* nvdimm bus registers virtio pmem device */ + struct nvdimm_bus *nvdimm_bus; + struct nvdimm_bus_descriptor nd_desc; +diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c +index dd00cc09ae5ec5..5b819bbd451afc 100644 +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -724,6 +724,7 @@ static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_nod + kfree(info.name); + if (ret) { + of_node_put(child); ++ of_node_put(info.np); + return ret; + } + } +diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c +index aae4e8ef9e3654..4b7e663feee3d6 100644 +--- a/drivers/of/unittest.c ++++ b/drivers/of/unittest.c +@@ -800,11 +800,13 @@ static void __init of_unittest_property_copy(void) + + new = __of_prop_dup(&p1, GFP_KERNEL); + unittest(new && propcmp(&p1, new), "empty property didn't copy correctly\n"); +- __of_prop_free(new); ++ if (new) ++ __of_prop_free(new); + + new = __of_prop_dup(&p2, GFP_KERNEL); + unittest(new && propcmp(&p2, new), "non-empty property didn't copy correctly\n"); +- __of_prop_free(new); ++ if (new) ++ __of_prop_free(new); + #endif + } + +diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c +index 8af7a837a0612c..615bb9b42c5137 100644 +--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c ++++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c +@@ -48,6 +48,8 @@ + #define PCIE_LTSSM_ENABLE_ENHANCE BIT(4) + #define PCIE_LTSSM_STATUS_MASK GENMASK(5, 0) + ++#define PCIE_TYPE0_HDR_DBI2_OFFSET 0x100000 ++ + struct rockchip_pcie { + struct dw_pcie pci; + void __iomem *apb_base; +@@ -198,6 +200,8 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *pp) + if (irq < 0) + return irq; + ++ pci->dbi_base2 = pci->dbi_base + PCIE_TYPE0_HDR_DBI2_OFFSET; ++ + ret = rockchip_pcie_init_irq_domain(rockchip); + if (ret < 0) + dev_err(dev, "failed to init irq domain\n"); +@@ -211,6 +215,10 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *pp) + rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE, + PCIE_CLIENT_GENERAL_CONTROL); + ++ /* Disable Root Ports BAR0 and BAR1 as they report bogus size */ ++ dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_0, 0x0); ++ dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_1, 0x0); ++ + return 0; + } + +diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c +index 48372013f26d23..82e575e4d3877a 100644 +--- a/drivers/pci/controller/pcie-mediatek.c ++++ b/drivers/pci/controller/pcie-mediatek.c +@@ -587,8 +587,10 @@ static int mtk_pcie_init_irq_domain(struct mtk_pcie_port *port, + + if (IS_ENABLED(CONFIG_PCI_MSI)) { + ret = mtk_pcie_allocate_msi_domains(port); +- if (ret) ++ if (ret) { ++ irq_domain_remove(port->irq_domain); + return ret; ++ } + } + + return 0; +diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c +index c28c3f094496a8..5b64203f100fc7 100644 +--- a/drivers/pci/endpoint/pci-ep-cfs.c ++++ b/drivers/pci/endpoint/pci-ep-cfs.c +@@ -65,8 +65,8 @@ static int pci_secondary_epc_epf_link(struct config_item *epf_item, + return 0; + } + +-static void pci_secondary_epc_epf_unlink(struct config_item *epc_item, +- struct config_item *epf_item) ++static void pci_secondary_epc_epf_unlink(struct config_item *epf_item, ++ struct config_item *epc_item) + { + struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent); + struct pci_epc_group *epc_group = to_pci_epc_group(epc_item); +@@ -126,8 +126,8 @@ static int pci_primary_epc_epf_link(struct config_item *epf_item, + return 0; + } + +-static void pci_primary_epc_epf_unlink(struct config_item *epc_item, +- struct config_item *epf_item) ++static void pci_primary_epc_epf_unlink(struct config_item *epf_item, ++ struct config_item *epc_item) + { + struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent); + struct pci_epc_group *epc_group = to_pci_epc_group(epc_item); +diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c +index f97c4f0e1c7a3d..b8bce45a599866 100644 +--- a/drivers/pci/iov.c ++++ b/drivers/pci/iov.c +@@ -447,7 +447,9 @@ static ssize_t sriov_numvfs_store(struct device *dev, + + if (num_vfs == 0) { + /* disable VFs */ ++ pci_lock_rescan_remove(); + ret = pdev->driver->sriov_configure(pdev, 0); ++ pci_unlock_rescan_remove(); + goto exit; + } + +@@ -459,7 +461,9 @@ static ssize_t sriov_numvfs_store(struct device *dev, + goto exit; + } + ++ pci_lock_rescan_remove(); + ret = pdev->driver->sriov_configure(pdev, num_vfs); ++ pci_unlock_rescan_remove(); + if (ret < 0) + goto exit; + +@@ -581,18 +585,15 @@ static int sriov_add_vfs(struct pci_dev *dev, u16 num_vfs) + if (dev->no_vf_scan) + return 0; + +- pci_lock_rescan_remove(); + for (i = 0; i < num_vfs; i++) { + rc = pci_iov_add_virtfn(dev, i); + if (rc) + goto failed; + } +- pci_unlock_rescan_remove(); + return 0; + failed: + while (i--) + pci_iov_remove_virtfn(dev, i); +- pci_unlock_rescan_remove(); + + return rc; + } +@@ -712,10 +713,8 @@ static void sriov_del_vfs(struct pci_dev *dev) + struct pci_sriov *iov = dev->sriov; + int i; + +- pci_lock_rescan_remove(); + for (i = 0; i < iov->num_VFs; i++) + pci_iov_remove_virtfn(dev, i); +- pci_unlock_rescan_remove(); + } + + static void sriov_disable(struct pci_dev *dev) +diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c +index b638731aa5ff2f..f6f4a778a98678 100644 +--- a/drivers/pci/msi/msi.c ++++ b/drivers/pci/msi/msi.c +@@ -737,7 +737,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, + + ret = msix_setup_interrupts(dev, entries, nvec, affd); + if (ret) +- goto out_disable; ++ goto out_unmap; + + /* Disable INTX */ + pci_intx_for_msi(dev, 0); +@@ -756,6 +756,8 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, + pcibios_free_irq(dev); + return 0; + ++out_unmap: ++ iounmap(dev->msix_base); + out_disable: + dev->msix_enabled = 0; + pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE, 0); +diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c +index 0f1e431bbfc20a..f97ac18a8dc8fc 100644 +--- a/drivers/pci/p2pdma.c ++++ b/drivers/pci/p2pdma.c +@@ -143,6 +143,7 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj, + ret = vm_insert_page(vma, vaddr, virt_to_page(kaddr)); + if (ret) { + gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len); ++ percpu_ref_put(ref); + return ret; + } + percpu_ref_get(ref); +diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c +index 61bded8623d218..508873c526e718 100644 +--- a/drivers/pci/pci-acpi.c ++++ b/drivers/pci/pci-acpi.c +@@ -246,21 +246,6 @@ static acpi_status decode_type1_hpx_record(union acpi_object *record, + return AE_OK; + } + +-static bool pcie_root_rcb_set(struct pci_dev *dev) +-{ +- struct pci_dev *rp = pcie_find_root_port(dev); +- u16 lnkctl; +- +- if (!rp) +- return false; +- +- pcie_capability_read_word(rp, PCI_EXP_LNKCTL, &lnkctl); +- if (lnkctl & PCI_EXP_LNKCTL_RCB) +- return true; +- +- return false; +-} +- + /* _HPX PCI Express Setting Record (Type 2) */ + struct hpx_type2 { + u32 revision; +@@ -286,6 +271,7 @@ static void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx) + { + int pos; + u32 reg32; ++ const struct pci_host_bridge *host; + + if (!hpx) + return; +@@ -293,6 +279,15 @@ static void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx) + if (!pci_is_pcie(dev)) + return; + ++ host = pci_find_host_bridge(dev->bus); ++ ++ /* ++ * Only do the _HPX Type 2 programming if OS owns PCIe native ++ * hotplug but not AER. ++ */ ++ if (!host->native_pcie_hotplug || host->native_aer) ++ return; ++ + if (hpx->revision > 1) { + pci_warn(dev, "PCIe settings rev %d not supported\n", + hpx->revision); +@@ -300,33 +295,27 @@ static void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx) + } + + /* +- * Don't allow _HPX to change MPS or MRRS settings. We manage +- * those to make sure they're consistent with the rest of the +- * platform. ++ * We only allow _HPX to program DEVCTL bits related to AER, namely ++ * PCI_EXP_DEVCTL_CERE, PCI_EXP_DEVCTL_NFERE, PCI_EXP_DEVCTL_FERE, ++ * and PCI_EXP_DEVCTL_URRE. ++ * ++ * The rest of DEVCTL is managed by the OS to make sure it's ++ * consistent with the rest of the platform. + */ +- hpx->pci_exp_devctl_and |= PCI_EXP_DEVCTL_PAYLOAD | +- PCI_EXP_DEVCTL_READRQ; +- hpx->pci_exp_devctl_or &= ~(PCI_EXP_DEVCTL_PAYLOAD | +- PCI_EXP_DEVCTL_READRQ); ++ hpx->pci_exp_devctl_and |= ~PCI_EXP_AER_FLAGS; ++ hpx->pci_exp_devctl_or &= PCI_EXP_AER_FLAGS; + + /* Initialize Device Control Register */ + pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, + ~hpx->pci_exp_devctl_and, hpx->pci_exp_devctl_or); + +- /* Initialize Link Control Register */ ++ /* Log if _HPX attempts to modify Link Control Register */ + if (pcie_cap_has_lnkctl(dev)) { +- +- /* +- * If the Root Port supports Read Completion Boundary of +- * 128, set RCB to 128. Otherwise, clear it. +- */ +- hpx->pci_exp_lnkctl_and |= PCI_EXP_LNKCTL_RCB; +- hpx->pci_exp_lnkctl_or &= ~PCI_EXP_LNKCTL_RCB; +- if (pcie_root_rcb_set(dev)) +- hpx->pci_exp_lnkctl_or |= PCI_EXP_LNKCTL_RCB; +- +- pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL, +- ~hpx->pci_exp_lnkctl_and, hpx->pci_exp_lnkctl_or); ++ if (hpx->pci_exp_lnkctl_and != 0xffff || ++ hpx->pci_exp_lnkctl_or != 0) ++ pci_info(dev, "_HPX attempts Link Control setting (AND %#06x OR %#06x)\n", ++ hpx->pci_exp_lnkctl_and, ++ hpx->pci_exp_lnkctl_or); + } + + /* Find Advanced Error Reporting Enhanced Capability */ +diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c +index 8c941d6267a5c5..b7a6d8a28fe930 100644 +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -1668,6 +1668,14 @@ static int pci_dma_configure(struct device *dev) + ret = acpi_dma_configure(dev, acpi_get_dma_attr(adev)); + } + ++ /* ++ * Attempt to enable ACS regardless of capability because some Root ++ * Ports (e.g. those quirked with *_intel_pch_acs_*) do not have ++ * the standard ACS capability but still support ACS via those ++ * quirks. ++ */ ++ pci_enable_acs(to_pci_dev(dev)); ++ + pci_put_host_bridge_device(bridge); + + if (!ret && !driver->driver_managed_dma) { +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index 9a3f6bb60eb4d8..d7d7913eb0ee93 100644 +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -986,7 +986,7 @@ static void pci_std_enable_acs(struct pci_dev *dev) + * pci_enable_acs - enable ACS if hardware support it + * @dev: the PCI device + */ +-static void pci_enable_acs(struct pci_dev *dev) ++void pci_enable_acs(struct pci_dev *dev) + { + if (!pci_acs_enable) + goto disable_acs_redir; +@@ -1427,6 +1427,9 @@ static int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state, bool + || (state == PCI_D2 && !dev->d2_support)) + return -EIO; + ++ if (dev->current_state == state) ++ return 0; ++ + pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); + if (PCI_POSSIBLE_ERROR(pmcsr)) { + pci_err(dev, "Unable to change power state from %s to %s, device inaccessible\n", +@@ -3758,14 +3761,6 @@ bool pci_acs_path_enabled(struct pci_dev *start, + void pci_acs_init(struct pci_dev *dev) + { + dev->acs_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); +- +- /* +- * Attempt to enable ACS regardless of capability because some Root +- * Ports (e.g. those quirked with *_intel_pch_acs_*) do not have +- * the standard ACS capability but still support ACS via those +- * quirks. +- */ +- pci_enable_acs(dev); + } + + /** +@@ -5790,10 +5785,9 @@ unlock: + /* Do any devices on or below this slot prevent a bus reset? */ + static bool pci_slot_resettable(struct pci_slot *slot) + { +- struct pci_dev *dev; ++ struct pci_dev *dev, *bridge = slot->bus->self; + +- if (slot->bus->self && +- (slot->bus->self->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)) ++ if (bridge && (bridge->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)) + return false; + + list_for_each_entry(dev, &slot->bus->devices, bus_list) { +@@ -5810,7 +5804,10 @@ static bool pci_slot_resettable(struct pci_slot *slot) + /* Lock devices from the top of the tree down */ + static void pci_slot_lock(struct pci_slot *slot) + { +- struct pci_dev *dev; ++ struct pci_dev *dev, *bridge = slot->bus->self; ++ ++ if (bridge) ++ pci_dev_lock(bridge); + + list_for_each_entry(dev, &slot->bus->devices, bus_list) { + if (!dev->slot || dev->slot != slot) +@@ -5825,7 +5822,7 @@ static void pci_slot_lock(struct pci_slot *slot) + /* Unlock devices from the bottom of the tree up */ + static void pci_slot_unlock(struct pci_slot *slot) + { +- struct pci_dev *dev; ++ struct pci_dev *dev, *bridge = slot->bus->self; + + list_for_each_entry(dev, &slot->bus->devices, bus_list) { + if (!dev->slot || dev->slot != slot) +@@ -5835,21 +5832,25 @@ static void pci_slot_unlock(struct pci_slot *slot) + else + pci_dev_unlock(dev); + } ++ ++ if (bridge) ++ pci_dev_unlock(bridge); + } + + /* Return 1 on successful lock, 0 on contention */ + static int pci_slot_trylock(struct pci_slot *slot) + { +- struct pci_dev *dev; ++ struct pci_dev *dev, *bridge = slot->bus->self; ++ ++ if (bridge && !pci_dev_trylock(bridge)) ++ return 0; + + list_for_each_entry(dev, &slot->bus->devices, bus_list) { + if (!dev->slot || dev->slot != slot) + continue; + if (dev->subordinate) { +- if (!pci_bus_trylock(dev->subordinate)) { +- pci_dev_unlock(dev); ++ if (!pci_bus_trylock(dev->subordinate)) + goto unlock; +- } + } else if (!pci_dev_trylock(dev)) + goto unlock; + } +@@ -5865,6 +5866,9 @@ unlock: + else + pci_dev_unlock(dev); + } ++ ++ if (bridge) ++ pci_dev_unlock(bridge); + return 0; + } + +diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h +index d69a17947ffcef..485f917641e11c 100644 +--- a/drivers/pci/pci.h ++++ b/drivers/pci/pci.h +@@ -22,6 +22,31 @@ + */ + #define PCIE_PME_TO_L2_TIMEOUT_US 10000 + ++/* Message Routing (r[2:0]); PCIe r6.0, sec 2.2.8 */ ++#define PCIE_MSG_TYPE_R_RC 0 ++#define PCIE_MSG_TYPE_R_ADDR 1 ++#define PCIE_MSG_TYPE_R_ID 2 ++#define PCIE_MSG_TYPE_R_BC 3 ++#define PCIE_MSG_TYPE_R_LOCAL 4 ++#define PCIE_MSG_TYPE_R_GATHER 5 ++ ++/* INTx Mechanism Messages; PCIe r6.0, sec 2.2.8.1 */ ++#define PCIE_MSG_CODE_ASSERT_INTA 0x20 ++#define PCIE_MSG_CODE_ASSERT_INTB 0x21 ++#define PCIE_MSG_CODE_ASSERT_INTC 0x22 ++#define PCIE_MSG_CODE_ASSERT_INTD 0x23 ++#define PCIE_MSG_CODE_DEASSERT_INTA 0x24 ++#define PCIE_MSG_CODE_DEASSERT_INTB 0x25 ++#define PCIE_MSG_CODE_DEASSERT_INTC 0x26 ++#define PCIE_MSG_CODE_DEASSERT_INTD 0x27 ++ ++#define PCI_BUS_BRIDGE_IO_WINDOW 0 ++#define PCI_BUS_BRIDGE_MEM_WINDOW 1 ++#define PCI_BUS_BRIDGE_PREF_MEM_WINDOW 2 ++ ++#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \ ++ PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) ++ + extern const unsigned char pcie_link_speed[]; + extern bool pci_early_dump; + +@@ -530,6 +555,7 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev, + } + + void pci_acs_init(struct pci_dev *dev); ++void pci_enable_acs(struct pci_dev *dev); + #ifdef CONFIG_PCI_QUIRKS + int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags); + int pci_dev_specific_enable_acs(struct pci_dev *dev); +diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c +index 8e700020ee0bc3..42a0f86b72fa5a 100644 +--- a/drivers/pci/pcie/aer.c ++++ b/drivers/pci/pcie/aer.c +@@ -218,9 +218,6 @@ void pcie_ecrc_get_policy(char *str) + } + #endif /* CONFIG_PCIE_ECRC */ + +-#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \ +- PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) +- + int pcie_aer_is_native(struct pci_dev *dev) + { + struct pci_host_bridge *host = pci_find_host_bridge(dev->bus); +diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c +index d6e5fef54c3b8d..dac3ba1b2552f1 100644 +--- a/drivers/pci/pcie/portdrv.c ++++ b/drivers/pci/pcie/portdrv.c +@@ -554,10 +554,10 @@ static int pcie_port_remove_service(struct device *dev) + + pciedev = to_pcie_device(dev); + driver = to_service_driver(dev->driver); +- if (driver && driver->remove) { ++ if (driver && driver->remove) + driver->remove(pciedev); +- put_device(dev); +- } ++ ++ put_device(dev); + return 0; + } + +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index 5557290b63dc15..cc56bf47c4a3f3 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -344,64 +344,12 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) + } + } + +-static void pci_read_bridge_windows(struct pci_dev *bridge) ++static void pci_read_bridge_io(struct pci_dev *dev, struct resource *res, ++ bool log) + { +- u16 io; +- u32 pmem, tmp; +- +- pci_read_config_word(bridge, PCI_IO_BASE, &io); +- if (!io) { +- pci_write_config_word(bridge, PCI_IO_BASE, 0xe0f0); +- pci_read_config_word(bridge, PCI_IO_BASE, &io); +- pci_write_config_word(bridge, PCI_IO_BASE, 0x0); +- } +- if (io) +- bridge->io_window = 1; +- +- /* +- * DECchip 21050 pass 2 errata: the bridge may miss an address +- * disconnect boundary by one PCI data phase. Workaround: do not +- * use prefetching on this device. +- */ +- if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001) +- return; +- +- pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); +- if (!pmem) { +- pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, +- 0xffe0fff0); +- pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); +- pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0); +- } +- if (!pmem) +- return; +- +- bridge->pref_window = 1; +- +- if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { +- +- /* +- * Bridge claims to have a 64-bit prefetchable memory +- * window; verify that the upper bits are actually +- * writable. +- */ +- pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &pmem); +- pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, +- 0xffffffff); +- pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &tmp); +- pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, pmem); +- if (tmp) +- bridge->pref_64_window = 1; +- } +-} +- +-static void pci_read_bridge_io(struct pci_bus *child) +-{ +- struct pci_dev *dev = child->self; + u8 io_base_lo, io_limit_lo; + unsigned long io_mask, io_granularity, base, limit; + struct pci_bus_region region; +- struct resource *res; + + io_mask = PCI_IO_RANGE_MASK; + io_granularity = 0x1000; +@@ -411,7 +359,6 @@ static void pci_read_bridge_io(struct pci_bus *child) + io_granularity = 0x400; + } + +- res = child->resource[0]; + pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); + pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo); + base = (io_base_lo & io_mask) << 8; +@@ -431,19 +378,18 @@ static void pci_read_bridge_io(struct pci_bus *child) + region.start = base; + region.end = limit + io_granularity - 1; + pcibios_bus_to_resource(dev->bus, res, ®ion); +- pci_info(dev, " bridge window %pR\n", res); ++ if (log) ++ pci_info(dev, " bridge window %pR\n", res); + } + } + +-static void pci_read_bridge_mmio(struct pci_bus *child) ++static void pci_read_bridge_mmio(struct pci_dev *dev, struct resource *res, ++ bool log) + { +- struct pci_dev *dev = child->self; + u16 mem_base_lo, mem_limit_lo; + unsigned long base, limit; + struct pci_bus_region region; +- struct resource *res; + +- res = child->resource[1]; + pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo); + pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo); + base = ((unsigned long) mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16; +@@ -453,20 +399,19 @@ static void pci_read_bridge_mmio(struct pci_bus *child) + region.start = base; + region.end = limit + 0xfffff; + pcibios_bus_to_resource(dev->bus, res, ®ion); +- pci_info(dev, " bridge window %pR\n", res); ++ if (log) ++ pci_info(dev, " bridge window %pR\n", res); + } + } + +-static void pci_read_bridge_mmio_pref(struct pci_bus *child) ++static void pci_read_bridge_mmio_pref(struct pci_dev *dev, struct resource *res, ++ bool log) + { +- struct pci_dev *dev = child->self; + u16 mem_base_lo, mem_limit_lo; + u64 base64, limit64; + pci_bus_addr_t base, limit; + struct pci_bus_region region; +- struct resource *res; + +- res = child->resource[2]; + pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); + pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); + base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16; +@@ -506,8 +451,75 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child) + region.start = base; + region.end = limit + 0xfffff; + pcibios_bus_to_resource(dev->bus, res, ®ion); +- pci_info(dev, " bridge window %pR\n", res); ++ if (log) ++ pci_info(dev, " bridge window %pR\n", res); ++ } ++} ++ ++static void pci_read_bridge_windows(struct pci_dev *bridge) ++{ ++ u32 buses; ++ u16 io; ++ u32 pmem, tmp; ++ struct resource res; ++ ++ pci_read_config_dword(bridge, PCI_PRIMARY_BUS, &buses); ++ res.flags = IORESOURCE_BUS; ++ res.start = (buses >> 8) & 0xff; ++ res.end = (buses >> 16) & 0xff; ++ pci_info(bridge, "PCI bridge to %pR%s\n", &res, ++ bridge->transparent ? " (subtractive decode)" : ""); ++ ++ pci_read_config_word(bridge, PCI_IO_BASE, &io); ++ if (!io) { ++ pci_write_config_word(bridge, PCI_IO_BASE, 0xe0f0); ++ pci_read_config_word(bridge, PCI_IO_BASE, &io); ++ pci_write_config_word(bridge, PCI_IO_BASE, 0x0); ++ } ++ if (io) { ++ bridge->io_window = 1; ++ pci_read_bridge_io(bridge, &res, true); + } ++ ++ pci_read_bridge_mmio(bridge, &res, true); ++ ++ /* ++ * DECchip 21050 pass 2 errata: the bridge may miss an address ++ * disconnect boundary by one PCI data phase. Workaround: do not ++ * use prefetching on this device. ++ */ ++ if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001) ++ return; ++ ++ pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); ++ if (!pmem) { ++ pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, ++ 0xffe0fff0); ++ pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); ++ pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0); ++ } ++ if (!pmem) ++ return; ++ ++ bridge->pref_window = 1; ++ ++ if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { ++ ++ /* ++ * Bridge claims to have a 64-bit prefetchable memory ++ * window; verify that the upper bits are actually ++ * writable. ++ */ ++ pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &pmem); ++ pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, ++ 0xffffffff); ++ pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &tmp); ++ pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, pmem); ++ if (tmp) ++ bridge->pref_64_window = 1; ++ } ++ ++ pci_read_bridge_mmio_pref(bridge, &res, true); + } + + void pci_read_bridge_bases(struct pci_bus *child) +@@ -527,9 +539,13 @@ void pci_read_bridge_bases(struct pci_bus *child) + for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) + child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i]; + +- pci_read_bridge_io(child); +- pci_read_bridge_mmio(child); +- pci_read_bridge_mmio_pref(child); ++ pci_read_bridge_io(child->self, ++ child->resource[PCI_BUS_BRIDGE_IO_WINDOW], false); ++ pci_read_bridge_mmio(child->self, ++ child->resource[PCI_BUS_BRIDGE_MEM_WINDOW], false); ++ pci_read_bridge_mmio_pref(child->self, ++ child->resource[PCI_BUS_BRIDGE_PREF_MEM_WINDOW], ++ false); + + if (dev->transparent) { + pci_bus_for_each_resource(child->parent, res) { +@@ -2101,7 +2117,8 @@ int pci_configure_extended_tags(struct pci_dev *dev, void *ign) + u16 ctl; + int ret; + +- if (!pci_is_pcie(dev)) ++ /* PCI_EXP_DEVCTL_EXT_TAG is RsvdP in VFs */ ++ if (!pci_is_pcie(dev) || dev->is_virtfn) + return 0; + + ret = pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap); +@@ -2287,6 +2304,37 @@ static void pci_configure_serr(struct pci_dev *dev) + } + } + ++static void pci_configure_rcb(struct pci_dev *dev) ++{ ++ struct pci_dev *rp; ++ u16 rp_lnkctl; ++ ++ /* ++ * Per PCIe r7.0, sec 7.5.3.7, RCB is only meaningful in Root Ports ++ * (where it is read-only), Endpoints, and Bridges. It may only be ++ * set for Endpoints and Bridges if it is set in the Root Port. For ++ * Endpoints, it is 'RsvdP' for Virtual Functions. ++ */ ++ if (!pci_is_pcie(dev) || ++ pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || ++ pci_pcie_type(dev) == PCI_EXP_TYPE_UPSTREAM || ++ pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM || ++ pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC || ++ dev->is_virtfn) ++ return; ++ ++ /* Root Port often not visible to virtualized guests */ ++ rp = pcie_find_root_port(dev); ++ if (!rp) ++ return; ++ ++ pcie_capability_read_word(rp, PCI_EXP_LNKCTL, &rp_lnkctl); ++ pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL, ++ PCI_EXP_LNKCTL_RCB, ++ (rp_lnkctl & PCI_EXP_LNKCTL_RCB) ? ++ PCI_EXP_LNKCTL_RCB : 0); ++} ++ + static void pci_configure_device(struct pci_dev *dev) + { + pci_configure_mps(dev); +@@ -2295,6 +2343,7 @@ static void pci_configure_device(struct pci_dev *dev) + pci_configure_ltr(dev); + pci_configure_eetlp_prefix(dev); + pci_configure_serr(dev); ++ pci_configure_rcb(dev); + + pci_acpi_program_hp_params(dev); + } +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 30a5f809ee798d..cab4cdbb31387e 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -3741,6 +3741,14 @@ static void quirk_no_bus_reset(struct pci_dev *dev) + dev->dev_flags |= PCI_DEV_FLAGS_NO_BUS_RESET; + } + ++/* ++ * After asserting Secondary Bus Reset to downstream devices via a GB10 ++ * Root Port, the link may not retrain correctly. ++ * https://lore.kernel.org/r/20251113084441.2124737-1-Johnny-CC.Chang@mediatek.com ++ */ ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x22CE, quirk_no_bus_reset); ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x22D0, quirk_no_bus_reset); ++ + /* + * Some NVIDIA GPU devices do not work with bus reset, SBR needs to be + * prevented for those affected devices. +@@ -3784,6 +3792,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CAVIUM, 0xa100, quirk_no_bus_reset); + */ + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0xb005, quirk_no_bus_reset); + ++/* ++ * Reports from users making use of PCI device assignment with ASM1164 ++ * controllers indicate an issue with bus reset where the device fails to ++ * retrain. The issue appears more common in configurations with multiple ++ * controllers. The device does indicate PM reset support (NoSoftRst-), ++ * therefore this still leaves a viable reset method. ++ * https://forum.proxmox.com/threads/problems-with-pcie-passthrough-with-two-identical-devices.149003/ ++ */ ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ASMEDIA, 0x1164, quirk_no_bus_reset); ++ + static void quirk_no_pm_reset(struct pci_dev *dev) + { + /* +@@ -5100,6 +5118,10 @@ static const struct pci_dev_acs_enabled { + { PCI_VENDOR_ID_QCOM, 0x0401, pci_quirk_qcom_rp_acs }, + /* QCOM SA8775P root port */ + { PCI_VENDOR_ID_QCOM, 0x0115, pci_quirk_qcom_rp_acs }, ++ /* QCOM Hamoa root port */ ++ { PCI_VENDOR_ID_QCOM, 0x0111, pci_quirk_qcom_rp_acs }, ++ /* QCOM Glymur root port */ ++ { PCI_VENDOR_ID_QCOM, 0x0120, pci_quirk_qcom_rp_acs }, + /* HXT SD4800 root ports. The ACS design is same as QCOM QDF2xxx */ + { PCI_VENDOR_ID_HXT, 0x0401, pci_quirk_qcom_rp_acs }, + /* Intel PCH root ports */ +@@ -5573,6 +5595,7 @@ static void quirk_no_ext_tags(struct pci_dev *pdev) + pci_walk_bus(bridge->bus, pci_configure_extended_tags, NULL); + } + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_3WARE, 0x1004, quirk_no_ext_tags); ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_3WARE, 0x1005, quirk_no_ext_tags); + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0132, quirk_no_ext_tags); + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0140, quirk_no_ext_tags); + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0141, quirk_no_ext_tags); +@@ -6180,6 +6203,10 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_PERICOM, 0x2303, + pci_fixup_pericom_acs_store_forward); + DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_PERICOM, 0x2303, + pci_fixup_pericom_acs_store_forward); ++DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_PERICOM, 0xb404, ++ pci_fixup_pericom_acs_store_forward); ++DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_PERICOM, 0xb404, ++ pci_fixup_pericom_acs_store_forward); + + static void nvidia_ion_ahci_fixup(struct pci_dev *pdev) + { +diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c +index 77aa37de59880f..9ca6fd74021005 100644 +--- a/drivers/perf/arm-cmn.c ++++ b/drivers/perf/arm-cmn.c +@@ -205,6 +205,7 @@ enum cmn_model { + enum cmn_part { + PART_CMN600 = 0x434, + PART_CMN650 = 0x436, ++ PART_CMN600AE = 0x438, + PART_CMN700 = 0x43c, + PART_CI700 = 0x43a, + }; +@@ -2167,6 +2168,9 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) + reg = readq_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_01); + part = FIELD_GET(CMN_CFGM_PID0_PART_0, reg); + part |= FIELD_GET(CMN_CFGM_PID1_PART_1, reg) << 8; ++ /* 600AE is close enough that it's not really worth more complexity */ ++ if (part == PART_CMN600AE) ++ part = PART_CMN600; + if (cmn->part && cmn->part != part) + dev_warn(cmn->dev, + "Firmware binding mismatch: expected part number 0x%x, found 0x%x\n", +@@ -2307,6 +2311,15 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) + arm_cmn_init_node_info(cmn, reg & CMN_CHILD_NODE_ADDR, dn); + dn->portid_bits = xp->portid_bits; + dn->deviceid_bits = xp->deviceid_bits; ++ /* ++ * Logical IDs are assigned from 0 per node type, so as ++ * soon as we see one bigger than expected, we can assume ++ * there are more than we can cope with. ++ */ ++ if (dn->logid > CMN_MAX_NODES_PER_EVENT) { ++ dev_err(cmn->dev, "Node ID invalid for supported CMN versions: %d\n", dn->logid); ++ return -ENODEV; ++ } + + switch (dn->type) { + case CMN_TYPE_DTC: +@@ -2355,7 +2368,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) + break; + /* Something has gone horribly wrong */ + default: +- dev_err(cmn->dev, "invalid device node type: 0x%x\n", dn->type); ++ dev_err(cmn->dev, "Device node type invalid for supported CMN versions: 0x%x\n", dn->type); + return -ENODEV; + } + } +@@ -2383,6 +2396,10 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) + cmn->mesh_x = cmn->num_xps; + cmn->mesh_y = cmn->num_xps / cmn->mesh_x; + ++ if (max(cmn->mesh_x, cmn->mesh_y) > CMN_MAX_DIMENSION) { ++ dev_err(cmn->dev, "Mesh size invalid for supported CMN versions: %dx%d\n", cmn->mesh_x, cmn->mesh_y); ++ return -ENODEV; ++ } + /* 1x1 config plays havoc with XP event encodings */ + if (cmn->num_xps == 1) + dev_warn(cmn->dev, "1x1 config not fully supported, translate XP events manually\n"); +diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c +index affa78376b6a80..5164078c06d258 100644 +--- a/drivers/perf/arm_spe_pmu.c ++++ b/drivers/perf/arm_spe_pmu.c +@@ -102,6 +102,8 @@ struct arm_spe_pmu { + /* Keep track of our dynamic hotplug state */ + static enum cpuhp_state arm_spe_pmu_online; + ++static void arm_spe_pmu_stop(struct perf_event *event, int flags); ++ + enum arm_spe_pmu_buf_fault_action { + SPE_PMU_BUF_FAULT_ACT_SPURIOUS, + SPE_PMU_BUF_FAULT_ACT_FATAL, +@@ -519,8 +521,8 @@ static u64 arm_spe_pmu_next_off(struct perf_output_handle *handle) + return limit; + } + +-static void arm_spe_perf_aux_output_begin(struct perf_output_handle *handle, +- struct perf_event *event) ++static int arm_spe_perf_aux_output_begin(struct perf_output_handle *handle, ++ struct perf_event *event) + { + u64 base, limit; + struct arm_spe_pmu_buf *buf; +@@ -528,7 +530,6 @@ static void arm_spe_perf_aux_output_begin(struct perf_output_handle *handle, + /* Start a new aux session */ + buf = perf_aux_output_begin(handle, event); + if (!buf) { +- event->hw.state |= PERF_HES_STOPPED; + /* + * We still need to clear the limit pointer, since the + * profiler might only be disabled by virtue of a fault. +@@ -548,6 +549,7 @@ static void arm_spe_perf_aux_output_begin(struct perf_output_handle *handle, + + out_write_limit: + write_sysreg_s(limit, SYS_PMBLIMITR_EL1); ++ return (limit & PMBLIMITR_EL1_E) ? 0 : -EIO; + } + + static void arm_spe_perf_aux_output_end(struct perf_output_handle *handle) +@@ -687,7 +689,10 @@ static irqreturn_t arm_spe_pmu_irq_handler(int irq, void *dev) + * when we get to it. + */ + if (!(handle->aux_flags & PERF_AUX_FLAG_TRUNCATED)) { +- arm_spe_perf_aux_output_begin(handle, event); ++ if (arm_spe_perf_aux_output_begin(handle, event)) { ++ arm_spe_pmu_stop(event, PERF_EF_UPDATE); ++ break; ++ } + isb(); + } + break; +@@ -782,9 +787,10 @@ static void arm_spe_pmu_start(struct perf_event *event, int flags) + struct perf_output_handle *handle = this_cpu_ptr(spe_pmu->handle); + + hwc->state = 0; +- arm_spe_perf_aux_output_begin(handle, event); +- if (hwc->state) ++ if (arm_spe_perf_aux_output_begin(handle, event)) { ++ arm_spe_pmu_stop(event, 0); + return; ++ } + + reg = arm_spe_event_to_pmsfcr(event); + write_sysreg_s(reg, SYS_PMSFCR_EL1); +diff --git a/drivers/perf/cxl_pmu.c b/drivers/perf/cxl_pmu.c +index c03df0f5288984..3e1a4f90061190 100644 +--- a/drivers/perf/cxl_pmu.c ++++ b/drivers/perf/cxl_pmu.c +@@ -885,7 +885,7 @@ static int cxl_pmu_probe(struct device *dev) + if (!irq_name) + return -ENOMEM; + +- rc = devm_request_irq(dev, irq, cxl_pmu_irq, IRQF_SHARED | IRQF_ONESHOT, ++ rc = devm_request_irq(dev, irq, cxl_pmu_irq, IRQF_SHARED | IRQF_NO_THREAD, + irq_name, info); + if (rc) + return rc; +diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c +index 043063699e0644..41194083e358ca 100644 +--- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c ++++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c +@@ -411,6 +411,7 @@ static struct platform_driver imx8mq_usb_phy_driver = { + .driver = { + .name = "imx8mq-usb-phy", + .of_match_table = imx8mq_usb_phy_of_match, ++ .suppress_bind_attrs = true, + } + }; + module_platform_driver(imx8mq_usb_phy_driver); +diff --git a/drivers/phy/marvell/phy-mvebu-cp110-utmi.c b/drivers/phy/marvell/phy-mvebu-cp110-utmi.c +index 4922a5f3327d51..30391d0d7d4b43 100644 +--- a/drivers/phy/marvell/phy-mvebu-cp110-utmi.c ++++ b/drivers/phy/marvell/phy-mvebu-cp110-utmi.c +@@ -326,7 +326,7 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev) + return -ENOMEM; + } + +- port->dr_mode = of_usb_get_dr_mode_by_phy(child, -1); ++ port->dr_mode = of_usb_get_dr_mode_by_phy(child, 0); + if ((port->dr_mode != USB_DR_MODE_HOST) && + (port->dr_mode != USB_DR_MODE_PERIPHERAL)) { + dev_err(&pdev->dev, +diff --git a/drivers/pinctrl/pinctrl-equilibrium.c b/drivers/pinctrl/pinctrl-equilibrium.c +index 5b5ddf7e5d0eb1..d7c89c310b3737 100644 +--- a/drivers/pinctrl/pinctrl-equilibrium.c ++++ b/drivers/pinctrl/pinctrl-equilibrium.c +@@ -850,6 +850,7 @@ static int pinbank_init(struct device_node *np, + + bank->pin_base = spec.args[1]; + bank->nr_pins = spec.args[2]; ++ of_node_put(spec.np); + + bank->aval_pinmap = readl(bank->membase + REG_AVAIL); + bank->id = id; +diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c +index 2ee0ee3b6ed14d..4aadafe2c50a52 100644 +--- a/drivers/pinctrl/pinctrl-single.c ++++ b/drivers/pinctrl/pinctrl-single.c +@@ -1363,6 +1363,7 @@ static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs) + } + range = devm_kzalloc(pcs->dev, sizeof(*range), GFP_KERNEL); + if (!range) { ++ of_node_put(gpiospec.np); + ret = -ENOMEM; + break; + } +@@ -1372,6 +1373,7 @@ static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs) + mutex_lock(&pcs->mutex); + list_add_tail(&range->node, &pcs->gpiofuncs); + mutex_unlock(&pcs->mutex); ++ of_node_put(gpiospec.np); + } + return ret; + } +diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c +index ddbc6317f2a745..422ef44b864233 100644 +--- a/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c ++++ b/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c +@@ -88,7 +88,7 @@ static const char * const i2s1_ws_groups[] = { "gpio7" }; + static const char * const i2s1_data_groups[] = { "gpio8", "gpio9" }; + static const char * const wsa_swr_clk_groups[] = { "gpio10" }; + static const char * const wsa_swr_data_groups[] = { "gpio11" }; +-static const char * const i2s2_data_groups[] = { "gpio12", "gpio12" }; ++static const char * const i2s2_data_groups[] = { "gpio12", "gpio13" }; + + static const struct lpi_pingroup sm8250_groups[] = { + LPI_PINGROUP(0, 0, swr_tx_clk, qua_mi2s_sclk, _, _), +diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c +index 376425bbd8ffb6..0f185b4b6f655c 100644 +--- a/drivers/platform/chrome/cros_ec_lightbar.c ++++ b/drivers/platform/chrome/cros_ec_lightbar.c +@@ -118,7 +118,7 @@ static int get_lightbar_version(struct cros_ec_dev *ec, + param = (struct ec_params_lightbar *)msg->data; + param->cmd = LIGHTBAR_CMD_VERSION; + msg->outsize = sizeof(param->cmd); +- msg->result = sizeof(resp->version); ++ msg->insize = sizeof(resp->version); + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + if (ret < 0 && ret != -EINVAL) { + ret = 0; +diff --git a/drivers/platform/chrome/cros_typec_switch.c b/drivers/platform/chrome/cros_typec_switch.c +index 0eefdcf14d63f6..28080f48315dcf 100644 +--- a/drivers/platform/chrome/cros_typec_switch.c ++++ b/drivers/platform/chrome/cros_typec_switch.c +@@ -230,20 +230,20 @@ static int cros_typec_register_switches(struct cros_typec_switch_data *sdata) + + adev = to_acpi_device_node(fwnode); + if (!adev) { +- dev_err(fwnode->dev, "Couldn't get ACPI device handle\n"); ++ dev_err(dev, "Couldn't get ACPI device handle for %pfwP\n", fwnode); + ret = -ENODEV; + goto err_switch; + } + + ret = acpi_evaluate_integer(adev->handle, "_ADR", NULL, &index); + if (ACPI_FAILURE(ret)) { +- dev_err(fwnode->dev, "_ADR wasn't evaluated\n"); ++ dev_err(dev, "_ADR wasn't evaluated for %pfwP\n", fwnode); + ret = -ENODATA; + goto err_switch; + } + + if (index >= EC_USB_PD_MAX_PORTS) { +- dev_err(fwnode->dev, "Invalid port index number: %llu\n", index); ++ dev_err(dev, "%pfwP: Invalid port index number: %llu\n", fwnode, index); + ret = -EINVAL; + goto err_switch; + } +diff --git a/drivers/power/reset/nvmem-reboot-mode.c b/drivers/power/reset/nvmem-reboot-mode.c +index e229308d43e25c..819f11bae788b3 100644 +--- a/drivers/power/reset/nvmem-reboot-mode.c ++++ b/drivers/power/reset/nvmem-reboot-mode.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + struct nvmem_reboot_mode { + struct reboot_mode_driver reboot; +@@ -19,12 +20,22 @@ struct nvmem_reboot_mode { + static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, + unsigned int magic) + { +- int ret; + struct nvmem_reboot_mode *nvmem_rbm; ++ size_t buf_len; ++ void *buf; ++ int ret; + + nvmem_rbm = container_of(reboot, struct nvmem_reboot_mode, reboot); + +- ret = nvmem_cell_write(nvmem_rbm->cell, &magic, sizeof(magic)); ++ buf = nvmem_cell_read(nvmem_rbm->cell, &buf_len); ++ if (IS_ERR(buf)) ++ return PTR_ERR(buf); ++ kfree(buf); ++ ++ if (buf_len > sizeof(magic)) ++ return -EINVAL; ++ ++ ret = nvmem_cell_write(nvmem_rbm->cell, &magic, buf_len); + if (ret < 0) + dev_err(reboot->dev, "update reboot mode bits failed\n"); + +diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c +index 308e68545d44d4..c6d513953b042b 100644 +--- a/drivers/power/supply/ab8500_charger.c ++++ b/drivers/power/supply/ab8500_charger.c +@@ -3456,26 +3456,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) + return ret; + } + +- /* Request interrupts */ +- for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { +- irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); +- if (irq < 0) +- return irq; +- +- ret = devm_request_threaded_irq(dev, +- irq, NULL, ab8500_charger_irq[i].isr, +- IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, +- ab8500_charger_irq[i].name, di); +- +- if (ret != 0) { +- dev_err(dev, "failed to request %s IRQ %d: %d\n" +- , ab8500_charger_irq[i].name, irq, ret); +- return ret; +- } +- dev_dbg(dev, "Requested %s IRQ %d: %d\n", +- ab8500_charger_irq[i].name, irq, ret); +- } +- + /* initialize lock */ + spin_lock_init(&di->usb_state.usb_lock); + mutex_init(&di->usb_ipt_crnt_lock); +@@ -3604,6 +3584,26 @@ static int ab8500_charger_probe(struct platform_device *pdev) + return PTR_ERR(di->usb_chg.psy); + } + ++ /* Request interrupts */ ++ for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { ++ irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); ++ if (irq < 0) ++ return irq; ++ ++ ret = devm_request_threaded_irq(dev, ++ irq, NULL, ab8500_charger_irq[i].isr, ++ IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, ++ ab8500_charger_irq[i].name, di); ++ ++ if (ret != 0) { ++ dev_err(dev, "failed to request %s IRQ %d: %d\n" ++ , ab8500_charger_irq[i].name, irq, ret); ++ return ret; ++ } ++ dev_dbg(dev, "Requested %s IRQ %d: %d\n", ++ ab8500_charger_irq[i].name, irq, ret); ++ } ++ + /* + * Check what battery we have, since we always have the USB + * psy, use that as a handle. +diff --git a/drivers/power/supply/act8945a_charger.c b/drivers/power/supply/act8945a_charger.c +index e9b5f42837729f..e9cb06daecea90 100644 +--- a/drivers/power/supply/act8945a_charger.c ++++ b/drivers/power/supply/act8945a_charger.c +@@ -597,14 +597,6 @@ static int act8945a_charger_probe(struct platform_device *pdev) + return irq ?: -ENXIO; + } + +- ret = devm_request_irq(&pdev->dev, irq, act8945a_status_changed, +- IRQF_TRIGGER_FALLING, "act8945a_interrupt", +- charger); +- if (ret) { +- dev_err(&pdev->dev, "failed to request nIRQ pin IRQ\n"); +- return ret; +- } +- + charger->desc.name = "act8945a-charger"; + charger->desc.get_property = act8945a_charger_get_property; + charger->desc.properties = act8945a_charger_props; +@@ -625,6 +617,14 @@ static int act8945a_charger_probe(struct platform_device *pdev) + return PTR_ERR(charger->psy); + } + ++ ret = devm_request_irq(&pdev->dev, irq, act8945a_status_changed, ++ IRQF_TRIGGER_FALLING, "act8945a_interrupt", ++ charger); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to request nIRQ pin IRQ\n"); ++ return ret; ++ } ++ + platform_set_drvdata(pdev, charger); + + INIT_WORK(&charger->work, act8945a_work); +diff --git a/drivers/power/supply/bq256xx_charger.c b/drivers/power/supply/bq256xx_charger.c +index c8368dae69c712..2b0216d32d5f77 100644 +--- a/drivers/power/supply/bq256xx_charger.c ++++ b/drivers/power/supply/bq256xx_charger.c +@@ -1746,6 +1746,12 @@ static int bq256xx_probe(struct i2c_client *client) + usb_register_notifier(bq->usb3_phy, &bq->usb_nb); + } + ++ ret = bq256xx_power_supply_init(bq, &psy_cfg, dev); ++ if (ret) { ++ dev_err(dev, "Failed to register power supply\n"); ++ return ret; ++ } ++ + if (client->irq) { + ret = devm_request_threaded_irq(dev, client->irq, NULL, + bq256xx_irq_handler_thread, +@@ -1758,12 +1764,6 @@ static int bq256xx_probe(struct i2c_client *client) + } + } + +- ret = bq256xx_power_supply_init(bq, &psy_cfg, dev); +- if (ret) { +- dev_err(dev, "Failed to register power supply\n"); +- return ret; +- } +- + ret = bq256xx_hw_init(bq); + if (ret) { + dev_err(dev, "Cannot initialize the chip.\n"); +diff --git a/drivers/power/supply/bq25980_charger.c b/drivers/power/supply/bq25980_charger.c +index d8411722266f51..fd00f9e5335487 100644 +--- a/drivers/power/supply/bq25980_charger.c ++++ b/drivers/power/supply/bq25980_charger.c +@@ -1241,6 +1241,12 @@ static int bq25980_probe(struct i2c_client *client) + return ret; + } + ++ ret = bq25980_power_supply_init(bq, dev); ++ if (ret) { ++ dev_err(dev, "Failed to register power supply\n"); ++ return ret; ++ } ++ + if (client->irq) { + ret = devm_request_threaded_irq(dev, client->irq, NULL, + bq25980_irq_handler_thread, +@@ -1251,12 +1257,6 @@ static int bq25980_probe(struct i2c_client *client) + return ret; + } + +- ret = bq25980_power_supply_init(bq, dev); +- if (ret) { +- dev_err(dev, "Failed to register power supply\n"); +- return ret; +- } +- + ret = bq25980_hw_init(bq); + if (ret) { + dev_err(dev, "Cannot initialize the chip.\n"); +diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c +index 1f06dee4b8b4e3..ff01d5d850f9a4 100644 +--- a/drivers/power/supply/bq27xxx_battery.c ++++ b/drivers/power/supply/bq27xxx_battery.c +@@ -1162,7 +1162,7 @@ static inline int bq27xxx_write(struct bq27xxx_device_info *di, int reg_index, + return -EINVAL; + + if (!di->bus.write) +- return -EPERM; ++ return -EOPNOTSUPP; + + ret = di->bus.write(di, di->regs[reg_index], value, single); + if (ret < 0) +@@ -1181,7 +1181,7 @@ static inline int bq27xxx_read_block(struct bq27xxx_device_info *di, int reg_ind + return -EINVAL; + + if (!di->bus.read_bulk) +- return -EPERM; ++ return -EOPNOTSUPP; + + ret = di->bus.read_bulk(di, di->regs[reg_index], data, len); + if (ret < 0) +@@ -1200,7 +1200,7 @@ static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in + return -EINVAL; + + if (!di->bus.write_bulk) +- return -EPERM; ++ return -EOPNOTSUPP; + + ret = di->bus.write_bulk(di, di->regs[reg_index], data, len); + if (ret < 0) +diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c +index 5dd76c0ac98dae..d84b81e7736287 100644 +--- a/drivers/power/supply/cpcap-battery.c ++++ b/drivers/power/supply/cpcap-battery.c +@@ -1122,10 +1122,6 @@ static int cpcap_battery_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, ddata); + +- error = cpcap_battery_init_interrupts(pdev, ddata); +- if (error) +- return error; +- + error = cpcap_battery_init_iio(ddata); + if (error) + return error; +@@ -1142,6 +1138,10 @@ static int cpcap_battery_probe(struct platform_device *pdev) + return error; + } + ++ error = cpcap_battery_init_interrupts(pdev, ddata); ++ if (error) ++ return error; ++ + atomic_set(&ddata->active, 1); + + error = cpcap_battery_calibrate(ddata); +diff --git a/drivers/power/supply/goldfish_battery.c b/drivers/power/supply/goldfish_battery.c +index a58d713d75ce81..4d204f0e18532f 100644 +--- a/drivers/power/supply/goldfish_battery.c ++++ b/drivers/power/supply/goldfish_battery.c +@@ -224,12 +224,6 @@ static int goldfish_battery_probe(struct platform_device *pdev) + if (data->irq < 0) + return -ENODEV; + +- ret = devm_request_irq(&pdev->dev, data->irq, +- goldfish_battery_interrupt, +- IRQF_SHARED, pdev->name, data); +- if (ret) +- return ret; +- + psy_cfg.drv_data = data; + + data->ac = power_supply_register(&pdev->dev, &ac_desc, &psy_cfg); +@@ -245,6 +239,12 @@ static int goldfish_battery_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, data); + ++ ret = devm_request_irq(&pdev->dev, data->irq, ++ goldfish_battery_interrupt, ++ IRQF_SHARED, pdev->name, data); ++ if (ret) ++ return ret; ++ + GOLDFISH_BATTERY_WRITE(data, BATTERY_INT_ENABLE, BATTERY_INT_MASK); + return 0; + } +diff --git a/drivers/power/supply/qcom_battmgr.c b/drivers/power/supply/qcom_battmgr.c +index 0c993780d3ef29..e5eade13281636 100644 +--- a/drivers/power/supply/qcom_battmgr.c ++++ b/drivers/power/supply/qcom_battmgr.c +@@ -981,7 +981,8 @@ static unsigned int qcom_battmgr_sc8280xp_parse_technology(const char *chemistry + if ((!strncmp(chemistry, "LIO", BATTMGR_CHEMISTRY_LEN)) || + (!strncmp(chemistry, "OOI", BATTMGR_CHEMISTRY_LEN))) + return POWER_SUPPLY_TECHNOLOGY_LION; +- if (!strncmp(chemistry, "LIP", BATTMGR_CHEMISTRY_LEN)) ++ if (!strncmp(chemistry, "LIP", BATTMGR_CHEMISTRY_LEN) || ++ !strncmp(chemistry, "LiP", BATTMGR_CHEMISTRY_LEN)) + return POWER_SUPPLY_TECHNOLOGY_LIPO; + + pr_err("Unknown battery technology '%s'\n", chemistry); +diff --git a/drivers/power/supply/rt9455_charger.c b/drivers/power/supply/rt9455_charger.c +index e4dbacd50a437d..248dc2b5e1f7c7 100644 +--- a/drivers/power/supply/rt9455_charger.c ++++ b/drivers/power/supply/rt9455_charger.c +@@ -1663,6 +1663,15 @@ static int rt9455_probe(struct i2c_client *client) + rt9455_charger_config.supplied_to = rt9455_charger_supplied_to; + rt9455_charger_config.num_supplicants = + ARRAY_SIZE(rt9455_charger_supplied_to); ++ ++ info->charger = devm_power_supply_register(dev, &rt9455_charger_desc, ++ &rt9455_charger_config); ++ if (IS_ERR(info->charger)) { ++ dev_err(dev, "Failed to register charger\n"); ++ ret = PTR_ERR(info->charger); ++ goto put_usb_notifier; ++ } ++ + ret = devm_request_threaded_irq(dev, client->irq, NULL, + rt9455_irq_handler_thread, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, +@@ -1678,14 +1687,6 @@ static int rt9455_probe(struct i2c_client *client) + goto put_usb_notifier; + } + +- info->charger = devm_power_supply_register(dev, &rt9455_charger_desc, +- &rt9455_charger_config); +- if (IS_ERR(info->charger)) { +- dev_err(dev, "Failed to register charger\n"); +- ret = PTR_ERR(info->charger); +- goto put_usb_notifier; +- } +- + return 0; + + put_usb_notifier: +diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c +index cdfc8466d129b7..f30a542d4716ce 100644 +--- a/drivers/power/supply/sbs-battery.c ++++ b/drivers/power/supply/sbs-battery.c +@@ -1173,24 +1173,6 @@ static int sbs_probe(struct i2c_client *client) + + i2c_set_clientdata(client, chip); + +- if (!chip->gpio_detect) +- goto skip_gpio; +- +- irq = gpiod_to_irq(chip->gpio_detect); +- if (irq <= 0) { +- dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq); +- goto skip_gpio; +- } +- +- rc = devm_request_threaded_irq(&client->dev, irq, NULL, sbs_irq, +- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, +- dev_name(&client->dev), chip); +- if (rc) { +- dev_warn(&client->dev, "Failed to request irq: %d\n", rc); +- goto skip_gpio; +- } +- +-skip_gpio: + /* + * Before we register, we might need to make sure we can actually talk + * to the battery. +@@ -1216,6 +1198,24 @@ skip_gpio: + return dev_err_probe(&client->dev, PTR_ERR(chip->power_supply), + "Failed to register power supply\n"); + ++ if (!chip->gpio_detect) ++ goto out; ++ ++ irq = gpiod_to_irq(chip->gpio_detect); ++ if (irq <= 0) { ++ dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq); ++ goto out; ++ } ++ ++ rc = devm_request_threaded_irq(&client->dev, irq, NULL, sbs_irq, ++ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, ++ dev_name(&client->dev), chip); ++ if (rc) { ++ dev_warn(&client->dev, "Failed to request irq: %d\n", rc); ++ goto out; ++ } ++ ++out: + dev_info(&client->dev, + "%s: battery gas gauge device registered\n", client->name); + +diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c +index f4b190adb33594..d3e5c2f7762a6f 100644 +--- a/drivers/power/supply/wm97xx_battery.c ++++ b/drivers/power/supply/wm97xx_battery.c +@@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev) + "failed to get charge GPIO\n"); + if (charge_gpiod) { + gpiod_set_consumer_name(charge_gpiod, "BATT CHRG"); +- ret = request_irq(gpiod_to_irq(charge_gpiod), +- wm97xx_chrg_irq, 0, +- "AC Detect", dev); +- if (ret) +- return dev_err_probe(&dev->dev, ret, +- "failed to request GPIO irq\n"); + props++; /* POWER_SUPPLY_PROP_STATUS */ + } + +@@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev) + props++; /* POWER_SUPPLY_PROP_VOLTAGE_MIN */ + + prop = kcalloc(props, sizeof(*prop), GFP_KERNEL); +- if (!prop) { +- ret = -ENOMEM; +- goto err3; +- } ++ if (!prop) ++ return -ENOMEM; + + prop[i++] = POWER_SUPPLY_PROP_PRESENT; + if (charge_gpiod) +@@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev) + schedule_work(&bat_work); + } else { + ret = PTR_ERR(bat_psy); +- goto err4; ++ goto free; ++ } ++ ++ if (charge_gpiod) { ++ ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq, ++ 0, "AC Detect", dev); ++ if (ret) { ++ dev_err_probe(&dev->dev, ret, ++ "failed to request GPIO irq\n"); ++ goto unregister; ++ } + } + + return 0; +-err4: ++ ++unregister: ++ power_supply_unregister(bat_psy); ++ ++free: + kfree(prop); +-err3: +- if (charge_gpiod) +- free_irq(gpiod_to_irq(charge_gpiod), dev); ++ + return ret; + } + +diff --git a/drivers/powercap/intel_rapl_tpmi.c b/drivers/powercap/intel_rapl_tpmi.c +index 1c48dba0ba96af..6958c2f0b76606 100644 +--- a/drivers/powercap/intel_rapl_tpmi.c ++++ b/drivers/powercap/intel_rapl_tpmi.c +@@ -156,7 +156,7 @@ static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset) + tpmi_domain_flags = tpmi_domain_header >> 32 & 0xffff; + + if (tpmi_domain_version == TPMI_VERSION_INVALID) { +- pr_warn(FW_BUG "Invalid version\n"); ++ pr_debug("Invalid version, other instances may be valid\n"); + return -ENODEV; + } + +diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c +index c12941f71e2cba..dcd6619a4b0277 100644 +--- a/drivers/rapidio/rio-scan.c ++++ b/drivers/rapidio/rio-scan.c +@@ -854,7 +854,8 @@ static struct rio_net *rio_scan_alloc_net(struct rio_mport *mport, + + if (idtab == NULL) { + pr_err("RIO: failed to allocate destID table\n"); +- rio_free_net(net); ++ kfree(net); ++ mport->net = NULL; + net = NULL; + } else { + net->enum_data = idtab; +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index 23cdf220ca7db5..a1a26743430c0c 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1466,6 +1466,33 @@ static int set_machine_constraints(struct regulator_dev *rdev) + int ret = 0; + const struct regulator_ops *ops = rdev->desc->ops; + ++ /* ++ * If there is no mechanism for controlling the regulator then ++ * flag it as always_on so we don't end up duplicating checks ++ * for this so much. Note that we could control the state of ++ * a supply to control the output on a regulator that has no ++ * direct control. ++ */ ++ if (!rdev->ena_pin && !ops->enable) { ++ if (rdev->supply_name && !rdev->supply) ++ return -EPROBE_DEFER; ++ ++ if (rdev->supply) ++ rdev->constraints->always_on = ++ rdev->supply->rdev->constraints->always_on; ++ else ++ rdev->constraints->always_on = true; ++ } ++ ++ /* ++ * If we want to enable this regulator, make sure that we know the ++ * supplying regulator. ++ */ ++ if (rdev->constraints->always_on || rdev->constraints->boot_on) { ++ if (rdev->supply_name && !rdev->supply) ++ return -EPROBE_DEFER; ++ } ++ + ret = machine_constraints_voltage(rdev, rdev->constraints); + if (ret != 0) + return ret; +@@ -1631,37 +1658,15 @@ static int set_machine_constraints(struct regulator_dev *rdev) + } + } + +- /* +- * If there is no mechanism for controlling the regulator then +- * flag it as always_on so we don't end up duplicating checks +- * for this so much. Note that we could control the state of +- * a supply to control the output on a regulator that has no +- * direct control. +- */ +- if (!rdev->ena_pin && !ops->enable) { +- if (rdev->supply_name && !rdev->supply) +- return -EPROBE_DEFER; +- +- if (rdev->supply) +- rdev->constraints->always_on = +- rdev->supply->rdev->constraints->always_on; +- else +- rdev->constraints->always_on = true; +- } +- + /* If the constraints say the regulator should be on at this point + * and we have control then make sure it is enabled. + */ + if (rdev->constraints->always_on || rdev->constraints->boot_on) { + bool supply_enabled = false; + +- /* If we want to enable this regulator, make sure that we know +- * the supplying regulator. +- */ +- if (rdev->supply_name && !rdev->supply) +- return -EPROBE_DEFER; +- +- /* If supplying regulator has already been enabled, ++ /* We have ensured a potential supply has been resolved above. ++ * ++ * If supplying regulator has already been enabled, + * it's not intended to have use_count increment + * when rdev is only boot-on. + */ +diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c +index 8fcda9b7454597..960fbd4b1d9b97 100644 +--- a/drivers/remoteproc/imx_dsp_rproc.c ++++ b/drivers/remoteproc/imx_dsp_rproc.c +@@ -1250,6 +1250,15 @@ static int imx_dsp_suspend(struct device *dev) + if (rproc->state != RPROC_RUNNING) + goto out; + ++ /* ++ * No channel available for sending messages; ++ * indicates no mailboxes present, so trigger PM runtime suspend ++ */ ++ if (!priv->tx_ch) { ++ dev_dbg(dev, "No initialized mbox tx channel, suspend directly.\n"); ++ goto out; ++ } ++ + reinit_completion(&priv->pm_comp); + + /* Tell DSP that suspend is happening */ +diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c +index 251f9840d85bd8..fda0e644f3106a 100644 +--- a/drivers/remoteproc/imx_rproc.c ++++ b/drivers/remoteproc/imx_rproc.c +@@ -674,6 +674,10 @@ imx_rproc_elf_find_loaded_rsc_table(struct rproc *rproc, const struct firmware * + { + struct imx_rproc *priv = rproc->priv; + ++ /* No resource table in the firmware */ ++ if (!rproc->table_ptr) ++ return NULL; ++ + if (priv->rsc_table) + return (struct resource_table *)priv->rsc_table; + +diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c +index c4c535b011812d..ecbece2b5ce7ca 100644 +--- a/drivers/remoteproc/mtk_scp.c ++++ b/drivers/remoteproc/mtk_scp.c +@@ -225,7 +225,7 @@ static irqreturn_t scp_irq_handler(int irq, void *priv) + struct mtk_scp *scp = priv; + int ret; + +- ret = clk_prepare_enable(scp->clk); ++ ret = clk_enable(scp->clk); + if (ret) { + dev_err(scp->dev, "failed to enable clocks\n"); + return IRQ_NONE; +@@ -233,7 +233,7 @@ static irqreturn_t scp_irq_handler(int irq, void *priv) + + scp->data->scp_irq_handler(scp); + +- clk_disable_unprepare(scp->clk); ++ clk_disable(scp->clk); + + return IRQ_HANDLED; + } +@@ -467,7 +467,7 @@ static int scp_load(struct rproc *rproc, const struct firmware *fw) + struct device *dev = scp->dev; + int ret; + +- ret = clk_prepare_enable(scp->clk); ++ ret = clk_enable(scp->clk); + if (ret) { + dev_err(dev, "failed to enable clocks\n"); + return ret; +@@ -482,7 +482,7 @@ static int scp_load(struct rproc *rproc, const struct firmware *fw) + + ret = scp_elf_load_segments(rproc, fw); + leave: +- clk_disable_unprepare(scp->clk); ++ clk_disable(scp->clk); + + return ret; + } +@@ -493,14 +493,14 @@ static int scp_parse_fw(struct rproc *rproc, const struct firmware *fw) + struct device *dev = scp->dev; + int ret; + +- ret = clk_prepare_enable(scp->clk); ++ ret = clk_enable(scp->clk); + if (ret) { + dev_err(dev, "failed to enable clocks\n"); + return ret; + } + + ret = scp_ipi_init(scp, fw); +- clk_disable_unprepare(scp->clk); ++ clk_disable(scp->clk); + return ret; + } + +@@ -511,7 +511,7 @@ static int scp_start(struct rproc *rproc) + struct scp_run *run = &scp->run; + int ret; + +- ret = clk_prepare_enable(scp->clk); ++ ret = clk_enable(scp->clk); + if (ret) { + dev_err(dev, "failed to enable clocks\n"); + return ret; +@@ -536,14 +536,14 @@ static int scp_start(struct rproc *rproc) + goto stop; + } + +- clk_disable_unprepare(scp->clk); ++ clk_disable(scp->clk); + dev_info(dev, "SCP is ready. FW version %s\n", run->fw_ver); + + return 0; + + stop: + scp->data->scp_reset_assert(scp); +- clk_disable_unprepare(scp->clk); ++ clk_disable(scp->clk); + return ret; + } + +@@ -638,7 +638,7 @@ static int scp_stop(struct rproc *rproc) + struct mtk_scp *scp = rproc->priv; + int ret; + +- ret = clk_prepare_enable(scp->clk); ++ ret = clk_enable(scp->clk); + if (ret) { + dev_err(scp->dev, "failed to enable clocks\n"); + return ret; +@@ -646,12 +646,29 @@ static int scp_stop(struct rproc *rproc) + + scp->data->scp_reset_assert(scp); + scp->data->scp_stop(scp); +- clk_disable_unprepare(scp->clk); ++ clk_disable(scp->clk); + + return 0; + } + ++static int scp_prepare(struct rproc *rproc) ++{ ++ struct mtk_scp *scp = rproc->priv; ++ ++ return clk_prepare(scp->clk); ++} ++ ++static int scp_unprepare(struct rproc *rproc) ++{ ++ struct mtk_scp *scp = rproc->priv; ++ ++ clk_unprepare(scp->clk); ++ return 0; ++} ++ + static const struct rproc_ops scp_ops = { ++ .prepare = scp_prepare, ++ .unprepare = scp_unprepare, + .start = scp_start, + .stop = scp_stop, + .load = scp_load, +diff --git a/drivers/remoteproc/mtk_scp_ipi.c b/drivers/remoteproc/mtk_scp_ipi.c +index 9c7c17b9d181f1..0c3ed37bd08210 100644 +--- a/drivers/remoteproc/mtk_scp_ipi.c ++++ b/drivers/remoteproc/mtk_scp_ipi.c +@@ -168,7 +168,7 @@ int scp_ipi_send(struct mtk_scp *scp, u32 id, void *buf, unsigned int len, + WARN_ON(len > sizeof(send_obj->share_buf)) || WARN_ON(!buf)) + return -EINVAL; + +- ret = clk_prepare_enable(scp->clk); ++ ret = clk_enable(scp->clk); + if (ret) { + dev_err(scp->dev, "failed to enable clock\n"); + return ret; +@@ -208,7 +208,7 @@ int scp_ipi_send(struct mtk_scp *scp, u32 id, void *buf, unsigned int len, + + unlock_mutex: + mutex_unlock(&scp->send_lock); +- clk_disable_unprepare(scp->clk); ++ clk_disable(scp->clk); + + return ret; + } +diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c +index 32b550c91d9f1c..662a674314045c 100644 +--- a/drivers/rpmsg/rpmsg_core.c ++++ b/drivers/rpmsg/rpmsg_core.c +@@ -413,50 +413,38 @@ field##_show(struct device *dev, \ + } \ + static DEVICE_ATTR_RO(field); + +-#define rpmsg_string_attr(field, member) \ +-static ssize_t \ +-field##_store(struct device *dev, struct device_attribute *attr, \ +- const char *buf, size_t sz) \ +-{ \ +- struct rpmsg_device *rpdev = to_rpmsg_device(dev); \ +- const char *old; \ +- char *new; \ +- \ +- new = kstrndup(buf, sz, GFP_KERNEL); \ +- if (!new) \ +- return -ENOMEM; \ +- new[strcspn(new, "\n")] = '\0'; \ +- \ +- device_lock(dev); \ +- old = rpdev->member; \ +- if (strlen(new)) { \ +- rpdev->member = new; \ +- } else { \ +- kfree(new); \ +- rpdev->member = NULL; \ +- } \ +- device_unlock(dev); \ +- \ +- kfree(old); \ +- \ +- return sz; \ +-} \ +-static ssize_t \ +-field##_show(struct device *dev, \ +- struct device_attribute *attr, char *buf) \ +-{ \ +- struct rpmsg_device *rpdev = to_rpmsg_device(dev); \ +- \ +- return sprintf(buf, "%s\n", rpdev->member); \ +-} \ +-static DEVICE_ATTR_RW(field) +- + /* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */ + rpmsg_show_attr(name, id.name, "%s\n"); + rpmsg_show_attr(src, src, "0x%x\n"); + rpmsg_show_attr(dst, dst, "0x%x\n"); + rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n"); +-rpmsg_string_attr(driver_override, driver_override); ++ ++static ssize_t driver_override_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct rpmsg_device *rpdev = to_rpmsg_device(dev); ++ int ret; ++ ++ ret = driver_set_override(dev, &rpdev->driver_override, buf, count); ++ if (ret) ++ return ret; ++ ++ return count; ++} ++ ++static ssize_t driver_override_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct rpmsg_device *rpdev = to_rpmsg_device(dev); ++ ssize_t len; ++ ++ device_lock(dev); ++ len = sysfs_emit(buf, "%s\n", rpdev->driver_override); ++ device_unlock(dev); ++ return len; ++} ++static DEVICE_ATTR_RW(driver_override); + + static ssize_t modalias_show(struct device *dev, + struct device_attribute *attr, char *buf) +diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c +index 93baffe110c00a..13de2cb07f75d3 100644 +--- a/drivers/rtc/interface.c ++++ b/drivers/rtc/interface.c +@@ -457,7 +457,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) + * are in, we can return -ETIME to signal that the timer has already + * expired, which is true in both cases. + */ +- if ((scheduled - now) <= 1) { ++ if (!err && (scheduled - now) <= 1) { + err = __rtc_read_time(rtc, &tm); + if (err) + return err; +diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c +index b6f96c10196ae3..f49af7d963fbd7 100644 +--- a/drivers/rtc/rtc-zynqmp.c ++++ b/drivers/rtc/rtc-zynqmp.c +@@ -330,7 +330,10 @@ static int xlnx_rtc_probe(struct platform_device *pdev) + &xrtcdev->freq); + if (ret) + xrtcdev->freq = RTC_CALIB_DEF; ++ } else { ++ xrtcdev->freq--; + } ++ + ret = readl(xrtcdev->reg_base + RTC_CALIB_RD); + if (!ret) + writel(xrtcdev->freq, (xrtcdev->reg_base + RTC_CALIB_WR)); +diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c +index 3ff46fc694f85e..e50592c3d30ca0 100644 +--- a/drivers/s390/cio/css.c ++++ b/drivers/s390/cio/css.c +@@ -247,7 +247,7 @@ struct subchannel *css_alloc_subchannel(struct subchannel_id schid, + err_lock: + kfree(sch->lock); + err: +- kfree(sch); ++ put_device(&sch->dev); + return ERR_PTR(ret); + } + +diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c +index 72ceaf650b0d56..dfe97e25635edf 100644 +--- a/drivers/scsi/BusLogic.c ++++ b/drivers/scsi/BusLogic.c +@@ -919,7 +919,8 @@ static int __init blogic_init_fp_probeinfo(struct blogic_adapter *adapter) + a particular probe order. + */ + +-static void __init blogic_init_probeinfo_list(struct blogic_adapter *adapter) ++static noinline_for_stack void __init ++blogic_init_probeinfo_list(struct blogic_adapter *adapter) + { + /* + If a PCI BIOS is present, interrogate it for MultiMaster and +@@ -1689,7 +1690,8 @@ common: + blogic_reportconfig reports the configuration of Host Adapter. + */ + +-static bool __init blogic_reportconfig(struct blogic_adapter *adapter) ++static noinline_for_stack bool __init ++blogic_reportconfig(struct blogic_adapter *adapter) + { + unsigned short alltgt_mask = (1 << adapter->maxdev) - 1; + unsigned short sync_ok, fast_ok; +diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c +index 05e1a63e00c3a1..ed40ae6b9800c0 100644 +--- a/drivers/scsi/csiostor/csio_scsi.c ++++ b/drivers/scsi/csiostor/csio_scsi.c +@@ -2074,7 +2074,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) + struct csio_scsi_level_data sld; + + if (!rn) +- goto fail; ++ goto fail_ret; + + csio_dbg(hw, "Request to reset LUN:%llu (ssni:0x%x tgtid:%d)\n", + cmnd->device->lun, rn->flowid, rn->scsi_id); +@@ -2220,6 +2220,7 @@ fail_ret_ioreq: + csio_put_scsi_ioreq_lock(hw, scsim, ioreq); + fail: + CSIO_INC_STATS(rn, n_lun_rst_fail); ++fail_ret: + return FAILED; + } + +diff --git a/drivers/scsi/elx/efct/efct_driver.c b/drivers/scsi/elx/efct/efct_driver.c +index 49fd2cfed70c70..37aba56e072177 100644 +--- a/drivers/scsi/elx/efct/efct_driver.c ++++ b/drivers/scsi/elx/efct/efct_driver.c +@@ -415,12 +415,6 @@ efct_intr_thread(int irq, void *handle) + return IRQ_HANDLED; + } + +-static irqreturn_t +-efct_intr_msix(int irq, void *handle) +-{ +- return IRQ_WAKE_THREAD; +-} +- + static int + efct_setup_msix(struct efct *efct, u32 num_intrs) + { +@@ -450,7 +444,7 @@ efct_setup_msix(struct efct *efct, u32 num_intrs) + intr_ctx->index = i; + + rc = request_threaded_irq(pci_irq_vector(efct->pci, i), +- efct_intr_msix, efct_intr_thread, 0, ++ NULL, efct_intr_thread, IRQF_ONESHOT, + EFCT_DRIVER_NAME, intr_ctx); + if (rc) { + dev_err(&efct->pci->dev, +diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c +index 0cdeb7aa550203..dc194c76f38b7c 100644 +--- a/drivers/scsi/smartpqi/smartpqi_init.c ++++ b/drivers/scsi/smartpqi/smartpqi_init.c +@@ -1240,7 +1240,8 @@ static inline int pqi_report_phys_luns(struct pqi_ctrl_info *ctrl_info, void **b + dev_err(&ctrl_info->pci_dev->dev, + "RPL returned unsupported data format %u\n", + rpl_response_format); +- return -EINVAL; ++ rc = -EINVAL; ++ goto out_free_rpl_list; + } else { + dev_warn(&ctrl_info->pci_dev->dev, + "RPL returned extended format 2 instead of 4\n"); +@@ -1252,8 +1253,10 @@ static inline int pqi_report_phys_luns(struct pqi_ctrl_info *ctrl_info, void **b + + rpl_16byte_wwid_list = kmalloc(struct_size(rpl_16byte_wwid_list, lun_entries, + num_physicals), GFP_KERNEL); +- if (!rpl_16byte_wwid_list) +- return -ENOMEM; ++ if (!rpl_16byte_wwid_list) { ++ rc = -ENOMEM; ++ goto out_free_rpl_list; ++ } + + put_unaligned_be32(num_physicals * sizeof(struct report_phys_lun_16byte_wwid), + &rpl_16byte_wwid_list->header.list_length); +@@ -1274,6 +1277,10 @@ static inline int pqi_report_phys_luns(struct pqi_ctrl_info *ctrl_info, void **b + *buffer = rpl_16byte_wwid_list; + + return 0; ++ ++out_free_rpl_list: ++ kfree(rpl_list); ++ return rc; + } + + static inline int pqi_report_logical_luns(struct pqi_ctrl_info *ctrl_info, void **buffer) +diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c +index 3a2f97cd527200..37d21e3de69423 100644 +--- a/drivers/soc/mediatek/mtk-svs.c ++++ b/drivers/soc/mediatek/mtk-svs.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -717,7 +718,7 @@ static ssize_t svs_enable_debug_write(struct file *filp, + struct svs_bank *svsb = file_inode(filp)->i_private; + struct svs_platform *svsp = dev_get_drvdata(svsb->dev); + int enabled, ret; +- char *buf = NULL; ++ char *buf __free(kfree) = NULL; + + if (count >= PAGE_SIZE) + return -EINVAL; +@@ -735,8 +736,6 @@ static ssize_t svs_enable_debug_write(struct file *filp, + svsb->mode_support = SVSB_MODE_ALL_DISABLE; + } + +- kfree(buf); +- + return count; + } + +diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c +index ab2418d2fe43a9..0c54a9525baf19 100644 +--- a/drivers/soc/qcom/cmd-db.c ++++ b/drivers/soc/qcom/cmd-db.c +@@ -354,15 +354,16 @@ static int cmd_db_dev_probe(struct platform_device *pdev) + return -EINVAL; + } + +- cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WC); +- if (!cmd_db_header) { +- ret = -ENOMEM; ++ cmd_db_header = devm_memremap(&pdev->dev, rmem->base, rmem->size, MEMREMAP_WC); ++ if (IS_ERR(cmd_db_header)) { ++ ret = PTR_ERR(cmd_db_header); + cmd_db_header = NULL; + return ret; + } + + if (!cmd_db_magic_matches(cmd_db_header)) { + dev_err(&pdev->dev, "Invalid Command DB Magic\n"); ++ cmd_db_header = NULL; + return -EINVAL; + } + +diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c +index 5217ff0a434f55..d039c660d04fbe 100644 +--- a/drivers/soc/qcom/smem.c ++++ b/drivers/soc/qcom/smem.c +@@ -1189,7 +1189,9 @@ static int qcom_smem_probe(struct platform_device *pdev) + smem->item_count = qcom_smem_get_item_count(smem); + break; + case SMEM_GLOBAL_HEAP_VERSION: +- qcom_smem_map_global(smem, size); ++ ret = qcom_smem_map_global(smem, size); ++ if (ret < 0) ++ return ret; + smem->item_count = SMEM_ITEM_COUNT; + break; + default: +diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c +index 7a3bdef5a7c0da..4724d4759dd07e 100644 +--- a/drivers/soc/ti/k3-socinfo.c ++++ b/drivers/soc/ti/k3-socinfo.c +@@ -87,7 +87,7 @@ static int k3_chipinfo_probe(struct platform_device *pdev) + if (IS_ERR(base)) + return PTR_ERR(base); + +- regmap = regmap_init_mmio(dev, base, &k3_chipinfo_regmap_cfg); ++ regmap = devm_regmap_init_mmio(dev, base, &k3_chipinfo_regmap_cfg); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + +diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c +index f49f8492dde512..e01aec084e39b7 100644 +--- a/drivers/soc/ti/pruss.c ++++ b/drivers/soc/ti/pruss.c +@@ -366,12 +366,10 @@ static int pruss_clk_mux_setup(struct pruss *pruss, struct clk *clk_mux, + + ret = devm_add_action_or_reset(dev, pruss_of_free_clk_provider, + clk_mux_np); +- if (ret) { ++ if (ret) + dev_err(dev, "failed to add clkmux free action %d", ret); +- goto put_clk_mux_np; +- } + +- return 0; ++ return ret; + + put_clk_mux_np: + of_node_put(clk_mux_np); +diff --git a/drivers/soundwire/dmi-quirks.c b/drivers/soundwire/dmi-quirks.c +index 91ab97a456fa9f..5854218e1a274e 100644 +--- a/drivers/soundwire/dmi-quirks.c ++++ b/drivers/soundwire/dmi-quirks.c +@@ -122,6 +122,17 @@ static const struct dmi_system_id adr_remap_quirk_table[] = { + }, + .driver_data = (void *)intel_tgl_bios, + }, ++ { ++ /* ++ * quirk used for Avell B.ON (OEM rebrand of NUC15 'Bishop County' ++ * LAPBC510 and LAPBC710) ++ */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Avell High Performance"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "B.ON"), ++ }, ++ .driver_data = (void *)intel_tgl_bios, ++ }, + { + /* quirk used for NUC15 'Rooks County' LAPRC510 and LAPRC710 skews */ + .matches = { +diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c +index 6a3b41dbfa701f..37a20652fd2e75 100644 +--- a/drivers/spi/spi-geni-qcom.c ++++ b/drivers/spi/spi-geni-qcom.c +@@ -548,10 +548,10 @@ static u32 get_xfer_len_in_words(struct spi_transfer *xfer, + { + u32 len; + +- if (!(mas->cur_bits_per_word % MIN_WORD_LEN)) +- len = xfer->len * BITS_PER_BYTE / mas->cur_bits_per_word; ++ if (!(xfer->bits_per_word % MIN_WORD_LEN)) ++ len = xfer->len * BITS_PER_BYTE / xfer->bits_per_word; + else +- len = xfer->len / (mas->cur_bits_per_word / BITS_PER_BYTE + 1); ++ len = xfer->len / (xfer->bits_per_word / BITS_PER_BYTE + 1); + len &= TRANS_LEN_MSK; + + return len; +@@ -571,7 +571,7 @@ static bool geni_can_dma(struct spi_controller *ctlr, + return true; + + len = get_xfer_len_in_words(xfer, mas); +- fifo_size = mas->tx_fifo_depth * mas->fifo_width_bits / mas->cur_bits_per_word; ++ fifo_size = mas->tx_fifo_depth * mas->fifo_width_bits / xfer->bits_per_word; + + if (len > fifo_size) + return true; +@@ -710,6 +710,12 @@ static int spi_geni_init(struct spi_geni_master *mas) + case 0: + mas->cur_xfer_mode = GENI_SE_FIFO; + geni_se_select_mode(se, GENI_SE_FIFO); ++ /* setup_fifo_params assumes that these registers start with a zero value */ ++ writel(0, se->base + SE_SPI_LOOPBACK); ++ writel(0, se->base + SE_SPI_DEMUX_SEL); ++ writel(0, se->base + SE_SPI_CPHA); ++ writel(0, se->base + SE_SPI_CPOL); ++ writel(0, se->base + SE_SPI_DEMUX_OUTPUT_INV); + ret = 0; + break; + } +diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c +index c581aa5fbf7cf7..932992b06022b0 100644 +--- a/drivers/spi/spi-mem.c ++++ b/drivers/spi/spi-mem.c +@@ -175,8 +175,19 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, + if (op->data.swap16 && !spi_mem_controller_is_capable(ctlr, swap16)) + return false; + +- if (op->cmd.nbytes != 2) +- return false; ++ /* Extra 8D-8D-8D limitations */ ++ if (op->cmd.dtr && op->cmd.buswidth == 8) { ++ if (op->cmd.nbytes != 2) ++ return false; ++ ++ if ((op->addr.nbytes % 2) || ++ (op->dummy.nbytes % 2) || ++ (op->data.nbytes % 2)) { ++ dev_err(&ctlr->dev, ++ "Even byte numbers not allowed in octal DTR operations\n"); ++ return false; ++ } ++ } + } else { + if (op->cmd.nbytes != 1) + return false; +@@ -590,9 +601,18 @@ spi_mem_dirmap_create(struct spi_mem *mem, + + desc->mem = mem; + desc->info = *info; +- if (ctlr->mem_ops && ctlr->mem_ops->dirmap_create) ++ if (ctlr->mem_ops && ctlr->mem_ops->dirmap_create) { ++ ret = spi_mem_access_start(mem); ++ if (ret) { ++ kfree(desc); ++ return ERR_PTR(ret); ++ } ++ + ret = ctlr->mem_ops->dirmap_create(desc); + ++ spi_mem_access_end(mem); ++ } ++ + if (ret) { + desc->nodirmap = true; + if (!spi_mem_supports_op(desc->mem, &desc->info.op_tmpl)) +diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c +index 211d9c76665bc4..96ee0e8456f4c5 100644 +--- a/drivers/spi/spi-stm32.c ++++ b/drivers/spi/spi-stm32.c +@@ -1507,11 +1507,12 @@ static void stm32h7_spi_data_idleness(struct stm32_spi *spi, u32 len) + cfg2_clrb |= STM32H7_SPI_CFG2_MIDI; + if ((len > 1) && (spi->cur_midi > 0)) { + u32 sck_period_ns = DIV_ROUND_UP(NSEC_PER_SEC, spi->cur_speed); +- u32 midi = min_t(u32, +- DIV_ROUND_UP(spi->cur_midi, sck_period_ns), +- FIELD_GET(STM32H7_SPI_CFG2_MIDI, +- STM32H7_SPI_CFG2_MIDI)); ++ u32 midi = DIV_ROUND_UP(spi->cur_midi, sck_period_ns); + ++ if ((spi->cur_bpw + midi) < 8) ++ midi = 8 - spi->cur_bpw; ++ ++ midi = min_t(u32, midi, FIELD_MAX(STM32H7_SPI_CFG2_MIDI)); + + dev_dbg(spi->dev, "period=%dns, midi=%d(=%dns)\n", + sck_period_ns, midi, midi * sck_period_ns); +diff --git a/drivers/spi/spi-wpcm-fiu.c b/drivers/spi/spi-wpcm-fiu.c +index 852ffe013d326e..c006889b37ebb3 100644 +--- a/drivers/spi/spi-wpcm-fiu.c ++++ b/drivers/spi/spi-wpcm-fiu.c +@@ -448,12 +448,10 @@ static int wpcm_fiu_probe(struct platform_device *pdev) + fiu = spi_controller_get_devdata(ctrl); + fiu->dev = dev; + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control"); +- fiu->regs = devm_ioremap_resource(dev, res); +- if (IS_ERR(fiu->regs)) { +- dev_err(dev, "Failed to map registers\n"); +- return PTR_ERR(fiu->regs); +- } ++ fiu->regs = devm_platform_ioremap_resource_byname(pdev, "control"); ++ if (IS_ERR(fiu->regs)) ++ return dev_err_probe(dev, PTR_ERR(fiu->regs), ++ "Failed to map registers\n"); + + fiu->clk = devm_clk_get_enabled(dev, NULL); + if (IS_ERR(fiu->clk)) +@@ -461,12 +459,11 @@ static int wpcm_fiu_probe(struct platform_device *pdev) + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory"); + fiu->memory = devm_ioremap_resource(dev, res); +- fiu->memory_size = min_t(size_t, resource_size(res), MAX_MEMORY_SIZE_TOTAL); +- if (IS_ERR(fiu->memory)) { +- dev_err(dev, "Failed to map flash memory window\n"); +- return PTR_ERR(fiu->memory); +- } ++ if (IS_ERR(fiu->memory)) ++ return dev_err_probe(dev, PTR_ERR(fiu->memory), ++ "Failed to map flash memory window\n"); + ++ fiu->memory_size = min_t(size_t, resource_size(res), MAX_MEMORY_SIZE_TOTAL); + fiu->shm_regmap = syscon_regmap_lookup_by_phandle_optional(dev->of_node, "nuvoton,shm"); + + wpcm_fiu_hw_init(fiu); +diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c +index 9999f84016992a..eb69500e080e05 100644 +--- a/drivers/staging/greybus/light.c ++++ b/drivers/staging/greybus/light.c +@@ -1029,14 +1029,18 @@ static int gb_lights_light_config(struct gb_lights *glights, u8 id) + if (!strlen(conf.name)) + return -EINVAL; + +- light->channels_count = conf.channel_count; + light->name = kstrndup(conf.name, NAMES_MAX, GFP_KERNEL); + if (!light->name) + return -ENOMEM; +- light->channels = kcalloc(light->channels_count, ++ light->channels = kcalloc(conf.channel_count, + sizeof(struct gb_channel), GFP_KERNEL); + if (!light->channels) + return -ENOMEM; ++ /* ++ * Publish channels_count only after channels allocation so cleanup ++ * doesn't walk a NULL channels pointer on allocation failure. ++ */ ++ light->channels_count = conf.channel_count; + + /* First we collect all the configurations for all channels */ + for (i = 0; i < light->channels_count; i++) { +diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c +index b221913733fb61..19b877f50fb627 100644 +--- a/drivers/staging/rtl8723bs/core/rtw_mlme.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c +@@ -876,8 +876,10 @@ static void find_network(struct adapter *adapter) + struct wlan_network *tgt_network = &pmlmepriv->cur_network; + + pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.mac_address); +- if (pwlan) +- pwlan->fixed = false; ++ if (!pwlan) ++ return; ++ ++ pwlan->fixed = false; + + if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && + (adapter->stapriv.asoc_sta_count == 1)) +diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +index af155fca39b8ca..f23aeb58d041d0 100644 +--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c ++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +@@ -316,9 +316,10 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl + len, notify_signal, GFP_ATOMIC); + + if (unlikely(!bss)) +- goto exit; ++ goto free_buf; + + cfg80211_put_bss(wiphy, bss); ++free_buf: + kfree(buf); + + exit: +diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c +index 49043148452429..335e6002df70f6 100644 +--- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c ++++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c +@@ -380,7 +380,8 @@ static int rtw_drv_init( + if (status != _SUCCESS) + goto free_if1; + +- if (sdio_alloc_irq(dvobj) != _SUCCESS) ++ status = sdio_alloc_irq(dvobj); ++ if (status != _SUCCESS) + goto free_if1; + + rtw_ndev_notifier_register(); +diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c +index 546b70434004cb..8bcac4adb9ecec 100644 +--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c ++++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c +@@ -348,8 +348,11 @@ int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc + + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR) { + ret = sysfs_create_group(&pdev->dev.kobj, &dlvr_attribute_group); +- if (ret) ++ if (ret) { ++ if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) ++ sysfs_remove_group(&pdev->dev.kobj, &fivr_attribute_group); + return ret; ++ } + } + + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) { +diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c +index 57b27f9ea1f034..60a05bfecde39c 100644 +--- a/drivers/tty/serial/8250/8250_dw.c ++++ b/drivers/tty/serial/8250/8250_dw.c +@@ -753,11 +753,18 @@ static int dw8250_runtime_suspend(struct device *dev) + + static int dw8250_runtime_resume(struct device *dev) + { ++ int ret; + struct dw8250_data *data = dev_get_drvdata(dev); + +- clk_prepare_enable(data->pclk); ++ ret = clk_prepare_enable(data->pclk); ++ if (ret) ++ return ret; + +- clk_prepare_enable(data->clk); ++ ret = clk_prepare_enable(data->clk); ++ if (ret) { ++ clk_disable_unprepare(data->pclk); ++ return ret; ++ } + + return 0; + } +diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c +index 9ed62bc7cdd83a..776373423b2a01 100644 +--- a/drivers/tty/serial/8250/8250_omap.c ++++ b/drivers/tty/serial/8250/8250_omap.c +@@ -924,7 +924,6 @@ static void __dma_rx_do_complete(struct uart_8250_port *p) + goto out; + + cookie = dma->rx_cookie; +- dma->rx_running = 0; + + /* Re-enable RX FIFO interrupt now that transfer is complete */ + if (priv->habit & UART_HAS_RHR_IT_DIS) { +@@ -958,6 +957,7 @@ static void __dma_rx_do_complete(struct uart_8250_port *p) + goto out; + ret = tty_insert_flip_string(tty_port, dma->rx_buf, count); + ++ dma->rx_running = 0; + p->port.icount.rx += ret; + p->port.icount.buf_overrun += count - ret; + out: +diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig +index 4f57833e3ec742..2b9b2235e29d6f 100644 +--- a/drivers/tty/serial/Kconfig ++++ b/drivers/tty/serial/Kconfig +@@ -479,14 +479,14 @@ config SERIAL_IMX + can enable its onboard serial port by enabling this option. + + config SERIAL_IMX_CONSOLE +- tristate "Console on IMX serial port" ++ bool "Console on IMX serial port" + depends on SERIAL_IMX + select SERIAL_CORE_CONSOLE + help + If you have enabled the serial port on the Freescale IMX +- CPU you can make it the console by answering Y/M to this option. ++ CPU you can make it the console by answering Y to this option. + +- Even if you say Y/M here, the currently visible virtual console ++ Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttymxc0". (Try "man bootparam" or see the documentation of +@@ -661,7 +661,7 @@ config SERIAL_SH_SCI_EARLYCON + default ARCH_RENESAS + + config SERIAL_SH_SCI_DMA +- bool "DMA support" if EXPERT ++ bool "Support for DMA on SuperH SCI(F)" if EXPERT + depends on SERIAL_SH_SCI && DMA_ENGINE + default ARCH_RENESAS + +diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c +index 9f53ee92486dc3..808b648e1f3885 100644 +--- a/drivers/ufs/core/ufshcd.c ++++ b/drivers/ufs/core/ufshcd.c +@@ -9836,6 +9836,8 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) + + if (req_dev_pwr_mode == UFS_ACTIVE_PWR_MODE && + req_link_state == UIC_LINK_ACTIVE_STATE) { ++ ufshcd_disable_auto_bkops(hba); ++ flush_work(&hba->eeh_work); + goto vops_suspend; + } + +diff --git a/drivers/ufs/host/Kconfig b/drivers/ufs/host/Kconfig +index 580c8d0bd8bbd8..626bb9002f4a12 100644 +--- a/drivers/ufs/host/Kconfig ++++ b/drivers/ufs/host/Kconfig +@@ -72,6 +72,7 @@ config SCSI_UFS_QCOM + config SCSI_UFS_MEDIATEK + tristate "Mediatek specific hooks to UFS controller platform driver" + depends on SCSI_UFSHCD_PLATFORM && ARCH_MEDIATEK ++ depends on PM + depends on RESET_CONTROLLER + select PHY_MTK_UFS + select RESET_TI_SYSCON +diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c +index 8b4a3cc8125310..606e90ce8ca70d 100644 +--- a/drivers/ufs/host/ufs-mediatek.c ++++ b/drivers/ufs/host/ufs-mediatek.c +@@ -1852,7 +1852,6 @@ static int ufs_mtk_remove(struct platform_device *pdev) + return 0; + } + +-#ifdef CONFIG_PM_SLEEP + static int ufs_mtk_system_suspend(struct device *dev) + { + struct ufs_hba *hba = dev_get_drvdata(dev); +@@ -1875,9 +1874,7 @@ static int ufs_mtk_system_resume(struct device *dev) + + return ufshcd_system_resume(dev); + } +-#endif + +-#ifdef CONFIG_PM + static int ufs_mtk_runtime_suspend(struct device *dev) + { + struct ufs_hba *hba = dev_get_drvdata(dev); +@@ -1900,13 +1897,10 @@ static int ufs_mtk_runtime_resume(struct device *dev) + + return ufshcd_runtime_resume(dev); + } +-#endif + + static const struct dev_pm_ops ufs_mtk_pm_ops = { +- SET_SYSTEM_SLEEP_PM_OPS(ufs_mtk_system_suspend, +- ufs_mtk_system_resume) +- SET_RUNTIME_PM_OPS(ufs_mtk_runtime_suspend, +- ufs_mtk_runtime_resume, NULL) ++ SYSTEM_SLEEP_PM_OPS(ufs_mtk_system_suspend, ufs_mtk_system_resume) ++ RUNTIME_PM_OPS(ufs_mtk_runtime_suspend, ufs_mtk_runtime_resume, NULL) + .prepare = ufshcd_suspend_prepare, + .complete = ufshcd_resume_complete, + }; +@@ -1916,7 +1910,7 @@ static struct platform_driver ufs_mtk_pltform = { + .remove = ufs_mtk_remove, + .driver = { + .name = "ufshcd-mtk", +- .pm = &ufs_mtk_pm_ops, ++ .pm = pm_ptr(&ufs_mtk_pm_ops), + .of_match_table = ufs_mtk_of_match, + }, + }; +diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c +index 5635e4d7ec880e..66080ab8c8e017 100644 +--- a/drivers/usb/dwc2/core.c ++++ b/drivers/usb/dwc2/core.c +@@ -572,6 +572,7 @@ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg) + { + switch (hsotg->dr_mode) { + case USB_DR_MODE_HOST: ++ dwc2_force_mode(hsotg, true); + /* + * NOTE: This is required for some rockchip soc based + * platforms on their host-only dwc2. +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index 45c9a399f8a554..11b938fd9de04f 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1892,6 +1892,20 @@ static int dwc3_get_clocks(struct dwc3 *dwc) + return 0; + } + ++static void dwc3_vbus_draw_work(struct work_struct *work) ++{ ++ struct dwc3 *dwc = container_of(work, struct dwc3, vbus_draw_work); ++ union power_supply_propval val = {0}; ++ int ret; ++ ++ val.intval = 1000 * (dwc->current_limit); ++ ret = power_supply_set_property(dwc->usb_psy, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val); ++ ++ if (ret < 0) ++ dev_dbg(dwc->dev, "Error (%d) setting vbus draw (%d mA)\n", ++ ret, dwc->current_limit); ++} ++ + static struct power_supply *dwc3_get_usb_power_supply(struct dwc3 *dwc) + { + struct power_supply *usb_psy; +@@ -1906,6 +1920,7 @@ static struct power_supply *dwc3_get_usb_power_supply(struct dwc3 *dwc) + if (!usb_psy) + return ERR_PTR(-EPROBE_DEFER); + ++ INIT_WORK(&dwc->vbus_draw_work, dwc3_vbus_draw_work); + return usb_psy; + } + +@@ -2097,8 +2112,10 @@ static void dwc3_remove(struct platform_device *pdev) + + dwc3_free_event_buffers(dwc); + +- if (dwc->usb_psy) ++ if (dwc->usb_psy) { ++ cancel_work_sync(&dwc->vbus_draw_work); + power_supply_put(dwc->usb_psy); ++ } + } + + #ifdef CONFIG_PM +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index 9fc91f5c0bdbf2..45084ca66806ef 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -1034,6 +1034,8 @@ struct dwc3_scratchpad_array { + * @role_switch_default_mode: default operation mode of controller while + * usb role is USB_ROLE_NONE. + * @usb_psy: pointer to power supply interface. ++ * @vbus_draw_work: Work to set the vbus drawing limit ++ * @current_limit: How much current to draw from vbus, in milliAmperes. + * @usb2_phy: pointer to USB2 PHY + * @usb3_phy: pointer to USB3 PHY + * @usb2_generic_phy: pointer to USB2 PHY +@@ -1202,6 +1204,8 @@ struct dwc3 { + enum usb_dr_mode role_switch_default_mode; + + struct power_supply *usb_psy; ++ struct work_struct vbus_draw_work; ++ unsigned int current_limit; + + u32 fladj; + u32 ref_clk_per; +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 8781ebeaab9041..7e6661781afffe 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -3139,8 +3139,6 @@ static void dwc3_gadget_set_ssp_rate(struct usb_gadget *g, + static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA) + { + struct dwc3 *dwc = gadget_to_dwc(g); +- union power_supply_propval val = {0}; +- int ret; + + if (dwc->usb2_phy) + return usb_phy_set_power(dwc->usb2_phy, mA); +@@ -3148,10 +3146,10 @@ static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA) + if (!dwc->usb_psy) + return -EOPNOTSUPP; + +- val.intval = 1000 * mA; +- ret = power_supply_set_property(dwc->usb_psy, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val); ++ dwc->current_limit = mA; ++ schedule_work(&dwc->vbus_draw_work); + +- return ret; ++ return 0; + } + + /** +diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c +index 35a652807fca87..c2e3fa997842ad 100644 +--- a/drivers/usb/gadget/udc/bdc/bdc_core.c ++++ b/drivers/usb/gadget/udc/bdc/bdc_core.c +@@ -35,8 +35,8 @@ static int poll_oip(struct bdc *bdc, u32 usec) + u32 status; + int ret; + +- ret = readl_poll_timeout(bdc->regs + BDC_BDCSC, status, +- (BDC_CSTS(status) != BDC_OIP), 10, usec); ++ ret = readl_poll_timeout_atomic(bdc->regs + BDC_BDCSC, status, ++ (BDC_CSTS(status) != BDC_OIP), 10, usec); + if (ret) + dev_err(bdc->dev, "operation timedout BDCSC: 0x%08x\n", status); + else +diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c +index 3a14b6b72d8c6f..114a80dd06fbb4 100644 +--- a/drivers/usb/gadget/udc/tegra-xudc.c ++++ b/drivers/usb/gadget/udc/tegra-xudc.c +@@ -3388,17 +3388,18 @@ static void tegra_xudc_device_params_init(struct tegra_xudc *xudc) + { + u32 val, imod; + ++ val = xudc_readl(xudc, BLCG); + if (xudc->soc->has_ipfs) { +- val = xudc_readl(xudc, BLCG); + val |= BLCG_ALL; + val &= ~(BLCG_DFPCI | BLCG_UFPCI | BLCG_FE | + BLCG_COREPLL_PWRDN); + val |= BLCG_IOPLL_0_PWRDN; + val |= BLCG_IOPLL_1_PWRDN; + val |= BLCG_IOPLL_2_PWRDN; +- +- xudc_writel(xudc, val, BLCG); ++ } else { ++ val &= ~BLCG_COREPLL_PWRDN; + } ++ xudc_writel(xudc, val, BLCG); + + if (xudc->soc->port_speed_quirk) + tegra_xudc_limit_port_speed(xudc); +@@ -3949,6 +3950,7 @@ static void tegra_xudc_remove(struct platform_device *pdev) + static int __maybe_unused tegra_xudc_powergate(struct tegra_xudc *xudc) + { + unsigned long flags; ++ u32 val; + + dev_dbg(xudc->dev, "entering ELPG\n"); + +@@ -3961,6 +3963,10 @@ static int __maybe_unused tegra_xudc_powergate(struct tegra_xudc *xudc) + + spin_unlock_irqrestore(&xudc->lock, flags); + ++ val = xudc_readl(xudc, BLCG); ++ val |= BLCG_COREPLL_PWRDN; ++ xudc_writel(xudc, val, BLCG); ++ + clk_bulk_disable_unprepare(xudc->soc->num_clks, xudc->clks); + + regulator_bulk_disable(xudc->soc->num_supplies, xudc->supplies); +diff --git a/drivers/usb/typec/ucsi/psy.c b/drivers/usb/typec/ucsi/psy.c +index c80c23d3384e89..3fc524190baf67 100644 +--- a/drivers/usb/typec/ucsi/psy.c ++++ b/drivers/usb/typec/ucsi/psy.c +@@ -87,15 +87,20 @@ static int ucsi_psy_get_voltage_max(struct ucsi_connector *con, + union power_supply_propval *val) + { + u32 pdo; ++ int max_voltage = 0; + + switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) { + case UCSI_CONSTAT_PWR_OPMODE_PD: +- if (con->num_pdos > 0) { +- pdo = con->src_pdos[con->num_pdos - 1]; +- val->intval = pdo_fixed_voltage(pdo) * 1000; +- } else { +- val->intval = 0; ++ for (int i = 0; i < con->num_pdos; i++) { ++ int pdo_voltage = 0; ++ ++ pdo = con->src_pdos[i]; ++ if (pdo_type(pdo) == PDO_TYPE_FIXED) ++ pdo_voltage = pdo_fixed_voltage(pdo) * 1000; ++ max_voltage = (pdo_voltage > max_voltage) ? pdo_voltage ++ : max_voltage; + } ++ val->intval = max_voltage; + break; + case UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0: + case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5: +@@ -143,6 +148,7 @@ static int ucsi_psy_get_current_max(struct ucsi_connector *con, + union power_supply_propval *val) + { + u32 pdo; ++ int max_current = 0; + + if (!(con->status.flags & UCSI_CONSTAT_CONNECTED)) { + val->intval = 0; +@@ -151,12 +157,16 @@ static int ucsi_psy_get_current_max(struct ucsi_connector *con, + + switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) { + case UCSI_CONSTAT_PWR_OPMODE_PD: +- if (con->num_pdos > 0) { +- pdo = con->src_pdos[con->num_pdos - 1]; +- val->intval = pdo_max_current(pdo) * 1000; +- } else { +- val->intval = 0; ++ for (int i = 0; i < con->num_pdos; i++) { ++ int pdo_current = 0; ++ ++ pdo = con->src_pdos[i]; ++ if (pdo_type(pdo) == PDO_TYPE_FIXED) ++ pdo_current = pdo_max_current(pdo) * 1000; ++ max_current = (pdo_current > max_current) ? pdo_current ++ : max_current; + } ++ val->intval = max_current; + break; + case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5: + val->intval = UCSI_TYPEC_1_5_CURRENT * 1000; +diff --git a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c +index 712b178c42aae5..e544fd0a710c0c 100644 +--- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c ++++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c +@@ -1152,8 +1152,7 @@ static void hisi_acc_vf_pci_aer_reset_done(struct pci_dev *pdev) + { + struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_drvdata(pdev); + +- if (hisi_acc_vdev->core_device.vdev.migration_flags != +- VFIO_MIGRATION_STOP_COPY) ++ if (!hisi_acc_vdev->core_device.vdev.mig_ops) + return; + + /* +diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c +index c29a195a0175c0..f4da76fa235eae 100644 +--- a/drivers/vhost/vdpa.c ++++ b/drivers/vhost/vdpa.c +@@ -1424,6 +1424,7 @@ static int vhost_vdpa_mmap(struct file *file, struct vm_area_struct *vma) + if (vma->vm_end - vma->vm_start != notify.size) + return -ENOTSUPP; + ++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP); + vma->vm_ops = &vhost_vdpa_vm_ops; + return 0; +diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c +index b19e5f73de8bb4..0d55818f554ec6 100644 +--- a/drivers/video/backlight/qcom-wled.c ++++ b/drivers/video/backlight/qcom-wled.c +@@ -1244,6 +1244,15 @@ static const struct wled_var_cfg wled4_ovp_cfg = { + .size = ARRAY_SIZE(wled4_ovp_values), + }; + ++static const u32 pmi8994_wled_ovp_values[] = { ++ 31000, 29500, 19400, 17800, ++}; ++ ++static const struct wled_var_cfg pmi8994_wled_ovp_cfg = { ++ .values = pmi8994_wled_ovp_values, ++ .size = ARRAY_SIZE(pmi8994_wled_ovp_values), ++}; ++ + static inline u32 wled5_ovp_values_fn(u32 idx) + { + /* +@@ -1357,6 +1366,29 @@ static int wled_configure(struct wled *wled) + }, + }; + ++ const struct wled_u32_opts pmi8994_wled_opts[] = { ++ { ++ .name = "qcom,current-boost-limit", ++ .val_ptr = &cfg->boost_i_limit, ++ .cfg = &wled4_boost_i_limit_cfg, ++ }, ++ { ++ .name = "qcom,current-limit-microamp", ++ .val_ptr = &cfg->string_i_limit, ++ .cfg = &wled4_string_i_limit_cfg, ++ }, ++ { ++ .name = "qcom,ovp-millivolt", ++ .val_ptr = &cfg->ovp, ++ .cfg = &pmi8994_wled_ovp_cfg, ++ }, ++ { ++ .name = "qcom,switching-freq", ++ .val_ptr = &cfg->switch_freq, ++ .cfg = &wled3_switch_freq_cfg, ++ }, ++ }; ++ + const struct wled_u32_opts wled5_opts[] = { + { + .name = "qcom,current-boost-limit", +@@ -1423,8 +1455,14 @@ static int wled_configure(struct wled *wled) + break; + + case 4: +- u32_opts = wled4_opts; +- size = ARRAY_SIZE(wled4_opts); ++ if (of_device_is_compatible(dev->of_node, "qcom,pmi8950-wled") || ++ of_device_is_compatible(dev->of_node, "qcom,pmi8994-wled")) { ++ u32_opts = pmi8994_wled_opts; ++ size = ARRAY_SIZE(pmi8994_wled_opts); ++ } else { ++ u32_opts = wled4_opts; ++ size = ARRAY_SIZE(wled4_opts); ++ } + *cfg = wled4_config_defaults; + wled->wled_set_brightness = wled4_set_brightness; + wled->wled_sync_toggle = wled3_sync_toggle; +diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c +index c137d6afe4840c..1b05dfbd5195e6 100644 +--- a/drivers/video/fbdev/au1200fb.c ++++ b/drivers/video/fbdev/au1200fb.c +@@ -1732,8 +1732,10 @@ static int au1200fb_drv_probe(struct platform_device *dev) + + /* Now hook interrupt too */ + irq = platform_get_irq(dev, 0); +- if (irq < 0) +- return irq; ++ if (irq < 0) { ++ ret = irq; ++ goto failed; ++ } + + ret = request_irq(irq, au1200fb_handle_irq, + IRQF_SHARED, "lcd", (void *)dev); +diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c +index 78a5b22c8d1507..703c4e851612c8 100644 +--- a/drivers/video/fbdev/core/fbcon.c ++++ b/drivers/video/fbdev/core/fbcon.c +@@ -1023,7 +1023,8 @@ static void fbcon_init(struct vc_data *vc, bool init) + return; + + if (!info->fbcon_par) +- con2fb_acquire_newinfo(vc, info, vc->vc_num); ++ if (con2fb_acquire_newinfo(vc, info, vc->vc_num)) ++ return; + + /* If we are not the first console on this + fb, copy the font from that console */ +diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h +index 25691d4b027bfc..7945b360862cb3 100644 +--- a/drivers/video/fbdev/core/fbcon.h ++++ b/drivers/video/fbdev/core/fbcon.h +@@ -30,7 +30,6 @@ struct fbcon_display { + #ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION + u_short scrollmode; /* Scroll Method, use fb_scrollmode() */ + #endif +- u_short inverse; /* != 0 text black on white as default */ + short yscroll; /* Hardware scrolling */ + int vrows; /* number of virtual rows */ + int cursor_shape; +diff --git a/drivers/video/fbdev/ffb.c b/drivers/video/fbdev/ffb.c +index e3a9bb7e9dea44..e8992bdd3c9a59 100644 +--- a/drivers/video/fbdev/ffb.c ++++ b/drivers/video/fbdev/ffb.c +@@ -336,6 +336,9 @@ struct ffb_dac { + }; + + #define FFB_DAC_UCTRL 0x1001 /* User Control */ ++#define FFB_DAC_UCTRL_OVENAB 0x00000008 /* Overlay Enable */ ++#define FFB_DAC_UCTRL_WMODE 0x00000030 /* Window Mode */ ++#define FFB_DAC_UCTRL_WM_COMB 0x00000000 /* Window Mode = Combined */ + #define FFB_DAC_UCTRL_MANREV 0x00000f00 /* 4-bit Manufacturing Revision */ + #define FFB_DAC_UCTRL_MANREV_SHIFT 8 + #define FFB_DAC_TGEN 0x6000 /* Timing Generator */ +@@ -426,7 +429,7 @@ static void ffb_switch_from_graph(struct ffb_par *par) + { + struct ffb_fbc __iomem *fbc = par->fbc; + struct ffb_dac __iomem *dac = par->dac; +- unsigned long flags; ++ unsigned long flags, uctrl; + + spin_lock_irqsave(&par->lock, flags); + FFBWait(par); +@@ -451,6 +454,15 @@ static void ffb_switch_from_graph(struct ffb_par *par) + upa_writel((FFB_DAC_CUR_CTRL_P0 | + FFB_DAC_CUR_CTRL_P1), &dac->value2); + ++ /* Disable overlay and window modes. */ ++ upa_writel(FFB_DAC_UCTRL, &dac->type); ++ uctrl = upa_readl(&dac->value); ++ uctrl &= ~FFB_DAC_UCTRL_WMODE; ++ uctrl |= FFB_DAC_UCTRL_WM_COMB; ++ uctrl &= ~FFB_DAC_UCTRL_OVENAB; ++ upa_writel(FFB_DAC_UCTRL, &dac->type); ++ upa_writel(uctrl, &dac->value); ++ + spin_unlock_irqrestore(&par->lock, flags); + } + +diff --git a/drivers/video/fbdev/vt8500lcdfb.c b/drivers/video/fbdev/vt8500lcdfb.c +index 42d39a9d5130f9..f62fe1a9dd6287 100644 +--- a/drivers/video/fbdev/vt8500lcdfb.c ++++ b/drivers/video/fbdev/vt8500lcdfb.c +@@ -367,7 +367,7 @@ static int vt8500lcd_probe(struct platform_device *pdev) + if (fbi->palette_cpu == NULL) { + dev_err(&pdev->dev, "Failed to allocate palette buffer\n"); + ret = -ENOMEM; +- goto failed_free_io; ++ goto failed_free_mem_virt; + } + + irq = platform_get_irq(pdev, 0); +@@ -431,6 +431,9 @@ failed_free_irq: + failed_free_palette: + dma_free_coherent(&pdev->dev, fbi->palette_size, + fbi->palette_cpu, fbi->palette_phys); ++failed_free_mem_virt: ++ dma_free_coherent(&pdev->dev, fbi->fb.fix.smem_len, ++ fbi->fb.screen_buffer, fbi->fb.fix.smem_start); + failed_free_io: + iounmap(fbi->regbase); + failed_free_res: +diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c +index bebd371c6b93ea..a6ec392253c3ee 100644 +--- a/drivers/video/of_display_timing.c ++++ b/drivers/video/of_display_timing.c +@@ -181,7 +181,7 @@ struct display_timings *of_get_display_timings(const struct device_node *np) + if (disp->num_timings == 0) { + /* should never happen, as entry was already found above */ + pr_err("%pOF: no timings specified\n", np); +- goto entryfail; ++ goto timingfail; + } + + disp->timings = kcalloc(disp->num_timings, +@@ -189,13 +189,13 @@ struct display_timings *of_get_display_timings(const struct device_node *np) + GFP_KERNEL); + if (!disp->timings) { + pr_err("%pOF: could not allocate timings array\n", np); +- goto entryfail; ++ goto timingfail; + } + + disp->num_timings = 0; + disp->native_mode = 0; + +- for_each_child_of_node(timings_np, entry) { ++ for_each_child_of_node_scoped(timings_np, child) { + struct display_timing *dt; + int r; + +@@ -206,7 +206,7 @@ struct display_timings *of_get_display_timings(const struct device_node *np) + goto timingfail; + } + +- r = of_parse_display_timing(entry, dt); ++ r = of_parse_display_timing(child, dt); + if (r) { + /* + * to not encourage wrong devicetrees, fail in case of +@@ -218,7 +218,7 @@ struct display_timings *of_get_display_timings(const struct device_node *np) + goto timingfail; + } + +- if (native_mode == entry) ++ if (native_mode == child) + disp->native_mode = disp->num_timings; + + disp->timings[disp->num_timings] = dt; +diff --git a/drivers/watchdog/imx7ulp_wdt.c b/drivers/watchdog/imx7ulp_wdt.c +index c703586c6e5f08..b6797845a48fb6 100644 +--- a/drivers/watchdog/imx7ulp_wdt.c ++++ b/drivers/watchdog/imx7ulp_wdt.c +@@ -342,6 +342,7 @@ static int imx7ulp_wdt_probe(struct platform_device *pdev) + watchdog_stop_on_reboot(wdog); + watchdog_stop_on_unregister(wdog); + watchdog_set_drvdata(wdog, imx7ulp_wdt); ++ watchdog_set_nowayout(wdog, nowayout); + + imx7ulp_wdt->hw = of_device_get_match_data(dev); + ret = imx7ulp_wdt_init(imx7ulp_wdt, wdog->timeout * imx7ulp_wdt->hw->wdog_clock_rate); +diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c +index 239947df613db1..1392e557fa371b 100644 +--- a/drivers/watchdog/it87_wdt.c ++++ b/drivers/watchdog/it87_wdt.c +@@ -183,6 +183,12 @@ static void _wdt_update_timeout(unsigned int t) + superio_outb(t >> 8, WDTVALMSB); + } + ++/* Internal function, should be called after superio_select(GPIO) */ ++static bool _wdt_running(void) ++{ ++ return superio_inb(WDTVALLSB) || (max_units > 255 && superio_inb(WDTVALMSB)); ++} ++ + static int wdt_update_timeout(unsigned int t) + { + int ret; +@@ -365,6 +371,12 @@ static int __init it87_wdt_init(void) + } + } + ++ /* wdt already left running by firmware? */ ++ if (_wdt_running()) { ++ pr_info("Left running by firmware.\n"); ++ set_bit(WDOG_HW_RUNNING, &wdt_dev.status); ++ } ++ + superio_exit(); + + if (timeout < 1 || timeout > max_units * 60) { +diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wdt.c +index 0606142ffc5e2d..3842a0b1b6cb8e 100644 +--- a/drivers/watchdog/starfive-wdt.c ++++ b/drivers/watchdog/starfive-wdt.c +@@ -444,7 +444,7 @@ static int starfive_wdt_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, wdt); + pm_runtime_enable(&pdev->dev); + if (pm_runtime_enabled(&pdev->dev)) { +- ret = pm_runtime_get_sync(&pdev->dev); ++ ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret < 0) + return ret; + } else { +diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c +index 204ec1bcbd526a..a76d5530533ff5 100644 +--- a/drivers/xen/balloon.c ++++ b/drivers/xen/balloon.c +@@ -716,6 +716,7 @@ static int __init balloon_add_regions(void) + static int __init balloon_init(void) + { + struct task_struct *task; ++ unsigned long current_pages; + int rc; + + if (!xen_domain()) +@@ -723,12 +724,18 @@ static int __init balloon_init(void) + + pr_info("Initialising balloon driver\n"); + +- if (xen_released_pages >= get_num_physpages()) { +- WARN(1, "Released pages underflow current target"); +- return -ERANGE; ++ if (xen_pv_domain()) { ++ if (xen_released_pages >= xen_start_info->nr_pages) ++ goto underflow; ++ current_pages = min(xen_start_info->nr_pages - ++ xen_released_pages, max_pfn); ++ } else { ++ if (xen_unpopulated_pages >= get_num_physpages()) ++ goto underflow; ++ current_pages = get_num_physpages() - xen_unpopulated_pages; + } + +- balloon_stats.current_pages = get_num_physpages() - xen_released_pages; ++ balloon_stats.current_pages = current_pages; + balloon_stats.target_pages = balloon_stats.current_pages; + balloon_stats.balloon_low = 0; + balloon_stats.balloon_high = 0; +@@ -759,6 +766,10 @@ static int __init balloon_init(void) + xen_balloon_init(); + + return 0; ++ ++ underflow: ++ WARN(1, "Released pages underflow current target"); ++ return -ERANGE; + } + subsys_initcall(balloon_init); + +diff --git a/drivers/xen/grant-dma-ops.c b/drivers/xen/grant-dma-ops.c +index 76f6f26265a3b8..12fbe89382593b 100644 +--- a/drivers/xen/grant-dma-ops.c ++++ b/drivers/xen/grant-dma-ops.c +@@ -362,7 +362,8 @@ static int xen_grant_init_backend_domid(struct device *dev, + if (np) { + ret = xen_dt_grant_init_backend_domid(dev, np, backend_domid); + of_node_put(np); +- } else if (IS_ENABLED(CONFIG_XEN_VIRTIO_FORCE_GRANT) || xen_pv_domain()) { ++ } else if (!xen_initial_domain() && ++ (IS_ENABLED(CONFIG_XEN_VIRTIO_FORCE_GRANT) || xen_pv_domain())) { + dev_info(dev, "Using dom0 as backend\n"); + *backend_domid = 0; + ret = 0; +diff --git a/drivers/xen/unpopulated-alloc.c b/drivers/xen/unpopulated-alloc.c +index a39f2d36dd9cfc..ae46291e99a9de 100644 +--- a/drivers/xen/unpopulated-alloc.c ++++ b/drivers/xen/unpopulated-alloc.c +@@ -18,6 +18,9 @@ static unsigned int list_count; + + static struct resource *target_resource; + ++/* Pages to subtract from the memory count when setting balloon target. */ ++unsigned long xen_unpopulated_pages __initdata; ++ + /* + * If arch is not happy with system "iomem_resource" being used for + * the region allocation it can provide it's own view by creating specific +diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c +index fcb335bb7b1878..1fdf5be1934301 100644 +--- a/drivers/xen/xenbus/xenbus_probe_frontend.c ++++ b/drivers/xen/xenbus/xenbus_probe_frontend.c +@@ -148,11 +148,9 @@ static void xenbus_frontend_dev_shutdown(struct device *_dev) + } + + static const struct dev_pm_ops xenbus_pm_ops = { +- .suspend = xenbus_dev_suspend, +- .resume = xenbus_frontend_dev_resume, + .freeze = xenbus_dev_suspend, + .thaw = xenbus_dev_cancel, +- .restore = xenbus_dev_resume, ++ .restore = xenbus_frontend_dev_resume, + }; + + static struct xen_bus_type xenbus_frontend = { +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 5e3d1a87b7e9da..774bdafc822c1d 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -6196,6 +6196,10 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) + range->minlen); + + trimmed += group_trimmed; ++ if (ret == -ERESTARTSYS || ret == -EINTR) { ++ btrfs_put_block_group(cache); ++ break; ++ } + if (ret) { + bg_failed++; + bg_ret = ret; +@@ -6209,6 +6213,9 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) + "failed to trim %llu block group(s), last error %d", + bg_failed, bg_ret); + ++ if (ret == -ERESTARTSYS || ret == -EINTR) ++ return ret; ++ + mutex_lock(&fs_devices->device_list_mutex); + list_for_each_entry(device, &fs_devices->devices, dev_list) { + if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) +@@ -6217,10 +6224,12 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) + ret = btrfs_trim_free_extents(device, &group_trimmed); + + trimmed += group_trimmed; ++ if (ret == -ERESTARTSYS || ret == -EINTR) ++ break; + if (ret) { + dev_failed++; + dev_ret = ret; +- break; ++ continue; + } + } + mutex_unlock(&fs_devices->device_list_mutex); +@@ -6230,6 +6239,8 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) + "failed to trim %llu device(s), last error %d", + dev_failed, dev_ret); + range->len = trimmed; ++ if (ret == -ERESTARTSYS || ret == -EINTR) ++ return ret; + if (bg_ret) + return bg_ret; + return dev_ret; +diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c +index c46ea2ecf18817..622febdb61e23e 100644 +--- a/fs/btrfs/qgroup.c ++++ b/fs/btrfs/qgroup.c +@@ -1129,11 +1129,14 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info) + } + if (ret > 0) { + /* +- * Shouldn't happen, but in case it does we +- * don't need to do the btrfs_next_item, just +- * continue. ++ * Shouldn't happen because the key should still ++ * be there (return 0), but in case it does it ++ * means we have reached the end of the tree - ++ * there are no more leaves with items that have ++ * a key greater than or equals to @found_key, ++ * so just stop the search loop. + */ +- continue; ++ break; + } + } + ret = btrfs_next_item(tree_root, path); +@@ -1601,8 +1604,10 @@ delete_item: + if (ret < 0 && ret != -ENOENT) + goto out; + ret2 = del_qgroup_relation_item(trans, dst, src); +- if (ret2 < 0 && ret2 != -ENOENT) ++ if (ret2 < 0 && ret2 != -ENOENT) { ++ ret = ret2; + goto out; ++ } + + /* At least one deletion succeeded, return 0 */ + if (!ret || !ret2) +diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c +index ce1e5b5dae3a0e..6dbbb03be562f5 100644 +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -2457,13 +2457,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans) + list_add_tail(&fs_info->chunk_root->dirty_list, + &cur_trans->switch_commits); + +- if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) { +- btrfs_set_root_node(&fs_info->block_group_root->root_item, +- fs_info->block_group_root->node); +- list_add_tail(&fs_info->block_group_root->dirty_list, +- &cur_trans->switch_commits); +- } +- + switch_commit_roots(trans); + + ASSERT(list_empty(&cur_trans->dirty_bgs)); +diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c +index 8207b0b4c43a01..6ce083a6ed61ff 100644 +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -3980,8 +3980,14 @@ again: + * this shouldn't happen, it means the last relocate + * failed + */ +- if (ret == 0) +- BUG(); /* FIXME break ? */ ++ if (unlikely(ret == 0)) { ++ btrfs_err(fs_info, ++ "unexpected exact match of CHUNK_ITEM in chunk tree, offset 0x%llx", ++ key.offset); ++ mutex_unlock(&fs_info->reclaim_bgs_lock); ++ ret = -EUCLEAN; ++ goto error; ++ } + + ret = btrfs_previous_item(chunk_root, path, 0, + BTRFS_CHUNK_ITEM_KEY); +diff --git a/fs/buffer.c b/fs/buffer.c +index 32df6163ffed5f..c225eef13279ba 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -2950,6 +2950,10 @@ bool try_to_free_buffers(struct folio *folio) + if (folio_test_writeback(folio)) + return false; + ++ /* Misconfigured folio check */ ++ if (WARN_ON_ONCE(!folio_buffers(folio))) ++ return true; ++ + if (mapping == NULL) { /* can this still happen? */ + ret = drop_buffers(folio, &buffers_to_free); + goto out; +diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c +index 2c92de964c5a2e..db4d11604e9d5c 100644 +--- a/fs/ceph/addr.c ++++ b/fs/ceph/addr.c +@@ -1833,6 +1833,7 @@ int ceph_uninline_data(struct file *file) + struct ceph_osd_request *req = NULL; + struct ceph_cap_flush *prealloc_cf = NULL; + struct folio *folio = NULL; ++ struct ceph_snap_context *snapc = NULL; + u64 inline_version = CEPH_INLINE_NONE; + struct page *pages[1]; + int err = 0; +@@ -1860,6 +1861,24 @@ int ceph_uninline_data(struct file *file) + if (inline_version == 1) /* initial version, no data */ + goto out_uninline; + ++ down_read(&fsc->mdsc->snap_rwsem); ++ spin_lock(&ci->i_ceph_lock); ++ if (__ceph_have_pending_cap_snap(ci)) { ++ struct ceph_cap_snap *capsnap = ++ list_last_entry(&ci->i_cap_snaps, ++ struct ceph_cap_snap, ++ ci_item); ++ snapc = ceph_get_snap_context(capsnap->context); ++ } else { ++ if (!ci->i_head_snapc) { ++ ci->i_head_snapc = ceph_get_snap_context( ++ ci->i_snap_realm->cached_context); ++ } ++ snapc = ceph_get_snap_context(ci->i_head_snapc); ++ } ++ spin_unlock(&ci->i_ceph_lock); ++ up_read(&fsc->mdsc->snap_rwsem); ++ + folio = read_mapping_folio(inode->i_mapping, 0, file); + if (IS_ERR(folio)) { + err = PTR_ERR(folio); +@@ -1875,7 +1894,7 @@ int ceph_uninline_data(struct file *file) + req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, + ceph_vino(inode), 0, &len, 0, 1, + CEPH_OSD_OP_CREATE, CEPH_OSD_FLAG_WRITE, +- NULL, 0, 0, false); ++ snapc, 0, 0, false); + if (IS_ERR(req)) { + err = PTR_ERR(req); + goto out_unlock; +@@ -1891,7 +1910,7 @@ int ceph_uninline_data(struct file *file) + req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, + ceph_vino(inode), 0, &len, 1, 3, + CEPH_OSD_OP_WRITE, CEPH_OSD_FLAG_WRITE, +- NULL, ci->i_truncate_seq, ++ snapc, ci->i_truncate_seq, + ci->i_truncate_size, false); + if (IS_ERR(req)) { + err = PTR_ERR(req); +@@ -1954,6 +1973,7 @@ out_unlock: + folio_put(folio); + } + out: ++ ceph_put_snap_context(snapc); + ceph_free_cap_flush(prealloc_cf); + dout("uninline_data %p %llx.%llx inline_version %llu = %d\n", + inode, ceph_vinop(inode), inline_version, err); +diff --git a/fs/ceph/file.c b/fs/ceph/file.c +index 0ec78d87519ba7..0757eb7611daa9 100644 +--- a/fs/ceph/file.c ++++ b/fs/ceph/file.c +@@ -2468,6 +2468,7 @@ static int ceph_zero_partial_object(struct inode *inode, + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); + struct ceph_osd_request *req; ++ struct ceph_snap_context *snapc; + int ret = 0; + loff_t zero = 0; + int op; +@@ -2482,12 +2483,25 @@ static int ceph_zero_partial_object(struct inode *inode, + op = CEPH_OSD_OP_ZERO; + } + ++ spin_lock(&ci->i_ceph_lock); ++ if (__ceph_have_pending_cap_snap(ci)) { ++ struct ceph_cap_snap *capsnap = ++ list_last_entry(&ci->i_cap_snaps, ++ struct ceph_cap_snap, ++ ci_item); ++ snapc = ceph_get_snap_context(capsnap->context); ++ } else { ++ BUG_ON(!ci->i_head_snapc); ++ snapc = ceph_get_snap_context(ci->i_head_snapc); ++ } ++ spin_unlock(&ci->i_ceph_lock); ++ + req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, + ceph_vino(inode), + offset, length, + 0, 1, op, + CEPH_OSD_FLAG_WRITE, +- NULL, 0, 0, false); ++ snapc, 0, 0, false); + if (IS_ERR(req)) { + ret = PTR_ERR(req); + goto out; +@@ -2501,6 +2515,7 @@ static int ceph_zero_partial_object(struct inode *inode, + ceph_osdc_put_request(req); + + out: ++ ceph_put_snap_context(snapc); + return ret; + } + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index a3d3c9fc64262f..8d9cd6574d3265 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3172,6 +3172,9 @@ static int ext4_split_extent_at(handle_t *handle, + BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) == + (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)); + ++ /* Do not cache extents that are in the process of being modified. */ ++ flags |= EXT4_EX_NOCACHE; ++ + ext_debug(inode, "logical block %llu\n", (unsigned long long)split); + + ext4_ext_show_leaf(inode, path); +@@ -3342,6 +3345,9 @@ static int ext4_split_extent(handle_t *handle, + ee_len = ext4_ext_get_actual_len(ex); + unwritten = ext4_ext_is_unwritten(ex); + ++ /* Do not cache extents that are in the process of being modified. */ ++ flags |= EXT4_EX_NOCACHE; ++ + if (map->m_lblk + map->m_len < ee_block + ee_len) { + split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT; + flags1 = flags | EXT4_GET_BLOCKS_PRE_IO; +@@ -5252,7 +5258,8 @@ again: + if (!extent) { + EXT4_ERROR_INODE(inode, "unexpected hole at %lu", + (unsigned long) *iterator); +- return -EFSCORRUPTED; ++ ret = -EFSCORRUPTED; ++ goto out; + } + if (SHIFT == SHIFT_LEFT && *iterator > + le32_to_cpu(extent->ee_block)) { +diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c +index 4f931f80cb3489..d34affd2075eb4 100644 +--- a/fs/ext4/ioctl.c ++++ b/fs/ext4/ioctl.c +@@ -963,6 +963,7 @@ static long ext4_ioctl_group_add(struct file *file, + + err = ext4_group_add(sb, input); + if (EXT4_SB(sb)->s_journal) { ++ ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_RESIZE, NULL); + jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); + err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal, 0); + jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); +@@ -1315,6 +1316,8 @@ setversion_out: + + err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); + if (EXT4_SB(sb)->s_journal) { ++ ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_RESIZE, ++ NULL); + jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); + err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal, 0); + jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 5ba161bd66a3ef..d095c4a218a3ac 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -1090,8 +1090,6 @@ static inline int should_optimize_scan(struct ext4_allocation_context *ac) + return 0; + if (ac->ac_criteria >= CR_GOAL_LEN_SLOW) + return 0; +- if (!ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS)) +- return 0; + return 1; + } + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index c5c6faa995e1c5..561f670768f966 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -5563,6 +5563,10 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) + clear_opt2(sb, MB_OPTIMIZE_SCAN); + } + ++ err = ext4_percpu_param_init(sbi); ++ if (err) ++ goto failed_mount5; ++ + err = ext4_mb_init(sb); + if (err) { + ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)", +@@ -5578,10 +5582,6 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) + sbi->s_journal->j_commit_callback = + ext4_journal_commit_callback; + +- err = ext4_percpu_param_init(sbi); +- if (err) +- goto failed_mount6; +- + if (ext4_has_feature_flex_bg(sb)) + if (!ext4_fill_flex_info(sb)) { + ext4_msg(sb, KERN_ERR, +@@ -5661,8 +5661,8 @@ failed_mount7: + failed_mount6: + ext4_mb_release(sb); + ext4_flex_groups_free(sbi); +- ext4_percpu_param_destroy(sbi); + failed_mount5: ++ ext4_percpu_param_destroy(sbi); + ext4_ext_release(sb); + ext4_release_system_zone(sb); + failed_mount4a: +diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c +index 2116c486843b7d..e189fbf95fcace 100644 +--- a/fs/fat/namei_msdos.c ++++ b/fs/fat/namei_msdos.c +@@ -325,7 +325,12 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry) + err = fat_remove_entries(dir, &sinfo); /* and releases bh */ + if (err) + goto out; +- drop_nlink(dir); ++ if (dir->i_nlink >= 3) ++ drop_nlink(dir); ++ else { ++ fat_fs_error(sb, "parent dir link count too low (%u)", ++ dir->i_nlink); ++ } + + clear_nlink(inode); + fat_truncate_time(inode, NULL, S_CTIME); +diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c +index 3cf22a6727f1b6..7d7ac30c6eff81 100644 +--- a/fs/fat/namei_vfat.c ++++ b/fs/fat/namei_vfat.c +@@ -806,7 +806,12 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry) + err = fat_remove_entries(dir, &sinfo); /* and releases bh */ + if (err) + goto out; +- drop_nlink(dir); ++ if (dir->i_nlink >= 3) ++ drop_nlink(dir); ++ else { ++ fat_fs_error(sb, "parent dir link count too low (%u)", ++ dir->i_nlink); ++ } + + clear_nlink(inode); + fat_truncate_time(inode, NULL, S_ATIME|S_MTIME); +diff --git a/fs/fs_struct.c b/fs/fs_struct.c +index 64c2d0814ed688..100bd3474476b2 100644 +--- a/fs/fs_struct.c ++++ b/fs/fs_struct.c +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + #include "internal.h" + + /* +diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c +index 7ed276a8f599d4..bc0f7023adcf33 100644 +--- a/fs/gfs2/bmap.c ++++ b/fs/gfs2/bmap.c +@@ -317,6 +317,12 @@ static void gfs2_metapath_ra(struct gfs2_glock *gl, __be64 *start, __be64 *end) + } + } + ++static inline struct buffer_head * ++metapath_dibh(struct metapath *mp) ++{ ++ return mp->mp_bh[0]; ++} ++ + static int __fillup_metapath(struct gfs2_inode *ip, struct metapath *mp, + unsigned int x, unsigned int h) + { +@@ -660,7 +666,7 @@ static int __gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap, + { + struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_sbd *sdp = GFS2_SB(inode); +- struct buffer_head *dibh = mp->mp_bh[0]; ++ struct buffer_head *dibh = metapath_dibh(mp); + u64 bn; + unsigned n, i, blks, alloced = 0, iblks = 0, branch_start = 0; + size_t dblks = iomap->length >> inode->i_blkbits; +@@ -1120,10 +1126,18 @@ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length, + goto out_unlock; + break; + default: +- goto out_unlock; ++ goto out; + } + + ret = gfs2_iomap_begin_write(inode, pos, length, flags, iomap, &mp); ++ if (ret) ++ goto out_unlock; ++ ++out: ++ if (iomap->type == IOMAP_INLINE) { ++ iomap->private = metapath_dibh(&mp); ++ get_bh(iomap->private); ++ } + + out_unlock: + release_metapath(&mp); +@@ -1137,6 +1151,9 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length, + struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_sbd *sdp = GFS2_SB(inode); + ++ if (iomap->private) ++ brelse(iomap->private); ++ + switch (flags & (IOMAP_WRITE | IOMAP_ZERO)) { + case IOMAP_WRITE: + if (flags & IOMAP_DIRECT) +diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c +index c4bc86c3535ba6..9265262807f098 100644 +--- a/fs/gfs2/glock.c ++++ b/fs/gfs2/glock.c +@@ -1396,31 +1396,45 @@ static int glocks_pending(unsigned int num_gh, struct gfs2_holder *ghs) + * gfs2_glock_async_wait - wait on multiple asynchronous glock acquisitions + * @num_gh: the number of holders in the array + * @ghs: the glock holder array ++ * @retries: number of retries attempted so far + * + * Returns: 0 on success, meaning all glocks have been granted and are held. + * -ESTALE if the request timed out, meaning all glocks were released, + * and the caller should retry the operation. + */ + +-int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs) ++int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs, ++ unsigned int retries) + { + struct gfs2_sbd *sdp = ghs[0].gh_gl->gl_name.ln_sbd; +- int i, ret = 0, timeout = 0; + unsigned long start_time = jiffies; ++ int i, ret = 0; ++ long timeout; + + might_sleep(); +- /* +- * Total up the (minimum hold time * 2) of all glocks and use that to +- * determine the max amount of time we should wait. +- */ +- for (i = 0; i < num_gh; i++) +- timeout += ghs[i].gh_gl->gl_hold_time << 1; + +- if (!wait_event_timeout(sdp->sd_async_glock_wait, ++ timeout = GL_GLOCK_MIN_HOLD; ++ if (retries) { ++ unsigned int max_shift; ++ long incr; ++ ++ /* Add a random delay and increase the timeout exponentially. */ ++ max_shift = BITS_PER_LONG - 2 - __fls(GL_GLOCK_HOLD_INCR); ++ incr = min(GL_GLOCK_HOLD_INCR << min(retries - 1, max_shift), ++ 10 * HZ - GL_GLOCK_MIN_HOLD); ++ schedule_timeout_interruptible(get_random_long() % (incr / 3)); ++ if (signal_pending(current)) ++ goto interrupted; ++ timeout += (incr / 3) + get_random_long() % (incr / 3); ++ } ++ ++ if (!wait_event_interruptible_timeout(sdp->sd_async_glock_wait, + !glocks_pending(num_gh, ghs), timeout)) { + ret = -ESTALE; /* request timed out. */ + goto out; + } ++ if (signal_pending(current)) ++ goto interrupted; + + for (i = 0; i < num_gh; i++) { + struct gfs2_holder *gh = &ghs[i]; +@@ -1444,6 +1458,10 @@ out: + } + } + return ret; ++ ++interrupted: ++ ret = -EINTR; ++ goto out; + } + + /** +diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h +index aae9fabbb76cc0..e86dccdd613321 100644 +--- a/fs/gfs2/glock.h ++++ b/fs/gfs2/glock.h +@@ -204,7 +204,8 @@ int gfs2_glock_poll(struct gfs2_holder *gh); + int gfs2_instantiate(struct gfs2_holder *gh); + int gfs2_glock_holder_ready(struct gfs2_holder *gh); + int gfs2_glock_wait(struct gfs2_holder *gh); +-int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs); ++int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs, ++ unsigned int retries); + void gfs2_glock_dq(struct gfs2_holder *gh); + void gfs2_glock_dq_wait(struct gfs2_holder *gh); + void gfs2_glock_dq_uninit(struct gfs2_holder *gh); +diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c +index 1cb5ce63fbf697..45040622d316e0 100644 +--- a/fs/gfs2/inode.c ++++ b/fs/gfs2/inode.c +@@ -1408,7 +1408,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, + unsigned int num_gh; + int dir_rename = 0; + struct gfs2_diradd da = { .nr_blocks = 0, .save_loc = 0, }; +- unsigned int x; ++ unsigned int retries = 0, x; + int error; + + gfs2_holder_mark_uninitialized(&r_gh); +@@ -1458,12 +1458,17 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, + num_gh++; + } + ++again: + for (x = 0; x < num_gh; x++) { + error = gfs2_glock_nq(ghs + x); + if (error) + goto out_gunlock; + } +- error = gfs2_glock_async_wait(num_gh, ghs); ++ error = gfs2_glock_async_wait(num_gh, ghs, retries); ++ if (error == -ESTALE) { ++ retries++; ++ goto again; ++ } + if (error) + goto out_gunlock; + +@@ -1652,7 +1657,7 @@ static int gfs2_exchange(struct inode *odir, struct dentry *odentry, + struct gfs2_sbd *sdp = GFS2_SB(odir); + struct gfs2_holder ghs[4], r_gh; + unsigned int num_gh; +- unsigned int x; ++ unsigned int retries = 0, x; + umode_t old_mode = oip->i_inode.i_mode; + umode_t new_mode = nip->i_inode.i_mode; + int error; +@@ -1696,13 +1701,18 @@ static int gfs2_exchange(struct inode *odir, struct dentry *odentry, + gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs + num_gh); + num_gh++; + ++again: + for (x = 0; x < num_gh; x++) { + error = gfs2_glock_nq(ghs + x); + if (error) + goto out_gunlock; + } + +- error = gfs2_glock_async_wait(num_gh, ghs); ++ error = gfs2_glock_async_wait(num_gh, ghs, retries); ++ if (error == -ESTALE) { ++ retries++; ++ goto again; ++ } + if (error) + goto out_gunlock; + +@@ -2095,6 +2105,14 @@ static int gfs2_getattr(struct mnt_idmap *idmap, + return 0; + } + ++static bool fault_in_fiemap(struct fiemap_extent_info *fi) ++{ ++ struct fiemap_extent __user *dest = fi->fi_extents_start; ++ size_t size = sizeof(*dest) * fi->fi_extents_max; ++ ++ return fault_in_safe_writeable((char __user *)dest, size) == 0; ++} ++ + static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + u64 start, u64 len) + { +@@ -2104,14 +2122,22 @@ static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + + inode_lock_shared(inode); + ++retry: + ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + if (ret) + goto out; + ++ pagefault_disable(); + ret = iomap_fiemap(inode, fieinfo, start, len, &gfs2_iomap_ops); ++ pagefault_enable(); + + gfs2_glock_dq_uninit(&gh); + ++ if (ret == -EFAULT && fault_in_fiemap(fieinfo)) { ++ fieinfo->fi_extents_mapped = 0; ++ goto retry; ++ } ++ + out: + inode_unlock_shared(inode); + return ret; +diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c +index c0089849be50ed..fb437598e26259 100644 +--- a/fs/hfsplus/bnode.c ++++ b/fs/hfsplus/bnode.c +@@ -629,7 +629,7 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num) + if (node) { + pr_crit("new node %u already hashed?\n", num); + WARN_ON(1); +- return node; ++ return ERR_PTR(-EEXIST); + } + node = __hfs_bnode_create(tree, num); + if (!node) +diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c +index 2619e5371ec9c7..2dd17192d11c37 100644 +--- a/fs/hfsplus/inode.c ++++ b/fs/hfsplus/inode.c +@@ -604,6 +604,7 @@ out: + int hfsplus_cat_write_inode(struct inode *inode) + { + struct inode *main_inode = inode; ++ struct hfs_btree *tree = HFSPLUS_SB(inode->i_sb)->cat_tree; + struct hfs_find_data fd; + hfsplus_cat_entry entry; + int res = 0; +@@ -614,7 +615,7 @@ int hfsplus_cat_write_inode(struct inode *inode) + if (!main_inode->i_nlink) + return 0; + +- if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb)->cat_tree, &fd)) ++ if (hfs_find_init(tree, &fd)) + /* panic? */ + return -EIO; + +@@ -679,6 +680,15 @@ int hfsplus_cat_write_inode(struct inode *inode) + set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags); + out: + hfs_find_exit(&fd); ++ ++ if (!res) { ++ res = hfs_btree_write(tree); ++ if (res) { ++ pr_err("b-tree write err: %d, ino %lu\n", ++ res, inode->i_ino); ++ } ++ } ++ + return res; + } + +diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c +index 7e889820a63d0b..954ceaa748e624 100644 +--- a/fs/hfsplus/super.c ++++ b/fs/hfsplus/super.c +@@ -52,6 +52,12 @@ static int hfsplus_system_read_inode(struct inode *inode) + return -EIO; + } + ++ /* ++ * Assign a dummy file type, for may_open() requires that ++ * an inode has a valid file type. ++ */ ++ inode->i_mode = S_IFREG; ++ + return 0; + } + +diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c +index 8158ab18e1ae8c..ec6b019f087fdc 100644 +--- a/fs/iomap/direct-io.c ++++ b/fs/iomap/direct-io.c +@@ -381,9 +381,13 @@ static loff_t iomap_dio_bio_iter(const struct iomap_iter *iter, + nr_pages = bio_iov_vecs_to_alloc(dio->submit.iter, BIO_MAX_VECS); + do { + size_t n; +- if (dio->error) { +- iov_iter_revert(dio->submit.iter, copied); +- copied = ret = 0; ++ ++ /* ++ * If completions already occurred and reported errors, give up now and ++ * don't bother submitting more bios. ++ */ ++ if (unlikely(data_race(dio->error))) { ++ ret = 0; + goto out; + } + +diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c +index cb6d1fda66a702..32e589bb663ae8 100644 +--- a/fs/jfs/jfs_logmgr.c ++++ b/fs/jfs/jfs_logmgr.c +@@ -2312,6 +2312,7 @@ int jfsIOWait(void *arg) + { + struct lbuf *bp; + ++ set_freezable(); + do { + spin_lock_irq(&log_redrive_lock); + while ((bp = log_redrive_list)) { +diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c +index 57d7a4300210d2..649184d712ad0e 100644 +--- a/fs/jfs/namei.c ++++ b/fs/jfs/namei.c +@@ -1227,7 +1227,7 @@ static int jfs_rename(struct mnt_idmap *idmap, struct inode *old_dir, + jfs_err("jfs_rename: dtInsert returned -EIO"); + goto out_tx; + } +- if (S_ISDIR(old_ip->i_mode)) ++ if (S_ISDIR(old_ip->i_mode) && old_dir != new_dir) + inc_nlink(new_dir); + } + /* +@@ -1243,7 +1243,9 @@ static int jfs_rename(struct mnt_idmap *idmap, struct inode *old_dir, + goto out_tx; + } + if (S_ISDIR(old_ip->i_mode)) { +- drop_nlink(old_dir); ++ if (new_ip || old_dir != new_dir) ++ drop_nlink(old_dir); ++ + if (old_dir != new_dir) { + /* + * Change inode number of parent for moved directory +diff --git a/fs/minix/inode.c b/fs/minix/inode.c +index ee8a6fe360e728..820c7753bd1059 100644 +--- a/fs/minix/inode.c ++++ b/fs/minix/inode.c +@@ -153,10 +153,38 @@ static int minix_remount (struct super_block * sb, int * flags, char * data) + static bool minix_check_superblock(struct super_block *sb) + { + struct minix_sb_info *sbi = minix_sb(sb); ++ unsigned long block; + +- if (sbi->s_imap_blocks == 0 || sbi->s_zmap_blocks == 0) ++ if (sbi->s_log_zone_size != 0) { ++ printk("minix-fs error: zone size must equal block size. " ++ "s_log_zone_size > 0 is not supported.\n"); ++ return false; ++ } ++ ++ if (sbi->s_ninodes < 1 || sbi->s_firstdatazone <= 4 || ++ sbi->s_firstdatazone >= sbi->s_nzones) + return false; + ++ /* Apparently minix can create filesystems that allocate more blocks for ++ * the bitmaps than needed. We simply ignore that, but verify it didn't ++ * create one with not enough blocks and bail out if so. ++ */ ++ block = minix_blocks_needed(sbi->s_ninodes, sb->s_blocksize); ++ if (sbi->s_imap_blocks < block) { ++ printk("MINIX-fs: file system does not have enough " ++ "imap blocks allocated. Refusing to mount.\n"); ++ return false; ++ } ++ ++ block = minix_blocks_needed( ++ (sbi->s_nzones - sbi->s_firstdatazone + 1), ++ sb->s_blocksize); ++ if (sbi->s_zmap_blocks < block) { ++ printk("MINIX-fs: file system does not have enough " ++ "zmap blocks allocated. Refusing to mount.\n"); ++ return false; ++ } ++ + /* + * s_max_size must not exceed the block mapping limitation. This check + * is only needed for V1 filesystems, since V2/V3 support an extra level +@@ -275,26 +303,6 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) + minix_set_bit(0,sbi->s_imap[0]->b_data); + minix_set_bit(0,sbi->s_zmap[0]->b_data); + +- /* Apparently minix can create filesystems that allocate more blocks for +- * the bitmaps than needed. We simply ignore that, but verify it didn't +- * create one with not enough blocks and bail out if so. +- */ +- block = minix_blocks_needed(sbi->s_ninodes, s->s_blocksize); +- if (sbi->s_imap_blocks < block) { +- printk("MINIX-fs: file system does not have enough " +- "imap blocks allocated. Refusing to mount.\n"); +- goto out_no_bitmap; +- } +- +- block = minix_blocks_needed( +- (sbi->s_nzones - sbi->s_firstdatazone + 1), +- s->s_blocksize); +- if (sbi->s_zmap_blocks < block) { +- printk("MINIX-fs: file system does not have enough " +- "zmap blocks allocated. Refusing to mount.\n"); +- goto out_no_bitmap; +- } +- + /* set up enough so that it can read an inode */ + s->s_op = &minix_sops; + s->s_time_min = 0; +diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c +index 32e922a20d0d4f..46f53f40b741aa 100644 +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -70,7 +70,7 @@ const struct address_space_operations nfs_dir_aops = { + .free_folio = nfs_readdir_clear_array, + }; + +-#define NFS_INIT_DTSIZE PAGE_SIZE ++#define NFS_INIT_DTSIZE SZ_64K + + static struct nfs_open_dir_context * + alloc_nfs_open_dir_context(struct inode *dir) +@@ -81,7 +81,7 @@ alloc_nfs_open_dir_context(struct inode *dir) + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL_ACCOUNT); + if (ctx != NULL) { + ctx->attr_gencount = nfsi->attr_gencount; +- ctx->dtsize = NFS_INIT_DTSIZE; ++ ctx->dtsize = min(NFS_SERVER(dir)->dtsize, NFS_INIT_DTSIZE); + spin_lock(&dir->i_lock); + if (list_empty(&nfsi->open_files) && + (nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER)) +diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c +index 0737d9a15d862c..7dae2004c65f90 100644 +--- a/fs/nfs/pnfs.c ++++ b/fs/nfs/pnfs.c +@@ -464,7 +464,8 @@ pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo, + }; + struct pnfs_layout_segment *lseg, *next; + +- set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); ++ if (test_and_set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) ++ return !list_empty(&lo->plh_segs); + clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(lo->plh_inode)->flags); + list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) + pnfs_clear_lseg_state(lseg, lseg_list); +diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c +index 8cca1329f3485c..c319c31b0f6476 100644 +--- a/fs/nfsd/nfs4idmap.c ++++ b/fs/nfsd/nfs4idmap.c +@@ -643,34 +643,74 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr, + return idmap_id_to_name(xdr, rqstp, type, id); + } + +-__be32 +-nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen, +- kuid_t *uid) ++/** ++ * nfsd_map_name_to_uid - Map user@domain to local UID ++ * @rqstp: RPC execution context ++ * @name: user@domain name to be mapped ++ * @namelen: length of name, in bytes ++ * @uid: OUT: mapped local UID value ++ * ++ * Returns nfs_ok on success or an NFSv4 status code on failure. ++ */ ++__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, ++ size_t namelen, kuid_t *uid) + { + __be32 status; + u32 id = -1; + ++ /* ++ * The idmap lookup below triggers an upcall that invokes ++ * cache_check(). RQ_USEDEFERRAL must be clear to prevent ++ * cache_check() from setting RQ_DROPME via svc_defer(). ++ * NFSv4 servers are not permitted to drop requests. Also ++ * RQ_DROPME will force NFSv4.1 session slot processing to ++ * be skipped. ++ */ ++ WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags)); ++ + if (name == NULL || namelen == 0) + return nfserr_inval; + + status = do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, &id); ++ if (status) ++ return status; + *uid = make_kuid(nfsd_user_namespace(rqstp), id); + if (!uid_valid(*uid)) + status = nfserr_badowner; + return status; + } + +-__be32 +-nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen, +- kgid_t *gid) ++/** ++ * nfsd_map_name_to_gid - Map user@domain to local GID ++ * @rqstp: RPC execution context ++ * @name: user@domain name to be mapped ++ * @namelen: length of name, in bytes ++ * @gid: OUT: mapped local GID value ++ * ++ * Returns nfs_ok on success or an NFSv4 status code on failure. ++ */ ++__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, ++ size_t namelen, kgid_t *gid) + { + __be32 status; + u32 id = -1; + ++ /* ++ * The idmap lookup below triggers an upcall that invokes ++ * cache_check(). RQ_USEDEFERRAL must be clear to prevent ++ * cache_check() from setting RQ_DROPME via svc_defer(). ++ * NFSv4 servers are not permitted to drop requests. Also ++ * RQ_DROPME will force NFSv4.1 session slot processing to ++ * be skipped. ++ */ ++ WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags)); ++ + if (name == NULL || namelen == 0) + return nfserr_inval; + + status = do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, &id); ++ if (status) ++ return status; + *gid = make_kgid(nfsd_user_namespace(rqstp), id); + if (!gid_valid(*gid)) + status = nfserr_badowner; +diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c +index a126fae2df5664..5767080362e85a 100644 +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -2763,8 +2763,6 @@ encode_op: + BUG_ON(cstate->replay_owner); + out: + cstate->status = status; +- /* Reset deferral mechanism for RPC deferrals */ +- set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); + return rpc_success; + } + +diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c +index 15189e683e834d..d84eaae7cd0b62 100644 +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -5492,6 +5492,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) + args->ops = args->iops; + args->rqstp = rqstp; + ++ /* ++ * NFSv4 operation decoders can invoke svc cache lookups ++ * that trigger svc_defer() when RQ_USEDEFERRAL is set, ++ * setting RQ_DROPME. This creates two problems: ++ * ++ * 1. Non-idempotency: Compounds make it too hard to avoid ++ * problems if a request is deferred and replayed. ++ * ++ * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set ++ * during decode but SEQUENCE executes successfully, the ++ * session slot will be marked INUSE. The request is then ++ * dropped before encoding, so the slot is never released, ++ * rendering it permanently unusable by the client. ++ */ ++ clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); ++ + return nfsd4_decode_compound(args); + } + +diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c +index e25989dd2c6bba..8f033e30e0d799 100644 +--- a/fs/ntfs3/attrib.c ++++ b/fs/ntfs3/attrib.c +@@ -449,8 +449,10 @@ again: + + is_ext = is_attr_ext(attr_b); + align = sbi->cluster_size; +- if (is_ext) ++ if (is_ext) { + align <<= attr_b->nres.c_unit; ++ keep_prealloc = false; ++ } + + old_valid = le64_to_cpu(attr_b->nres.valid_size); + old_size = le64_to_cpu(attr_b->nres.data_size); +@@ -1367,19 +1369,28 @@ int attr_load_runs_range(struct ntfs_inode *ni, enum ATTR_TYPE type, + CLST vcn; + CLST vcn_last = (to - 1) >> cluster_bits; + CLST lcn, clen; +- int err; ++ int err = 0; ++ int retry = 0; + + for (vcn = from >> cluster_bits; vcn <= vcn_last; vcn += clen) { + if (!run_lookup_entry(run, vcn, &lcn, &clen, NULL)) { ++ if (retry != 0) { /* Next run_lookup_entry(vcn) also failed. */ ++ err = -EINVAL; ++ break; ++ } + err = attr_load_runs_vcn(ni, type, name, name_len, run, + vcn); + if (err) +- return err; ++ break; ++ + clen = 0; /* Next run_lookup_entry(vcn) must be success. */ ++ retry++; + } ++ else ++ retry = 0; + } + +- return 0; ++ return err; + } + + #ifdef CONFIG_NTFS3_LZX_XPRESS +diff --git a/fs/ntfs3/attrlist.c b/fs/ntfs3/attrlist.c +index 9f4bd8d260901c..9355b4416719d0 100644 +--- a/fs/ntfs3/attrlist.c ++++ b/fs/ntfs3/attrlist.c +@@ -52,6 +52,11 @@ int ntfs_load_attr_list(struct ntfs_inode *ni, struct ATTRIB *attr) + + if (!attr->non_res) { + lsize = le32_to_cpu(attr->res.data_size); ++ if (!lsize) { ++ err = -EINVAL; ++ goto out; ++ } ++ + /* attr is resident: lsize < record_size (1K or 4K) */ + le = kvmalloc(al_aligned(lsize), GFP_KERNEL); + if (!le) { +@@ -66,6 +71,10 @@ int ntfs_load_attr_list(struct ntfs_inode *ni, struct ATTRIB *attr) + u16 run_off = le16_to_cpu(attr->nres.run_off); + + lsize = le64_to_cpu(attr->nres.data_size); ++ if (!lsize) { ++ err = -EINVAL; ++ goto out; ++ } + + run_init(&ni->attr_list.run); + +diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c +index a7fe2e02c32ee6..212737a816d7af 100644 +--- a/fs/ntfs3/file.c ++++ b/fs/ntfs3/file.c +@@ -901,8 +901,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) + goto out; + + if (lcn == SPARSE_LCN) { +- ni->i_valid = valid = +- frame_vbo + ((u64)clen << sbi->cluster_bits); ++ valid = frame_vbo + ((u64)clen << sbi->cluster_bits); ++ if (ni->i_valid == valid) { ++ err = -EINVAL; ++ goto out; ++ } ++ ni->i_valid = valid; + continue; + } + +diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c +index 2a1aeab53ea4b5..598b7f42b5e7ec 100644 +--- a/fs/ntfs3/fslog.c ++++ b/fs/ntfs3/fslog.c +@@ -3431,6 +3431,9 @@ move_data: + + e1 = Add2Ptr(attr, le16_to_cpu(lrh->attr_off)); + esize = le16_to_cpu(e1->size); ++ if (PtrOffset(e1, Add2Ptr(hdr, used)) < esize) ++ goto dirty_vol; ++ + e2 = Add2Ptr(e1, esize); + + memmove(e1, e2, PtrOffset(e2, Add2Ptr(hdr, used))); +diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c +index 446079b0866d4c..e17d4c1ba06f0a 100644 +--- a/fs/ntfs3/fsntfs.c ++++ b/fs/ntfs3/fsntfs.c +@@ -1272,6 +1272,12 @@ int ntfs_read_run_nb(struct ntfs_sb_info *sbi, const struct runs_tree *run, + + } while (len32); + ++ if (!run) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ /* Get next fragment to read. */ + vcn_next = vcn + clen; + if (!run_get_entry(run, ++idx, &vcn, &lcn, &clen) || + vcn != vcn_next) { +diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c +index f227db9f76c2b4..4330c2b39e505a 100644 +--- a/fs/ntfs3/index.c ++++ b/fs/ntfs3/index.c +@@ -1192,7 +1192,12 @@ int indx_find(struct ntfs_index *indx, struct ntfs_inode *ni, + return -EINVAL; + } + +- fnd_push(fnd, node, e); ++ err = fnd_push(fnd, node, e); ++ ++ if (err) { ++ put_indx_node(node); ++ return err; ++ } + } + + *entry = e; +diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c +index c2268b9e20a6d3..d0cb529b612a7f 100644 +--- a/fs/ocfs2/xattr.c ++++ b/fs/ocfs2/xattr.c +@@ -6373,6 +6373,10 @@ static int ocfs2_reflink_xattr_header(handle_t *handle, + (void *)last - (void *)xe); + memset(last, 0, + sizeof(struct ocfs2_xattr_entry)); ++ last = &new_xh->xh_entries[le16_to_cpu(new_xh->xh_count)] - 1; ++ } else { ++ memset(xe, 0, sizeof(struct ocfs2_xattr_entry)); ++ last = NULL; + } + + /* +diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c +index de39e067ae65a5..0d667e95345737 100644 +--- a/fs/overlayfs/readdir.c ++++ b/fs/overlayfs/readdir.c +@@ -659,7 +659,7 @@ static bool ovl_fill_real(struct dir_context *ctx, const char *name, + container_of(ctx, struct ovl_readdir_translate, ctx); + struct dir_context *orig_ctx = rdt->orig_ctx; + +- if (rdt->parent_ino && strcmp(name, "..") == 0) { ++ if (rdt->parent_ino && namelen == 2 && !strncmp(name, "..", 2)) { + ino = rdt->parent_ino; + } else if (rdt->cache) { + struct ovl_cache_entry *p; +diff --git a/fs/proc/array.c b/fs/proc/array.c +index 5e4f7b411fbdb9..363d9331216b91 100644 +--- a/fs/proc/array.c ++++ b/fs/proc/array.c +@@ -531,7 +531,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, + } + + sid = task_session_nr_ns(task, ns); +- ppid = task_tgid_nr_ns(task->real_parent, ns); ++ ppid = task_ppid_nr_ns(task, ns); + pgid = task_pgrp_nr_ns(task, ns); + + unlock_task_sighand(task, &flags); +diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c +index f1848cdd6d3485..7b6d6378a3b87d 100644 +--- a/fs/pstore/ram_core.c ++++ b/fs/pstore/ram_core.c +@@ -298,6 +298,17 @@ void persistent_ram_save_old(struct persistent_ram_zone *prz) + if (!size) + return; + ++ /* ++ * If the existing buffer is differently sized, free it so a new ++ * one is allocated. This can happen when persistent_ram_save_old() ++ * is called early in boot and later for a timer-triggered ++ * survivable crash when the crash dumps don't match in size ++ * (which would be extremely unlikely given kmsg buffers usually ++ * exceed prz buffer sizes). ++ */ ++ if (prz->old_log && prz->old_log_size != size) ++ persistent_ram_free_old(prz); ++ + if (!prz->old_log) { + persistent_ram_ecc_old(prz); + prz->old_log = kvzalloc(size, GFP_KERNEL); +@@ -446,6 +457,13 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size, + vaddr = vmap(pages, page_count, VM_MAP | VM_IOREMAP, prot); + kfree(pages); + ++ /* ++ * vmap() may fail and return NULL. Do not add the offset in this ++ * case, otherwise a NULL mapping would appear successful. ++ */ ++ if (!vaddr) ++ return NULL; ++ + /* + * Since vmap() uses page granularity, we must add the offset + * into the page here, to get the byte granularity address +diff --git a/fs/quota/quota.c b/fs/quota/quota.c +index 0e41fb84060f52..5be53cae2c95d7 100644 +--- a/fs/quota/quota.c ++++ b/fs/quota/quota.c +@@ -899,6 +899,7 @@ retry: + sb_start_write(sb); + sb_end_write(sb); + put_super(sb); ++ cond_resched(); + goto retry; + } + return sb; +diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c +index e92a61e934e447..d83161285a1754 100644 +--- a/fs/smb/client/cached_dir.c ++++ b/fs/smb/client/cached_dir.c +@@ -769,11 +769,11 @@ static void cfids_laundromat_worker(struct work_struct *work) + + dput(dentry); + if (cfid->is_open) { +- spin_lock(&cifs_tcp_ses_lock); ++ spin_lock(&cfid->tcon->tc_lock); + ++cfid->tcon->tc_count; + trace_smb3_tcon_ref(cfid->tcon->debug_id, cfid->tcon->tc_count, + netfs_trace_tcon_ref_get_cached_laundromat); +- spin_unlock(&cifs_tcp_ses_lock); ++ spin_unlock(&cfid->tcon->tc_lock); + queue_work(serverclose_wq, &cfid->close_work); + } else + /* +diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c +index 86c89917f18e90..59220ebd6eccef 100644 +--- a/fs/smb/client/connect.c ++++ b/fs/smb/client/connect.c +@@ -4065,7 +4065,9 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, + ses->ses_status = SES_IN_SETUP; + + /* force iface_list refresh */ ++ spin_lock(&ses->iface_lock); + ses->iface_last_update = 0; ++ spin_unlock(&ses->iface_lock); + } + spin_unlock(&ses->ses_lock); + +diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c +index d436057ed77e32..4e7d5c612256d6 100644 +--- a/fs/smb/client/smb2file.c ++++ b/fs/smb/client/smb2file.c +@@ -123,6 +123,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 + &err_buftype); + if (rc == -EACCES && retry_without_read_attributes) { + free_rsp_buf(err_buftype, err_iov.iov_base); ++ memset(&err_iov, 0, sizeof(err_iov)); ++ err_buftype = CIFS_NO_BUFFER; + oparms->desired_access &= ~FILE_READ_ATTRIBUTES; + rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, + &err_buftype); +diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c +index fadc5fc274eb28..70a9536b03c637 100644 +--- a/fs/smb/client/smb2misc.c ++++ b/fs/smb/client/smb2misc.c +@@ -807,14 +807,14 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, + int rc; + + cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count); +- spin_lock(&cifs_tcp_ses_lock); ++ spin_lock(&tcon->tc_lock); + if (tcon->tc_count <= 0) { + struct TCP_Server_Info *server = NULL; + + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_see_cancelled_close); + WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative"); +- spin_unlock(&cifs_tcp_ses_lock); ++ spin_unlock(&tcon->tc_lock); + + if (tcon->ses) { + server = tcon->ses->server; +@@ -828,7 +828,7 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, + tcon->tc_count++; + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_get_cancelled_close); +- spin_unlock(&cifs_tcp_ses_lock); ++ spin_unlock(&tcon->tc_lock); + + rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0, + persistent_fid, volatile_fid); +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index 138b3ed08217c9..63752bd02aafe3 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -595,13 +595,6 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, + p = buf; + + spin_lock(&ses->iface_lock); +- /* do not query too frequently, this time with lock held */ +- if (ses->iface_last_update && +- time_before(jiffies, ses->iface_last_update + +- (SMB_INTERFACE_POLL_INTERVAL * HZ))) { +- spin_unlock(&ses->iface_lock); +- return 0; +- } + + /* + * Go through iface_list and mark them as inactive +@@ -624,7 +617,6 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, + "Empty network interface list returned by server %s\n", + ses->server->hostname); + rc = -EOPNOTSUPP; +- ses->iface_last_update = jiffies; + goto out; + } + +@@ -753,8 +745,6 @@ next_iface: + + sizeof(p->Next) && p->Next)) + cifs_dbg(VFS, "%s: incomplete interface info\n", __func__); + +- ses->iface_last_update = jiffies; +- + out: + /* + * Go through the list again and put the inactive entries +@@ -783,10 +773,17 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_ + struct TCP_Server_Info *pserver; + + /* do not query too frequently */ ++ spin_lock(&ses->iface_lock); + if (ses->iface_last_update && + time_before(jiffies, ses->iface_last_update + +- (SMB_INTERFACE_POLL_INTERVAL * HZ))) ++ (SMB_INTERFACE_POLL_INTERVAL * HZ))) { ++ spin_unlock(&ses->iface_lock); + return 0; ++ } ++ ++ ses->iface_last_update = jiffies; ++ ++ spin_unlock(&ses->iface_lock); + + rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, + FSCTL_QUERY_NETWORK_INTERFACE_INFO, +@@ -1147,6 +1144,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, + + replay_again: + /* reinitialize for possible replay */ ++ used_len = 0; + flags = CIFS_CP_CREATE_CLOSE_OP; + oplock = SMB2_OPLOCK_LEVEL_NONE; + server = cifs_pick_channel(ses); +@@ -1545,6 +1543,7 @@ smb2_ioctl_query_info(const unsigned int xid, + + replay_again: + /* reinitialize for possible replay */ ++ buffer = NULL; + flags = CIFS_CP_CREATE_CLOSE_OP; + oplock = SMB2_OPLOCK_LEVEL_NONE; + server = cifs_pick_channel(ses); +@@ -2941,7 +2940,9 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, + struct cifs_tcon, + tcon_list); + if (tcon) { ++ spin_lock(&tcon->tc_lock); + tcon->tc_count++; ++ spin_unlock(&tcon->tc_lock); + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_get_dfs_refer); + } +@@ -3006,13 +3007,9 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, + out: + if (tcon && !tcon->ipc) { + /* ipc tcons are not refcounted */ +- spin_lock(&cifs_tcp_ses_lock); +- tcon->tc_count--; ++ cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_dfs_refer); + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_dec_dfs_refer); +- /* tc_count can never go negative */ +- WARN_ON(tcon->tc_count < 0); +- spin_unlock(&cifs_tcp_ses_lock); + } + kfree(utf16_path); + kfree(dfs_req); +diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c +index a8890ae2171445..ea73fc5da60309 100644 +--- a/fs/smb/client/smb2pdu.c ++++ b/fs/smb/client/smb2pdu.c +@@ -2850,6 +2850,7 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, + + replay_again: + /* reinitialize for possible replay */ ++ pc_buf = NULL; + flags = 0; + n_iov = 2; + server = cifs_pick_channel(ses); +@@ -4174,7 +4175,9 @@ void smb2_reconnect_server(struct work_struct *work) + + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { + if (tcon->need_reconnect || tcon->need_reopen_files) { ++ spin_lock(&tcon->tc_lock); + tcon->tc_count++; ++ spin_unlock(&tcon->tc_lock); + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_get_reconnect_server); + list_add_tail(&tcon->rlist, &tmp_list); +diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c +index be9be8f3633196..359ab64e17d990 100644 +--- a/fs/smb/client/smbdirect.c ++++ b/fs/smb/client/smbdirect.c +@@ -91,8 +91,23 @@ int smbd_send_credit_target = 255; + /* The maximum single message size can be sent to remote peer */ + int smbd_max_send_size = 1364; + +-/* The maximum fragmented upper-layer payload receive size supported */ +-int smbd_max_fragmented_recv_size = 1024 * 1024; ++/* ++ * The maximum fragmented upper-layer payload receive size supported ++ * ++ * Assume max_payload_per_credit is ++ * smbd_max_receive_size - 24 = 1340 ++ * ++ * The maximum number would be ++ * smbd_receive_credit_max * max_payload_per_credit ++ * ++ * 1340 * 255 = 341700 (0x536C4) ++ * ++ * The minimum value from the spec is 131072 (0x20000) ++ * ++ * For now we use the logic we used in ksmbd before: ++ * (1364 * 255) / 2 = 173910 (0x2A756) ++ */ ++int smbd_max_fragmented_recv_size = (1364 * 255) / 2; + + /* The maximum single-message size which can be received */ + int smbd_max_receive_size = 1364; +diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h +index 4dfdc521c5c985..17e7ce3b14af06 100644 +--- a/fs/smb/client/trace.h ++++ b/fs/smb/client/trace.h +@@ -42,6 +42,7 @@ + EM(netfs_trace_tcon_ref_put_cancelled_close_fid, "PUT Cn-Fid") \ + EM(netfs_trace_tcon_ref_put_cancelled_mid, "PUT Cn-Mid") \ + EM(netfs_trace_tcon_ref_put_mnt_ctx, "PUT MntCtx") \ ++ EM(netfs_trace_tcon_ref_put_dfs_refer, "PUT DfsRfr") \ + EM(netfs_trace_tcon_ref_put_reconnect_server, "PUT Reconn") \ + EM(netfs_trace_tcon_ref_put_tlink, "PUT Tlink ") \ + EM(netfs_trace_tcon_ref_see_cancelled_close, "SEE Cn-Cls") \ +diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c +index 4e5ede2a296a58..dcb09702cde26d 100644 +--- a/fs/xfs/libxfs/xfs_attr_leaf.c ++++ b/fs/xfs/libxfs/xfs_attr_leaf.c +@@ -1498,6 +1498,7 @@ xfs_attr3_leaf_add_work( + struct xfs_attr_leaf_name_local *name_loc; + struct xfs_attr_leaf_name_remote *name_rmt; + struct xfs_mount *mp; ++ int old_end, new_end; + int tmp; + int i; + +@@ -1590,17 +1591,49 @@ xfs_attr3_leaf_add_work( + if (be16_to_cpu(entry->nameidx) < ichdr->firstused) + ichdr->firstused = be16_to_cpu(entry->nameidx); + +- ASSERT(ichdr->firstused >= ichdr->count * sizeof(xfs_attr_leaf_entry_t) +- + xfs_attr3_leaf_hdr_size(leaf)); +- tmp = (ichdr->count - 1) * sizeof(xfs_attr_leaf_entry_t) +- + xfs_attr3_leaf_hdr_size(leaf); ++ new_end = ichdr->count * sizeof(struct xfs_attr_leaf_entry) + ++ xfs_attr3_leaf_hdr_size(leaf); ++ old_end = new_end - sizeof(struct xfs_attr_leaf_entry); ++ ++ ASSERT(ichdr->firstused >= new_end); + + for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { +- if (ichdr->freemap[i].base == tmp) { +- ichdr->freemap[i].base += sizeof(xfs_attr_leaf_entry_t); ++ int diff = 0; ++ ++ if (ichdr->freemap[i].base == old_end) { ++ /* ++ * This freemap entry starts at the old end of the ++ * leaf entry array, so we need to adjust its base ++ * upward to accomodate the larger array. ++ */ ++ diff = sizeof(struct xfs_attr_leaf_entry); ++ } else if (ichdr->freemap[i].size > 0 && ++ ichdr->freemap[i].base < new_end) { ++ /* ++ * This freemap entry starts in the space claimed by ++ * the new leaf entry. Adjust its base upward to ++ * reflect that. ++ */ ++ diff = new_end - ichdr->freemap[i].base; ++ } ++ ++ if (diff) { ++ ichdr->freemap[i].base += diff; + ichdr->freemap[i].size -= +- min_t(uint16_t, ichdr->freemap[i].size, +- sizeof(xfs_attr_leaf_entry_t)); ++ min_t(uint16_t, ichdr->freemap[i].size, diff); ++ } ++ ++ /* ++ * Don't leave zero-length freemaps with nonzero base lying ++ * around, because we don't want the code in _remove that ++ * matches on base address to get confused and create ++ * overlapping freemaps. If we end up with no freemap entries ++ * then the next _add will compact the leaf block and ++ * regenerate the freemaps. ++ */ ++ if (ichdr->freemap[i].size == 0 && ichdr->freemap[i].base > 0) { ++ ichdr->freemap[i].base = 0; ++ ichdr->holes = 1; + } + } + ichdr->usedbytes += xfs_attr_leaf_entsize(leaf, args->index); +diff --git a/fs/xfs/scrub/attr.c b/fs/xfs/scrub/attr.c +index 147babe738d201..c785d80bbfe50d 100644 +--- a/fs/xfs/scrub/attr.c ++++ b/fs/xfs/scrub/attr.c +@@ -343,7 +343,10 @@ xchk_xattr_entry( + rentry = xfs_attr3_leaf_name_remote(leaf, idx); + namesize = xfs_attr_leaf_entsize_remote(rentry->namelen); + name_end = (char *)rentry + namesize; +- if (rentry->namelen == 0 || rentry->valueblk == 0) ++ if (rentry->namelen == 0) ++ xchk_da_set_corrupt(ds, level); ++ if (rentry->valueblk == 0 && ++ !(ent->flags & XFS_ATTR_INCOMPLETE)) + xchk_da_set_corrupt(ds, level); + } + if (name_end > buf_end) +diff --git a/fs/xfs/scrub/btree.c b/fs/xfs/scrub/btree.c +index c3a9f33e5a8d12..2afc7e5cc08fcc 100644 +--- a/fs/xfs/scrub/btree.c ++++ b/fs/xfs/scrub/btree.c +@@ -42,6 +42,8 @@ __xchk_btree_process_error( + break; + case -EFSBADCRC: + case -EFSCORRUPTED: ++ case -EIO: ++ case -ENODATA: + /* Note the badness but don't abort. */ + sc->sm->sm_flags |= errflag; + *error = 0; +diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c +index f10cd4fb0abd0d..36814c09bf1034 100644 +--- a/fs/xfs/scrub/common.c ++++ b/fs/xfs/scrub/common.c +@@ -83,6 +83,8 @@ __xchk_process_error( + break; + case -EFSBADCRC: + case -EFSCORRUPTED: ++ case -EIO: ++ case -ENODATA: + /* Note the badness but don't abort. */ + sc->sm->sm_flags |= errflag; + *error = 0; +@@ -137,6 +139,8 @@ __xchk_fblock_process_error( + break; + case -EFSBADCRC: + case -EFSCORRUPTED: ++ case -EIO: ++ case -ENODATA: + /* Note the badness but don't abort. */ + sc->sm->sm_flags |= errflag; + *error = 0; +diff --git a/fs/xfs/scrub/dabtree.c b/fs/xfs/scrub/dabtree.c +index 82b150d3b8b700..338199d7b84165 100644 +--- a/fs/xfs/scrub/dabtree.c ++++ b/fs/xfs/scrub/dabtree.c +@@ -45,6 +45,8 @@ xchk_da_process_error( + break; + case -EFSBADCRC: + case -EFSCORRUPTED: ++ case -EIO: ++ case -ENODATA: + /* Note the badness but don't abort. */ + sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT; + *error = 0; +diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h +index be1dd4c1a91744..16646fdd1f8415 100644 +--- a/include/acpi/ghes.h ++++ b/include/acpi/ghes.h +@@ -21,6 +21,7 @@ struct ghes { + struct acpi_hest_generic_v2 *generic_v2; + }; + struct acpi_hest_generic_status *estatus; ++ unsigned int estatus_length; + unsigned long flags; + union { + struct list_head list; +diff --git a/include/asm-generic/audit_change_attr.h b/include/asm-generic/audit_change_attr.h +index 331670807cf011..6c311d4d37f4e6 100644 +--- a/include/asm-generic/audit_change_attr.h ++++ b/include/asm-generic/audit_change_attr.h +@@ -20,6 +20,9 @@ __NR_fremovexattr, + __NR_fchownat, + __NR_fchmodat, + #endif ++#ifdef __NR_fchmodat2 ++__NR_fchmodat2, ++#endif + #ifdef __NR_chown32 + __NR_chown32, + __NR_fchown32, +diff --git a/include/asm-generic/audit_read.h b/include/asm-generic/audit_read.h +index 7bb7b5a83ae2e5..fb9991f53fb6f9 100644 +--- a/include/asm-generic/audit_read.h ++++ b/include/asm-generic/audit_read.h +@@ -4,9 +4,15 @@ __NR_readlink, + #endif + __NR_quotactl, + __NR_listxattr, ++#ifdef __NR_listxattrat ++__NR_listxattrat, ++#endif + __NR_llistxattr, + __NR_flistxattr, + __NR_getxattr, ++#ifdef __NR_getxattrat ++__NR_getxattrat, ++#endif + __NR_lgetxattr, + __NR_fgetxattr, + #ifdef __NR_readlinkat +diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h +index 082a6e980d0178..3e38a470c5cbe4 100644 +--- a/include/drm/drm_of.h ++++ b/include/drm/drm_of.h +@@ -4,6 +4,7 @@ + + #include + #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DRM_PANEL_BRIDGE) ++#include + #include + #endif + +@@ -163,6 +164,8 @@ static inline int drm_of_panel_bridge_remove(const struct device_node *np, + bridge = of_drm_find_bridge(remote); + drm_panel_bridge_remove(bridge); + ++ of_node_put(remote); ++ + return 0; + #else + return -EINVAL; +diff --git a/include/linux/audit.h b/include/linux/audit.h +index 7ca75f8873799d..517c665da25975 100644 +--- a/include/linux/audit.h ++++ b/include/linux/audit.h +@@ -125,12 +125,6 @@ enum audit_nfcfgop { + extern int __init audit_register_class(int class, unsigned *list); + extern int audit_classify_syscall(int abi, unsigned syscall); + extern int audit_classify_arch(int arch); +-/* only for compat system calls */ +-extern unsigned compat_write_class[]; +-extern unsigned compat_read_class[]; +-extern unsigned compat_dir_class[]; +-extern unsigned compat_chattr_class[]; +-extern unsigned compat_signal_class[]; + + /* audit_names->type values */ + #define AUDIT_TYPE_UNKNOWN 0 /* we don't know yet */ +diff --git a/include/linux/audit_arch.h b/include/linux/audit_arch.h +index 0e34d673ef1712..2b8153791e6a5d 100644 +--- a/include/linux/audit_arch.h ++++ b/include/linux/audit_arch.h +@@ -23,4 +23,11 @@ enum auditsc_class_t { + + extern int audit_classify_compat_syscall(int abi, unsigned syscall); + ++/* only for compat system calls */ ++extern unsigned compat_write_class[]; ++extern unsigned compat_read_class[]; ++extern unsigned compat_dir_class[]; ++extern unsigned compat_chattr_class[]; ++extern unsigned compat_signal_class[]; ++ + #endif +diff --git a/include/linux/cache.h b/include/linux/cache.h +index 9900d20b76c282..ca2a05682a54b5 100644 +--- a/include/linux/cache.h ++++ b/include/linux/cache.h +@@ -13,6 +13,32 @@ + #define SMP_CACHE_BYTES L1_CACHE_BYTES + #endif + ++/** ++ * SMP_CACHE_ALIGN - align a value to the L2 cacheline size ++ * @x: value to align ++ * ++ * On some architectures, L2 ("SMP") CL size is bigger than L1, and sometimes, ++ * this needs to be accounted. ++ * ++ * Return: aligned value. ++ */ ++#ifndef SMP_CACHE_ALIGN ++#define SMP_CACHE_ALIGN(x) ALIGN(x, SMP_CACHE_BYTES) ++#endif ++ ++/* ++ * ``__aligned_largest`` aligns a field to the value most optimal for the ++ * target architecture to perform memory operations. Get the actual value ++ * to be able to use it anywhere else. ++ */ ++#ifndef __LARGEST_ALIGN ++#define __LARGEST_ALIGN sizeof(struct { long x; } __aligned_largest) ++#endif ++ ++#ifndef LARGEST_ALIGN ++#define LARGEST_ALIGN(x) ALIGN(x, __LARGEST_ALIGN) ++#endif ++ + /* + * __read_mostly is used to keep rarely changing variables out of frequently + * updated cachelines. Its use should be reserved for data that is used +@@ -85,6 +111,64 @@ + #define cache_line_size() L1_CACHE_BYTES + #endif + ++#ifndef __cacheline_group_begin ++#define __cacheline_group_begin(GROUP) \ ++ __u8 __cacheline_group_begin__##GROUP[0] ++#endif ++ ++#ifndef __cacheline_group_end ++#define __cacheline_group_end(GROUP) \ ++ __u8 __cacheline_group_end__##GROUP[0] ++#endif ++ ++/** ++ * __cacheline_group_begin_aligned - declare an aligned group start ++ * @GROUP: name of the group ++ * @...: optional group alignment ++ * ++ * The following block inside a struct: ++ * ++ * __cacheline_group_begin_aligned(grp); ++ * field a; ++ * field b; ++ * __cacheline_group_end_aligned(grp); ++ * ++ * will always be aligned to either the specified alignment or ++ * ``SMP_CACHE_BYTES``. ++ */ ++#define __cacheline_group_begin_aligned(GROUP, ...) \ ++ __cacheline_group_begin(GROUP) \ ++ __aligned((__VA_ARGS__ + 0) ? : SMP_CACHE_BYTES) ++ ++/** ++ * __cacheline_group_end_aligned - declare an aligned group end ++ * @GROUP: name of the group ++ * @...: optional alignment (same as was in __cacheline_group_begin_aligned()) ++ * ++ * Note that the end marker is aligned to sizeof(long) to allow more precise ++ * size assertion. It also declares a padding at the end to avoid next field ++ * falling into this cacheline. ++ */ ++#define __cacheline_group_end_aligned(GROUP, ...) \ ++ __cacheline_group_end(GROUP) __aligned(sizeof(long)); \ ++ struct { } __cacheline_group_pad__##GROUP \ ++ __aligned((__VA_ARGS__ + 0) ? : SMP_CACHE_BYTES) ++ ++#ifndef CACHELINE_ASSERT_GROUP_MEMBER ++#define CACHELINE_ASSERT_GROUP_MEMBER(TYPE, GROUP, MEMBER) \ ++ BUILD_BUG_ON(!(offsetof(TYPE, MEMBER) >= \ ++ offsetofend(TYPE, __cacheline_group_begin__##GROUP) && \ ++ offsetofend(TYPE, MEMBER) <= \ ++ offsetof(TYPE, __cacheline_group_end__##GROUP))) ++#endif ++ ++#ifndef CACHELINE_ASSERT_GROUP_SIZE ++#define CACHELINE_ASSERT_GROUP_SIZE(TYPE, GROUP, SIZE) \ ++ BUILD_BUG_ON(offsetof(TYPE, __cacheline_group_end__##GROUP) - \ ++ offsetofend(TYPE, __cacheline_group_begin__##GROUP) > \ ++ SIZE) ++#endif ++ + /* + * Helper to add padding within a struct to ensure data fall into separate + * cachelines. +diff --git a/include/linux/capability.h b/include/linux/capability.h +index 0c356a5179917e..767c535dbd38ec 100644 +--- a/include/linux/capability.h ++++ b/include/linux/capability.h +@@ -208,6 +208,12 @@ static inline bool checkpoint_restore_ns_capable(struct user_namespace *ns) + ns_capable(ns, CAP_SYS_ADMIN); + } + ++static inline bool checkpoint_restore_ns_capable_noaudit(struct user_namespace *ns) ++{ ++ return ns_capable_noaudit(ns, CAP_CHECKPOINT_RESTORE) || ++ ns_capable_noaudit(ns, CAP_SYS_ADMIN); ++} ++ + /* audit system wants to get cap info from files as well */ + int get_vfs_caps_from_disk(struct mnt_idmap *idmap, + const struct dentry *dentry, +diff --git a/include/linux/clk.h b/include/linux/clk.h +index 06f1b292f8a00a..862ef29ee5f0e3 100644 +--- a/include/linux/clk.h ++++ b/include/linux/clk.h +@@ -216,6 +216,23 @@ int clk_rate_exclusive_get(struct clk *clk); + */ + void clk_rate_exclusive_put(struct clk *clk); + ++/** ++ * clk_save_context - save clock context for poweroff ++ * ++ * Saves the context of the clock register for powerstates in which the ++ * contents of the registers will be lost. Occurs deep within the suspend ++ * code so locking is not necessary. ++ */ ++int clk_save_context(void); ++ ++/** ++ * clk_restore_context - restore clock context after poweroff ++ * ++ * This occurs with all clocks enabled. Occurs deep within the resume code ++ * so locking is not necessary. ++ */ ++void clk_restore_context(void); ++ + #else + + static inline int clk_notifier_register(struct clk *clk, +@@ -276,6 +293,13 @@ static inline int clk_rate_exclusive_get(struct clk *clk) + + static inline void clk_rate_exclusive_put(struct clk *clk) {} + ++static inline int clk_save_context(void) ++{ ++ return 0; ++} ++ ++static inline void clk_restore_context(void) {} ++ + #endif + + #ifdef CONFIG_HAVE_CLK_PREPARE +@@ -872,23 +896,6 @@ struct clk *clk_get_parent(struct clk *clk); + */ + struct clk *clk_get_sys(const char *dev_id, const char *con_id); + +-/** +- * clk_save_context - save clock context for poweroff +- * +- * Saves the context of the clock register for powerstates in which the +- * contents of the registers will be lost. Occurs deep within the suspend +- * code so locking is not necessary. +- */ +-int clk_save_context(void); +- +-/** +- * clk_restore_context - restore clock context after poweroff +- * +- * This occurs with all clocks enabled. Occurs deep within the resume code +- * so locking is not necessary. +- */ +-void clk_restore_context(void); +- + #else /* !CONFIG_HAVE_CLK */ + + static inline struct clk *clk_get(struct device *dev, const char *id) +@@ -1055,13 +1062,6 @@ static inline struct clk *clk_get_sys(const char *dev_id, const char *con_id) + return NULL; + } + +-static inline int clk_save_context(void) +-{ +- return 0; +-} +- +-static inline void clk_restore_context(void) {} +- + #endif + + /* clk_prepare_enable helps cases using clk_enable in non-atomic context. */ +diff --git a/include/linux/cper.h b/include/linux/cper.h +index ad1ed24730917c..c588e5c2a96c6d 100644 +--- a/include/linux/cper.h ++++ b/include/linux/cper.h +@@ -568,7 +568,8 @@ void cper_mem_err_pack(const struct cper_sec_mem_err *, + const char *cper_mem_err_unpack(struct trace_seq *, + struct cper_mem_err_compact *); + void cper_print_proc_arm(const char *pfx, +- const struct cper_sec_proc_arm *proc); ++ const struct cper_sec_proc_arm *proc, ++ u32 length); + void cper_print_proc_ia(const char *pfx, + const struct cper_sec_proc_ia *proc); + int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg); +diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h +index e8921871ef9aaa..5c3eaf9fc90c4e 100644 +--- a/include/linux/ftrace.h ++++ b/include/linux/ftrace.h +@@ -89,11 +89,13 @@ struct ftrace_direct_func; + defined(CONFIG_DYNAMIC_FTRACE) + const char * + ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, +- unsigned long *off, char **modname, char *sym); ++ unsigned long *off, char **modname, ++ const unsigned char **modbuildid, char *sym); + #else + static inline const char * + ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, +- unsigned long *off, char **modname, char *sym) ++ unsigned long *off, char **modname, ++ const unsigned char **modbuildid, char *sym) + { + return NULL; + } +diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h +index ddb27fc0ee8c88..b157ff4f727fba 100644 +--- a/include/linux/inetdevice.h ++++ b/include/linux/inetdevice.h +@@ -38,11 +38,11 @@ struct in_device { + struct ip_mc_list *mc_tomb; + unsigned long mr_v1_seen; + unsigned long mr_v2_seen; +- unsigned long mr_maxdelay; + unsigned long mr_qi; /* Query Interval */ + unsigned long mr_qri; /* Query Response Interval */ + unsigned char mr_qrv; /* Query Robustness Variable */ + unsigned char mr_gq_running; ++ u32 mr_maxdelay; + u32 mr_ifc_count; + struct timer_list mr_gq_timer; /* general query timer */ + struct timer_list mr_ifc_timer; /* interface change timer */ +diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h +index a3241e4d754868..4816d4f4721011 100644 +--- a/include/linux/mfd/wm8350/core.h ++++ b/include/linux/mfd/wm8350/core.h +@@ -663,7 +663,7 @@ static inline int wm8350_register_irq(struct wm8350 *wm8350, int irq, + return -ENODEV; + + return request_threaded_irq(irq + wm8350->irq_base, NULL, +- handler, flags, name, data); ++ handler, flags | IRQF_ONESHOT, name, data); + } + + static inline void wm8350_free_irq(struct wm8350 *wm8350, int irq, void *data) +diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h +index c0e0468b25a180..c29ecbfbf3da24 100644 +--- a/include/linux/mlx5/driver.h ++++ b/include/linux/mlx5/driver.h +@@ -1288,12 +1288,12 @@ static inline bool mlx5_rl_is_supported(struct mlx5_core_dev *dev) + static inline int mlx5_core_is_mp_slave(struct mlx5_core_dev *dev) + { + return MLX5_CAP_GEN(dev, affiliate_nic_vport_criteria) && +- MLX5_CAP_GEN(dev, num_vhca_ports) <= 1; ++ MLX5_CAP_GEN_MAX(dev, num_vhca_ports) <= 1; + } + + static inline int mlx5_core_is_mp_master(struct mlx5_core_dev *dev) + { +- return MLX5_CAP_GEN(dev, num_vhca_ports) > 1; ++ return MLX5_CAP_GEN_MAX(dev, num_vhca_ports) > 1; + } + + static inline int mlx5_core_mp_enabled(struct mlx5_core_dev *dev) +diff --git a/include/linux/module.h b/include/linux/module.h +index f58d1eb260fa9e..10603f725cae53 100644 +--- a/include/linux/module.h ++++ b/include/linux/module.h +@@ -735,6 +735,15 @@ static inline void __module_get(struct module *module) + __mod ? __mod->name : "kernel"; \ + }) + ++static inline const unsigned char *module_buildid(struct module *mod) ++{ ++#ifdef CONFIG_STACKTRACE_BUILD_ID ++ return mod->build_id; ++#else ++ return NULL; ++#endif ++} ++ + /* Dereference module function descriptor */ + void *dereference_module_function_descriptor(struct module *mod, void *ptr); + +diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h +index 5c2ccc6494529e..980e1fdf67eda0 100644 +--- a/include/linux/mtd/spinand.h ++++ b/include/linux/mtd/spinand.h +@@ -195,7 +195,7 @@ struct spinand_device; + + /** + * struct spinand_id - SPI NAND id structure +- * @data: buffer containing the id bytes. Currently 4 bytes large, but can ++ * @data: buffer containing the id bytes. Currently 5 bytes large, but can + * be extended if required + * @len: ID length + */ +diff --git a/include/linux/psp.h b/include/linux/psp.h +index 92e60aeef21e13..b337dcce1e9916 100644 +--- a/include/linux/psp.h ++++ b/include/linux/psp.h +@@ -18,6 +18,7 @@ + * and should include an appropriate local definition in their source file. + */ + #define PSP_CMDRESP_STS GENMASK(15, 0) ++#define PSP_TEE_STS_RING_BUSY 0x0000000d /* Ring already initialized */ + #define PSP_CMDRESP_CMD GENMASK(23, 16) + #define PSP_CMDRESP_RESERVED GENMASK(29, 24) + #define PSP_CMDRESP_RECOVERY BIT(30) +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 69b392dc10aa37..1a91645fa24975 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -1122,6 +1122,38 @@ static inline struct dst_entry *skb_dst(const struct sk_buff *skb) + return (struct dst_entry *)(skb->_skb_refdst & SKB_DST_PTRMASK); + } + ++/** ++ * skb_dstref_steal() - return current dst_entry value and clear it ++ * @skb: buffer ++ * ++ * Resets skb dst_entry without adjusting its reference count. Useful in ++ * cases where dst_entry needs to be temporarily reset and restored. ++ * Note that the returned value cannot be used directly because it ++ * might contain SKB_DST_NOREF bit. ++ * ++ * When in doubt, prefer skb_dst_drop() over skb_dstref_steal() to correctly ++ * handle dst_entry reference counting. ++ * ++ * Returns: original skb dst_entry. ++ */ ++static inline unsigned long skb_dstref_steal(struct sk_buff *skb) ++{ ++ unsigned long refdst = skb->_skb_refdst; ++ ++ skb->_skb_refdst = 0; ++ return refdst; ++} ++ ++/** ++ * skb_dstref_restore() - restore skb dst_entry removed via skb_dstref_steal() ++ * @skb: buffer ++ * @refdst: dst entry from a call to skb_dstref_steal() ++ */ ++static inline void skb_dstref_restore(struct sk_buff *skb, unsigned long refdst) ++{ ++ skb->_skb_refdst = refdst; ++} ++ + /** + * skb_dst_set - sets skb dst + * @skb: buffer +diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h +index 32bbebf5b71e3c..e923f1c24ce4b3 100644 +--- a/include/linux/skmsg.h ++++ b/include/linux/skmsg.h +@@ -93,6 +93,8 @@ struct sk_psock { + struct sk_buff_head ingress_skb; + struct list_head ingress_msg; + spinlock_t ingress_lock; ++ /** @msg_tot_len: Total bytes queued in ingress_msg list. */ ++ u32 msg_tot_len; + unsigned long state; + struct list_head link; + spinlock_t link_lock; +@@ -132,6 +134,8 @@ int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from, + struct sk_msg *msg, u32 bytes); + int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, + int len, int flags); ++int __sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, ++ int len, int flags, int *copied_from_self); + bool sk_msg_is_readable(struct sock *sk); + + static inline void sk_msg_check_to_free(struct sk_msg *msg, u32 i, u32 bytes) +@@ -310,6 +314,27 @@ static inline void sock_drop(struct sock *sk, struct sk_buff *skb) + kfree_skb(skb); + } + ++static inline u32 sk_psock_get_msg_len_nolock(struct sk_psock *psock) ++{ ++ /* Used by ioctl to read msg_tot_len only; lock-free for performance */ ++ return READ_ONCE(psock->msg_tot_len); ++} ++ ++static inline void sk_psock_msg_len_add_locked(struct sk_psock *psock, int diff) ++{ ++ /* Use WRITE_ONCE to ensure correct read in sk_psock_get_msg_len_nolock(). ++ * ingress_lock should be held to prevent concurrent updates to msg_tot_len ++ */ ++ WRITE_ONCE(psock->msg_tot_len, psock->msg_tot_len + diff); ++} ++ ++static inline void sk_psock_msg_len_add(struct sk_psock *psock, int diff) ++{ ++ spin_lock_bh(&psock->ingress_lock); ++ sk_psock_msg_len_add_locked(psock, diff); ++ spin_unlock_bh(&psock->ingress_lock); ++} ++ + static inline bool sk_psock_queue_msg(struct sk_psock *psock, + struct sk_msg *msg) + { +@@ -318,6 +343,7 @@ static inline bool sk_psock_queue_msg(struct sk_psock *psock, + spin_lock_bh(&psock->ingress_lock); + if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) { + list_add_tail(&msg->list, &psock->ingress_msg); ++ sk_psock_msg_len_add_locked(psock, msg->sg.size); + ret = true; + } else { + sk_msg_free(psock->sk, msg); +@@ -334,18 +360,25 @@ static inline struct sk_msg *sk_psock_dequeue_msg(struct sk_psock *psock) + + spin_lock_bh(&psock->ingress_lock); + msg = list_first_entry_or_null(&psock->ingress_msg, struct sk_msg, list); +- if (msg) ++ if (msg) { + list_del(&msg->list); ++ sk_psock_msg_len_add_locked(psock, -msg->sg.size); ++ } + spin_unlock_bh(&psock->ingress_lock); + return msg; + } + ++static inline struct sk_msg *sk_psock_peek_msg_locked(struct sk_psock *psock) ++{ ++ return list_first_entry_or_null(&psock->ingress_msg, struct sk_msg, list); ++} ++ + static inline struct sk_msg *sk_psock_peek_msg(struct sk_psock *psock) + { + struct sk_msg *msg; + + spin_lock_bh(&psock->ingress_lock); +- msg = list_first_entry_or_null(&psock->ingress_msg, struct sk_msg, list); ++ msg = sk_psock_peek_msg_locked(psock); + spin_unlock_bh(&psock->ingress_lock); + return msg; + } +@@ -509,6 +542,39 @@ static inline bool sk_psock_strp_enabled(struct sk_psock *psock) + return !!psock->saved_data_ready; + } + ++/* for tcp only, sk is locked */ ++static inline ssize_t sk_psock_msg_inq(struct sock *sk) ++{ ++ struct sk_psock *psock; ++ ssize_t inq = 0; ++ ++ psock = sk_psock_get(sk); ++ if (likely(psock)) { ++ inq = sk_psock_get_msg_len_nolock(psock); ++ sk_psock_put(sk, psock); ++ } ++ return inq; ++} ++ ++/* for udp only, sk is not locked */ ++static inline ssize_t sk_msg_first_len(struct sock *sk) ++{ ++ struct sk_psock *psock; ++ struct sk_msg *msg; ++ ssize_t inq = 0; ++ ++ psock = sk_psock_get(sk); ++ if (likely(psock)) { ++ spin_lock_bh(&psock->ingress_lock); ++ msg = sk_psock_peek_msg_locked(psock); ++ if (msg) ++ inq = msg->sg.size; ++ spin_unlock_bh(&psock->ingress_lock); ++ sk_psock_put(sk, psock); ++ } ++ return inq; ++} ++ + #if IS_ENABLED(CONFIG_NET_SOCK_MSG) + + #define BPF_F_STRPARSER (1UL << 1) +diff --git a/include/linux/tcp.h b/include/linux/tcp.h +index 9b371aa7c79623..e15452df9804f6 100644 +--- a/include/linux/tcp.h ++++ b/include/linux/tcp.h +@@ -471,15 +471,17 @@ enum tsq_enum { + TCP_MTU_REDUCED_DEFERRED, /* tcp_v{4|6}_err() could not call + * tcp_v{4|6}_mtu_reduced() + */ ++ TCP_ACK_DEFERRED, /* TX pure ack is deferred */ + }; + + enum tsq_flags { +- TSQF_THROTTLED = (1UL << TSQ_THROTTLED), +- TSQF_QUEUED = (1UL << TSQ_QUEUED), +- TCPF_TSQ_DEFERRED = (1UL << TCP_TSQ_DEFERRED), +- TCPF_WRITE_TIMER_DEFERRED = (1UL << TCP_WRITE_TIMER_DEFERRED), +- TCPF_DELACK_TIMER_DEFERRED = (1UL << TCP_DELACK_TIMER_DEFERRED), +- TCPF_MTU_REDUCED_DEFERRED = (1UL << TCP_MTU_REDUCED_DEFERRED), ++ TSQF_THROTTLED = BIT(TSQ_THROTTLED), ++ TSQF_QUEUED = BIT(TSQ_QUEUED), ++ TCPF_TSQ_DEFERRED = BIT(TCP_TSQ_DEFERRED), ++ TCPF_WRITE_TIMER_DEFERRED = BIT(TCP_WRITE_TIMER_DEFERRED), ++ TCPF_DELACK_TIMER_DEFERRED = BIT(TCP_DELACK_TIMER_DEFERRED), ++ TCPF_MTU_REDUCED_DEFERRED = BIT(TCP_MTU_REDUCED_DEFERRED), ++ TCPF_ACK_DEFERRED = BIT(TCP_ACK_DEFERRED), + }; + + #define tcp_sk(ptr) container_of_const(ptr, struct tcp_sock, inet_conn.icsk_inet.sk) +diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h +index fe95d13c5e4d86..4035cb45035608 100644 +--- a/include/linux/trace_events.h ++++ b/include/linux/trace_events.h +@@ -695,6 +695,11 @@ static inline void hist_poll_wakeup(void) + + #define hist_poll_wait(file, wait) \ + poll_wait(file, &hist_poll_wq, wait) ++ ++#else ++static inline void hist_poll_wakeup(void) ++{ ++} + #endif + + #define __TRACE_EVENT_FLAGS(name, value) \ +diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h +index 457879938fc198..3366090a86bd2f 100644 +--- a/include/linux/u64_stats_sync.h ++++ b/include/linux/u64_stats_sync.h +@@ -89,6 +89,11 @@ static inline void u64_stats_add(u64_stats_t *p, unsigned long val) + local64_add(val, &p->v); + } + ++static inline void u64_stats_sub(u64_stats_t *p, s64 val) ++{ ++ local64_sub(val, &p->v); ++} ++ + static inline void u64_stats_inc(u64_stats_t *p) + { + local64_inc(&p->v); +@@ -130,6 +135,11 @@ static inline void u64_stats_add(u64_stats_t *p, unsigned long val) + p->v += val; + } + ++static inline void u64_stats_sub(u64_stats_t *p, s64 val) ++{ ++ p->v -= val; ++} ++ + static inline void u64_stats_inc(u64_stats_t *p) + { + p->v++; +diff --git a/include/media/dvb_vb2.h b/include/media/dvb_vb2.h +index 8cb88452cd6c28..0fbbfc65157e64 100644 +--- a/include/media/dvb_vb2.h ++++ b/include/media/dvb_vb2.h +@@ -124,7 +124,7 @@ static inline int dvb_vb2_release(struct dvb_vb2_ctx *ctx) + return 0; + }; + #define dvb_vb2_is_streaming(ctx) (0) +-#define dvb_vb2_fill_buffer(ctx, file, wait, flags) (0) ++#define dvb_vb2_fill_buffer(ctx, file, wait, flags, flush) (0) + + static inline __poll_t dvb_vb2_poll(struct dvb_vb2_ctx *ctx, + struct file *file, +@@ -166,10 +166,12 @@ int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx); + * @buffer_flags: + * pointer to buffer flags as defined by &enum dmx_buffer_flags. + * can be NULL. ++ * @flush: flush the buffer, even if it isn't full. + */ + int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, + const unsigned char *src, int len, +- enum dmx_buffer_flags *buffer_flags); ++ enum dmx_buffer_flags *buffer_flags, ++ bool flush); + + /** + * dvb_vb2_poll - Wrapper to vb2_core_streamon() for Digital TV +diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h +index 08574278645de1..a57fd4573783d4 100644 +--- a/include/net/bluetooth/l2cap.h ++++ b/include/net/bluetooth/l2cap.h +@@ -487,6 +487,8 @@ struct l2cap_ecred_reconf_req { + #define L2CAP_RECONF_SUCCESS 0x0000 + #define L2CAP_RECONF_INVALID_MTU 0x0001 + #define L2CAP_RECONF_INVALID_MPS 0x0002 ++#define L2CAP_RECONF_INVALID_CID 0x0003 ++#define L2CAP_RECONF_INVALID_PARAMS 0x0004 + + struct l2cap_ecred_reconf_rsp { + __le16 result; +diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h +index e85834722b8f2b..3eb715f66cbf66 100644 +--- a/include/net/inet_connection_sock.h ++++ b/include/net/inet_connection_sock.h +@@ -326,11 +326,10 @@ void inet_csk_update_fastreuse(struct inet_bind_bucket *tb, + + struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu); + +-#define TCP_PINGPONG_THRESH 1 +- + static inline void inet_csk_enter_pingpong_mode(struct sock *sk) + { +- inet_csk(sk)->icsk_ack.pingpong = TCP_PINGPONG_THRESH; ++ inet_csk(sk)->icsk_ack.pingpong = ++ READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_pingpong_thresh); + } + + static inline void inet_csk_exit_pingpong_mode(struct sock *sk) +@@ -340,7 +339,16 @@ static inline void inet_csk_exit_pingpong_mode(struct sock *sk) + + static inline bool inet_csk_in_pingpong_mode(struct sock *sk) + { +- return inet_csk(sk)->icsk_ack.pingpong >= TCP_PINGPONG_THRESH; ++ return inet_csk(sk)->icsk_ack.pingpong >= ++ READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_pingpong_thresh); ++} ++ ++static inline void inet_csk_inc_pingpong_cnt(struct sock *sk) ++{ ++ struct inet_connection_sock *icsk = inet_csk(sk); ++ ++ if (icsk->icsk_ack.pingpong < U8_MAX) ++ icsk->icsk_ack.pingpong++; + } + + static inline bool inet_csk_has_ulp(const struct sock *sk) +diff --git a/include/net/ioam6.h b/include/net/ioam6.h +index 781d2d8b2f29d9..3f99eb445de61f 100644 +--- a/include/net/ioam6.h ++++ b/include/net/ioam6.h +@@ -59,6 +59,8 @@ void ioam6_fill_trace_data(struct sk_buff *skb, + struct ioam6_trace_hdr *trace, + bool is_input); + ++u8 ioam6_trace_compute_nodelen(u32 trace_type); ++ + int ioam6_init(void); + void ioam6_exit(void); + +diff --git a/include/net/ip.h b/include/net/ip.h +index d8bf1f0a6919c4..bacdb4fecc89be 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -790,11 +790,8 @@ static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) + ip_cmsg_recv_offset(msg, skb->sk, skb, 0, 0); + } + +-bool icmp_global_allow(void); +-void icmp_global_consume(void); +- +-extern int sysctl_icmp_msgs_per_sec; +-extern int sysctl_icmp_msgs_burst; ++bool icmp_global_allow(struct net *net); ++void icmp_global_consume(struct net *net); + + #ifdef CONFIG_PROC_FS + int ip_misc_proc_init(void); +diff --git a/include/net/ipv6.h b/include/net/ipv6.h +index c6932d1a3fa806..d98f5390ffad38 100644 +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -1017,11 +1017,11 @@ static inline int ip6_default_np_autolabel(struct net *net) + #if IS_ENABLED(CONFIG_IPV6) + static inline int ip6_multipath_hash_policy(const struct net *net) + { +- return net->ipv6.sysctl.multipath_hash_policy; ++ return READ_ONCE(net->ipv6.sysctl.multipath_hash_policy); + } + static inline u32 ip6_multipath_hash_fields(const struct net *net) + { +- return net->ipv6.sysctl.multipath_hash_fields; ++ return READ_ONCE(net->ipv6.sysctl.multipath_hash_fields); + } + #else + static inline int ip6_multipath_hash_policy(const struct net *net) +@@ -1293,12 +1293,15 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, + + static inline int ip6_sock_set_v6only(struct sock *sk) + { +- if (inet_sk(sk)->inet_num) +- return -EINVAL; ++ int ret = 0; ++ + lock_sock(sk); +- sk->sk_ipv6only = true; ++ if (inet_sk(sk)->inet_num) ++ ret = -EINVAL; ++ else ++ sk->sk_ipv6only = true; + release_sock(sk); +- return 0; ++ return ret; + } + + static inline void ip6_sock_set_recverr(struct sock *sk) +diff --git a/include/net/netfilter/nf_conntrack_count.h b/include/net/netfilter/nf_conntrack_count.h +index 115bb7e572f7d0..bf22661925b813 100644 +--- a/include/net/netfilter/nf_conntrack_count.h ++++ b/include/net/netfilter/nf_conntrack_count.h +@@ -13,6 +13,7 @@ struct nf_conncount_list { + u32 last_gc; /* jiffies at most recent gc */ + struct list_head head; /* connections with the same filtering key */ + unsigned int count; /* length of list */ ++ unsigned int last_gc_count; /* length of list at most recent gc */ + }; + + struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family, +diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h +index 7a41c479153673..521529e61ae1c9 100644 +--- a/include/net/netns/ipv4.h ++++ b/include/net/netns/ipv4.h +@@ -42,6 +42,44 @@ struct inet_timewait_death_row { + struct tcp_fastopen_context; + + struct netns_ipv4 { ++ /* Cacheline organization can be found documented in ++ * Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst. ++ * Please update the document when adding new fields. ++ */ ++ ++ /* TX readonly hotpath cache lines */ ++ __cacheline_group_begin(netns_ipv4_read_tx); ++ u8 sysctl_tcp_early_retrans; ++ u8 sysctl_tcp_tso_win_divisor; ++ u8 sysctl_tcp_tso_rtt_log; ++ u8 sysctl_tcp_autocorking; ++ int sysctl_tcp_min_snd_mss; ++ unsigned int sysctl_tcp_notsent_lowat; ++ int sysctl_tcp_limit_output_bytes; ++ int sysctl_tcp_min_rtt_wlen; ++ int sysctl_tcp_wmem[3]; ++ u8 sysctl_ip_fwd_use_pmtu; ++ __cacheline_group_end(netns_ipv4_read_tx); ++ ++ /* TXRX readonly hotpath cache lines */ ++ __cacheline_group_begin(netns_ipv4_read_txrx); ++ u8 sysctl_tcp_moderate_rcvbuf; ++ __cacheline_group_end(netns_ipv4_read_txrx); ++ ++ /* RX readonly hotpath cache line */ ++ __cacheline_group_begin(netns_ipv4_read_rx); ++ u8 sysctl_ip_early_demux; ++ u8 sysctl_tcp_early_demux; ++ int sysctl_tcp_reordering; ++ int sysctl_tcp_rmem[3]; ++ __cacheline_group_end(netns_ipv4_read_rx); ++ ++ /* ICMP rate limiter hot cache line. */ ++ __cacheline_group_begin_aligned(icmp); ++ atomic_t icmp_global_credit; ++ u32 icmp_global_stamp; ++ __cacheline_group_end_aligned(icmp); ++ + struct inet_timewait_death_row tcp_death_row; + struct udp_table *udp_table; + +@@ -84,6 +122,8 @@ struct netns_ipv4 { + u8 sysctl_icmp_errors_use_inbound_ifaddr; + int sysctl_icmp_ratelimit; + int sysctl_icmp_ratemask; ++ int sysctl_icmp_msgs_per_sec; ++ int sysctl_icmp_msgs_burst; + + u32 ip_rt_min_pmtu; + int ip_rt_mtu_expires; +@@ -96,17 +136,14 @@ struct netns_ipv4 { + + u8 sysctl_ip_default_ttl; + u8 sysctl_ip_no_pmtu_disc; +- u8 sysctl_ip_fwd_use_pmtu; + u8 sysctl_ip_fwd_update_priority; + u8 sysctl_ip_nonlocal_bind; + u8 sysctl_ip_autobind_reuse; + /* Shall we try to damage output packets if routing dev changes? */ + u8 sysctl_ip_dynaddr; +- u8 sysctl_ip_early_demux; + #ifdef CONFIG_NET_L3_MASTER_DEV + u8 sysctl_raw_l3mdev_accept; + #endif +- u8 sysctl_tcp_early_demux; + u8 sysctl_udp_early_demux; + + u8 sysctl_nexthop_compat_mode; +@@ -119,7 +156,6 @@ struct netns_ipv4 { + u8 sysctl_tcp_mtu_probing; + int sysctl_tcp_mtu_probe_floor; + int sysctl_tcp_base_mss; +- int sysctl_tcp_min_snd_mss; + int sysctl_tcp_probe_threshold; + u32 sysctl_tcp_probe_interval; + +@@ -132,17 +168,17 @@ struct netns_ipv4 { + u8 sysctl_tcp_syncookies; + u8 sysctl_tcp_migrate_req; + u8 sysctl_tcp_comp_sack_nr; +- int sysctl_tcp_reordering; ++ u8 sysctl_tcp_backlog_ack_defer; ++ u8 sysctl_tcp_pingpong_thresh; ++ + u8 sysctl_tcp_retries1; + u8 sysctl_tcp_retries2; + u8 sysctl_tcp_orphan_retries; + u8 sysctl_tcp_tw_reuse; + int sysctl_tcp_fin_timeout; +- unsigned int sysctl_tcp_notsent_lowat; + u8 sysctl_tcp_sack; + u8 sysctl_tcp_window_scaling; + u8 sysctl_tcp_timestamps; +- u8 sysctl_tcp_early_retrans; + u8 sysctl_tcp_recovery; + u8 sysctl_tcp_thin_linear_timeouts; + u8 sysctl_tcp_slow_start_after_idle; +@@ -158,21 +194,13 @@ struct netns_ipv4 { + u8 sysctl_tcp_frto; + u8 sysctl_tcp_nometrics_save; + u8 sysctl_tcp_no_ssthresh_metrics_save; +- u8 sysctl_tcp_moderate_rcvbuf; +- u8 sysctl_tcp_tso_win_divisor; + u8 sysctl_tcp_workaround_signed_windows; +- int sysctl_tcp_limit_output_bytes; + int sysctl_tcp_challenge_ack_limit; +- int sysctl_tcp_min_rtt_wlen; + u8 sysctl_tcp_min_tso_segs; +- u8 sysctl_tcp_tso_rtt_log; +- u8 sysctl_tcp_autocorking; + u8 sysctl_tcp_reflect_tos; + int sysctl_tcp_invalid_ratelimit; + int sysctl_tcp_pacing_ss_ratio; + int sysctl_tcp_pacing_ca_ratio; +- int sysctl_tcp_wmem[3]; +- int sysctl_tcp_rmem[3]; + unsigned int sysctl_tcp_child_ehash_entries; + unsigned long sysctl_tcp_comp_sack_delay_ns; + unsigned long sysctl_tcp_comp_sack_slack_ns; +diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h +index de1d88d41270cf..038fa78835bed6 100644 +--- a/include/rdma/ib_verbs.h ++++ b/include/rdma/ib_verbs.h +@@ -1096,7 +1096,7 @@ struct ib_qp_cap { + + /* + * Maximum number of rdma_rw_ctx structures in flight at a time. +- * ib_create_qp() will calculate the right amount of neededed WRs ++ * ib_create_qp() will calculate the right amount of needed WRs + * and MRs based on this. + */ + u32 max_rdma_ctxs; +diff --git a/include/rdma/rw.h b/include/rdma/rw.h +index d606cac482338b..9a8f4b76ce588d 100644 +--- a/include/rdma/rw.h ++++ b/include/rdma/rw.h +@@ -66,6 +66,8 @@ int rdma_rw_ctx_post(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u32 port_num, + + unsigned int rdma_rw_mr_factor(struct ib_device *device, u32 port_num, + unsigned int maxpages); ++unsigned int rdma_rw_max_send_wr(struct ib_device *dev, u32 port_num, ++ unsigned int max_rdma_ctxs, u32 create_flags); + void rdma_rw_init_qp(struct ib_device *dev, struct ib_qp_init_attr *attr); + int rdma_rw_init_mrs(struct ib_qp *qp, struct ib_qp_init_attr *attr); + void rdma_rw_cleanup_mrs(struct ib_qp *qp); +diff --git a/include/uapi/linux/hyperv.h b/include/uapi/linux/hyperv.h +index aaa502a7bff46c..1749b35ab2c21d 100644 +--- a/include/uapi/linux/hyperv.h ++++ b/include/uapi/linux/hyperv.h +@@ -362,7 +362,7 @@ struct hv_kvp_exchg_msg_value { + __u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; + __u32 value_u32; + __u64 value_u64; +- }; ++ } __attribute__((packed)); + } __attribute__((packed)); + + struct hv_kvp_msg_enumerate { +diff --git a/include/uapi/linux/netfilter_bridge.h b/include/uapi/linux/netfilter_bridge.h +index 1610fdbab98dfc..ad520d3e9df8f7 100644 +--- a/include/uapi/linux/netfilter_bridge.h ++++ b/include/uapi/linux/netfilter_bridge.h +@@ -5,6 +5,10 @@ + /* bridge-specific defines for netfilter. + */ + ++#ifndef __KERNEL__ ++#include /* for __UAPI_DEF_ETHHDR if defined */ ++#endif ++ + #include + #include + #include +diff --git a/include/uapi/linux/vbox_vmmdev_types.h b/include/uapi/linux/vbox_vmmdev_types.h +index f8a8d6b3c5219d..436678d4fb24f3 100644 +--- a/include/uapi/linux/vbox_vmmdev_types.h ++++ b/include/uapi/linux/vbox_vmmdev_types.h +@@ -236,7 +236,7 @@ struct vmmdev_hgcm_function_parameter32 { + /** Relative to the request header. */ + __u32 offset; + } page_list; +- } u; ++ } __packed u; + } __packed; + VMMDEV_ASSERT_SIZE(vmmdev_hgcm_function_parameter32, 4 + 8); + +@@ -251,7 +251,7 @@ struct vmmdev_hgcm_function_parameter64 { + union { + __u64 phys_addr; + __u64 linear_addr; +- } u; ++ } __packed u; + } __packed pointer; + struct { + /** Size of the buffer described by the page list. */ +diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h +index 78380fc2374ea5..8d2efb9e5d664b 100644 +--- a/include/ufs/ufshcd.h ++++ b/include/ufs/ufshcd.h +@@ -1329,17 +1329,13 @@ static inline void *ufshcd_get_variant(struct ufs_hba *hba) + return hba->priv; + } + +-#ifdef CONFIG_PM + extern int ufshcd_runtime_suspend(struct device *dev); + extern int ufshcd_runtime_resume(struct device *dev); +-#endif +-#ifdef CONFIG_PM_SLEEP + extern int ufshcd_system_suspend(struct device *dev); + extern int ufshcd_system_resume(struct device *dev); + extern int ufshcd_system_freeze(struct device *dev); + extern int ufshcd_system_thaw(struct device *dev); + extern int ufshcd_system_restore(struct device *dev); +-#endif + + extern int ufshcd_dme_configure_adapt(struct ufs_hba *hba, + int agreed_gear, +diff --git a/include/xen/xen.h b/include/xen/xen.h +index a1e5b3f18d69f9..86fe96fe518345 100644 +--- a/include/xen/xen.h ++++ b/include/xen/xen.h +@@ -62,11 +62,13 @@ extern u64 xen_saved_max_mem_size; + #endif + + #ifdef CONFIG_XEN_UNPOPULATED_ALLOC ++extern unsigned long xen_unpopulated_pages; + int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages); + void xen_free_unpopulated_pages(unsigned int nr_pages, struct page **pages); + #include + int arch_xen_unpopulated_init(struct resource **res); + #else ++#define xen_unpopulated_pages 0UL + #include + static inline int xen_alloc_unpopulated_pages(unsigned int nr_pages, + struct page **pages) +diff --git a/io_uring/cancel.h b/io_uring/cancel.h +index fc98622e6166e1..7e6d0fca7db28a 100644 +--- a/io_uring/cancel.h ++++ b/io_uring/cancel.h +@@ -4,10 +4,8 @@ + + struct io_cancel_data { + struct io_ring_ctx *ctx; +- union { +- u64 data; +- struct file *file; +- }; ++ u64 data; ++ struct file *file; + u8 opcode; + u32 flags; + int seq; +diff --git a/io_uring/filetable.c b/io_uring/filetable.c +index ff74d41d9e53c5..aa9f0abcd8eeab 100644 +--- a/io_uring/filetable.c ++++ b/io_uring/filetable.c +@@ -22,6 +22,10 @@ static int io_file_bitmap_get(struct io_ring_ctx *ctx) + if (!table->bitmap) + return -ENFILE; + ++ if (table->alloc_hint < ctx->file_alloc_start || ++ table->alloc_hint >= ctx->file_alloc_end) ++ table->alloc_hint = ctx->file_alloc_start; ++ + do { + ret = find_next_zero_bit(table->bitmap, nr, table->alloc_hint); + if (ret != nr) +diff --git a/io_uring/sync.c b/io_uring/sync.c +index 255f68c37e55cc..27bd0a26500bcf 100644 +--- a/io_uring/sync.c ++++ b/io_uring/sync.c +@@ -62,6 +62,8 @@ int io_fsync_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) + return -EINVAL; + + sync->off = READ_ONCE(sqe->off); ++ if (sync->off < 0) ++ return -EINVAL; + sync->len = READ_ONCE(sqe->len); + req->flags |= REQ_F_FORCE_ASYNC; + return 0; +diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c +index b2f39a86f47341..22b12a482ba912 100644 +--- a/ipc/ipc_sysctl.c ++++ b/ipc/ipc_sysctl.c +@@ -215,7 +215,7 @@ static int ipc_permissions(struct ctl_table_header *head, struct ctl_table *tabl + if (((table->data == &ns->ids[IPC_SEM_IDS].next_id) || + (table->data == &ns->ids[IPC_MSG_IDS].next_id) || + (table->data == &ns->ids[IPC_SHM_IDS].next_id)) && +- checkpoint_restore_ns_capable(ns->user_ns)) ++ checkpoint_restore_ns_capable_noaudit(ns->user_ns)) + mode = 0666; + else + #endif +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 45b2f06de452ce..4af7c96f6985da 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -13136,21 +13136,17 @@ static void __scalar64_min_max_lsh(struct bpf_reg_state *dst_reg, + u64 umin_val, u64 umax_val) + { + /* Special case <<32 because it is a common compiler pattern to sign +- * extend subreg by doing <<32 s>>32. In this case if 32bit bounds are +- * positive we know this shift will also be positive so we can track +- * bounds correctly. Otherwise we lose all sign bit information except +- * what we can pick up from var_off. Perhaps we can generalize this +- * later to shifts of any length. ++ * extend subreg by doing <<32 s>>32. smin/smax assignments are correct ++ * because s32 bounds don't flip sign when shifting to the left by ++ * 32bits. + */ +- if (umin_val == 32 && umax_val == 32 && dst_reg->s32_max_value >= 0) ++ if (umin_val == 32 && umax_val == 32) { + dst_reg->smax_value = (s64)dst_reg->s32_max_value << 32; +- else +- dst_reg->smax_value = S64_MAX; +- +- if (umin_val == 32 && umax_val == 32 && dst_reg->s32_min_value >= 0) + dst_reg->smin_value = (s64)dst_reg->s32_min_value << 32; +- else ++ } else { ++ dst_reg->smax_value = S64_MAX; + dst_reg->smin_value = S64_MIN; ++ } + + /* If we might shift our top bit out, then we know nothing */ + if (dst_reg->umax_value > 1ULL << (63 - umax_val)) { +diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config +index 4722b998a32453..7471b4062b7a09 100644 +--- a/kernel/configs/debug.config ++++ b/kernel/configs/debug.config +@@ -29,7 +29,6 @@ CONFIG_SECTION_MISMATCH_WARN_ONLY=y + # CONFIG_UBSAN_ALIGNMENT is not set + # CONFIG_UBSAN_DIV_ZERO is not set + # CONFIG_UBSAN_TRAP is not set +-# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set + CONFIG_DEBUG_FS=y + CONFIG_DEBUG_FS_ALLOW_ALL=y + CONFIG_DEBUG_IRQFLAGS=y +diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c +index 07f33601cac281..cd44e9c4275330 100644 +--- a/kernel/kallsyms.c ++++ b/kernel/kallsyms.c +@@ -431,8 +431,8 @@ static const char *kallsyms_lookup_buildid(unsigned long addr, + offset, modname, namebuf); + + if (!ret) +- ret = ftrace_mod_address_lookup(addr, symbolsize, +- offset, modname, namebuf); ++ ret = ftrace_mod_address_lookup(addr, symbolsize, offset, ++ modname, modbuildid, namebuf); + + found: + cleanup_symbol_name(namebuf); +diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c +index 830344627e9f20..92a169f0b2b575 100644 +--- a/kernel/kexec_file.c ++++ b/kernel/kexec_file.c +@@ -797,6 +797,60 @@ out: + } + + #ifdef CONFIG_ARCH_SUPPORTS_KEXEC_PURGATORY ++/* ++ * kexec_purgatory_find_symbol - find a symbol in the purgatory ++ * @pi: Purgatory to search in. ++ * @name: Name of the symbol. ++ * ++ * Return: pointer to symbol in read-only symtab on success, NULL on error. ++ */ ++static const Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi, ++ const char *name) ++{ ++ const Elf_Shdr *sechdrs; ++ const Elf_Ehdr *ehdr; ++ const Elf_Sym *syms; ++ const char *strtab; ++ int i, k; ++ ++ if (!pi->ehdr) ++ return NULL; ++ ++ ehdr = pi->ehdr; ++ sechdrs = (void *)ehdr + ehdr->e_shoff; ++ ++ for (i = 0; i < ehdr->e_shnum; i++) { ++ if (sechdrs[i].sh_type != SHT_SYMTAB) ++ continue; ++ ++ if (sechdrs[i].sh_link >= ehdr->e_shnum) ++ /* Invalid strtab section number */ ++ continue; ++ strtab = (void *)ehdr + sechdrs[sechdrs[i].sh_link].sh_offset; ++ syms = (void *)ehdr + sechdrs[i].sh_offset; ++ ++ /* Go through symbols for a match */ ++ for (k = 0; k < sechdrs[i].sh_size/sizeof(Elf_Sym); k++) { ++ if (ELF_ST_BIND(syms[k].st_info) != STB_GLOBAL) ++ continue; ++ ++ if (strcmp(strtab + syms[k].st_name, name) != 0) ++ continue; ++ ++ if (syms[k].st_shndx == SHN_UNDEF || ++ syms[k].st_shndx >= ehdr->e_shnum) { ++ pr_debug("Symbol: %s has bad section index %d.\n", ++ name, syms[k].st_shndx); ++ return NULL; ++ } ++ ++ /* Found the symbol we are looking for */ ++ return &syms[k]; ++ } ++ } ++ ++ return NULL; ++} + /* + * kexec_purgatory_setup_kbuf - prepare buffer to load purgatory. + * @pi: Purgatory to be loaded. +@@ -875,6 +929,10 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi, + unsigned long offset; + size_t sechdrs_size; + Elf_Shdr *sechdrs; ++ const Elf_Sym *entry_sym; ++ u16 entry_shndx = 0; ++ unsigned long entry_off = 0; ++ bool start_fixed = false; + int i; + + /* +@@ -892,6 +950,12 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi, + bss_addr = kbuf->mem + kbuf->bufsz; + kbuf->image->start = pi->ehdr->e_entry; + ++ entry_sym = kexec_purgatory_find_symbol(pi, "purgatory_start"); ++ if (entry_sym) { ++ entry_shndx = entry_sym->st_shndx; ++ entry_off = entry_sym->st_value; ++ } ++ + for (i = 0; i < pi->ehdr->e_shnum; i++) { + unsigned long align; + void *src, *dst; +@@ -909,6 +973,13 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi, + + offset = ALIGN(offset, align); + ++ if (!start_fixed && entry_sym && i == entry_shndx && ++ (sechdrs[i].sh_flags & SHF_EXECINSTR) && ++ entry_off < sechdrs[i].sh_size) { ++ kbuf->image->start = kbuf->mem + offset + entry_off; ++ start_fixed = true; ++ } ++ + /* + * Check if the segment contains the entry point, if so, + * calculate the value of image->start based on it. +@@ -919,13 +990,14 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi, + * is not set to the initial value, and warn the user so they + * have a chance to fix their purgatory's linker script. + */ +- if (sechdrs[i].sh_flags & SHF_EXECINSTR && ++ if (!start_fixed && sechdrs[i].sh_flags & SHF_EXECINSTR && + pi->ehdr->e_entry >= sechdrs[i].sh_addr && + pi->ehdr->e_entry < (sechdrs[i].sh_addr + + sechdrs[i].sh_size) && +- !WARN_ON(kbuf->image->start != pi->ehdr->e_entry)) { ++ kbuf->image->start == pi->ehdr->e_entry) { + kbuf->image->start -= sechdrs[i].sh_addr; + kbuf->image->start += kbuf->mem + offset; ++ start_fixed = true; + } + + src = (void *)pi->ehdr + sechdrs[i].sh_offset; +@@ -1043,61 +1115,6 @@ out_free_kbuf: + return ret; + } + +-/* +- * kexec_purgatory_find_symbol - find a symbol in the purgatory +- * @pi: Purgatory to search in. +- * @name: Name of the symbol. +- * +- * Return: pointer to symbol in read-only symtab on success, NULL on error. +- */ +-static const Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi, +- const char *name) +-{ +- const Elf_Shdr *sechdrs; +- const Elf_Ehdr *ehdr; +- const Elf_Sym *syms; +- const char *strtab; +- int i, k; +- +- if (!pi->ehdr) +- return NULL; +- +- ehdr = pi->ehdr; +- sechdrs = (void *)ehdr + ehdr->e_shoff; +- +- for (i = 0; i < ehdr->e_shnum; i++) { +- if (sechdrs[i].sh_type != SHT_SYMTAB) +- continue; +- +- if (sechdrs[i].sh_link >= ehdr->e_shnum) +- /* Invalid strtab section number */ +- continue; +- strtab = (void *)ehdr + sechdrs[sechdrs[i].sh_link].sh_offset; +- syms = (void *)ehdr + sechdrs[i].sh_offset; +- +- /* Go through symbols for a match */ +- for (k = 0; k < sechdrs[i].sh_size/sizeof(Elf_Sym); k++) { +- if (ELF_ST_BIND(syms[k].st_info) != STB_GLOBAL) +- continue; +- +- if (strcmp(strtab + syms[k].st_name, name) != 0) +- continue; +- +- if (syms[k].st_shndx == SHN_UNDEF || +- syms[k].st_shndx >= ehdr->e_shnum) { +- pr_debug("Symbol: %s has bad section index %d.\n", +- name, syms[k].st_shndx); +- return NULL; +- } +- +- /* Found the symbol we are looking for */ +- return &syms[k]; +- } +- } +- +- return NULL; +-} +- + void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name) + { + struct purgatory_info *pi = &image->purgatory_info; +diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c +index ef73ae7c89094b..84280897911333 100644 +--- a/kernel/module/kallsyms.c ++++ b/kernel/module/kallsyms.c +@@ -336,13 +336,8 @@ const char *module_address_lookup(unsigned long addr, + if (mod) { + if (modname) + *modname = mod->name; +- if (modbuildid) { +-#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) +- *modbuildid = mod->build_id; +-#else +- *modbuildid = NULL; +-#endif +- } ++ if (modbuildid) ++ *modbuildid = module_buildid(mod); + + ret = find_kallsyms_symbol(mod, addr, size, offset); + } +diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c +index 607b2e68fa4c20..81f0a730c54b24 100644 +--- a/kernel/rcu/tree.c ++++ b/kernel/rcu/tree.c +@@ -4379,6 +4379,54 @@ rcu_boot_init_percpu_data(int cpu) + rcu_boot_init_nocb_percpu_data(rdp); + } + ++#ifdef CONFIG_RCU_EXP_KTHREAD ++struct kthread_worker *rcu_exp_gp_kworker; ++struct kthread_worker *rcu_exp_par_gp_kworker; ++ ++static void __init rcu_start_exp_gp_kworkers(void) ++{ ++ const char *par_gp_kworker_name = "rcu_exp_par_gp_kthread_worker"; ++ const char *gp_kworker_name = "rcu_exp_gp_kthread_worker"; ++ struct sched_param param = { .sched_priority = kthread_prio }; ++ ++ rcu_exp_gp_kworker = kthread_create_worker(0, gp_kworker_name); ++ if (IS_ERR_OR_NULL(rcu_exp_gp_kworker)) { ++ pr_err("Failed to create %s!\n", gp_kworker_name); ++ rcu_exp_gp_kworker = NULL; ++ return; ++ } ++ ++ rcu_exp_par_gp_kworker = kthread_create_worker(0, par_gp_kworker_name); ++ if (IS_ERR_OR_NULL(rcu_exp_par_gp_kworker)) { ++ pr_err("Failed to create %s!\n", par_gp_kworker_name); ++ rcu_exp_par_gp_kworker = NULL; ++ kthread_destroy_worker(rcu_exp_gp_kworker); ++ rcu_exp_gp_kworker = NULL; ++ return; ++ } ++ ++ sched_setscheduler_nocheck(rcu_exp_gp_kworker->task, SCHED_FIFO, ¶m); ++ sched_setscheduler_nocheck(rcu_exp_par_gp_kworker->task, SCHED_FIFO, ++ ¶m); ++} ++ ++static inline void rcu_alloc_par_gp_wq(void) ++{ ++} ++#else /* !CONFIG_RCU_EXP_KTHREAD */ ++struct workqueue_struct *rcu_par_gp_wq; ++ ++static void __init rcu_start_exp_gp_kworkers(void) ++{ ++} ++ ++static inline void rcu_alloc_par_gp_wq(void) ++{ ++ rcu_par_gp_wq = alloc_workqueue("rcu_par_gp", WQ_MEM_RECLAIM, 0); ++ WARN_ON(!rcu_par_gp_wq); ++} ++#endif /* CONFIG_RCU_EXP_KTHREAD */ ++ + /* + * Invoked early in the CPU-online process, when pretty much all services + * are available. The incoming CPU is not present. +@@ -4686,54 +4734,6 @@ static int rcu_pm_notify(struct notifier_block *self, + return NOTIFY_OK; + } + +-#ifdef CONFIG_RCU_EXP_KTHREAD +-struct kthread_worker *rcu_exp_gp_kworker; +-struct kthread_worker *rcu_exp_par_gp_kworker; +- +-static void __init rcu_start_exp_gp_kworkers(void) +-{ +- const char *par_gp_kworker_name = "rcu_exp_par_gp_kthread_worker"; +- const char *gp_kworker_name = "rcu_exp_gp_kthread_worker"; +- struct sched_param param = { .sched_priority = kthread_prio }; +- +- rcu_exp_gp_kworker = kthread_create_worker(0, gp_kworker_name); +- if (IS_ERR_OR_NULL(rcu_exp_gp_kworker)) { +- pr_err("Failed to create %s!\n", gp_kworker_name); +- rcu_exp_gp_kworker = NULL; +- return; +- } +- +- rcu_exp_par_gp_kworker = kthread_create_worker(0, par_gp_kworker_name); +- if (IS_ERR_OR_NULL(rcu_exp_par_gp_kworker)) { +- pr_err("Failed to create %s!\n", par_gp_kworker_name); +- rcu_exp_par_gp_kworker = NULL; +- kthread_destroy_worker(rcu_exp_gp_kworker); +- rcu_exp_gp_kworker = NULL; +- return; +- } +- +- sched_setscheduler_nocheck(rcu_exp_gp_kworker->task, SCHED_FIFO, ¶m); +- sched_setscheduler_nocheck(rcu_exp_par_gp_kworker->task, SCHED_FIFO, +- ¶m); +-} +- +-static inline void rcu_alloc_par_gp_wq(void) +-{ +-} +-#else /* !CONFIG_RCU_EXP_KTHREAD */ +-struct workqueue_struct *rcu_par_gp_wq; +- +-static void __init rcu_start_exp_gp_kworkers(void) +-{ +-} +- +-static inline void rcu_alloc_par_gp_wq(void) +-{ +- rcu_par_gp_wq = alloc_workqueue("rcu_par_gp", WQ_MEM_RECLAIM, 0); +- WARN_ON(!rcu_par_gp_wq); +-} +-#endif /* CONFIG_RCU_EXP_KTHREAD */ +- + /* + * Spawn the kthreads that handle RCU's grace periods. + */ +@@ -4874,7 +4874,7 @@ static void __init rcu_init_one(void) + init_waitqueue_head(&rnp->exp_wq[2]); + init_waitqueue_head(&rnp->exp_wq[3]); + spin_lock_init(&rnp->exp_lock); +- mutex_init(&rnp->boost_kthread_mutex); ++ mutex_init(&rnp->kthread_mutex); + raw_spin_lock_init(&rnp->exp_poll_lock); + rnp->exp_seq_poll_rq = RCU_GET_STATE_COMPLETED; + INIT_WORK(&rnp->exp_poll_wq, sync_rcu_do_polled_gp); +diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h +index 71403d22a84655..b79599b2059cc8 100644 +--- a/kernel/rcu/tree.h ++++ b/kernel/rcu/tree.h +@@ -113,7 +113,7 @@ struct rcu_node { + /* side effect, not as a lock. */ + unsigned long boost_time; + /* When to start boosting (jiffies). */ +- struct mutex boost_kthread_mutex; ++ struct mutex kthread_mutex; + /* Exclusion for thread spawning and affinity */ + /* manipulation. */ + struct task_struct *boost_kthread_task; +@@ -203,7 +203,7 @@ struct rcu_data { + /* during and after the last grace */ + /* period it is aware of. */ + struct irq_work defer_qs_iw; /* Obtain later scheduler attention. */ +- int defer_qs_iw_pending; /* Scheduler attention pending? */ ++ int defer_qs_pending; /* irqwork or softirq pending? */ + struct work_struct strict_work; /* Schedule readers for strict GPs. */ + + /* 2) batch handling */ +diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h +index 8707f155afb6df..8cf1adcd259ba9 100644 +--- a/kernel/rcu/tree_plugin.h ++++ b/kernel/rcu/tree_plugin.h +@@ -475,8 +475,8 @@ rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags) + union rcu_special special; + + rdp = this_cpu_ptr(&rcu_data); +- if (rdp->defer_qs_iw_pending == DEFER_QS_PENDING) +- rdp->defer_qs_iw_pending = DEFER_QS_IDLE; ++ if (rdp->defer_qs_pending == DEFER_QS_PENDING) ++ rdp->defer_qs_pending = DEFER_QS_IDLE; + + /* + * If RCU core is waiting for this CPU to exit its critical section, +@@ -615,11 +615,10 @@ notrace void rcu_preempt_deferred_qs(struct task_struct *t) + */ + static void rcu_preempt_deferred_qs_handler(struct irq_work *iwp) + { +- unsigned long flags; + struct rcu_data *rdp; + ++ lockdep_assert_irqs_disabled(); + rdp = container_of(iwp, struct rcu_data, defer_qs_iw); +- local_irq_save(flags); + + /* + * If the IRQ work handler happens to run in the middle of RCU read-side +@@ -635,9 +634,76 @@ static void rcu_preempt_deferred_qs_handler(struct irq_work *iwp) + * 5. Deferred QS reporting does not happen. + */ + if (rcu_preempt_depth() > 0) +- WRITE_ONCE(rdp->defer_qs_iw_pending, DEFER_QS_IDLE); ++ WRITE_ONCE(rdp->defer_qs_pending, DEFER_QS_IDLE); ++} + +- local_irq_restore(flags); ++/* ++ * Check if expedited grace period processing during unlock is needed. ++ * ++ * This function determines whether expedited handling is required based on: ++ * 1. Task blocking an expedited grace period (based on a heuristic, could be ++ * false-positive, see below.) ++ * 2. CPU participating in an expedited grace period ++ * 3. Strict grace period mode requiring expedited handling ++ * 4. RCU priority deboosting needs when interrupts were disabled ++ * ++ * @t: The task being checked ++ * @rdp: The per-CPU RCU data ++ * @rnp: The RCU node for this CPU ++ * @irqs_were_disabled: Whether interrupts were disabled before rcu_read_unlock() ++ * ++ * Returns true if expedited processing of the rcu_read_unlock() is needed. ++ */ ++static bool rcu_unlock_needs_exp_handling(struct task_struct *t, ++ struct rcu_data *rdp, ++ struct rcu_node *rnp, ++ bool irqs_were_disabled) ++{ ++ /* ++ * Check if this task is blocking an expedited grace period. If the ++ * task was preempted within an RCU read-side critical section and is ++ * on the expedited grace period blockers list (exp_tasks), we need ++ * expedited handling to unblock the expedited GP. This is not an exact ++ * check because 't' might not be on the exp_tasks list at all - its ++ * just a fast heuristic that can be false-positive sometimes. ++ */ ++ if (t->rcu_blocked_node && READ_ONCE(t->rcu_blocked_node->exp_tasks)) ++ return true; ++ ++ /* ++ * Check if this CPU is participating in an expedited grace period. ++ * The expmask bitmap tracks which CPUs need to check in for the ++ * current expedited GP. If our CPU's bit is set, we need expedited ++ * handling to help complete the expedited GP. ++ */ ++ if (rdp->grpmask & READ_ONCE(rnp->expmask)) ++ return true; ++ ++ /* ++ * In CONFIG_RCU_STRICT_GRACE_PERIOD=y kernels, all grace periods ++ * are treated as short for testing purposes even if that means ++ * disturbing the system more. Check if either: ++ * - This CPU has not yet reported a quiescent state, or ++ * - This task was preempted within an RCU critical section ++ * In either case, require expedited handling for strict GP mode. ++ */ ++ if (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD) && ++ ((rdp->grpmask & READ_ONCE(rnp->qsmask)) || t->rcu_blocked_node)) ++ return true; ++ ++ /* ++ * RCU priority boosting case: If a task is subject to RCU priority ++ * boosting and exits an RCU read-side critical section with interrupts ++ * disabled, we need expedited handling to ensure timely deboosting. ++ * Without this, a low-priority task could incorrectly run at high ++ * real-time priority for an extended period degrading real-time ++ * responsiveness. This applies to all CONFIG_RCU_BOOST=y kernels, ++ * not just to PREEMPT_RT. ++ */ ++ if (IS_ENABLED(CONFIG_RCU_BOOST) && irqs_were_disabled && t->rcu_blocked_node) ++ return true; ++ ++ return false; + } + + /* +@@ -659,22 +725,21 @@ static void rcu_read_unlock_special(struct task_struct *t) + local_irq_save(flags); + irqs_were_disabled = irqs_disabled_flags(flags); + if (preempt_bh_were_disabled || irqs_were_disabled) { +- bool expboost; // Expedited GP in flight or possible boosting. ++ bool needs_exp; // Expedited handling needed. + struct rcu_data *rdp = this_cpu_ptr(&rcu_data); + struct rcu_node *rnp = rdp->mynode; + +- expboost = (t->rcu_blocked_node && READ_ONCE(t->rcu_blocked_node->exp_tasks)) || +- (rdp->grpmask & READ_ONCE(rnp->expmask)) || +- (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD) && +- ((rdp->grpmask & READ_ONCE(rnp->qsmask)) || t->rcu_blocked_node)) || +- (IS_ENABLED(CONFIG_RCU_BOOST) && irqs_were_disabled && +- t->rcu_blocked_node); ++ needs_exp = rcu_unlock_needs_exp_handling(t, rdp, rnp, irqs_were_disabled); ++ + // Need to defer quiescent state until everything is enabled. +- if (use_softirq && (in_hardirq() || (expboost && !irqs_were_disabled))) { ++ if (use_softirq && (in_hardirq() || (needs_exp && !irqs_were_disabled))) { + // Using softirq, safe to awaken, and either the + // wakeup is free or there is either an expedited + // GP in flight or a potential need to deboost. +- raise_softirq_irqoff(RCU_SOFTIRQ); ++ if (rdp->defer_qs_pending != DEFER_QS_PENDING) { ++ rdp->defer_qs_pending = DEFER_QS_PENDING; ++ raise_softirq_irqoff(RCU_SOFTIRQ); ++ } + } else { + // Enabling BH or preempt does reschedule, so... + // Also if no expediting and no possible deboosting, +@@ -683,11 +748,11 @@ static void rcu_read_unlock_special(struct task_struct *t) + set_tsk_need_resched(current); + set_preempt_need_resched(); + if (IS_ENABLED(CONFIG_IRQ_WORK) && irqs_were_disabled && +- expboost && rdp->defer_qs_iw_pending != DEFER_QS_PENDING && ++ needs_exp && rdp->defer_qs_pending != DEFER_QS_PENDING && + cpu_online(rdp->cpu)) { + // Get scheduler to re-evaluate and call hooks. + // If !IRQ_WORK, FQS scan will eventually IPI. +- rdp->defer_qs_iw_pending = DEFER_QS_PENDING; ++ rdp->defer_qs_pending = DEFER_QS_PENDING; + irq_work_queue_on(&rdp->defer_qs_iw, rdp->cpu); + } + } +@@ -1229,7 +1294,7 @@ static void rcu_spawn_one_boost_kthread(struct rcu_node *rnp) + struct sched_param sp; + struct task_struct *t; + +- mutex_lock(&rnp->boost_kthread_mutex); ++ mutex_lock(&rnp->kthread_mutex); + if (rnp->boost_kthread_task || !rcu_scheduler_fully_active) + goto out; + +@@ -1246,7 +1311,7 @@ static void rcu_spawn_one_boost_kthread(struct rcu_node *rnp) + wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */ + + out: +- mutex_unlock(&rnp->boost_kthread_mutex); ++ mutex_unlock(&rnp->kthread_mutex); + } + + /* +@@ -1258,7 +1323,7 @@ static void rcu_spawn_one_boost_kthread(struct rcu_node *rnp) + * no outgoing CPU. If there are no CPUs left in the affinity set, + * this function allows the kthread to execute on any CPU. + * +- * Any future concurrent calls are serialized via ->boost_kthread_mutex. ++ * Any future concurrent calls are serialized via ->kthread_mutex. + */ + static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) + { +@@ -1271,7 +1336,7 @@ static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) + return; + if (!zalloc_cpumask_var(&cm, GFP_KERNEL)) + return; +- mutex_lock(&rnp->boost_kthread_mutex); ++ mutex_lock(&rnp->kthread_mutex); + mask = rcu_rnp_online_cpus(rnp); + for_each_leaf_node_possible_cpu(rnp, cpu) + if ((mask & leaf_node_cpu_bit(rnp, cpu)) && +@@ -1284,7 +1349,7 @@ static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) + cpumask_clear_cpu(outgoingcpu, cm); + } + set_cpus_allowed_ptr(t, cm); +- mutex_unlock(&rnp->boost_kthread_mutex); ++ mutex_unlock(&rnp->kthread_mutex); + free_cpumask_var(cm); + } + +diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c +index 2d0acdd32108ab..0b420a65b31dc9 100644 +--- a/kernel/sched/rt.c ++++ b/kernel/sched/rt.c +@@ -2219,6 +2219,7 @@ static void push_rt_tasks(struct rq *rq) + */ + static int rto_next_cpu(struct root_domain *rd) + { ++ int this_cpu = smp_processor_id(); + int next; + int cpu; + +@@ -2242,6 +2243,10 @@ static int rto_next_cpu(struct root_domain *rd) + + rd->rto_cpu = cpu; + ++ /* Do not send IPI to self */ ++ if (cpu == this_cpu) ++ continue; ++ + if (cpu < nr_cpu_ids) + return cpu; + +diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c +index 0320f49bd1f4a0..03f488f93cddf6 100644 +--- a/kernel/time/hrtimer.c ++++ b/kernel/time/hrtimer.c +@@ -1715,7 +1715,7 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base, + + lockdep_assert_held(&cpu_base->lock); + +- debug_deactivate(timer); ++ debug_hrtimer_deactivate(timer); + base->running = timer; + + /* +diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c +index 8f2d44e741510f..94f7ed57d43e51 100644 +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -7046,7 +7046,8 @@ ftrace_func_address_lookup(struct ftrace_mod_map *mod_map, + + const char * + ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, +- unsigned long *off, char **modname, char *sym) ++ unsigned long *off, char **modname, ++ const unsigned char **modbuildid, char *sym) + { + struct ftrace_mod_map *mod_map; + const char *ret = NULL; +@@ -7058,6 +7059,8 @@ ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, + if (ret) { + if (modname) + *modname = mod_map->mod->name; ++ if (modbuildid) ++ *modbuildid = module_buildid(mod_map->mod); + break; + } + } +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index a111be83c36939..29720531ac8188 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -8831,7 +8831,7 @@ tracing_init_tracefs_percpu(struct trace_array *tr, long cpu) + trace_create_cpu_file("stats", TRACE_MODE_READ, d_cpu, + tr, cpu, &tracing_stats_fops); + +- trace_create_cpu_file("buffer_size_kb", TRACE_MODE_READ, d_cpu, ++ trace_create_cpu_file("buffer_size_kb", TRACE_MODE_WRITE, d_cpu, + tr, cpu, &tracing_entries_fops); + + #ifdef CONFIG_TRACER_SNAPSHOT +diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c +index 382e07cd49f9f6..106ae22f0464d3 100644 +--- a/kernel/trace/trace_events.c ++++ b/kernel/trace/trace_events.c +@@ -1169,6 +1169,9 @@ static void remove_event_file_dir(struct trace_event_file *file) + free_event_filter(file->filter); + file->flags |= EVENT_FILE_FL_FREED; + event_file_put(file); ++ ++ /* Wake up hist poll waiters to notice the EVENT_FILE_FL_FREED flag. */ ++ hist_poll_wakeup(); + } + + /* +@@ -3575,11 +3578,6 @@ void trace_put_event_file(struct trace_event_file *file) + EXPORT_SYMBOL_GPL(trace_put_event_file); + + #ifdef CONFIG_DYNAMIC_FTRACE +- +-/* Avoid typos */ +-#define ENABLE_EVENT_STR "enable_event" +-#define DISABLE_EVENT_STR "disable_event" +- + struct event_probe_data { + struct trace_event_file *file; + unsigned long count; +diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c +index 99d1e8b57f85d3..19b3d388fbc69e 100644 +--- a/kernel/trace/trace_events_hist.c ++++ b/kernel/trace/trace_events_hist.c +@@ -5760,7 +5760,7 @@ static __poll_t event_hist_poll(struct file *file, struct poll_table_struct *wai + + guard(mutex)(&event_mutex); + +- event_file = event_file_data(file); ++ event_file = event_file_file(file); + if (!event_file) + return EPOLLERR; + +@@ -5798,7 +5798,7 @@ static int event_hist_open(struct inode *inode, struct file *file) + + guard(mutex)(&event_mutex); + +- event_file = event_file_data(file); ++ event_file = event_file_file(file); + if (!event_file) { + ret = -ENODEV; + goto err; +@@ -6889,7 +6889,7 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops, + + remove_hist_vars(hist_data); + +- kfree(trigger_data); ++ trigger_data_free(trigger_data); + + destroy_hist_data(hist_data); + goto out; +diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c +index 3bd6071441ade9..bc437b6ce8969e 100644 +--- a/kernel/trace/trace_hwlat.c ++++ b/kernel/trace/trace_hwlat.c +@@ -102,9 +102,9 @@ struct hwlat_sample { + /* keep the global state somewhere. */ + static struct hwlat_data { + +- struct mutex lock; /* protect changes */ ++ struct mutex lock; /* protect changes */ + +- u64 count; /* total since reset */ ++ atomic64_t count; /* total since reset */ + + u64 sample_window; /* total sampling window (on+off) */ + u64 sample_width; /* active sampling portion of window */ +@@ -195,8 +195,7 @@ void trace_hwlat_callback(bool enter) + * get_sample - sample the CPU TSC and look for likely hardware latencies + * + * Used to repeatedly capture the CPU TSC (or similar), looking for potential +- * hardware-induced latency. Called with interrupts disabled and with +- * hwlat_data.lock held. ++ * hardware-induced latency. Called with interrupts disabled. + */ + static int get_sample(void) + { +@@ -206,6 +205,7 @@ static int get_sample(void) + time_type start, t1, t2, last_t2; + s64 diff, outer_diff, total, last_total = 0; + u64 sample = 0; ++ u64 sample_width = READ_ONCE(hwlat_data.sample_width); + u64 thresh = tracing_thresh; + u64 outer_sample = 0; + int ret = -1; +@@ -269,7 +269,7 @@ static int get_sample(void) + if (diff > sample) + sample = diff; /* only want highest value */ + +- } while (total <= hwlat_data.sample_width); ++ } while (total <= sample_width); + + barrier(); /* finish the above in the view for NMIs */ + trace_hwlat_callback_enabled = false; +@@ -287,8 +287,7 @@ static int get_sample(void) + if (kdata->nmi_total_ts) + do_div(kdata->nmi_total_ts, NSEC_PER_USEC); + +- hwlat_data.count++; +- s.seqnum = hwlat_data.count; ++ s.seqnum = atomic64_inc_return(&hwlat_data.count); + s.duration = sample; + s.outer_duration = outer_sample; + s.nmi_total_ts = kdata->nmi_total_ts; +@@ -837,7 +836,7 @@ static int hwlat_tracer_init(struct trace_array *tr) + + hwlat_trace = tr; + +- hwlat_data.count = 0; ++ atomic64_set(&hwlat_data.count, 0); + tr->max_latency = 0; + save_tracing_thresh = tracing_thresh; + +diff --git a/kernel/ucount.c b/kernel/ucount.c +index a7fd89693bd2a1..44ede7a6b805a6 100644 +--- a/kernel/ucount.c ++++ b/kernel/ucount.c +@@ -45,7 +45,7 @@ static int set_permissions(struct ctl_table_header *head, + int mode; + + /* Allow users with CAP_SYS_RESOURCE unrestrained access */ +- if (ns_capable(user_ns, CAP_SYS_RESOURCE)) ++ if (ns_capable_noaudit(user_ns, CAP_SYS_RESOURCE)) + mode = (table->mode & S_IRWXU) >> 6; + else + /* Allow all others at most read-only access */ +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index 59b6efb2a11c36..641914d86154d7 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -101,6 +101,8 @@ enum { + MAYDAY_INTERVAL = HZ / 10, /* and then every 100ms */ + CREATE_COOLDOWN = HZ, /* time to breath after fail */ + ++ RESCUER_BATCH = 16, /* process items per turn */ ++ + /* + * Rescue workers are used only on emergencies and shared by + * all cpus. Give MIN_NICE. +@@ -254,6 +256,7 @@ struct pool_workqueue { + struct list_head inactive_works; /* L: inactive works */ + struct list_head pwqs_node; /* WR: node on wq->pwqs */ + struct list_head mayday_node; /* MD: node on wq->maydays */ ++ struct work_struct mayday_cursor; /* L: cursor on pool->worklist */ + + u64 stats[PWQ_NR_STATS]; + +@@ -1015,6 +1018,12 @@ static struct worker *find_worker_executing_work(struct worker_pool *pool, + return NULL; + } + ++static void mayday_cursor_func(struct work_struct *work) ++{ ++ /* should not be processed, only for marking position */ ++ BUG(); ++} ++ + /** + * move_linked_works - move linked works to a list + * @work: start of series of works to be scheduled +@@ -1077,6 +1086,16 @@ static bool assign_work(struct work_struct *work, struct worker *worker, + + lockdep_assert_held(&pool->lock); + ++ /* The cursor work should not be processed */ ++ if (unlikely(work->func == mayday_cursor_func)) { ++ /* only worker_thread() can possibly take this branch */ ++ WARN_ON_ONCE(worker->rescue_wq); ++ if (nextp) ++ *nextp = list_next_entry(work, entry); ++ list_del_init(&work->entry); ++ return false; ++ } ++ + /* + * A single work shouldn't be executed concurrently by multiple workers. + * __queue_work() ensures that @work doesn't jump to a different pool +@@ -2808,6 +2827,35 @@ sleep: + goto woke_up; + } + ++static bool assign_rescuer_work(struct pool_workqueue *pwq, struct worker *rescuer) ++{ ++ struct worker_pool *pool = pwq->pool; ++ struct work_struct *cursor = &pwq->mayday_cursor; ++ struct work_struct *work, *n; ++ ++ /* need rescue? */ ++ if (!pwq->nr_active || !need_to_create_worker(pool)) ++ return false; ++ ++ /* search from the start or cursor if available */ ++ if (list_empty(&cursor->entry)) ++ work = list_first_entry(&pool->worklist, struct work_struct, entry); ++ else ++ work = list_next_entry(cursor, entry); ++ ++ /* find the next work item to rescue */ ++ list_for_each_entry_safe_from(work, n, &pool->worklist, entry) { ++ if (get_work_pwq(work) == pwq && assign_work(work, rescuer, &n)) { ++ pwq->stats[PWQ_STAT_RESCUED]++; ++ /* put the cursor for next search */ ++ list_move_tail(&cursor->entry, &n->entry); ++ return true; ++ } ++ } ++ ++ return false; ++} ++ + /** + * rescuer_thread - the rescuer thread function + * @__rescuer: self +@@ -2862,7 +2910,7 @@ repeat: + struct pool_workqueue *pwq = list_first_entry(&wq->maydays, + struct pool_workqueue, mayday_node); + struct worker_pool *pool = pwq->pool; +- struct work_struct *work, *n; ++ unsigned int count = 0; + + __set_current_state(TASK_RUNNING); + list_del_init(&pwq->mayday_node); +@@ -2873,30 +2921,18 @@ repeat: + + raw_spin_lock_irq(&pool->lock); + +- /* +- * Slurp in all works issued via this workqueue and +- * process'em. +- */ + WARN_ON_ONCE(!list_empty(&rescuer->scheduled)); +- list_for_each_entry_safe(work, n, &pool->worklist, entry) { +- if (get_work_pwq(work) == pwq && +- assign_work(work, rescuer, &n)) +- pwq->stats[PWQ_STAT_RESCUED]++; +- } + +- if (!list_empty(&rescuer->scheduled)) { ++ while (assign_rescuer_work(pwq, rescuer)) { + process_scheduled_works(rescuer); + + /* +- * The above execution of rescued work items could +- * have created more to rescue through +- * pwq_activate_first_inactive() or chained +- * queueing. Let's put @pwq back on mayday list so +- * that such back-to-back work items, which may be +- * being used to relieve memory pressure, don't +- * incur MAYDAY_INTERVAL delay inbetween. ++ * If the per-turn work item limit is reached and other ++ * PWQs are in mayday, requeue mayday for this PWQ and ++ * let the rescuer handle the other PWQs first. + */ +- if (pwq->nr_active && need_to_create_worker(pool)) { ++ if (++count > RESCUER_BATCH && !list_empty(&pwq->wq->maydays) && ++ pwq->nr_active && need_to_create_worker(pool)) { + raw_spin_lock(&wq_mayday_lock); + /* + * Queue iff we aren't racing destruction +@@ -2907,9 +2943,14 @@ repeat: + list_add_tail(&pwq->mayday_node, &wq->maydays); + } + raw_spin_unlock(&wq_mayday_lock); ++ break; + } + } + ++ /* The cursor can not be left behind without the rescuer watching it. */ ++ if (!list_empty(&pwq->mayday_cursor.entry) && list_empty(&pwq->mayday_node)) ++ list_del_init(&pwq->mayday_cursor.entry); ++ + /* + * Put the reference grabbed by send_mayday(). @pool won't + * go away while we're still attached to it. +@@ -4222,6 +4263,19 @@ static void init_pwq(struct pool_workqueue *pwq, struct workqueue_struct *wq, + INIT_LIST_HEAD(&pwq->pwqs_node); + INIT_LIST_HEAD(&pwq->mayday_node); + kthread_init_work(&pwq->release_work, pwq_release_workfn); ++ ++ /* ++ * Set the dummy cursor work with valid function and get_work_pwq(). ++ * ++ * The cursor work should only be in the pwq->pool->worklist, and ++ * should not be treated as a processable work item. ++ * ++ * WORK_STRUCT_PENDING and WORK_STRUCT_INACTIVE just make it less ++ * surprise for kernel debugging tools and reviewers. ++ */ ++ INIT_WORK(&pwq->mayday_cursor, mayday_cursor_func); ++ atomic_long_set(&pwq->mayday_cursor.data, (unsigned long)pwq | ++ WORK_STRUCT_PENDING | WORK_STRUCT_PWQ | WORK_STRUCT_INACTIVE); + } + + /* sync @pwq with the current state of its associated wq and link it */ +diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug +index 1aae81c57b2c9a..e56f9e1b18fdf0 100644 +--- a/lib/Kconfig.debug ++++ b/lib/Kconfig.debug +@@ -1619,33 +1619,6 @@ config STACKTRACE + It is also used by various kernel debugging features that require + stack trace generation. + +-config WARN_ALL_UNSEEDED_RANDOM +- bool "Warn for all uses of unseeded randomness" +- default n +- help +- Some parts of the kernel contain bugs relating to their use of +- cryptographically secure random numbers before it's actually possible +- to generate those numbers securely. This setting ensures that these +- flaws don't go unnoticed, by enabling a message, should this ever +- occur. This will allow people with obscure setups to know when things +- are going wrong, so that they might contact developers about fixing +- it. +- +- Unfortunately, on some models of some architectures getting +- a fully seeded CRNG is extremely difficult, and so this can +- result in dmesg getting spammed for a surprisingly long +- time. This is really bad from a security perspective, and +- so architecture maintainers really need to do what they can +- to get the CRNG seeded sooner after the system is booted. +- However, since users cannot do anything actionable to +- address this, by default this option is disabled. +- +- Say Y here if you want to receive warnings for all uses of +- unseeded randomness. This will be of use primarily for +- those developers interested in improving the security of +- Linux kernels running on their architecture (or +- subarchitecture). +- + config DEBUG_KOBJECT + bool "kobject debugging" + depends on DEBUG_KERNEL +diff --git a/mm/highmem.c b/mm/highmem.c +index e19269093a93cf..87c2fe3d2f3d11 100644 +--- a/mm/highmem.c ++++ b/mm/highmem.c +@@ -169,12 +169,13 @@ struct page *__kmap_to_page(void *vaddr) + for (i = 0; i < kctrl->idx; i++) { + unsigned long base_addr; + int idx; ++ pte_t pteval = kctrl->pteval[i]; + + idx = arch_kmap_local_map_idx(i, pte_pfn(pteval)); + base_addr = __fix_to_virt(FIX_KMAP_BEGIN + idx); + + if (base_addr == base) +- return pte_page(kctrl->pteval[i]); ++ return pte_page(pteval); + } + } + +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 6c042f7796e48b..b617fb364b15d1 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -4057,6 +4057,20 @@ restart: + compact_result == COMPACT_DEFERRED) + goto nopage; + ++ /* ++ * THP page faults may attempt local node only first, ++ * but are then allowed to only compact, not reclaim, ++ * see alloc_pages_mpol(). ++ * ++ * Compaction can fail for other reasons than those ++ * checked above and we don't want such THP allocations ++ * to put reclaim pressure on a single node in a ++ * situation where other nodes might have plenty of ++ * available memory. ++ */ ++ if (gfp_mask & __GFP_THISNODE) ++ goto nopage; ++ + /* + * Looks like reclaim/compaction is worth trying, but + * sync compaction could be very expensive, so keep +diff --git a/net/atm/signaling.c b/net/atm/signaling.c +index e70ae2c113f954..358fbe5e4d1d06 100644 +--- a/net/atm/signaling.c ++++ b/net/atm/signaling.c +@@ -22,6 +22,36 @@ + + struct atm_vcc *sigd = NULL; + ++/* ++ * find_get_vcc - validate and get a reference to a vcc pointer ++ * @vcc: the vcc pointer to validate ++ * ++ * This function validates that @vcc points to a registered VCC in vcc_hash. ++ * If found, it increments the socket reference count and returns the vcc. ++ * The caller must call sock_put(sk_atm(vcc)) when done. ++ * ++ * Returns the vcc pointer if valid, NULL otherwise. ++ */ ++static struct atm_vcc *find_get_vcc(struct atm_vcc *vcc) ++{ ++ int i; ++ ++ read_lock(&vcc_sklist_lock); ++ for (i = 0; i < VCC_HTABLE_SIZE; i++) { ++ struct sock *s; ++ ++ sk_for_each(s, &vcc_hash[i]) { ++ if (atm_sk(s) == vcc) { ++ sock_hold(s); ++ read_unlock(&vcc_sklist_lock); ++ return vcc; ++ } ++ } ++ } ++ read_unlock(&vcc_sklist_lock); ++ return NULL; ++} ++ + static void sigd_put_skb(struct sk_buff *skb) + { + if (!sigd) { +@@ -69,7 +99,14 @@ static int sigd_send(struct atm_vcc *vcc, struct sk_buff *skb) + + msg = (struct atmsvc_msg *) skb->data; + WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc)); +- vcc = *(struct atm_vcc **) &msg->vcc; ++ ++ vcc = find_get_vcc(*(struct atm_vcc **)&msg->vcc); ++ if (!vcc) { ++ pr_debug("invalid vcc pointer in msg\n"); ++ dev_kfree_skb(skb); ++ return -EINVAL; ++ } ++ + pr_debug("%d (0x%lx)\n", (int)msg->type, (unsigned long)vcc); + sk = sk_atm(vcc); + +@@ -100,7 +137,16 @@ static int sigd_send(struct atm_vcc *vcc, struct sk_buff *skb) + clear_bit(ATM_VF_WAITING, &vcc->flags); + break; + case as_indicate: +- vcc = *(struct atm_vcc **)&msg->listen_vcc; ++ /* Release the reference from msg->vcc, we'll use msg->listen_vcc instead */ ++ sock_put(sk); ++ ++ vcc = find_get_vcc(*(struct atm_vcc **)&msg->listen_vcc); ++ if (!vcc) { ++ pr_debug("invalid listen_vcc pointer in msg\n"); ++ dev_kfree_skb(skb); ++ return -EINVAL; ++ } ++ + sk = sk_atm(vcc); + pr_debug("as_indicate!!!\n"); + lock_sock(sk); +@@ -115,6 +161,8 @@ static int sigd_send(struct atm_vcc *vcc, struct sk_buff *skb) + sk->sk_state_change(sk); + as_indicate_complete: + release_sock(sk); ++ /* Paired with find_get_vcc(msg->listen_vcc) above */ ++ sock_put(sk); + return 0; + case as_close: + set_bit(ATM_VF_RELEASED, &vcc->flags); +@@ -131,11 +179,15 @@ as_indicate_complete: + break; + default: + pr_alert("bad message type %d\n", (int)msg->type); ++ /* Paired with find_get_vcc(msg->vcc) above */ ++ sock_put(sk); + return -EINVAL; + } + sk->sk_state_change(sk); + out: + dev_kfree_skb(skb); ++ /* Paired with find_get_vcc(msg->vcc) above */ ++ sock_put(sk); + return 0; + } + +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index ff9d2520ba749c..30feeaf7e64248 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -951,6 +951,7 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t + switch (type) { + case ACL_LINK: + conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK; ++ conn->link_policy = hdev->link_policy; + conn->mtu = hdev->acl_mtu; + break; + case LE_LINK: +@@ -2517,8 +2518,8 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active) + + timer: + if (hdev->idle_timeout > 0) +- queue_delayed_work(hdev->workqueue, &conn->idle_work, +- msecs_to_jiffies(hdev->idle_timeout)); ++ mod_delayed_work(hdev->workqueue, &conn->idle_work, ++ msecs_to_jiffies(hdev->idle_timeout)); + } + + /* Drop all connection on the device */ +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index f0eb52d5c05811..6a14f760710774 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -6860,8 +6860,6 @@ static int hci_acl_create_conn_sync(struct hci_dev *hdev, void *data) + + conn->attempt++; + +- conn->link_policy = hdev->link_policy; +- + memset(&cp, 0, sizeof(cp)); + bacpy(&cp.bdaddr, &conn->dst); + cp.pscan_rep_mode = 0x02; +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index ad46112cb596bf..0cbd6c29212385 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -4863,6 +4863,13 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn, + goto response_unlock; + } + ++ /* Check if Key Size is sufficient for the security level */ ++ if (!l2cap_check_enc_key_size(conn->hcon, pchan)) { ++ result = L2CAP_CR_LE_BAD_KEY_SIZE; ++ chan = NULL; ++ goto response_unlock; ++ } ++ + /* Check for valid dynamic CID range */ + if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) { + result = L2CAP_CR_LE_INVALID_SCID; +@@ -5059,7 +5066,16 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, + + if (!smp_sufficient_security(conn->hcon, pchan->sec_level, + SMP_ALLOW_STK)) { +- result = L2CAP_CR_LE_AUTHENTICATION; ++ result = pchan->sec_level == BT_SECURITY_MEDIUM ? ++ L2CAP_CR_LE_ENCRYPTION : L2CAP_CR_LE_AUTHENTICATION; ++ goto unlock; ++ } ++ ++ /* Check if the listening channel has set an output MTU then the ++ * requested MTU shall be less than or equal to that value. ++ */ ++ if (pchan->omtu && mtu < pchan->omtu) { ++ result = L2CAP_CR_LE_UNACCEPT_PARAMS; + goto unlock; + } + +@@ -5260,14 +5276,14 @@ static inline int l2cap_ecred_reconf_req(struct l2cap_conn *conn, + struct l2cap_ecred_reconf_req *req = (void *) data; + struct l2cap_ecred_reconf_rsp rsp; + u16 mtu, mps, result; +- struct l2cap_chan *chan; ++ struct l2cap_chan *chan[L2CAP_ECRED_MAX_CID] = {}; + int i, num_scid; + + if (!enable_ecred) + return -EINVAL; + +- if (cmd_len < sizeof(*req) || cmd_len - sizeof(*req) % sizeof(u16)) { +- result = L2CAP_CR_LE_INVALID_PARAMS; ++ if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) { ++ result = L2CAP_RECONF_INVALID_CID; + goto respond; + } + +@@ -5277,42 +5293,69 @@ static inline int l2cap_ecred_reconf_req(struct l2cap_conn *conn, + BT_DBG("mtu %u mps %u", mtu, mps); + + if (mtu < L2CAP_ECRED_MIN_MTU) { +- result = L2CAP_RECONF_INVALID_MTU; ++ result = L2CAP_RECONF_INVALID_PARAMS; + goto respond; + } + + if (mps < L2CAP_ECRED_MIN_MPS) { +- result = L2CAP_RECONF_INVALID_MPS; ++ result = L2CAP_RECONF_INVALID_PARAMS; + goto respond; + } + + cmd_len -= sizeof(*req); + num_scid = cmd_len / sizeof(u16); ++ ++ if (num_scid > L2CAP_ECRED_MAX_CID) { ++ result = L2CAP_RECONF_INVALID_PARAMS; ++ goto respond; ++ } ++ + result = L2CAP_RECONF_SUCCESS; + ++ /* Check if each SCID, MTU and MPS are valid */ + for (i = 0; i < num_scid; i++) { + u16 scid; + + scid = __le16_to_cpu(req->scid[i]); +- if (!scid) +- return -EPROTO; ++ if (!scid) { ++ result = L2CAP_RECONF_INVALID_CID; ++ goto respond; ++ } + +- chan = __l2cap_get_chan_by_dcid(conn, scid); +- if (!chan) +- continue; ++ chan[i] = __l2cap_get_chan_by_dcid(conn, scid); ++ if (!chan[i]) { ++ result = L2CAP_RECONF_INVALID_CID; ++ goto respond; ++ } + +- /* If the MTU value is decreased for any of the included +- * channels, then the receiver shall disconnect all +- * included channels. ++ /* The MTU field shall be greater than or equal to the greatest ++ * current MTU size of these channels. + */ +- if (chan->omtu > mtu) { +- BT_ERR("chan %p decreased MTU %u -> %u", chan, +- chan->omtu, mtu); ++ if (chan[i]->omtu > mtu) { ++ BT_ERR("chan %p decreased MTU %u -> %u", chan[i], ++ chan[i]->omtu, mtu); + result = L2CAP_RECONF_INVALID_MTU; ++ goto respond; + } + +- chan->omtu = mtu; +- chan->remote_mps = mps; ++ /* If more than one channel is being configured, the MPS field ++ * shall be greater than or equal to the current MPS size of ++ * each of these channels. If only one channel is being ++ * configured, the MPS field may be less than the current MPS ++ * of that channel. ++ */ ++ if (chan[i]->remote_mps >= mps && i) { ++ BT_ERR("chan %p decreased MPS %u -> %u", chan[i], ++ chan[i]->remote_mps, mps); ++ result = L2CAP_RECONF_INVALID_MPS; ++ goto respond; ++ } ++ } ++ ++ /* Commit the new MTU and MPS values after checking they are valid */ ++ for (i = 0; i < num_scid; i++) { ++ chan[i]->omtu = mtu; ++ chan[i]->remote_mps = mps; + } + + respond: +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index 59630dbeda20d6..250cc0bc552e01 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1027,10 +1027,17 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, + break; + } + +- /* Setting is not supported as it's the remote side that +- * decides this. +- */ +- err = -EPERM; ++ /* Only allow setting output MTU when not connected */ ++ if (sk->sk_state == BT_CONNECTED) { ++ err = -EISCONN; ++ break; ++ } ++ ++ err = copy_safe_from_sockptr(&mtu, sizeof(mtu), optval, optlen); ++ if (err) ++ break; ++ ++ chan->omtu = mtu; + break; + + case BT_RCVMTU: +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index 4a2d94e8717e6f..4e75ec75c70210 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -243,14 +243,11 @@ br_multicast_port_vid_to_port_ctx(struct net_bridge_port *port, u16 vid) + + lockdep_assert_held_once(&port->br->multicast_lock); + +- if (!br_opt_get(port->br, BROPT_MCAST_VLAN_SNOOPING_ENABLED)) +- return NULL; +- + /* Take RCU to access the vlan. */ + rcu_read_lock(); + + vlan = br_vlan_find(nbp_vlan_group_rcu(port), vid); +- if (vlan && !br_multicast_port_ctx_vlan_disabled(&vlan->port_mcast_ctx)) ++ if (vlan) + pmctx = &vlan->port_mcast_ctx; + + rcu_read_unlock(); +@@ -700,7 +697,10 @@ br_multicast_port_ngroups_inc_one(struct net_bridge_mcast_port *pmctx, + u32 max = READ_ONCE(pmctx->mdb_max_entries); + u32 n = READ_ONCE(pmctx->mdb_n_entries); + +- if (max && n >= max) { ++ /* enforce the max limit when it's a port pmctx or a port-vlan pmctx ++ * with snooping enabled ++ */ ++ if (!br_multicast_port_ctx_vlan_disabled(pmctx) && max && n >= max) { + NL_SET_ERR_MSG_FMT_MOD(extack, "%s is already in %u groups, and mcast_max_groups=%u", + what, n, max); + return -E2BIG; +@@ -735,9 +735,7 @@ static int br_multicast_port_ngroups_inc(struct net_bridge_port *port, + return err; + } + +- /* Only count on the VLAN context if VID is given, and if snooping on +- * that VLAN is enabled. +- */ ++ /* Only count on the VLAN context if VID is given */ + if (!group->vid) + return 0; + +@@ -2009,6 +2007,18 @@ void br_multicast_port_ctx_init(struct net_bridge_port *port, + timer_setup(&pmctx->ip6_own_query.timer, + br_ip6_multicast_port_query_expired, 0); + #endif ++ /* initialize mdb_n_entries if a new port vlan is being created */ ++ if (vlan) { ++ struct net_bridge_port_group *pg; ++ u32 n = 0; ++ ++ spin_lock_bh(&port->br->multicast_lock); ++ hlist_for_each_entry(pg, &port->mglist, mglist) ++ if (pg->key.addr.vid == vlan->vid) ++ n++; ++ WRITE_ONCE(pmctx->mdb_n_entries, n); ++ spin_unlock_bh(&port->br->multicast_lock); ++ } + } + + void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx) +@@ -2092,25 +2102,6 @@ static void __br_multicast_enable_port_ctx(struct net_bridge_mcast_port *pmctx) + br_ip4_multicast_add_router(brmctx, pmctx); + br_ip6_multicast_add_router(brmctx, pmctx); + } +- +- if (br_multicast_port_ctx_is_vlan(pmctx)) { +- struct net_bridge_port_group *pg; +- u32 n = 0; +- +- /* The mcast_n_groups counter might be wrong. First, +- * BR_VLFLAG_MCAST_ENABLED is toggled before temporary entries +- * are flushed, thus mcast_n_groups after the toggle does not +- * reflect the true values. And second, permanent entries added +- * while BR_VLFLAG_MCAST_ENABLED was disabled, are not reflected +- * either. Thus we have to refresh the counter. +- */ +- +- hlist_for_each_entry(pg, &pmctx->port->mglist, mglist) { +- if (pg->key.addr.vid == pmctx->vlan->vid) +- n++; +- } +- WRITE_ONCE(pmctx->mdb_n_entries, n); +- } + } + + static void br_multicast_enable_port_ctx(struct net_bridge_mcast_port *pmctx) +diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c +index 051d22c0e4ad4b..3397d105f74f95 100644 +--- a/net/ceph/crypto.c ++++ b/net/ceph/crypto.c +@@ -37,9 +37,6 @@ static int set_secret(struct ceph_crypto_key *key, void *buf) + return -ENOTSUPP; + } + +- if (!key->len) +- return -EINVAL; +- + key->key = kmemdup(buf, key->len, GFP_NOIO); + if (!key->key) { + ret = -ENOMEM; +@@ -95,6 +92,11 @@ int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end) + ceph_decode_copy(p, &key->created, sizeof(key->created)); + key->len = ceph_decode_16(p); + ceph_decode_need(p, end, key->len, bad); ++ if (key->len > CEPH_MAX_KEY_LEN) { ++ pr_err("secret too big %d\n", key->len); ++ return -EINVAL; ++ } ++ + ret = set_secret(key, *p); + memzero_explicit(*p, key->len); + *p += key->len; +diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h +index 13bd526349fa1b..0d32f1649f3d08 100644 +--- a/net/ceph/crypto.h ++++ b/net/ceph/crypto.h +@@ -5,7 +5,7 @@ + #include + #include + +-#define CEPH_KEY_LEN 16 ++#define CEPH_MAX_KEY_LEN 16 + #define CEPH_MAX_CON_SECRET_LEN 64 + + /* +diff --git a/net/ceph/messenger_v2.c b/net/ceph/messenger_v2.c +index 85819872443966..f82029bd33db8b 100644 +--- a/net/ceph/messenger_v2.c ++++ b/net/ceph/messenger_v2.c +@@ -2393,7 +2393,7 @@ bad: + */ + static int process_auth_done(struct ceph_connection *con, void *p, void *end) + { +- u8 session_key_buf[CEPH_KEY_LEN + 16]; ++ u8 session_key_buf[CEPH_MAX_KEY_LEN + 16]; + u8 con_secret_buf[CEPH_MAX_CON_SECRET_LEN + 16]; + u8 *session_key = PTR_ALIGN(&session_key_buf[0], 16); + u8 *con_secret = PTR_ALIGN(&con_secret_buf[0], 16); +diff --git a/net/core/dev.c b/net/core/dev.c +index 206194bb8fcadd..56b6797589f561 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -701,7 +701,7 @@ static struct net_device_path *dev_fwd_path(struct net_device_path_stack *stack) + { + int k = stack->num_paths++; + +- if (WARN_ON_ONCE(k >= NET_DEVICE_PATH_STACK_MAX)) ++ if (k >= NET_DEVICE_PATH_STACK_MAX) + return NULL; + + return &stack->path[k]; +@@ -4424,6 +4424,8 @@ int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) + * to -1 or to their cpu id, but not to our id. + */ + if (READ_ONCE(txq->xmit_lock_owner) != cpu) { ++ bool is_list = false; ++ + if (dev_xmit_recursion()) + goto recursion_alert; + +@@ -4434,17 +4436,28 @@ int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) + HARD_TX_LOCK(dev, txq, cpu); + + if (!netif_xmit_stopped(txq)) { ++ is_list = !!skb->next; ++ + dev_xmit_recursion_inc(); + skb = dev_hard_start_xmit(skb, dev, txq, &rc); + dev_xmit_recursion_dec(); +- if (dev_xmit_complete(rc)) { +- HARD_TX_UNLOCK(dev, txq); +- goto out; +- } ++ ++ /* GSO segments a single SKB into ++ * a list of frames. TCP expects error ++ * to mean none of the data was sent. ++ */ ++ if (is_list) ++ rc = NETDEV_TX_OK; + } + HARD_TX_UNLOCK(dev, txq); ++ if (!skb) /* xmit completed */ ++ goto out; ++ + net_crit_ratelimited("Virtual device %s asks to queue packet!\n", + dev->name); ++ /* NETDEV_TX_BUSY or queue was stopped */ ++ if (!is_list) ++ rc = -ENETDOWN; + } else { + /* Recursion is detected! It is possible, + * unfortunately +@@ -4452,10 +4465,10 @@ int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) + recursion_alert: + net_crit_ratelimited("Dead loop on virtual device %s, fix it urgently!\n", + dev->name); ++ rc = -ENETDOWN; + } + } + +- rc = -ENETDOWN; + rcu_read_unlock_bh(); + + dev_core_stats_tx_dropped_inc(dev); +diff --git a/net/core/filter.c b/net/core/filter.c +index ddb6d3dd34deb7..e5dc1f699297b0 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -4118,7 +4118,7 @@ static const struct bpf_func_proto bpf_xdp_store_bytes_proto = { + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, +- .arg3_type = ARG_PTR_TO_UNINIT_MEM, ++ .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, + .arg4_type = ARG_CONST_SIZE, + }; + +diff --git a/net/core/gro.c b/net/core/gro.c +index 87889cb75d2194..92cb86d4ce50ac 100644 +--- a/net/core/gro.c ++++ b/net/core/gro.c +@@ -386,7 +386,7 @@ static void gro_pull_from_frag0(struct sk_buff *skb, int grow) + { + struct skb_shared_info *pinfo = skb_shinfo(skb); + +- BUG_ON(skb->end - skb->tail < grow); ++ DEBUG_NET_WARN_ON_ONCE(skb->end - skb->tail < grow); + + memcpy(skb_tail_pointer(skb), NAPI_GRO_CB(skb)->frag0, grow); + +diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c +index 20829e0c36cdbf..b99fdca441f318 100644 +--- a/net/core/net_namespace.c ++++ b/net/core/net_namespace.c +@@ -1144,11 +1144,56 @@ out: + rtnl_set_sk_err(net, RTNLGRP_NSID, err); + } + ++#ifdef CONFIG_NET_NS ++static void __init netns_ipv4_struct_check(void) ++{ ++ /* TX readonly hotpath cache lines */ ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, ++ sysctl_tcp_early_retrans); ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, ++ sysctl_tcp_tso_win_divisor); ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, ++ sysctl_tcp_tso_rtt_log); ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, ++ sysctl_tcp_autocorking); ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, ++ sysctl_tcp_min_snd_mss); ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, ++ sysctl_tcp_notsent_lowat); ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, ++ sysctl_tcp_limit_output_bytes); ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, ++ sysctl_tcp_min_rtt_wlen); ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, ++ sysctl_tcp_wmem); ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, ++ sysctl_ip_fwd_use_pmtu); ++ CACHELINE_ASSERT_GROUP_SIZE(struct netns_ipv4, netns_ipv4_read_tx, 33); ++ ++ /* TXRX readonly hotpath cache lines */ ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_txrx, ++ sysctl_tcp_moderate_rcvbuf); ++ CACHELINE_ASSERT_GROUP_SIZE(struct netns_ipv4, netns_ipv4_read_txrx, 1); ++ ++ /* RX readonly hotpath cache line */ ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_rx, ++ sysctl_ip_early_demux); ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_rx, ++ sysctl_tcp_early_demux); ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_rx, ++ sysctl_tcp_reordering); ++ CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_rx, ++ sysctl_tcp_rmem); ++ CACHELINE_ASSERT_GROUP_SIZE(struct netns_ipv4, netns_ipv4_read_rx, 18); ++} ++#endif ++ + void __init net_ns_init(void) + { + struct net_generic *ng; + + #ifdef CONFIG_NET_NS ++ netns_ipv4_struct_check(); + net_cachep = kmem_cache_create("net_namespace", sizeof(struct net), + SMP_CACHE_BYTES, + SLAB_PANIC|SLAB_ACCOUNT, NULL); +diff --git a/net/core/skmsg.c b/net/core/skmsg.c +index 6225547808a6ba..5d557ba9c0cb47 100644 +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -408,22 +408,26 @@ out: + } + EXPORT_SYMBOL_GPL(sk_msg_memcopy_from_iter); + +-/* Receive sk_msg from psock->ingress_msg to @msg. */ +-int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, +- int len, int flags) ++int __sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, ++ int len, int flags, int *copied_from_self) + { + struct iov_iter *iter = &msg->msg_iter; + int peek = flags & MSG_PEEK; + struct sk_msg *msg_rx; + int i, copied = 0; ++ bool from_self; + + msg_rx = sk_psock_peek_msg(psock); ++ if (copied_from_self) ++ *copied_from_self = 0; ++ + while (copied != len) { + struct scatterlist *sge; + + if (unlikely(!msg_rx)) + break; + ++ from_self = msg_rx->sk == sk; + i = msg_rx->sg.start; + do { + struct page *page; +@@ -442,6 +446,9 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, + } + + copied += copy; ++ if (from_self && copied_from_self) ++ *copied_from_self += copy; ++ + if (likely(!peek)) { + sge->offset += copy; + sge->length -= copy; +@@ -450,6 +457,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, + atomic_sub(copy, &sk->sk_rmem_alloc); + } + msg_rx->sg.size -= copy; ++ sk_psock_msg_len_add(psock, -copy); + + if (!sge->length) { + sk_msg_iter_var_next(i); +@@ -486,6 +494,13 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, + out: + return copied; + } ++ ++/* Receive sk_msg from psock->ingress_msg to @msg. */ ++int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, ++ int len, int flags) ++{ ++ return __sk_msg_recvmsg(sk, psock, msg, len, flags, NULL); ++} + EXPORT_SYMBOL_GPL(sk_msg_recvmsg); + + bool sk_msg_is_readable(struct sock *sk) +@@ -615,6 +630,12 @@ static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb + if (unlikely(!msg)) + return -EAGAIN; + skb_set_owner_r(skb, sk); ++ ++ /* This is used in tcp_bpf_recvmsg_parser() to determine whether the ++ * data originates from the socket's own protocol stack. No need to ++ * refcount sk because msg's lifetime is bound to sk via the ingress_msg. ++ */ ++ msg->sk = sk; + err = sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg, take_ref); + if (err < 0) + kfree(msg); +@@ -800,9 +821,11 @@ static void __sk_psock_purge_ingress_msg(struct sk_psock *psock) + list_del(&msg->list); + if (!msg->skb) + atomic_sub(msg->sg.size, &psock->sk->sk_rmem_alloc); ++ sk_psock_msg_len_add(psock, -msg->sg.size); + sk_msg_free(psock->sk, msg); + kfree(msg); + } ++ WARN_ON_ONCE(psock->msg_tot_len); + } + + static void __sk_psock_zap_ingress(struct sk_psock *psock) +@@ -908,6 +931,7 @@ int sk_psock_msg_verdict(struct sock *sk, struct sk_psock *psock, + sk_msg_compute_data_pointers(msg); + msg->sk = sk; + ret = bpf_prog_run_pin_on_cpu(prog, msg); ++ msg->sk = NULL; + ret = sk_psock_map_verd(ret, msg->sk_redir); + psock->apply_bytes = msg->apply_bytes; + if (ret == __SK_REDIRECT) { +diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h +index f9b9e26c32c193..0b72796dd1ad38 100644 +--- a/net/ipv4/fib_lookup.h ++++ b/net/ipv4/fib_lookup.h +@@ -28,8 +28,10 @@ struct fib_alias { + /* Don't write on fa_state unless needed, to keep it shared on all cpus */ + static inline void fib_alias_accessed(struct fib_alias *fa) + { +- if (!(fa->fa_state & FA_S_ACCESSED)) +- fa->fa_state |= FA_S_ACCESSED; ++ u8 fa_state = READ_ONCE(fa->fa_state); ++ ++ if (!(fa_state & FA_S_ACCESSED)) ++ WRITE_ONCE(fa->fa_state, fa_state | FA_S_ACCESSED); + } + + /* Exported by fib_semantics.c */ +diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c +index 4d148d0892327f..c9e1526e749b2b 100644 +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -1285,7 +1285,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb, + new_fa->fa_dscp = fa->fa_dscp; + new_fa->fa_info = fi; + new_fa->fa_type = cfg->fc_type; +- state = fa->fa_state; ++ state = READ_ONCE(fa->fa_state); + new_fa->fa_state = state & ~FA_S_ACCESSED; + new_fa->fa_slen = fa->fa_slen; + new_fa->tb_id = tb->tb_id; +@@ -1751,7 +1751,7 @@ int fib_table_delete(struct net *net, struct fib_table *tb, + + fib_remove_alias(t, tp, l, fa_to_delete); + +- if (fa_to_delete->fa_state & FA_S_ACCESSED) ++ if (READ_ONCE(fa_to_delete->fa_state) & FA_S_ACCESSED) + rt_cache_flush(cfg->fc_nlinfo.nl_net); + + fib_release_info(fa_to_delete->fa_info); +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index b17549c4e5de8a..784591ed5bb7ce 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -221,22 +221,15 @@ static inline void icmp_xmit_unlock(struct sock *sk) + spin_unlock(&sk->sk_lock.slock); + } + +-int sysctl_icmp_msgs_per_sec __read_mostly = 1000; +-int sysctl_icmp_msgs_burst __read_mostly = 50; +- +-static struct { +- atomic_t credit; +- u32 stamp; +-} icmp_global; +- + /** + * icmp_global_allow - Are we allowed to send one more ICMP message ? ++ * @net: network namespace + * + * Uses a token bucket to limit our ICMP messages to ~sysctl_icmp_msgs_per_sec. + * Returns false if we reached the limit and can not send another packet. + * Works in tandem with icmp_global_consume(). + */ +-bool icmp_global_allow(void) ++bool icmp_global_allow(struct net *net) + { + u32 delta, now, oldstamp; + int incr, new, old; +@@ -245,36 +238,37 @@ bool icmp_global_allow(void) + * Then later icmp_global_consume() could consume more credits, + * this is an acceptable race. + */ +- if (atomic_read(&icmp_global.credit) > 0) ++ if (atomic_read(&net->ipv4.icmp_global_credit) > 0) + return true; + + now = jiffies; +- oldstamp = READ_ONCE(icmp_global.stamp); ++ oldstamp = READ_ONCE(net->ipv4.icmp_global_stamp); + delta = min_t(u32, now - oldstamp, HZ); + if (delta < HZ / 50) + return false; + +- incr = READ_ONCE(sysctl_icmp_msgs_per_sec) * delta / HZ; ++ incr = READ_ONCE(net->ipv4.sysctl_icmp_msgs_per_sec); ++ incr = div_u64((u64)incr * delta, HZ); + if (!incr) + return false; + +- if (cmpxchg(&icmp_global.stamp, oldstamp, now) == oldstamp) { +- old = atomic_read(&icmp_global.credit); ++ if (cmpxchg(&net->ipv4.icmp_global_stamp, oldstamp, now) == oldstamp) { ++ old = atomic_read(&net->ipv4.icmp_global_credit); + do { +- new = min(old + incr, READ_ONCE(sysctl_icmp_msgs_burst)); +- } while (!atomic_try_cmpxchg(&icmp_global.credit, &old, new)); ++ new = min(old + incr, READ_ONCE(net->ipv4.sysctl_icmp_msgs_burst)); ++ } while (!atomic_try_cmpxchg(&net->ipv4.icmp_global_credit, &old, new)); + } + return true; + } + EXPORT_SYMBOL(icmp_global_allow); + +-void icmp_global_consume(void) ++void icmp_global_consume(struct net *net) + { + int credits = get_random_u32_below(3); + + /* Note: this might make icmp_global.credit negative. */ + if (credits) +- atomic_sub(credits, &icmp_global.credit); ++ atomic_sub(credits, &net->ipv4.icmp_global_credit); + } + EXPORT_SYMBOL(icmp_global_consume); + +@@ -300,7 +294,7 @@ static bool icmpv4_global_allow(struct net *net, int type, int code, + if (icmpv4_mask_allow(net, type, code)) + return true; + +- if (icmp_global_allow()) { ++ if (icmp_global_allow(net)) { + *apply_ratelimit = true; + return true; + } +@@ -337,7 +331,7 @@ out: + if (!rc) + __ICMP_INC_STATS(net, ICMP_MIB_RATELIMITHOST); + else +- icmp_global_consume(); ++ icmp_global_consume(net); + return rc; + } + +@@ -546,14 +540,30 @@ static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4, + goto relookup_failed; + } + /* Ugh! */ +- orefdst = skb_in->_skb_refdst; /* save old refdst */ +- skb_dst_set(skb_in, NULL); ++ orefdst = skb_dstref_steal(skb_in); + err = ip_route_input(skb_in, fl4_dec.daddr, fl4_dec.saddr, + dscp, rt2->dst.dev); + + dst_release(&rt2->dst); + rt2 = skb_rtable(skb_in); +- skb_in->_skb_refdst = orefdst; /* restore old refdst */ ++ /* steal dst entry from skb_in, don't drop refcnt */ ++ skb_dstref_steal(skb_in); ++ skb_dstref_restore(skb_in, orefdst); ++ ++ /* ++ * At this point, fl4_dec.daddr should NOT be local (we ++ * checked fl4_dec.saddr above). However, a race condition ++ * may occur if the address is added to the interface ++ * concurrently. In that case, ip_route_input() returns a ++ * LOCAL route with dst.output=ip_rt_bug, which must not ++ * be used for output. ++ */ ++ if (!err && rt2 && rt2->rt_type == RTN_LOCAL) { ++ net_warn_ratelimited("detected local route for %pI4 during ICMP sending, src %pI4\n", ++ &fl4_dec.daddr, &fl4_dec.saddr); ++ dst_release(&rt2->dst); ++ err = -EINVAL; ++ } + } + + if (err) +@@ -840,16 +850,22 @@ static void icmp_socket_deliver(struct sk_buff *skb, u32 info) + /* Checkin full IP header plus 8 bytes of protocol to + * avoid additional coding at protocol handlers. + */ +- if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) { +- __ICMP_INC_STATS(dev_net_rcu(skb->dev), ICMP_MIB_INERRORS); +- return; +- } ++ if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) ++ goto out; ++ ++ /* IPPROTO_RAW sockets are not supposed to receive anything. */ ++ if (protocol == IPPROTO_RAW) ++ goto out; + + raw_icmp_error(skb, protocol, info); + + ipprot = rcu_dereference(inet_protos[protocol]); + if (ipprot && ipprot->err_handler) + ipprot->err_handler(skb, info); ++ return; ++ ++out: ++ __ICMP_INC_STATS(dev_net_rcu(skb->dev), ICMP_MIB_INERRORS); + } + + static bool icmp_tag_validation(int proto) +@@ -1498,6 +1514,8 @@ static int __net_init icmp_sk_init(struct net *net) + net->ipv4.sysctl_icmp_ratelimit = 1 * HZ; + net->ipv4.sysctl_icmp_ratemask = 0x1818; + net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr = 0; ++ net->ipv4.sysctl_icmp_msgs_per_sec = 1000; ++ net->ipv4.sysctl_icmp_msgs_burst = 50; + + return 0; + } +diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c +index d515881d02a6f7..2836020bf12d5e 100644 +--- a/net/ipv4/igmp.c ++++ b/net/ipv4/igmp.c +@@ -224,7 +224,7 @@ static void igmp_start_timer(struct ip_mc_list *im, int max_delay) + + static void igmp_gq_start_timer(struct in_device *in_dev) + { +- int tv = get_random_u32_below(in_dev->mr_maxdelay); ++ int tv = get_random_u32_below(READ_ONCE(in_dev->mr_maxdelay)); + unsigned long exp = jiffies + tv + 2; + + if (in_dev->mr_gq_running && +@@ -1006,7 +1006,7 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb, + max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE); + if (!max_delay) + max_delay = 1; /* can't mod w/ 0 */ +- in_dev->mr_maxdelay = max_delay; ++ WRITE_ONCE(in_dev->mr_maxdelay, max_delay); + + /* RFC3376, 4.1.6. QRV and 4.1.7. QQIC, when the most recently + * received value was zero, use the default or statically +diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c +index b4c59708fc0956..d898e1523a453e 100644 +--- a/net/ipv4/ip_options.c ++++ b/net/ipv4/ip_options.c +@@ -615,14 +615,13 @@ int ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev) + } + memcpy(&nexthop, &optptr[srrptr-1], 4); + +- orefdst = skb->_skb_refdst; +- skb_dst_set(skb, NULL); ++ orefdst = skb_dstref_steal(skb); + err = ip_route_input(skb, nexthop, iph->saddr, ip4h_dscp(iph), + dev); + rt2 = skb_rtable(skb); + if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) { + skb_dst_drop(skb); +- skb->_skb_refdst = orefdst; ++ skb_dstref_restore(skb, orefdst); + return -EINVAL; + } + refdst_drop(orefdst); +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index 47f2e7dd554ad4..fa13cfa2fa00f9 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -159,7 +159,7 @@ void ping_unhash(struct sock *sk) + pr_debug("ping_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); + spin_lock(&ping_table.lock); + if (sk_del_node_init_rcu(sk)) { +- isk->inet_num = 0; ++ WRITE_ONCE(isk->inet_num, 0); + isk->inet_sport = 0; + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); + } +@@ -192,31 +192,35 @@ static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident) + } + + sk_for_each_rcu(sk, hslot) { ++ int bound_dev_if; ++ + if (!net_eq(sock_net(sk), net)) + continue; + isk = inet_sk(sk); + + pr_debug("iterate\n"); +- if (isk->inet_num != ident) ++ if (READ_ONCE(isk->inet_num) != ident) + continue; + ++ bound_dev_if = READ_ONCE(sk->sk_bound_dev_if); + if (skb->protocol == htons(ETH_P_IP) && + sk->sk_family == AF_INET) { ++ __be32 rcv_saddr = READ_ONCE(isk->inet_rcv_saddr); ++ + pr_debug("found: %p: num=%d, daddr=%pI4, dif=%d\n", sk, +- (int) isk->inet_num, &isk->inet_rcv_saddr, +- sk->sk_bound_dev_if); ++ ident, &rcv_saddr, ++ bound_dev_if); + +- if (isk->inet_rcv_saddr && +- isk->inet_rcv_saddr != ip_hdr(skb)->daddr) ++ if (rcv_saddr && rcv_saddr != ip_hdr(skb)->daddr) + continue; + #if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6) && + sk->sk_family == AF_INET6) { + + pr_debug("found: %p: num=%d, daddr=%pI6c, dif=%d\n", sk, +- (int) isk->inet_num, ++ ident, + &sk->sk_v6_rcv_saddr, +- sk->sk_bound_dev_if); ++ bound_dev_if); + + if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr) && + !ipv6_addr_equal(&sk->sk_v6_rcv_saddr, +@@ -227,8 +231,8 @@ static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident) + continue; + } + +- if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif && +- sk->sk_bound_dev_if != sdif) ++ if (bound_dev_if && bound_dev_if != dif && ++ bound_dev_if != sdif) + continue; + + goto exit; +@@ -403,7 +407,9 @@ static void ping_set_saddr(struct sock *sk, struct sockaddr *saddr) + if (saddr->sa_family == AF_INET) { + struct inet_sock *isk = inet_sk(sk); + struct sockaddr_in *addr = (struct sockaddr_in *) saddr; +- isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr; ++ ++ isk->inet_saddr = addr->sin_addr.s_addr; ++ WRITE_ONCE(isk->inet_rcv_saddr, addr->sin_addr.s_addr); + #if IS_ENABLED(CONFIG_IPV6) + } else if (saddr->sa_family == AF_INET6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) saddr; +@@ -860,7 +866,8 @@ int ping_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags, + struct sk_buff *skb; + int copied, err; + +- pr_debug("ping_recvmsg(sk=%p,sk->num=%u)\n", isk, isk->inet_num); ++ pr_debug("ping_recvmsg(sk=%p,sk->num=%u)\n", isk, ++ READ_ONCE(isk->inet_num)); + + err = -EOPNOTSUPP; + if (flags & MSG_OOB) +diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c +index 6ac890b4073f45..96f1b8d39fac11 100644 +--- a/net/ipv4/sysctl_net_ipv4.c ++++ b/net/ipv4/sysctl_net_ipv4.c +@@ -547,22 +547,6 @@ static struct ctl_table ipv4_table[] = { + .mode = 0444, + .proc_handler = proc_tcp_available_ulp, + }, +- { +- .procname = "icmp_msgs_per_sec", +- .data = &sysctl_icmp_msgs_per_sec, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = proc_dointvec_minmax, +- .extra1 = SYSCTL_ZERO, +- }, +- { +- .procname = "icmp_msgs_burst", +- .data = &sysctl_icmp_msgs_burst, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = proc_dointvec_minmax, +- .extra1 = SYSCTL_ZERO, +- }, + { + .procname = "udp_mem", + .data = &sysctl_udp_mem, +@@ -649,6 +633,22 @@ static struct ctl_table ipv4_net_table[] = { + .mode = 0644, + .proc_handler = proc_dointvec + }, ++ { ++ .procname = "icmp_msgs_per_sec", ++ .data = &init_net.ipv4.sysctl_icmp_msgs_per_sec, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ }, ++ { ++ .procname = "icmp_msgs_burst", ++ .data = &init_net.ipv4.sysctl_icmp_msgs_burst, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ }, + { + .procname = "ping_group_range", + .data = &init_net.ipv4.ping_group_range.range, +@@ -1366,6 +1366,15 @@ static struct ctl_table ipv4_net_table[] = { + .proc_handler = proc_dou8vec_minmax, + .extra1 = SYSCTL_ZERO, + }, ++ { ++ .procname = "tcp_backlog_ack_defer", ++ .data = &init_net.ipv4.sysctl_tcp_backlog_ack_defer, ++ .maxlen = sizeof(u8), ++ .mode = 0644, ++ .proc_handler = proc_dou8vec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ .extra2 = SYSCTL_ONE, ++ }, + { + .procname = "tcp_reflect_tos", + .data = &init_net.ipv4.sysctl_tcp_reflect_tos, +@@ -1489,6 +1498,14 @@ static struct ctl_table ipv4_net_table[] = { + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, ++ { ++ .procname = "tcp_pingpong_thresh", ++ .data = &init_net.ipv4.sysctl_tcp_pingpong_thresh, ++ .maxlen = sizeof(u8), ++ .mode = 0644, ++ .proc_handler = proc_dou8vec_minmax, ++ .extra1 = SYSCTL_ONE, ++ }, + { } + }; + +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 5dde0aed314405..2bae34d63c3db7 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -468,6 +468,9 @@ static void tcp_tx_timestamp(struct sock *sk, u16 tsflags) + { + struct sk_buff *skb = tcp_write_queue_tail(sk); + ++ if (unlikely(!skb)) ++ skb = skb_rb_last(&sk->tcp_rtx_queue); ++ + if (tsflags && skb) { + struct skb_shared_info *shinfo = skb_shinfo(skb); + struct tcp_skb_cb *tcb = TCP_SKB_CB(skb); +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 7518d2af630880..06a185bb1e35cf 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -10,6 +10,7 @@ + + #include + #include ++#include + + void tcp_eat_skb(struct sock *sk, struct sk_buff *skb) + { +@@ -226,6 +227,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, + int peek = flags & MSG_PEEK; + struct sk_psock *psock; + struct tcp_sock *tcp; ++ int copied_from_self = 0; + int copied = 0; + u32 seq; + +@@ -262,7 +264,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, + } + + msg_bytes_ready: +- copied = sk_msg_recvmsg(sk, psock, msg, len, flags); ++ copied = __sk_msg_recvmsg(sk, psock, msg, len, flags, &copied_from_self); + /* The typical case for EFAULT is the socket was gracefully + * shutdown with a FIN pkt. So check here the other case is + * some error on copy_page_to_iter which would be unexpected. +@@ -277,7 +279,7 @@ msg_bytes_ready: + goto out; + } + } +- seq += copied; ++ seq += copied_from_self; + if (!copied) { + long timeo; + int data; +@@ -331,6 +333,24 @@ unlock: + return copied; + } + ++static int tcp_bpf_ioctl(struct sock *sk, int cmd, int *karg) ++{ ++ bool slow; ++ ++ if (cmd != SIOCINQ) ++ return tcp_ioctl(sk, cmd, karg); ++ ++ /* works similar as tcp_ioctl */ ++ if (sk->sk_state == TCP_LISTEN) ++ return -EINVAL; ++ ++ slow = lock_sock_fast(sk); ++ *karg = sk_psock_msg_inq(sk); ++ unlock_sock_fast(sk, slow); ++ ++ return 0; ++} ++ + static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, + int flags, int *addr_len) + { +@@ -609,6 +629,7 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS], + prot[TCP_BPF_BASE].close = sock_map_close; + prot[TCP_BPF_BASE].recvmsg = tcp_bpf_recvmsg; + prot[TCP_BPF_BASE].sock_is_readable = sk_msg_is_readable; ++ prot[TCP_BPF_BASE].ioctl = tcp_bpf_ioctl; + + prot[TCP_BPF_TX] = prot[TCP_BPF_BASE]; + prot[TCP_BPF_TX].sendmsg = tcp_bpf_sendmsg; +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 8834cd41b38408..f67967c7577146 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -5678,6 +5678,14 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible) + tcp_in_quickack_mode(sk) || + /* Protocol state mandates a one-time immediate ACK */ + inet_csk(sk)->icsk_ack.pending & ICSK_ACK_NOW) { ++ /* If we are running from __release_sock() in user context, ++ * Defer the ack until tcp_release_cb(). ++ */ ++ if (sock_owned_by_user_nocheck(sk) && ++ READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_backlog_ack_defer)) { ++ set_bit(TCP_ACK_DEFERRED, &sk->sk_tsq_flags); ++ return; ++ } + send_now: + tcp_send_ack(sk); + return; +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index 2f49a504c9d3e3..ab4be34e58bb23 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -3279,6 +3279,7 @@ static int __net_init tcp_sk_init(struct net *net) + net->ipv4.sysctl_tcp_comp_sack_delay_ns = NSEC_PER_MSEC; + net->ipv4.sysctl_tcp_comp_sack_slack_ns = 100 * NSEC_PER_USEC; + net->ipv4.sysctl_tcp_comp_sack_nr = 44; ++ net->ipv4.sysctl_tcp_backlog_ack_defer = 1; + net->ipv4.sysctl_tcp_fastopen = TFO_CLIENT_ENABLE; + net->ipv4.sysctl_tcp_fastopen_blackhole_timeout = 0; + atomic_set(&net->ipv4.tfo_active_disable_times, 0); +@@ -3302,6 +3303,8 @@ static int __net_init tcp_sk_init(struct net *net) + net->ipv4.sysctl_tcp_syn_linear_timeouts = 4; + net->ipv4.sysctl_tcp_shrink_window = 0; + ++ net->ipv4.sysctl_tcp_pingpong_thresh = 1; ++ + return 0; + } + +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 88551db62ca29d..db8f2830c67bf2 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -170,10 +170,10 @@ static void tcp_event_data_sent(struct tcp_sock *tp, + tp->lsndtime = now; + + /* If it is a reply for ato after last received +- * packet, enter pingpong mode. ++ * packet, increase pingpong count. + */ + if ((u32)(now - icsk->icsk_ack.lrcvtime) < icsk->icsk_ack.ato) +- inet_csk_enter_pingpong_mode(sk); ++ inet_csk_inc_pingpong_cnt(sk); + } + + /* Account for an ACK we sent. */ +@@ -1083,7 +1083,8 @@ static void tcp_tasklet_func(struct tasklet_struct *t) + #define TCP_DEFERRED_ALL (TCPF_TSQ_DEFERRED | \ + TCPF_WRITE_TIMER_DEFERRED | \ + TCPF_DELACK_TIMER_DEFERRED | \ +- TCPF_MTU_REDUCED_DEFERRED) ++ TCPF_MTU_REDUCED_DEFERRED | \ ++ TCPF_ACK_DEFERRED) + /** + * tcp_release_cb - tcp release_sock() callback + * @sk: socket +@@ -1130,6 +1131,8 @@ void tcp_release_cb(struct sock *sk) + inet_csk(sk)->icsk_af_ops->mtu_reduced(sk); + __sock_put(sk); + } ++ if ((flags & TCPF_ACK_DEFERRED) && inet_csk_ack_scheduled(sk)) ++ tcp_send_ack(sk); + } + EXPORT_SYMBOL(tcp_release_cb); + +diff --git a/net/ipv4/udp_bpf.c b/net/ipv4/udp_bpf.c +index 0735d820e413f3..91233e37cd97a2 100644 +--- a/net/ipv4/udp_bpf.c ++++ b/net/ipv4/udp_bpf.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + + #include "udp_impl.h" + +@@ -111,12 +112,26 @@ enum { + static DEFINE_SPINLOCK(udpv6_prot_lock); + static struct proto udp_bpf_prots[UDP_BPF_NUM_PROTS]; + ++static int udp_bpf_ioctl(struct sock *sk, int cmd, int *karg) ++{ ++ if (cmd != SIOCINQ) ++ return udp_ioctl(sk, cmd, karg); ++ ++ /* Since we don't hold a lock, sk_receive_queue may contain data. ++ * BPF might only be processing this data at the moment. We only ++ * care about the data in the ingress_msg here. ++ */ ++ *karg = sk_msg_first_len(sk); ++ return 0; ++} ++ + static void udp_bpf_rebuild_protos(struct proto *prot, const struct proto *base) + { +- *prot = *base; +- prot->close = sock_map_close; +- prot->recvmsg = udp_bpf_recvmsg; +- prot->sock_is_readable = sk_msg_is_readable; ++ *prot = *base; ++ prot->close = sock_map_close; ++ prot->recvmsg = udp_bpf_recvmsg; ++ prot->sock_is_readable = sk_msg_is_readable; ++ prot->ioctl = udp_bpf_ioctl; + } + + static void udp_bpf_check_v6_needs_rebuild(struct proto *ops) +diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c +index 02e9ffb63af197..676284b6efe8b9 100644 +--- a/net/ipv6/exthdrs.c ++++ b/net/ipv6/exthdrs.c +@@ -313,7 +313,7 @@ fail_and_free: + } + + extlen = (skb_transport_header(skb)[1] + 1) << 3; +- if (extlen > net->ipv6.sysctl.max_dst_opts_len) ++ if (extlen > READ_ONCE(net->ipv6.sysctl.max_dst_opts_len)) + goto fail_and_free; + + opt->lastopt = opt->dst1 = skb_network_header_len(skb); +@@ -321,7 +321,8 @@ fail_and_free: + dstbuf = opt->dst1; + #endif + +- if (ip6_parse_tlv(false, skb, net->ipv6.sysctl.max_dst_opts_cnt)) { ++ if (ip6_parse_tlv(false, skb, ++ READ_ONCE(net->ipv6.sysctl.max_dst_opts_cnt))) { + skb->transport_header += extlen; + opt = IP6CB(skb); + #if IS_ENABLED(CONFIG_IPV6_MIP6) +@@ -937,6 +938,11 @@ static bool ipv6_hop_ioam(struct sk_buff *skb, int optoff) + if (hdr->opt_len < 2 + sizeof(*trace) + trace->remlen * 4) + goto drop; + ++ /* Inconsistent Pre-allocated Trace header */ ++ if (trace->nodelen != ++ ioam6_trace_compute_nodelen(be32_to_cpu(trace->type_be32))) ++ goto drop; ++ + /* Ignore if the IOAM namespace is unknown */ + ns = ioam6_namespace(ipv6_skb_net(skb), trace->namespace_id); + if (!ns) +@@ -1053,11 +1059,12 @@ fail_and_free: + } + + extlen = (skb_transport_header(skb)[1] + 1) << 3; +- if (extlen > net->ipv6.sysctl.max_hbh_opts_len) ++ if (extlen > READ_ONCE(net->ipv6.sysctl.max_hbh_opts_len)) + goto fail_and_free; + + opt->flags |= IP6SKB_HOPBYHOP; +- if (ip6_parse_tlv(true, skb, net->ipv6.sysctl.max_hbh_opts_cnt)) { ++ if (ip6_parse_tlv(true, skb, ++ READ_ONCE(net->ipv6.sysctl.max_hbh_opts_cnt))) { + skb->transport_header += extlen; + opt = IP6CB(skb); + opt->nhoff = sizeof(struct ipv6hdr); +diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c +index c7e815b7ca0870..1d1c56e0e24607 100644 +--- a/net/ipv6/icmp.c ++++ b/net/ipv6/icmp.c +@@ -181,7 +181,7 @@ static bool icmpv6_global_allow(struct net *net, int type, + if (icmpv6_mask_allow(net, type)) + return true; + +- if (icmp_global_allow()) { ++ if (icmp_global_allow(net)) { + *apply_ratelimit = true; + return true; + } +@@ -231,7 +231,7 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type, + __ICMP6_INC_STATS(net, ip6_dst_idev(dst), + ICMP6_MIB_RATELIMITHOST); + else +- icmp_global_consume(); ++ icmp_global_consume(net); + dst_release(dst); + return res; + } +@@ -869,6 +869,12 @@ enum skb_drop_reason icmpv6_notify(struct sk_buff *skb, u8 type, + if (reason != SKB_NOT_DROPPED_YET) + goto out; + ++ if (nexthdr == IPPROTO_RAW) { ++ /* Add a more specific reason later ? */ ++ reason = SKB_DROP_REASON_NOT_SPECIFIED; ++ goto out; ++ } ++ + /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. + Without this we will not able f.e. to make source routed + pmtu discovery. +diff --git a/net/ipv6/ioam6.c b/net/ipv6/ioam6.c +index 571f0e4d9cf3d0..a35b6fdbc93e90 100644 +--- a/net/ipv6/ioam6.c ++++ b/net/ipv6/ioam6.c +@@ -630,6 +630,20 @@ struct ioam6_namespace *ioam6_namespace(struct net *net, __be16 id) + return rhashtable_lookup_fast(&nsdata->namespaces, &id, rht_ns_params); + } + ++#define IOAM6_MASK_SHORT_FIELDS 0xff1ffc00 ++#define IOAM6_MASK_WIDE_FIELDS 0x00e00000 ++ ++u8 ioam6_trace_compute_nodelen(u32 trace_type) ++{ ++ u8 nodelen = hweight32(trace_type & IOAM6_MASK_SHORT_FIELDS) ++ * (sizeof(__be32) / 4); ++ ++ nodelen += hweight32(trace_type & IOAM6_MASK_WIDE_FIELDS) ++ * (sizeof(__be64) / 4); ++ ++ return nodelen; ++} ++ + static void __ioam6_fill_trace_data(struct sk_buff *skb, + struct ioam6_namespace *ns, + struct ioam6_trace_hdr *trace, +diff --git a/net/ipv6/ioam6_iptunnel.c b/net/ipv6/ioam6_iptunnel.c +index a5cfc5b0b206bb..3a6065faaf9bfe 100644 +--- a/net/ipv6/ioam6_iptunnel.c ++++ b/net/ipv6/ioam6_iptunnel.c +@@ -22,9 +22,6 @@ + #include + #include + +-#define IOAM6_MASK_SHORT_FIELDS 0xff100000 +-#define IOAM6_MASK_WIDE_FIELDS 0xe00000 +- + struct ioam6_lwt_encap { + struct ipv6_hopopt_hdr eh; + u8 pad[2]; /* 2-octet padding for 4n-alignment */ +@@ -88,13 +85,8 @@ static bool ioam6_validate_trace_hdr(struct ioam6_trace_hdr *trace) + trace->type.bit21) + return false; + +- trace->nodelen = 0; + fields = be32_to_cpu(trace->type_be32); +- +- trace->nodelen += hweight32(fields & IOAM6_MASK_SHORT_FIELDS) +- * (sizeof(__be32) / 4); +- trace->nodelen += hweight32(fields & IOAM6_MASK_WIDE_FIELDS) +- * (sizeof(__be64) / 4); ++ trace->nodelen = ioam6_trace_compute_nodelen(fields); + + return true; + } +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index fe57884ca7238a..6fe867579118ba 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -1137,7 +1137,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt, + fib6_add_gc_list(iter); + } + if (!(rt->fib6_flags & (RTF_ADDRCONF | RTF_PREFIX_RT)) && +- !iter->fib6_nh->fib_nh_gw_family) { ++ (iter->nh || !iter->fib6_nh->fib_nh_gw_family)) { + iter->fib6_flags &= ~RTF_ADDRCONF; + iter->fib6_flags &= ~RTF_PREFIX_RT; + } +diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c +index f24faa78ee82d8..e5d76e782b9613 100644 +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -57,6 +57,7 @@ static int xfrm6_get_saddr(xfrm_address_t *saddr, + struct dst_entry *dst; + struct net_device *dev; + struct inet6_dev *idev; ++ int err; + + dst = xfrm6_dst_lookup(params); + if (IS_ERR(dst)) +@@ -68,9 +69,11 @@ static int xfrm6_get_saddr(xfrm_address_t *saddr, + return -EHOSTUNREACH; + } + dev = idev->dev; +- ipv6_dev_get_saddr(dev_net(dev), dev, ¶ms->daddr->in6, 0, +- &saddr->in6); ++ err = ipv6_dev_get_saddr(dev_net(dev), dev, ¶ms->daddr->in6, 0, ++ &saddr->in6); + dst_release(dst); ++ if (err) ++ return -EHOSTUNREACH; + return 0; + } + +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index f3856856aa446b..85ef9042873bef 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -2048,8 +2048,8 @@ static void mptcp_rcv_space_adjust(struct mptcp_sock *msk, int copied) + + msk->rcvq_space.copied += copied; + +- mstamp = div_u64(tcp_clock_ns(), NSEC_PER_USEC); +- time = tcp_stamp_us_delta(mstamp, msk->rcvq_space.time); ++ mstamp = mptcp_stamp(); ++ time = tcp_stamp_us_delta(mstamp, READ_ONCE(msk->rcvq_space.time)); + + rtt_us = msk->rcvq_space.rtt_us; + if (rtt_us && time < (rtt_us >> 3)) +@@ -3451,6 +3451,7 @@ struct sock *mptcp_sk_clone_init(const struct sock *sk, + __mptcp_propagate_sndbuf(nsk, ssk); + + mptcp_rcv_space_init(msk, ssk); ++ msk->rcvq_space.time = mptcp_stamp(); + + if (mp_opt->suboptions & OPTION_MPTCP_MPC_ACK) + __mptcp_subflow_fully_established(msk, subflow, mp_opt); +@@ -3468,8 +3469,6 @@ void mptcp_rcv_space_init(struct mptcp_sock *msk, const struct sock *ssk) + msk->rcvq_space.copied = 0; + msk->rcvq_space.rtt_us = 0; + +- msk->rcvq_space.time = tp->tcp_mstamp; +- + /* initial rcv_space offering made to peer */ + msk->rcvq_space.space = min_t(u32, tp->rcv_wnd, + TCP_INIT_CWND * tp->advmss); +@@ -3688,6 +3687,7 @@ void mptcp_finish_connect(struct sock *ssk) + * accessing the field below + */ + WRITE_ONCE(msk->local_key, subflow->local_key); ++ WRITE_ONCE(msk->rcvq_space.time, mptcp_stamp()); + + mptcp_pm_new_connection(msk, ssk, 0); + } +diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h +index 0fbc1f13bd2d4c..58805fbf1f961c 100644 +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -786,6 +786,11 @@ static inline bool mptcp_is_fully_established(struct sock *sk) + READ_ONCE(mptcp_sk(sk)->fully_established); + } + ++static inline u64 mptcp_stamp(void) ++{ ++ return div_u64(tcp_clock_ns(), NSEC_PER_USEC); ++} ++ + void mptcp_rcv_space_init(struct mptcp_sock *msk, const struct sock *ssk); + void mptcp_data_ready(struct sock *sk, struct sock *ssk); + bool mptcp_finish_join(struct sock *sk); +diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c +index a2c5a7ba0c6fce..ae9ad439449fa5 100644 +--- a/net/netfilter/nf_conncount.c ++++ b/net/netfilter/nf_conncount.c +@@ -34,8 +34,9 @@ + + #define CONNCOUNT_SLOTS 256U + +-#define CONNCOUNT_GC_MAX_NODES 8 +-#define MAX_KEYLEN 5 ++#define CONNCOUNT_GC_MAX_NODES 8 ++#define CONNCOUNT_GC_MAX_COLLECT 64 ++#define MAX_KEYLEN 5 + + /* we will save the tuples of all connections we care about */ + struct nf_conncount_tuple { +@@ -178,16 +179,28 @@ static int __nf_conncount_add(struct net *net, + return -ENOENT; + + if (ct && nf_ct_is_confirmed(ct)) { +- err = -EEXIST; +- goto out_put; ++ /* local connections are confirmed in postrouting so confirmation ++ * might have happened before hitting connlimit ++ */ ++ if (skb->skb_iif != LOOPBACK_IFINDEX) { ++ err = -EEXIST; ++ goto out_put; ++ } ++ ++ /* this is likely a local connection, skip optimization to avoid ++ * adding duplicates from a 'packet train' ++ */ ++ goto check_connections; + } + +- if ((u32)jiffies == list->last_gc) ++ if ((u32)jiffies == list->last_gc && ++ (list->count - list->last_gc_count) < CONNCOUNT_GC_MAX_COLLECT) + goto add_new_node; + ++check_connections: + /* check the saved connections */ + list_for_each_entry_safe(conn, conn_n, &list->head, node) { +- if (collect > CONNCOUNT_GC_MAX_NODES) ++ if (collect > CONNCOUNT_GC_MAX_COLLECT) + break; + + found = find_or_evict(net, list, conn); +@@ -230,6 +243,7 @@ static int __nf_conncount_add(struct net *net, + nf_ct_put(found_ct); + } + list->last_gc = (u32)jiffies; ++ list->last_gc_count = list->count; + + add_new_node: + if (WARN_ON_ONCE(list->count > INT_MAX)) { +@@ -277,13 +291,14 @@ void nf_conncount_list_init(struct nf_conncount_list *list) + spin_lock_init(&list->list_lock); + INIT_LIST_HEAD(&list->head); + list->count = 0; ++ list->last_gc_count = 0; + list->last_gc = (u32)jiffies; + } + EXPORT_SYMBOL_GPL(nf_conncount_list_init); + + /* Return true if the list is empty. Must be called with BH disabled. */ +-bool nf_conncount_gc_list(struct net *net, +- struct nf_conncount_list *list) ++static bool __nf_conncount_gc_list(struct net *net, ++ struct nf_conncount_list *list) + { + const struct nf_conntrack_tuple_hash *found; + struct nf_conncount_tuple *conn, *conn_n; +@@ -295,10 +310,6 @@ bool nf_conncount_gc_list(struct net *net, + if ((u32)jiffies == READ_ONCE(list->last_gc)) + return false; + +- /* don't bother if other cpu is already doing GC */ +- if (!spin_trylock(&list->list_lock)) +- return false; +- + list_for_each_entry_safe(conn, conn_n, &list->head, node) { + found = find_or_evict(net, list, conn); + if (IS_ERR(found)) { +@@ -320,14 +331,29 @@ bool nf_conncount_gc_list(struct net *net, + } + + nf_ct_put(found_ct); +- if (collected > CONNCOUNT_GC_MAX_NODES) ++ if (collected > CONNCOUNT_GC_MAX_COLLECT) + break; + } + + if (!list->count) + ret = true; + list->last_gc = (u32)jiffies; +- spin_unlock(&list->list_lock); ++ list->last_gc_count = list->count; ++ ++ return ret; ++} ++ ++bool nf_conncount_gc_list(struct net *net, ++ struct nf_conncount_list *list) ++{ ++ bool ret; ++ ++ /* don't bother if other cpu is already doing GC */ ++ if (!spin_trylock_bh(&list->list_lock)) ++ return false; ++ ++ ret = __nf_conncount_gc_list(net, list); ++ spin_unlock_bh(&list->list_lock); + + return ret; + } +diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c +index 540d97715bd23d..62aa22a0787695 100644 +--- a/net/netfilter/nf_conntrack_h323_asn1.c ++++ b/net/netfilter/nf_conntrack_h323_asn1.c +@@ -796,7 +796,7 @@ static int decode_choice(struct bitstr *bs, const struct field_t *f, + + if (ext || (son->attr & OPEN)) { + BYTE_ALIGN(bs); +- if (nf_h323_error_boundary(bs, len, 0)) ++ if (nf_h323_error_boundary(bs, 2, 0)) + return H323_ERROR_BOUND; + len = get_len(bs); + if (nf_h323_error_boundary(bs, len, 0)) +diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c +index 5a9bce24f3c3d9..ed983421e2eb2f 100644 +--- a/net/netfilter/nf_conntrack_h323_main.c ++++ b/net/netfilter/nf_conntrack_h323_main.c +@@ -1186,13 +1186,13 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct, + { + struct net *net = nf_ct_net(ct); + struct nf_conntrack_expect *exp; +- struct nf_conntrack_tuple tuple; ++ struct nf_conntrack_tuple tuple = { ++ .src.l3num = nf_ct_l3num(ct), ++ .dst.protonum = IPPROTO_TCP, ++ .dst.u.tcp.port = port, ++ }; + +- memset(&tuple.src.u3, 0, sizeof(tuple.src.u3)); +- tuple.src.u.tcp.port = 0; + memcpy(&tuple.dst.u3, addr, sizeof(tuple.dst.u3)); +- tuple.dst.u.tcp.port = port; +- tuple.dst.protonum = IPPROTO_TCP; + + exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple); + if (exp && exp->master == ct) +diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c +index e831637bc8ca8f..cb260eb3d012c3 100644 +--- a/net/netfilter/nf_conntrack_proto_generic.c ++++ b/net/netfilter/nf_conntrack_proto_generic.c +@@ -67,6 +67,7 @@ void nf_conntrack_generic_init_net(struct net *net) + const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = + { + .l4proto = 255, ++ .allow_clash = true, + #ifdef CONFIG_NF_CONNTRACK_TIMEOUT + .ctnl_timeout = { + .nlattr_to_obj = generic_timeout_nlattr_to_obj, +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index a0a5d19fa8506b..41614e897ec8fd 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -2581,6 +2581,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, + + err_register_hook: + nft_chain_del(chain); ++ synchronize_rcu(); + err_chain_add: + nft_trans_destroy(trans); + err_trans: +@@ -10824,6 +10825,13 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb, + ret = __nf_tables_abort(net, action); + nft_gc_seq_end(nft_net, gc_seq); + ++ if (action == NFNL_ABORT_NONE) { ++ struct nft_table *table; ++ ++ list_for_each_entry(table, &nft_net->tables, list) ++ table->validate_state = NFT_VALIDATE_SKIP; ++ } ++ + WARN_ON_ONCE(!list_empty(&nft_net->commit_list)); + + /* module autoload needs to happen after GC sequence update because it +diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c +index 7ca4f0d21fe2a2..1e8142e64e8082 100644 +--- a/net/netfilter/nft_compat.c ++++ b/net/netfilter/nft_compat.c +@@ -134,7 +134,8 @@ static void nft_target_eval_bridge(const struct nft_expr *expr, + } + + static const struct nla_policy nft_target_policy[NFTA_TARGET_MAX + 1] = { +- [NFTA_TARGET_NAME] = { .type = NLA_NUL_STRING }, ++ [NFTA_TARGET_NAME] = { .type = NLA_NUL_STRING, ++ .len = XT_EXTENSION_MAXNAMELEN, }, + [NFTA_TARGET_REV] = NLA_POLICY_MAX(NLA_BE32, 255), + [NFTA_TARGET_INFO] = { .type = NLA_BINARY }, + }; +@@ -434,7 +435,8 @@ static void nft_match_eval(const struct nft_expr *expr, + } + + static const struct nla_policy nft_match_policy[NFTA_MATCH_MAX + 1] = { +- [NFTA_MATCH_NAME] = { .type = NLA_NUL_STRING }, ++ [NFTA_MATCH_NAME] = { .type = NLA_NUL_STRING, ++ .len = XT_EXTENSION_MAXNAMELEN }, + [NFTA_MATCH_REV] = NLA_POLICY_MAX(NLA_BE32, 255), + [NFTA_MATCH_INFO] = { .type = NLA_BINARY }, + }; +@@ -693,7 +695,12 @@ static int nfnl_compat_get_rcu(struct sk_buff *skb, + + name = nla_data(tb[NFTA_COMPAT_NAME]); + rev = ntohl(nla_get_be32(tb[NFTA_COMPAT_REV])); +- target = ntohl(nla_get_be32(tb[NFTA_COMPAT_TYPE])); ++ /* x_tables api checks for 'target == 1' to mean target, ++ * everything else means 'match'. ++ * In x_tables world, the number is set by kernel, not ++ * userspace. ++ */ ++ target = nla_get_be32(tb[NFTA_COMPAT_TYPE]) == htonl(1); + + switch(family) { + case AF_INET: +diff --git a/net/netfilter/nft_connlimit.c b/net/netfilter/nft_connlimit.c +index 83a7d5769396cf..5dd50b3ab5a452 100644 +--- a/net/netfilter/nft_connlimit.c ++++ b/net/netfilter/nft_connlimit.c +@@ -232,13 +232,8 @@ static void nft_connlimit_destroy_clone(const struct nft_ctx *ctx, + static bool nft_connlimit_gc(struct net *net, const struct nft_expr *expr) + { + struct nft_connlimit *priv = nft_expr_priv(expr); +- bool ret; + +- local_bh_disable(); +- ret = nf_conncount_gc_list(net, priv->list); +- local_bh_enable(); +- +- return ret; ++ return nf_conncount_gc_list(net, priv->list); + } + + static struct nft_expr_type nft_connlimit_type; +diff --git a/net/netfilter/nft_counter.c b/net/netfilter/nft_counter.c +index cc732532949630..0d70325280cc57 100644 +--- a/net/netfilter/nft_counter.c ++++ b/net/netfilter/nft_counter.c +@@ -117,8 +117,8 @@ static void nft_counter_reset(struct nft_counter_percpu_priv *priv, + nft_sync = this_cpu_ptr(&nft_counter_sync); + + u64_stats_update_begin(nft_sync); +- u64_stats_add(&this_cpu->packets, -total->packets); +- u64_stats_add(&this_cpu->bytes, -total->bytes); ++ u64_stats_sub(&this_cpu->packets, total->packets); ++ u64_stats_sub(&this_cpu->bytes, total->bytes); + u64_stats_update_end(nft_sync); + + local_bh_enable(); +diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c +index 2f1012bde1f34e..5a74ee4b7dfb35 100644 +--- a/net/netfilter/nft_set_hash.c ++++ b/net/netfilter/nft_set_hash.c +@@ -525,15 +525,20 @@ bool nft_hash_lookup(const struct net *net, const struct nft_set *set, + static void *nft_hash_get(const struct net *net, const struct nft_set *set, + const struct nft_set_elem *elem, unsigned int flags) + { ++ const u32 *key = (const u32 *)&elem->key.val; + struct nft_hash *priv = nft_set_priv(set); + u8 genmask = nft_genmask_cur(net); + struct nft_hash_elem *he; + u32 hash; + +- hash = jhash(elem->key.val.data, set->klen, priv->seed); ++ if (set->klen == 4) ++ hash = jhash_1word(*key, priv->seed); ++ else ++ hash = jhash(key, set->klen, priv->seed); ++ + hash = reciprocal_scale(hash, priv->buckets); + hlist_for_each_entry_rcu(he, &priv->table[hash], node) { +- if (!memcmp(nft_set_ext_key(&he->ext), elem->key.val.data, set->klen) && ++ if (!memcmp(nft_set_ext_key(&he->ext), key, set->klen) && + nft_set_elem_active(&he->ext, genmask)) + return he; + } +diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c +index 04672238e17dce..9c9b07f2def1b1 100644 +--- a/net/netfilter/nft_set_rbtree.c ++++ b/net/netfilter/nft_set_rbtree.c +@@ -305,11 +305,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set, + return false; + } + ++/* Only for anonymous sets which do not allow updates, all element are active. */ ++static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe) ++{ ++ struct rb_node *node; ++ ++ node = rb_prev(&rbe->node); ++ if (!node) ++ return NULL; ++ ++ return rb_entry(node, struct nft_rbtree_elem, node); ++} ++ + static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, + struct nft_rbtree_elem *new, + struct nft_set_ext **ext) + { +- struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL; ++ struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev; + struct rb_node *node, *next, *parent, **p, *first = NULL; + struct nft_rbtree *priv = nft_set_priv(set); + u8 cur_genmask = nft_genmask_cur(net); +@@ -441,11 +453,19 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, + /* - new start element with existing closest, less or equal key value + * being a start element: partial overlap, reported as -ENOTEMPTY. + * Anonymous sets allow for two consecutive start element since they +- * are constant, skip them to avoid bogus overlap reports. ++ * are constant, but validate that this new start element does not ++ * sit in between an existing start and end elements: partial overlap, ++ * reported as -ENOTEMPTY. + */ +- if (!nft_set_is_anonymous(set) && rbe_le && +- nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) +- return -ENOTEMPTY; ++ if (rbe_le && ++ nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) { ++ if (!nft_set_is_anonymous(set)) ++ return -ENOTEMPTY; ++ ++ rbe_prev = nft_rbtree_prev_active(rbe_le); ++ if (rbe_prev && nft_rbtree_interval_end(rbe_prev)) ++ return -ENOTEMPTY; ++ } + + /* - new end element with existing closest, less or equal key value + * being a end element: partial overlap, reported as -ENOTEMPTY. +diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c +index 37704ab0179923..0d32d4841cb325 100644 +--- a/net/netfilter/xt_tcpmss.c ++++ b/net/netfilter/xt_tcpmss.c +@@ -61,7 +61,7 @@ tcpmss_mt(const struct sk_buff *skb, struct xt_action_param *par) + return (mssval >= info->mss_min && + mssval <= info->mss_max) ^ info->invert; + } +- if (op[i] < 2) ++ if (op[i] < 2 || i == optlen - 1) + i++; + else + i += op[i+1] ? : 1; +diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c +index e90f70385813a8..a106f4352356df 100644 +--- a/net/nfc/hci/llc_shdlc.c ++++ b/net/nfc/hci/llc_shdlc.c +@@ -762,6 +762,14 @@ static void llc_shdlc_deinit(struct nfc_llc *llc) + { + struct llc_shdlc *shdlc = nfc_llc_get_data(llc); + ++ timer_shutdown_sync(&shdlc->connect_timer); ++ timer_shutdown_sync(&shdlc->t1_timer); ++ timer_shutdown_sync(&shdlc->t2_timer); ++ shdlc->t1_active = false; ++ shdlc->t2_active = false; ++ ++ cancel_work_sync(&shdlc->sm_work); ++ + skb_queue_purge(&shdlc->rcv_q); + skb_queue_purge(&shdlc->send_q); + skb_queue_purge(&shdlc->ack_pending_q); +diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c +index cb2a672105dc1a..df0f1200082cfd 100644 +--- a/net/nfc/nci/ntf.c ++++ b/net/nfc/nci/ntf.c +@@ -58,7 +58,7 @@ static int nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, + struct nci_conn_info *conn_info; + int i; + +- if (skb->len < sizeof(struct nci_core_conn_credit_ntf)) ++ if (skb->len < offsetofend(struct nci_core_conn_credit_ntf, num_entries)) + return -EINVAL; + + ntf = (struct nci_core_conn_credit_ntf *)skb->data; +@@ -68,6 +68,10 @@ static int nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, + if (ntf->num_entries > NCI_MAX_NUM_CONN) + ntf->num_entries = NCI_MAX_NUM_CONN; + ++ if (skb->len < offsetofend(struct nci_core_conn_credit_ntf, num_entries) + ++ ntf->num_entries * sizeof(struct conn_credit_entry)) ++ return -EINVAL; ++ + /* update the credits */ + for (i = 0; i < ntf->num_entries; i++) { + ntf->conn_entries[i].conn_id = +@@ -138,23 +142,48 @@ static int nci_core_conn_intf_error_ntf_packet(struct nci_dev *ndev, + static const __u8 * + nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, + struct rf_tech_specific_params_nfca_poll *nfca_poll, +- const __u8 *data) ++ const __u8 *data, ssize_t data_len) + { ++ /* Check if we have enough data for sens_res (2 bytes) */ ++ if (data_len < 2) ++ return ERR_PTR(-EINVAL); ++ + nfca_poll->sens_res = __le16_to_cpu(*((__le16 *)data)); + data += 2; ++ data_len -= 2; ++ ++ /* Check if we have enough data for nfcid1_len (1 byte) */ ++ if (data_len < 1) ++ return ERR_PTR(-EINVAL); + + nfca_poll->nfcid1_len = min_t(__u8, *data++, NFC_NFCID1_MAXSIZE); ++ data_len--; + + pr_debug("sens_res 0x%x, nfcid1_len %d\n", + nfca_poll->sens_res, nfca_poll->nfcid1_len); + ++ /* Check if we have enough data for nfcid1 */ ++ if (data_len < nfca_poll->nfcid1_len) ++ return ERR_PTR(-EINVAL); ++ + memcpy(nfca_poll->nfcid1, data, nfca_poll->nfcid1_len); + data += nfca_poll->nfcid1_len; ++ data_len -= nfca_poll->nfcid1_len; ++ ++ /* Check if we have enough data for sel_res_len (1 byte) */ ++ if (data_len < 1) ++ return ERR_PTR(-EINVAL); + + nfca_poll->sel_res_len = *data++; ++ data_len--; ++ ++ if (nfca_poll->sel_res_len != 0) { ++ /* Check if we have enough data for sel_res (1 byte) */ ++ if (data_len < 1) ++ return ERR_PTR(-EINVAL); + +- if (nfca_poll->sel_res_len != 0) + nfca_poll->sel_res = *data++; ++ } + + pr_debug("sel_res_len %d, sel_res 0x%x\n", + nfca_poll->sel_res_len, +@@ -166,12 +195,21 @@ nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, + static const __u8 * + nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev, + struct rf_tech_specific_params_nfcb_poll *nfcb_poll, +- const __u8 *data) ++ const __u8 *data, ssize_t data_len) + { ++ /* Check if we have enough data for sensb_res_len (1 byte) */ ++ if (data_len < 1) ++ return ERR_PTR(-EINVAL); ++ + nfcb_poll->sensb_res_len = min_t(__u8, *data++, NFC_SENSB_RES_MAXSIZE); ++ data_len--; + + pr_debug("sensb_res_len %d\n", nfcb_poll->sensb_res_len); + ++ /* Check if we have enough data for sensb_res */ ++ if (data_len < nfcb_poll->sensb_res_len) ++ return ERR_PTR(-EINVAL); ++ + memcpy(nfcb_poll->sensb_res, data, nfcb_poll->sensb_res_len); + data += nfcb_poll->sensb_res_len; + +@@ -181,14 +219,29 @@ nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev, + static const __u8 * + nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev, + struct rf_tech_specific_params_nfcf_poll *nfcf_poll, +- const __u8 *data) ++ const __u8 *data, ssize_t data_len) + { ++ /* Check if we have enough data for bit_rate (1 byte) */ ++ if (data_len < 1) ++ return ERR_PTR(-EINVAL); ++ + nfcf_poll->bit_rate = *data++; ++ data_len--; ++ ++ /* Check if we have enough data for sensf_res_len (1 byte) */ ++ if (data_len < 1) ++ return ERR_PTR(-EINVAL); ++ + nfcf_poll->sensf_res_len = min_t(__u8, *data++, NFC_SENSF_RES_MAXSIZE); ++ data_len--; + + pr_debug("bit_rate %d, sensf_res_len %d\n", + nfcf_poll->bit_rate, nfcf_poll->sensf_res_len); + ++ /* Check if we have enough data for sensf_res */ ++ if (data_len < nfcf_poll->sensf_res_len) ++ return ERR_PTR(-EINVAL); ++ + memcpy(nfcf_poll->sensf_res, data, nfcf_poll->sensf_res_len); + data += nfcf_poll->sensf_res_len; + +@@ -198,22 +251,49 @@ nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev, + static const __u8 * + nci_extract_rf_params_nfcv_passive_poll(struct nci_dev *ndev, + struct rf_tech_specific_params_nfcv_poll *nfcv_poll, +- const __u8 *data) ++ const __u8 *data, ssize_t data_len) + { ++ /* Skip 1 byte (reserved) */ ++ if (data_len < 1) ++ return ERR_PTR(-EINVAL); ++ + ++data; ++ data_len--; ++ ++ /* Check if we have enough data for dsfid (1 byte) */ ++ if (data_len < 1) ++ return ERR_PTR(-EINVAL); ++ + nfcv_poll->dsfid = *data++; ++ data_len--; ++ ++ /* Check if we have enough data for uid (8 bytes) */ ++ if (data_len < NFC_ISO15693_UID_MAXSIZE) ++ return ERR_PTR(-EINVAL); ++ + memcpy(nfcv_poll->uid, data, NFC_ISO15693_UID_MAXSIZE); + data += NFC_ISO15693_UID_MAXSIZE; ++ + return data; + } + + static const __u8 * + nci_extract_rf_params_nfcf_passive_listen(struct nci_dev *ndev, + struct rf_tech_specific_params_nfcf_listen *nfcf_listen, +- const __u8 *data) ++ const __u8 *data, ssize_t data_len) + { ++ /* Check if we have enough data for local_nfcid2_len (1 byte) */ ++ if (data_len < 1) ++ return ERR_PTR(-EINVAL); ++ + nfcf_listen->local_nfcid2_len = min_t(__u8, *data++, + NFC_NFCID2_MAXSIZE); ++ data_len--; ++ ++ /* Check if we have enough data for local_nfcid2 */ ++ if (data_len < nfcf_listen->local_nfcid2_len) ++ return ERR_PTR(-EINVAL); ++ + memcpy(nfcf_listen->local_nfcid2, data, nfcf_listen->local_nfcid2_len); + data += nfcf_listen->local_nfcid2_len; + +@@ -364,7 +444,7 @@ static int nci_rf_discover_ntf_packet(struct nci_dev *ndev, + const __u8 *data; + bool add_target = true; + +- if (skb->len < sizeof(struct nci_rf_discover_ntf)) ++ if (skb->len < offsetofend(struct nci_rf_discover_ntf, rf_tech_specific_params_len)) + return -EINVAL; + + data = skb->data; +@@ -380,26 +460,42 @@ static int nci_rf_discover_ntf_packet(struct nci_dev *ndev, + pr_debug("rf_tech_specific_params_len %d\n", + ntf.rf_tech_specific_params_len); + ++ if (skb->len < (data - skb->data) + ++ ntf.rf_tech_specific_params_len + sizeof(ntf.ntf_type)) ++ return -EINVAL; ++ + if (ntf.rf_tech_specific_params_len > 0) { + switch (ntf.rf_tech_and_mode) { + case NCI_NFC_A_PASSIVE_POLL_MODE: + data = nci_extract_rf_params_nfca_passive_poll(ndev, +- &(ntf.rf_tech_specific_params.nfca_poll), data); ++ &(ntf.rf_tech_specific_params.nfca_poll), data, ++ ntf.rf_tech_specific_params_len); ++ if (IS_ERR(data)) ++ return PTR_ERR(data); + break; + + case NCI_NFC_B_PASSIVE_POLL_MODE: + data = nci_extract_rf_params_nfcb_passive_poll(ndev, +- &(ntf.rf_tech_specific_params.nfcb_poll), data); ++ &(ntf.rf_tech_specific_params.nfcb_poll), data, ++ ntf.rf_tech_specific_params_len); ++ if (IS_ERR(data)) ++ return PTR_ERR(data); + break; + + case NCI_NFC_F_PASSIVE_POLL_MODE: + data = nci_extract_rf_params_nfcf_passive_poll(ndev, +- &(ntf.rf_tech_specific_params.nfcf_poll), data); ++ &(ntf.rf_tech_specific_params.nfcf_poll), data, ++ ntf.rf_tech_specific_params_len); ++ if (IS_ERR(data)) ++ return PTR_ERR(data); + break; + + case NCI_NFC_V_PASSIVE_POLL_MODE: + data = nci_extract_rf_params_nfcv_passive_poll(ndev, +- &(ntf.rf_tech_specific_params.nfcv_poll), data); ++ &(ntf.rf_tech_specific_params.nfcv_poll), data, ++ ntf.rf_tech_specific_params_len); ++ if (IS_ERR(data)) ++ return PTR_ERR(data); + break; + + default: +@@ -574,7 +670,7 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, + const __u8 *data; + int err = NCI_STATUS_OK; + +- if (skb->len < sizeof(struct nci_rf_intf_activated_ntf)) ++ if (skb->len < offsetofend(struct nci_rf_intf_activated_ntf, rf_tech_specific_params_len)) + return -EINVAL; + + data = skb->data; +@@ -606,26 +702,41 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, + if (ntf.rf_interface == NCI_RF_INTERFACE_NFCEE_DIRECT) + goto listen; + ++ if (skb->len < (data - skb->data) + ntf.rf_tech_specific_params_len) ++ return -EINVAL; ++ + if (ntf.rf_tech_specific_params_len > 0) { + switch (ntf.activation_rf_tech_and_mode) { + case NCI_NFC_A_PASSIVE_POLL_MODE: + data = nci_extract_rf_params_nfca_passive_poll(ndev, +- &(ntf.rf_tech_specific_params.nfca_poll), data); ++ &(ntf.rf_tech_specific_params.nfca_poll), data, ++ ntf.rf_tech_specific_params_len); ++ if (IS_ERR(data)) ++ return -EINVAL; + break; + + case NCI_NFC_B_PASSIVE_POLL_MODE: + data = nci_extract_rf_params_nfcb_passive_poll(ndev, +- &(ntf.rf_tech_specific_params.nfcb_poll), data); ++ &(ntf.rf_tech_specific_params.nfcb_poll), data, ++ ntf.rf_tech_specific_params_len); ++ if (IS_ERR(data)) ++ return -EINVAL; + break; + + case NCI_NFC_F_PASSIVE_POLL_MODE: + data = nci_extract_rf_params_nfcf_passive_poll(ndev, +- &(ntf.rf_tech_specific_params.nfcf_poll), data); ++ &(ntf.rf_tech_specific_params.nfcf_poll), data, ++ ntf.rf_tech_specific_params_len); ++ if (IS_ERR(data)) ++ return -EINVAL; + break; + + case NCI_NFC_V_PASSIVE_POLL_MODE: + data = nci_extract_rf_params_nfcv_passive_poll(ndev, +- &(ntf.rf_tech_specific_params.nfcv_poll), data); ++ &(ntf.rf_tech_specific_params.nfcv_poll), data, ++ ntf.rf_tech_specific_params_len); ++ if (IS_ERR(data)) ++ return -EINVAL; + break; + + case NCI_NFC_A_PASSIVE_LISTEN_MODE: +@@ -635,7 +746,9 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, + case NCI_NFC_F_PASSIVE_LISTEN_MODE: + data = nci_extract_rf_params_nfcf_passive_listen(ndev, + &(ntf.rf_tech_specific_params.nfcf_listen), +- data); ++ data, ntf.rf_tech_specific_params_len); ++ if (IS_ERR(data)) ++ return -EINVAL; + break; + + default: +@@ -646,6 +759,13 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, + } + } + ++ if (skb->len < (data - skb->data) + ++ sizeof(ntf.data_exch_rf_tech_and_mode) + ++ sizeof(ntf.data_exch_tx_bit_rate) + ++ sizeof(ntf.data_exch_rx_bit_rate) + ++ sizeof(ntf.activation_params_len)) ++ return -EINVAL; ++ + ntf.data_exch_rf_tech_and_mode = *data++; + ntf.data_exch_tx_bit_rate = *data++; + ntf.data_exch_rx_bit_rate = *data++; +@@ -657,6 +777,9 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, + pr_debug("data_exch_rx_bit_rate 0x%x\n", ntf.data_exch_rx_bit_rate); + pr_debug("activation_params_len %d\n", ntf.activation_params_len); + ++ if (skb->len < (data - skb->data) + ntf.activation_params_len) ++ return -EINVAL; ++ + if (ntf.activation_params_len > 0) { + switch (ntf.rf_interface) { + case NCI_RF_INTERFACE_ISO_DEP: +diff --git a/net/rds/connection.c b/net/rds/connection.c +index b4cc699c5fad37..98c0d5ff9de9c6 100644 +--- a/net/rds/connection.c ++++ b/net/rds/connection.c +@@ -381,6 +381,8 @@ void rds_conn_shutdown(struct rds_conn_path *cp) + if (!rds_conn_path_transition(cp, RDS_CONN_UP, + RDS_CONN_DISCONNECTING) && + !rds_conn_path_transition(cp, RDS_CONN_ERROR, ++ RDS_CONN_DISCONNECTING) && ++ !rds_conn_path_transition(cp, RDS_CONN_RESETTING, + RDS_CONN_DISCONNECTING)) { + rds_conn_path_error(cp, + "shutdown called in state %d\n", +@@ -426,6 +428,8 @@ void rds_conn_shutdown(struct rds_conn_path *cp) + * to the conn hash, so we never trigger a reconnect on this + * conn - the reconnect is always triggered by the active peer. */ + cancel_delayed_work_sync(&cp->cp_conn_w); ++ ++ clear_bit(RDS_RECONNECT_PENDING, &cp->cp_flags); + rcu_read_lock(); + if (!hlist_unhashed(&conn->c_hash_node)) { + rcu_read_unlock(); +diff --git a/net/rds/send.c b/net/rds/send.c +index 09a28011065493..4a24ee9c22d7c9 100644 +--- a/net/rds/send.c ++++ b/net/rds/send.c +@@ -1382,9 +1382,11 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len) + else + queue_delayed_work(rds_wq, &cpath->cp_send_w, 1); + rcu_read_unlock(); ++ ++ if (ret) ++ goto out; + } +- if (ret) +- goto out; ++ + rds_message_put(rm); + + for (ind = 0; ind < vct.indx; ind++) +diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c +index 53b3535a1e4a84..2e2f1a67504967 100644 +--- a/net/rds/tcp_listen.c ++++ b/net/rds/tcp_listen.c +@@ -59,9 +59,6 @@ void rds_tcp_keepalive(struct socket *sock) + * socket and force a reconneect from smaller -> larger ip addr. The reason + * we special case cp_index 0 is to allow the rds probe ping itself to itself + * get through efficiently. +- * Since reconnects are only initiated from the node with the numerically +- * smaller ip address, we recycle conns in RDS_CONN_ERROR on the passive side +- * by moving them to CONNECTING in this function. + */ + static + struct rds_tcp_connection *rds_tcp_accept_one_path(struct rds_connection *conn) +@@ -86,8 +83,6 @@ struct rds_tcp_connection *rds_tcp_accept_one_path(struct rds_connection *conn) + struct rds_conn_path *cp = &conn->c_path[i]; + + if (rds_conn_path_transition(cp, RDS_CONN_DOWN, +- RDS_CONN_CONNECTING) || +- rds_conn_path_transition(cp, RDS_CONN_ERROR, + RDS_CONN_CONNECTING)) { + return cp->cp_transport_data; + } +diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c +index ce7008cf291c3f..8675be6b1a2de6 100644 +--- a/net/sched/act_skbedit.c ++++ b/net/sched/act_skbedit.c +@@ -128,7 +128,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, + struct tcf_skbedit *d; + u32 flags = 0, *priority = NULL, *mark = NULL, *mask = NULL; + u16 *queue_mapping = NULL, *ptype = NULL; +- u16 mapping_mod = 1; ++ u32 mapping_mod = 1; + bool exists = false; + int ret = 0, err; + u32 index; +@@ -196,6 +196,10 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, + } + + mapping_mod = *queue_mapping_max - *queue_mapping + 1; ++ if (mapping_mod > U16_MAX) { ++ NL_SET_ERR_MSG_MOD(extack, "The range of queue_mapping is invalid."); ++ return -EINVAL; ++ } + flags |= SKBEDIT_F_TXQ_SKBHASH; + } + if (*pure_flags & SKBEDIT_F_INHERITDSFIELD) +diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c +index 00753bc5f1b147..13a948e2f83d4f 100644 +--- a/net/sunrpc/auth_gss/auth_gss.c ++++ b/net/sunrpc/auth_gss/auth_gss.c +@@ -39,6 +39,8 @@ static const struct rpc_authops authgss_ops; + static const struct rpc_credops gss_credops; + static const struct rpc_credops gss_nullops; + ++static void gss_free_callback(struct kref *kref); ++ + #define GSS_RETRY_EXPIRED 5 + static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED; + +@@ -551,6 +553,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, + } + return gss_msg; + err_put_pipe_version: ++ kref_put(&gss_auth->kref, gss_free_callback); + put_pipe_version(gss_auth->net); + err_free_msg: + kfree(gss_msg); +diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c +index cb32ab9a839521..ee91f4d641e6fe 100644 +--- a/net/sunrpc/auth_gss/gss_rpc_xdr.c ++++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c +@@ -320,29 +320,47 @@ static int gssx_dec_status(struct xdr_stream *xdr, + + /* status->minor_status */ + p = xdr_inline_decode(xdr, 8); +- if (unlikely(p == NULL)) +- return -ENOSPC; ++ if (unlikely(p == NULL)) { ++ err = -ENOSPC; ++ goto out_free_mech; ++ } + p = xdr_decode_hyper(p, &status->minor_status); + + /* status->major_status_string */ + err = gssx_dec_buffer(xdr, &status->major_status_string); + if (err) +- return err; ++ goto out_free_mech; + + /* status->minor_status_string */ + err = gssx_dec_buffer(xdr, &status->minor_status_string); + if (err) +- return err; ++ goto out_free_major_status_string; + + /* status->server_ctx */ + err = gssx_dec_buffer(xdr, &status->server_ctx); + if (err) +- return err; ++ goto out_free_minor_status_string; + + /* we assume we have no options for now, so simply consume them */ + /* status->options */ + err = dummy_dec_opt_array(xdr, &status->options); ++ if (err) ++ goto out_free_server_ctx; + ++ return 0; ++ ++out_free_server_ctx: ++ kfree(status->server_ctx.data); ++ status->server_ctx.data = NULL; ++out_free_minor_status_string: ++ kfree(status->minor_status_string.data); ++ status->minor_status_string.data = NULL; ++out_free_major_status_string: ++ kfree(status->major_status_string.data); ++ status->major_status_string.data = NULL; ++out_free_mech: ++ kfree(status->mech.data); ++ status->mech.data = NULL; + return err; + } + +@@ -505,28 +523,35 @@ static int gssx_dec_name(struct xdr_stream *xdr, + /* name->name_type */ + err = gssx_dec_buffer(xdr, &dummy_netobj); + if (err) +- return err; ++ goto out_free_display_name; + + /* name->exported_name */ + err = gssx_dec_buffer(xdr, &dummy_netobj); + if (err) +- return err; ++ goto out_free_display_name; + + /* name->exported_composite_name */ + err = gssx_dec_buffer(xdr, &dummy_netobj); + if (err) +- return err; ++ goto out_free_display_name; + + /* we assume we have no attributes for now, so simply consume them */ + /* name->name_attributes */ + err = dummy_dec_nameattr_array(xdr, &dummy_name_attr_array); + if (err) +- return err; ++ goto out_free_display_name; + + /* we assume we have no options for now, so simply consume them */ + /* name->extensions */ + err = dummy_dec_opt_array(xdr, &dummy_option_array); ++ if (err) ++ goto out_free_display_name; + ++ return 0; ++ ++out_free_display_name: ++ kfree(name->display_name.data); ++ name->display_name.data = NULL; + return err; + } + +@@ -649,32 +674,34 @@ static int gssx_dec_ctx(struct xdr_stream *xdr, + /* ctx->state */ + err = gssx_dec_buffer(xdr, &ctx->state); + if (err) +- return err; ++ goto out_free_exported_context_token; + + /* ctx->need_release */ + err = gssx_dec_bool(xdr, &ctx->need_release); + if (err) +- return err; ++ goto out_free_state; + + /* ctx->mech */ + err = gssx_dec_buffer(xdr, &ctx->mech); + if (err) +- return err; ++ goto out_free_state; + + /* ctx->src_name */ + err = gssx_dec_name(xdr, &ctx->src_name); + if (err) +- return err; ++ goto out_free_mech; + + /* ctx->targ_name */ + err = gssx_dec_name(xdr, &ctx->targ_name); + if (err) +- return err; ++ goto out_free_src_name; + + /* ctx->lifetime */ + p = xdr_inline_decode(xdr, 8+8); +- if (unlikely(p == NULL)) +- return -ENOSPC; ++ if (unlikely(p == NULL)) { ++ err = -ENOSPC; ++ goto out_free_targ_name; ++ } + p = xdr_decode_hyper(p, &ctx->lifetime); + + /* ctx->ctx_flags */ +@@ -683,17 +710,36 @@ static int gssx_dec_ctx(struct xdr_stream *xdr, + /* ctx->locally_initiated */ + err = gssx_dec_bool(xdr, &ctx->locally_initiated); + if (err) +- return err; ++ goto out_free_targ_name; + + /* ctx->open */ + err = gssx_dec_bool(xdr, &ctx->open); + if (err) +- return err; ++ goto out_free_targ_name; + + /* we assume we have no options for now, so simply consume them */ + /* ctx->options */ + err = dummy_dec_opt_array(xdr, &ctx->options); ++ if (err) ++ goto out_free_targ_name; ++ ++ return 0; + ++out_free_targ_name: ++ kfree(ctx->targ_name.display_name.data); ++ ctx->targ_name.display_name.data = NULL; ++out_free_src_name: ++ kfree(ctx->src_name.display_name.data); ++ ctx->src_name.display_name.data = NULL; ++out_free_mech: ++ kfree(ctx->mech.data); ++ ctx->mech.data = NULL; ++out_free_state: ++ kfree(ctx->state.data); ++ ctx->state.data = NULL; ++out_free_exported_context_token: ++ kfree(ctx->exported_context_token.data); ++ ctx->exported_context_token.data = NULL; + return err; + } + +diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c +index 2abd895046ee3d..b8d13b522298b8 100644 +--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c ++++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c +@@ -363,12 +363,12 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, + */ + static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) + { ++ unsigned int ctxts, rq_depth, maxpayload; + struct svcxprt_rdma *listen_rdma; + struct svcxprt_rdma *newxprt = NULL; + struct rdma_conn_param conn_param; + struct rpcrdma_connect_private pmsg; + struct ib_qp_init_attr qp_attr; +- unsigned int ctxts, rq_depth; + struct ib_device *dev; + int ret = 0; + RPC_IFDEBUG(struct sockaddr *sap); +@@ -391,37 +391,46 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) + dev = newxprt->sc_cm_id->device; + newxprt->sc_port_num = newxprt->sc_cm_id->port_num; + +- /* Qualify the transport resource defaults with the +- * capabilities of this particular device */ ++ newxprt->sc_max_req_size = svcrdma_max_req_size; ++ newxprt->sc_max_requests = svcrdma_max_requests; ++ newxprt->sc_max_bc_requests = svcrdma_max_bc_requests; ++ newxprt->sc_recv_batch = RPCRDMA_MAX_RECV_BATCH; ++ newxprt->sc_fc_credits = cpu_to_be32(newxprt->sc_max_requests); ++ ++ /* Qualify the transport's resource defaults with the ++ * capabilities of this particular device. ++ */ ++ + /* Transport header, head iovec, tail iovec */ + newxprt->sc_max_send_sges = 3; + /* Add one SGE per page list entry */ + newxprt->sc_max_send_sges += (svcrdma_max_req_size / PAGE_SIZE) + 1; + if (newxprt->sc_max_send_sges > dev->attrs.max_send_sge) + newxprt->sc_max_send_sges = dev->attrs.max_send_sge; +- newxprt->sc_max_req_size = svcrdma_max_req_size; +- newxprt->sc_max_requests = svcrdma_max_requests; +- newxprt->sc_max_bc_requests = svcrdma_max_bc_requests; +- newxprt->sc_recv_batch = RPCRDMA_MAX_RECV_BATCH; + rq_depth = newxprt->sc_max_requests + newxprt->sc_max_bc_requests + + newxprt->sc_recv_batch; + if (rq_depth > dev->attrs.max_qp_wr) { +- pr_warn("svcrdma: reducing receive depth to %d\n", +- dev->attrs.max_qp_wr); + rq_depth = dev->attrs.max_qp_wr; + newxprt->sc_recv_batch = 1; + newxprt->sc_max_requests = rq_depth - 2; + newxprt->sc_max_bc_requests = 2; + } +- newxprt->sc_fc_credits = cpu_to_be32(newxprt->sc_max_requests); +- ctxts = rdma_rw_mr_factor(dev, newxprt->sc_port_num, RPCSVC_MAXPAGES); +- ctxts *= newxprt->sc_max_requests; +- newxprt->sc_sq_depth = rq_depth + ctxts; +- if (newxprt->sc_sq_depth > dev->attrs.max_qp_wr) { +- pr_warn("svcrdma: reducing send depth to %d\n", +- dev->attrs.max_qp_wr); ++ ++ /* Estimate the needed number of rdma_rw contexts. The maximum ++ * Read and Write chunks have one segment each. Each request ++ * can involve one Read chunk and either a Write chunk or Reply ++ * chunk; thus a factor of three. ++ */ ++ maxpayload = min(xprt->xpt_server->sv_max_payload, ++ RPCSVC_MAXPAYLOAD_RDMA); ++ ctxts = newxprt->sc_max_requests * 3 * ++ rdma_rw_mr_factor(dev, newxprt->sc_port_num, ++ maxpayload >> PAGE_SHIFT); ++ ++ newxprt->sc_sq_depth = rq_depth + ++ rdma_rw_max_send_wr(dev, newxprt->sc_port_num, ctxts, 0); ++ if (newxprt->sc_sq_depth > dev->attrs.max_qp_wr) + newxprt->sc_sq_depth = dev->attrs.max_qp_wr; +- } + atomic_set(&newxprt->sc_sq_avail, newxprt->sc_sq_depth); + + newxprt->sc_pd = ib_alloc_pd(dev, 0); +diff --git a/net/tipc/crypto.c b/net/tipc/crypto.c +index 2721baf9fd2b32..d7736d90027155 100644 +--- a/net/tipc/crypto.c ++++ b/net/tipc/crypto.c +@@ -460,7 +460,7 @@ static void tipc_aead_users_dec(struct tipc_aead __rcu *aead, int lim) + rcu_read_lock(); + tmp = rcu_dereference(aead); + if (tmp) +- atomic_add_unless(&rcu_dereference(aead)->users, -1, lim); ++ atomic_add_unless(&tmp->users, -1, lim); + rcu_read_unlock(); + } + +diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c +index d1180370fdf41c..e6555254ddb85f 100644 +--- a/net/tipc/name_table.c ++++ b/net/tipc/name_table.c +@@ -348,7 +348,8 @@ static bool tipc_service_insert_publ(struct net *net, + + /* Return if the publication already exists */ + list_for_each_entry(_p, &sr->all_publ, all_publ) { +- if (_p->key == key && (!_p->sk.node || _p->sk.node == node)) { ++ if (_p->key == key && _p->sk.ref == p->sk.ref && ++ (!_p->sk.node || _p->sk.node == node)) { + pr_debug("Failed to bind duplicate %u,%u,%u/%u:%u/%u\n", + p->sr.type, p->sr.lower, p->sr.upper, + node, p->sk.ref, key); +@@ -388,7 +389,8 @@ static struct publication *tipc_service_remove_publ(struct service_range *r, + u32 node = sk->node; + + list_for_each_entry(p, &r->all_publ, all_publ) { +- if (p->key != key || (node && node != p->sk.node)) ++ if (p->key != key || p->sk.ref != sk->ref || ++ (node && node != p->sk.node)) + continue; + list_del(&p->all_publ); + list_del(&p->local_publ); +diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c +index 7eccd6708d6649..aca3132689cf18 100644 +--- a/net/vmw_vsock/vmci_transport.c ++++ b/net/vmw_vsock/vmci_transport.c +@@ -161,7 +161,7 @@ vmci_transport_packet_init(struct vmci_transport_packet *pkt, + + case VMCI_TRANSPORT_PACKET_TYPE_WAITING_READ: + case VMCI_TRANSPORT_PACKET_TYPE_WAITING_WRITE: +- memcpy(&pkt->u.wait, wait, sizeof(pkt->u.wait)); ++ pkt->u.wait = *wait; + break; + + case VMCI_TRANSPORT_PACKET_TYPE_REQUEST2: +diff --git a/net/wireless/core.c b/net/wireless/core.c +index f6693983b5e986..0baa4c6ab16940 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1331,8 +1331,10 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev, + __cfg80211_leave_ocb(rdev, dev); + break; + case NL80211_IFTYPE_P2P_DEVICE: ++ cfg80211_stop_p2p_device(rdev, wdev); ++ break; + case NL80211_IFTYPE_NAN: +- /* cannot happen, has no netdev */ ++ cfg80211_stop_nan(rdev, wdev); + break; + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_MONITOR: +diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c +index e3acfac7430ae0..52abda40dfb3f2 100644 +--- a/net/wireless/wext-compat.c ++++ b/net/wireless/wext-compat.c +@@ -735,7 +735,7 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev, + + idx = erq->flags & IW_ENCODE_INDEX; + if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) { +- if (idx < 4 || idx > 5) { ++ if (idx < 5 || idx > 6) { + idx = wdev->wext.default_mgmt_key; + if (idx < 0) + return -EINVAL; +diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c +index 7188d3592dde4e..a73b3c9d7e4d42 100644 +--- a/net/xfrm/xfrm_device.c ++++ b/net/xfrm/xfrm_device.c +@@ -515,6 +515,14 @@ static int xfrm_dev_down(struct net_device *dev) + return NOTIFY_DONE; + } + ++static int xfrm_dev_unregister(struct net_device *dev) ++{ ++ xfrm_dev_state_flush(dev_net(dev), dev, true); ++ xfrm_dev_policy_flush(dev_net(dev), dev, true); ++ ++ return NOTIFY_DONE; ++} ++ + static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) + { + struct net_device *dev = netdev_notifier_info_to_dev(ptr); +@@ -527,8 +535,10 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void + return xfrm_api_check(dev); + + case NETDEV_DOWN: +- case NETDEV_UNREGISTER: + return xfrm_dev_down(dev); ++ ++ case NETDEV_UNREGISTER: ++ return xfrm_dev_unregister(dev); + } + return NOTIFY_DONE; + } +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 2edb0f868c5738..b516dd15113ed6 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -3734,8 +3734,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, + struct xfrm_tmpl *tp[XFRM_MAX_DEPTH]; + struct xfrm_tmpl *stp[XFRM_MAX_DEPTH]; + struct xfrm_tmpl **tpp = tp; ++ int i, k = 0; + int ti = 0; +- int i, k; + + sp = skb_sec_path(skb); + if (!sp) +@@ -3761,6 +3761,12 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, + tpp = stp; + } + ++ if (pol->xdo.type == XFRM_DEV_OFFLOAD_PACKET && sp == &dummy) ++ /* This policy template was already checked by HW ++ * and secpath was removed in __xfrm_policy_check2. ++ */ ++ goto out; ++ + /* For each tunnel xfrm, find the first matching tmpl. + * For each tmpl before that, find corresponding xfrm. + * Order is _important_. Later we will implement +@@ -3770,7 +3776,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, + * verified to allow them to be skipped in future policy + * checks (e.g. nested tunnels). + */ +- for (i = xfrm_nr-1, k = 0; i >= 0; i--) { ++ for (i = xfrm_nr - 1; i >= 0; i--) { + k = xfrm_policy_ok(tpp[i], sp, k, family, if_id); + if (k < 0) { + if (k < -1) +@@ -3786,6 +3792,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, + goto reject; + } + ++out: + xfrm_pols_put(pols, npols); + sp->verified_cnt = k; + +diff --git a/scripts/kernel-doc b/scripts/kernel-doc +index 6e199a745ccb25..d963fdf40e9006 100755 +--- a/scripts/kernel-doc ++++ b/scripts/kernel-doc +@@ -1592,6 +1592,11 @@ sub push_parameter($$$$$) { + $parameterdescs{$param} = "anonymous\n"; + $anon_struct_union = 1; + } ++ elsif ($param =~ "__cacheline_group" ) ++ # handle cache group enforcing variables: they do not need be described in header files ++ { ++ return; # ignore __cacheline_group_begin and __cacheline_group_end ++ } + + # warn if parameter has no description + # (but ignore ones starting with # as these are not parameters +diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c +index 3eb7fda8a98ff4..96a6e68730981b 100644 +--- a/scripts/mod/modpost.c ++++ b/scripts/mod/modpost.c +@@ -608,6 +608,10 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname) + /* Special register function linked on all modules during final link of .ko */ + if (strstarts(symname, "_restgpr0_") || + strstarts(symname, "_savegpr0_") || ++ strstarts(symname, "_restgpr1_") || ++ strstarts(symname, "_savegpr1_") || ++ strstarts(symname, "_restfpr_") || ++ strstarts(symname, "_savefpr_") || + strstarts(symname, "_restvr_") || + strstarts(symname, "_savevr_") || + strcmp(symname, ".TOC.") == 0) +diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c +index 23b2853ce3c428..6885ecd4afddca 100644 +--- a/security/apparmor/apparmorfs.c ++++ b/security/apparmor/apparmorfs.c +@@ -619,23 +619,23 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms, + + if (profile_unconfined(profile)) + return; +- if (rules->file.dfa && *match_str == AA_CLASS_FILE) { +- state = aa_dfa_match_len(rules->file.dfa, +- rules->file.start[AA_CLASS_FILE], ++ if (rules->file->dfa && *match_str == AA_CLASS_FILE) { ++ state = aa_dfa_match_len(rules->file->dfa, ++ rules->file->start[AA_CLASS_FILE], + match_str + 1, match_len - 1); + if (state) { + struct path_cond cond = { }; + +- tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); ++ tmp = *(aa_lookup_fperms(rules->file, state, &cond)); + } +- } else if (rules->policy.dfa) { ++ } else if (rules->policy->dfa) { + if (!RULE_MEDIATES(rules, *match_str)) + return; /* no change to current perms */ +- state = aa_dfa_match_len(rules->policy.dfa, +- rules->policy.start[0], ++ state = aa_dfa_match_len(rules->policy->dfa, ++ rules->policy->start[0], + match_str, match_len); + if (state) +- tmp = *aa_lookup_perms(&rules->policy, state); ++ tmp = *aa_lookup_perms(rules->policy, state); + } + aa_apply_modes_to_perms(profile, &tmp); + aa_perms_accum_raw(perms, &tmp); +@@ -1096,7 +1096,7 @@ static int seq_profile_attach_show(struct seq_file *seq, void *v) + struct aa_profile *profile = labels_profile(label); + if (profile->attach.xmatch_str) + seq_printf(seq, "%s\n", profile->attach.xmatch_str); +- else if (profile->attach.xmatch.dfa) ++ else if (profile->attach.xmatch->dfa) + seq_puts(seq, "\n"); + else + seq_printf(seq, "%s\n", profile->base.name); +@@ -1637,6 +1637,15 @@ static const char *rawdata_get_link_base(struct dentry *dentry, + + label = aa_get_label_rcu(&proxy->label); + profile = labels_profile(label); ++ ++ /* rawdata can be null when aa_g_export_binary is unset during ++ * runtime and a profile is replaced ++ */ ++ if (!profile->rawdata) { ++ aa_put_label(label); ++ return ERR_PTR(-ENOENT); ++ } ++ + depth = profile_depth(profile); + target = gen_symlink_name(depth, profile->rawdata->name, name); + aa_put_label(label); +diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c +index 543105cf7e334d..d6500ec4f6b636 100644 +--- a/security/apparmor/domain.c ++++ b/security/apparmor/domain.c +@@ -77,7 +77,7 @@ out: + /**** TODO: dedup to aa_label_match - needs perm and dfa, merging + * specifically this is an exact copy of aa_label_match except + * aa_compute_perms is replaced with aa_compute_fperms +- * and policy.dfa with file.dfa ++ * and policy->dfa with file->dfa + ****/ + /* match a profile and its associated ns component if needed + * Assumes visibility test has already been done. +@@ -93,16 +93,16 @@ static inline aa_state_t match_component(struct aa_profile *profile, + const char *ns_name; + + if (stack) +- state = aa_dfa_match(rules->file.dfa, state, "&"); ++ state = aa_dfa_match(rules->file->dfa, state, "&"); + if (profile->ns == tp->ns) +- return aa_dfa_match(rules->file.dfa, state, tp->base.hname); ++ return aa_dfa_match(rules->file->dfa, state, tp->base.hname); + + /* try matching with namespace name and then profile */ + ns_name = aa_ns_name(profile->ns, tp->ns, true); +- state = aa_dfa_match_len(rules->file.dfa, state, ":", 1); +- state = aa_dfa_match(rules->file.dfa, state, ns_name); +- state = aa_dfa_match_len(rules->file.dfa, state, ":", 1); +- return aa_dfa_match(rules->file.dfa, state, tp->base.hname); ++ state = aa_dfa_match_len(rules->file->dfa, state, ":", 1); ++ state = aa_dfa_match(rules->file->dfa, state, ns_name); ++ state = aa_dfa_match_len(rules->file->dfa, state, ":", 1); ++ return aa_dfa_match(rules->file->dfa, state, tp->base.hname); + } + + /** +@@ -150,12 +150,12 @@ next: + label_for_each_cont(i, label, tp) { + if (!aa_ns_visible(profile->ns, tp->ns, subns)) + continue; +- state = aa_dfa_match(rules->file.dfa, state, "//&"); ++ state = aa_dfa_match(rules->file->dfa, state, "//&"); + state = match_component(profile, tp, false, state); + if (!state) + goto fail; + } +- *perms = *(aa_lookup_fperms(&(rules->file), state, &cond)); ++ *perms = *(aa_lookup_fperms(rules->file, state, &cond)); + aa_apply_modes_to_perms(profile, perms); + if ((perms->allow & request) != request) + return -EACCES; +@@ -210,7 +210,7 @@ static int label_components_match(struct aa_profile *profile, + return 0; + + next: +- tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); ++ tmp = *(aa_lookup_fperms(rules->file, state, &cond)); + aa_apply_modes_to_perms(profile, &tmp); + aa_perms_accum(perms, &tmp); + label_for_each_cont(i, label, tp) { +@@ -219,7 +219,7 @@ next: + state = match_component(profile, tp, stack, start); + if (!state) + goto fail; +- tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); ++ tmp = *(aa_lookup_fperms(rules->file, state, &cond)); + aa_apply_modes_to_perms(profile, &tmp); + aa_perms_accum(perms, &tmp); + } +@@ -316,7 +316,7 @@ static int aa_xattrs_match(const struct linux_binprm *bprm, + might_sleep(); + + /* transition from exec match to xattr set */ +- state = aa_dfa_outofband_transition(attach->xmatch.dfa, state); ++ state = aa_dfa_outofband_transition(attach->xmatch->dfa, state); + d = bprm->file->f_path.dentry; + + for (i = 0; i < attach->xattr_count; i++) { +@@ -330,20 +330,20 @@ static int aa_xattrs_match(const struct linux_binprm *bprm, + * that not present xattr can be distinguished from a 0 + * length value or rule that matches any value + */ +- state = aa_dfa_null_transition(attach->xmatch.dfa, ++ state = aa_dfa_null_transition(attach->xmatch->dfa, + state); + /* Check xattr value */ +- state = aa_dfa_match_len(attach->xmatch.dfa, state, ++ state = aa_dfa_match_len(attach->xmatch->dfa, state, + value, size); +- index = ACCEPT_TABLE(attach->xmatch.dfa)[state]; +- perm = attach->xmatch.perms[index].allow; ++ index = ACCEPT_TABLE(attach->xmatch->dfa)[state]; ++ perm = attach->xmatch->perms[index].allow; + if (!(perm & MAY_EXEC)) { + ret = -EINVAL; + goto out; + } + } + /* transition to next element */ +- state = aa_dfa_outofband_transition(attach->xmatch.dfa, state); ++ state = aa_dfa_outofband_transition(attach->xmatch->dfa, state); + if (size < 0) { + /* + * No xattr match, so verify if transition to +@@ -412,16 +412,16 @@ restart: + * as another profile, signal a conflict and refuse to + * match. + */ +- if (attach->xmatch.dfa) { ++ if (attach->xmatch->dfa) { + unsigned int count; + aa_state_t state; + u32 index, perm; + +- state = aa_dfa_leftmatch(attach->xmatch.dfa, +- attach->xmatch.start[AA_CLASS_XMATCH], ++ state = aa_dfa_leftmatch(attach->xmatch->dfa, ++ attach->xmatch->start[AA_CLASS_XMATCH], + name, &count); +- index = ACCEPT_TABLE(attach->xmatch.dfa)[state]; +- perm = attach->xmatch.perms[index].allow; ++ index = ACCEPT_TABLE(attach->xmatch->dfa)[state]; ++ perm = attach->xmatch->perms[index].allow; + /* any accepting state means a valid match. */ + if (perm & MAY_EXEC) { + int ret = 0; +@@ -524,7 +524,7 @@ struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, + /* TODO: move lookup parsing to unpack time so this is a straight + * index into the resultant label + */ +- for (*name = rules->file.trans.table[index]; !label && *name; ++ for (*name = rules->file->trans.table[index]; !label && *name; + *name = next_name(xtype, *name)) { + if (xindex & AA_X_CHILD) { + struct aa_profile *new_profile; +@@ -577,7 +577,7 @@ static struct aa_label *x_to_label(struct aa_profile *profile, + break; + case AA_X_TABLE: + /* TODO: fix when perm mapping done at unload */ +- stack = rules->file.trans.table[xindex & AA_X_INDEX_MASK]; ++ stack = rules->file->trans.table[xindex & AA_X_INDEX_MASK]; + if (*stack != '&') { + /* released by caller */ + new = x_table_lookup(profile, xindex, lookupname); +@@ -636,7 +636,7 @@ static struct aa_label *profile_transition(const struct cred *subj_cred, + typeof(*rules), list); + struct aa_label *new = NULL; + const char *info = NULL, *name = NULL, *target = NULL; +- aa_state_t state = rules->file.start[AA_CLASS_FILE]; ++ aa_state_t state = rules->file->start[AA_CLASS_FILE]; + struct aa_perms perms = {}; + bool nonewprivs = false; + int error = 0; +@@ -670,7 +670,7 @@ static struct aa_label *profile_transition(const struct cred *subj_cred, + } + + /* find exec permissions for name */ +- state = aa_str_perms(&(rules->file), state, name, cond, &perms); ++ state = aa_str_perms(rules->file, state, name, cond, &perms); + if (perms.allow & MAY_EXEC) { + /* exec permission determine how to transition */ + new = x_to_label(profile, bprm, name, perms.xindex, &target, +@@ -736,7 +736,7 @@ static int profile_onexec(const struct cred *subj_cred, + { + struct aa_ruleset *rules = list_first_entry(&profile->rules, + typeof(*rules), list); +- aa_state_t state = rules->file.start[AA_CLASS_FILE]; ++ aa_state_t state = rules->file->start[AA_CLASS_FILE]; + struct aa_perms perms = {}; + const char *xname = NULL, *info = "change_profile onexec"; + int error = -EACCES; +@@ -769,7 +769,7 @@ static int profile_onexec(const struct cred *subj_cred, + } + + /* find exec permissions for name */ +- state = aa_str_perms(&(rules->file), state, xname, cond, &perms); ++ state = aa_str_perms(rules->file, state, xname, cond, &perms); + if (!(perms.allow & AA_MAY_ONEXEC)) { + info = "no change_onexec valid for executable"; + goto audit; +@@ -778,7 +778,7 @@ static int profile_onexec(const struct cred *subj_cred, + * onexec permission is linked to exec with a standard pairing + * exec\0change_profile + */ +- state = aa_dfa_null_transition(rules->file.dfa, state); ++ state = aa_dfa_null_transition(rules->file->dfa, state); + error = change_profile_perms(profile, onexec, stack, AA_MAY_ONEXEC, + state, &perms); + if (error) { +@@ -1298,7 +1298,7 @@ static int change_profile_perms_wrapper(const char *op, const char *name, + + if (!error) + error = change_profile_perms(profile, target, stack, request, +- rules->file.start[AA_CLASS_FILE], ++ rules->file->start[AA_CLASS_FILE], + perms); + if (error) + error = aa_audit_file(subj_cred, profile, perms, op, request, +diff --git a/security/apparmor/file.c b/security/apparmor/file.c +index a51b83cf696899..e9e71d7bdcb6eb 100644 +--- a/security/apparmor/file.c ++++ b/security/apparmor/file.c +@@ -236,7 +236,7 @@ static int __aa_path_perm(const char *op, const struct cred *subj_cred, + + if (profile_unconfined(profile)) + return 0; +- aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], ++ aa_str_perms(rules->file, rules->file->start[AA_CLASS_FILE], + name, cond, perms); + if (request & ~perms->allow) + e = -EACCES; +@@ -353,16 +353,16 @@ static int profile_path_link(const struct cred *subj_cred, + + error = -EACCES; + /* aa_str_perms - handles the case of the dfa being NULL */ +- state = aa_str_perms(&(rules->file), +- rules->file.start[AA_CLASS_FILE], lname, ++ state = aa_str_perms(rules->file, ++ rules->file->start[AA_CLASS_FILE], lname, + cond, &lperms); + + if (!(lperms.allow & AA_MAY_LINK)) + goto audit; + + /* test to see if target can be paired with link */ +- state = aa_dfa_null_transition(rules->file.dfa, state); +- aa_str_perms(&(rules->file), state, tname, cond, &perms); ++ state = aa_dfa_null_transition(rules->file->dfa, state); ++ aa_str_perms(rules->file, state, tname, cond, &perms); + + /* force audit/quiet masks for link are stored in the second entry + * in the link pair. +@@ -384,7 +384,7 @@ static int profile_path_link(const struct cred *subj_cred, + /* Do link perm subset test requiring allowed permission on link are + * a subset of the allowed permissions on target. + */ +- aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], ++ aa_str_perms(rules->file, rules->file->start[AA_CLASS_FILE], + tname, cond, &perms); + + /* AA_MAY_LINK is not considered in the subset test */ +diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h +index 6e88e99da80f6b..1ec00113a056fc 100644 +--- a/security/apparmor/include/lib.h ++++ b/security/apparmor/include/lib.h +@@ -16,6 +16,8 @@ + + #include "match.h" + ++extern struct aa_dfa *stacksplitdfa; ++ + /* + * DEBUG remains global (no per profile flag) since it is mostly used in sysctl + * which is not related to profile accesses. +diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h +index e59305abb85a33..ae31a8a631fc6a 100644 +--- a/security/apparmor/include/match.h ++++ b/security/apparmor/include/match.h +@@ -102,9 +102,6 @@ struct aa_dfa { + struct table_header *tables[YYTD_ID_TSIZE]; + }; + +-extern struct aa_dfa *nulldfa; +-extern struct aa_dfa *stacksplitdfa; +- + #define byte_to_byte(X) (X) + + #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX) \ +@@ -122,9 +119,6 @@ static inline size_t table_size(size_t len, size_t el_size) + return ALIGN(sizeof(struct table_header) + len * el_size, 8); + } + +-int aa_setup_dfa_engine(void); +-void aa_teardown_dfa_engine(void); +- + #define aa_state_t unsigned int + + struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags); +diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h +index fa15a5c7febb89..bb682d51341299 100644 +--- a/security/apparmor/include/policy.h ++++ b/security/apparmor/include/policy.h +@@ -74,12 +74,14 @@ enum profile_mode { + + + /* struct aa_policydb - match engine for a policy ++ * count: refcount for the pdb + * dfa: dfa pattern match + * perms: table of permissions + * strs: table of strings, index by x + * start: set of start states for the different classes of data + */ + struct aa_policydb { ++ struct kref count; + struct aa_dfa *dfa; + struct { + struct aa_perms *perms; +@@ -89,13 +91,36 @@ struct aa_policydb { + aa_state_t start[AA_CLASS_LAST + 1]; + }; + +-static inline void aa_destroy_policydb(struct aa_policydb *policy) ++extern struct aa_policydb *nullpdb; ++ ++struct aa_policydb *aa_alloc_pdb(gfp_t gfp); ++void aa_pdb_free_kref(struct kref *kref); ++ ++/** ++ * aa_get_pdb - increment refcount on @pdb ++ * @pdb: policydb (MAYBE NULL) ++ * ++ * Returns: pointer to @pdb if @pdb is NULL will return NULL ++ * Requires: @pdb must be held with valid refcount when called ++ */ ++static inline struct aa_policydb *aa_get_pdb(struct aa_policydb *pdb) + { +- aa_put_dfa(policy->dfa); +- if (policy->perms) +- kvfree(policy->perms); +- aa_free_str_table(&policy->trans); ++ if (pdb) ++ kref_get(&(pdb->count)); + ++ return pdb; ++} ++ ++/** ++ * aa_put_pdb - put a pdb refcount ++ * @pdb: pdb to put refcount (MAYBE NULL) ++ * ++ * Requires: if @pdb != NULL that a valid refcount be held ++ */ ++static inline void aa_put_pdb(struct aa_policydb *pdb) ++{ ++ if (pdb) ++ kref_put(&pdb->count, aa_pdb_free_kref); + } + + static inline struct aa_perms *aa_lookup_perms(struct aa_policydb *policy, +@@ -139,8 +164,8 @@ struct aa_ruleset { + int size; + + /* TODO: merge policy and file */ +- struct aa_policydb policy; +- struct aa_policydb file; ++ struct aa_policydb *policy; ++ struct aa_policydb *file; + struct aa_caps caps; + + struct aa_rlimit rlimits; +@@ -159,7 +184,7 @@ struct aa_ruleset { + */ + struct aa_attachment { + const char *xmatch_str; +- struct aa_policydb xmatch; ++ struct aa_policydb *xmatch; + unsigned int xmatch_len; + int xattr_count; + char **xattrs; +@@ -276,10 +301,10 @@ static inline aa_state_t RULE_MEDIATES(struct aa_ruleset *rules, + unsigned char class) + { + if (class <= AA_CLASS_LAST) +- return rules->policy.start[class]; ++ return rules->policy->start[class]; + else +- return aa_dfa_match_len(rules->policy.dfa, +- rules->policy.start[0], &class, 1); ++ return aa_dfa_match_len(rules->policy->dfa, ++ rules->policy->start[0], &class, 1); + } + + static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF) +@@ -289,7 +314,7 @@ static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF) + + if (!state) + return DFA_NOMATCH; +- return aa_dfa_match_len(rules->policy.dfa, state, (char *) &be_af, 2); ++ return aa_dfa_match_len(rules->policy->dfa, state, (char *) &be_af, 2); + } + + static inline aa_state_t ANY_RULE_MEDIATES(struct list_head *head, +diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c +index c0d0dbd7b4c4b3..0cdf4340b02d5b 100644 +--- a/security/apparmor/ipc.c ++++ b/security/apparmor/ipc.c +@@ -92,8 +92,8 @@ static int profile_signal_perm(const struct cred *cred, + ad->subj_cred = cred; + ad->peer = peer; + /* TODO: secondary cache check */ +- state = aa_dfa_next(rules->policy.dfa, +- rules->policy.start[AA_CLASS_SIGNAL], ++ state = aa_dfa_next(rules->policy->dfa, ++ rules->policy->start[AA_CLASS_SIGNAL], + ad->signal); + aa_label_match(profile, rules, peer, state, false, request, &perms); + aa_apply_modes_to_perms(profile, &perms); +diff --git a/security/apparmor/label.c b/security/apparmor/label.c +index 8a2af96f4da57b..d64c838f5d84e6 100644 +--- a/security/apparmor/label.c ++++ b/security/apparmor/label.c +@@ -1269,14 +1269,14 @@ static inline aa_state_t match_component(struct aa_profile *profile, + const char *ns_name; + + if (profile->ns == tp->ns) +- return aa_dfa_match(rules->policy.dfa, state, tp->base.hname); ++ return aa_dfa_match(rules->policy->dfa, state, tp->base.hname); + + /* try matching with namespace name and then profile */ + ns_name = aa_ns_name(profile->ns, tp->ns, true); +- state = aa_dfa_match_len(rules->policy.dfa, state, ":", 1); +- state = aa_dfa_match(rules->policy.dfa, state, ns_name); +- state = aa_dfa_match_len(rules->policy.dfa, state, ":", 1); +- return aa_dfa_match(rules->policy.dfa, state, tp->base.hname); ++ state = aa_dfa_match_len(rules->policy->dfa, state, ":", 1); ++ state = aa_dfa_match(rules->policy->dfa, state, ns_name); ++ state = aa_dfa_match_len(rules->policy->dfa, state, ":", 1); ++ return aa_dfa_match(rules->policy->dfa, state, tp->base.hname); + } + + /** +@@ -1288,7 +1288,7 @@ static inline aa_state_t match_component(struct aa_profile *profile, + * @request: permissions to request + * @perms: perms struct to set + * +- * Returns: 0 on success else ERROR ++ * Returns: state match stopped at or DFA_NOMATCH if aborted early + * + * For the label A//&B//&C this does the perm match for A//&B//&C + * @perms should be preinitialized with allperms OR a previous permission +@@ -1315,27 +1315,23 @@ static int label_compound_match(struct aa_profile *profile, + + /* no component visible */ + *perms = allperms; +- return 0; ++ return state; + + next: + label_for_each_cont(i, label, tp) { + if (!aa_ns_visible(profile->ns, tp->ns, subns)) + continue; +- state = aa_dfa_match(rules->policy.dfa, state, "//&"); ++ state = aa_dfa_match(rules->policy->dfa, state, "//&"); + state = match_component(profile, rules, tp, state); + if (!state) + goto fail; + } +- *perms = *aa_lookup_perms(&rules->policy, state); +- aa_apply_modes_to_perms(profile, perms); +- if ((perms->allow & request) != request) +- return -EACCES; +- +- return 0; ++ *perms = *aa_lookup_perms(rules->policy, state); ++ return state; + + fail: + *perms = nullperms; +- return state; ++ return DFA_NOMATCH; + } + + /** +@@ -1348,7 +1344,7 @@ fail: + * @request: permissions to request + * @perms: an initialized perms struct to add accumulation to + * +- * Returns: 0 on success else ERROR ++ * Returns: the state the match finished in, may be the none matching state + * + * For the label A//&B//&C this does the perm match for each of A and B and C + * @perms should be preinitialized with allperms OR a previous permission +@@ -1376,11 +1372,10 @@ static int label_components_match(struct aa_profile *profile, + } + + /* no subcomponents visible - no change in perms */ +- return 0; ++ return state; + + next: +- tmp = *aa_lookup_perms(&rules->policy, state); +- aa_apply_modes_to_perms(profile, &tmp); ++ tmp = *aa_lookup_perms(rules->policy, state); + aa_perms_accum(perms, &tmp); + label_for_each_cont(i, label, tp) { + if (!aa_ns_visible(profile->ns, tp->ns, subns)) +@@ -1388,19 +1383,18 @@ next: + state = match_component(profile, rules, tp, start); + if (!state) + goto fail; +- tmp = *aa_lookup_perms(&rules->policy, state); +- aa_apply_modes_to_perms(profile, &tmp); ++ tmp = *aa_lookup_perms(rules->policy, state); + aa_perms_accum(perms, &tmp); + } + + if ((perms->allow & request) != request) +- return -EACCES; ++ return DFA_NOMATCH; + +- return 0; ++ return state; + + fail: + *perms = nullperms; +- return -EACCES; ++ return DFA_NOMATCH; + } + + /** +@@ -1419,11 +1413,12 @@ int aa_label_match(struct aa_profile *profile, struct aa_ruleset *rules, + struct aa_label *label, aa_state_t state, bool subns, + u32 request, struct aa_perms *perms) + { +- int error = label_compound_match(profile, rules, label, state, subns, +- request, perms); +- if (!error) +- return error; ++ aa_state_t tmp = label_compound_match(profile, rules, label, state, subns, ++ request, perms); ++ if ((perms->allow & request) == request) ++ return tmp; + ++ /* failed compound_match try component matches */ + *perms = allperms; + return label_components_match(profile, rules, label, state, subns, + request, perms); +diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c +index 7182a8b821fbdb..cd569fbbfe36d2 100644 +--- a/security/apparmor/lib.c ++++ b/security/apparmor/lib.c +@@ -342,8 +342,8 @@ void aa_profile_match_label(struct aa_profile *profile, + /* TODO: doesn't yet handle extended types */ + aa_state_t state; + +- state = aa_dfa_next(rules->policy.dfa, +- rules->policy.start[AA_CLASS_LABEL], ++ state = aa_dfa_next(rules->policy->dfa, ++ rules->policy->start[AA_CLASS_LABEL], + type); + aa_label_match(profile, rules, label, state, false, request, perms); + } +diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c +index 5303a51eff9c10..641f6510d7cb0d 100644 +--- a/security/apparmor/lsm.c ++++ b/security/apparmor/lsm.c +@@ -1909,6 +1909,69 @@ static int __init apparmor_nf_ip_init(void) + __initcall(apparmor_nf_ip_init); + #endif + ++static char nulldfa_src[] = { ++ #include "nulldfa.in" ++}; ++struct aa_dfa *nulldfa; ++ ++static char stacksplitdfa_src[] = { ++ #include "stacksplitdfa.in" ++}; ++struct aa_dfa *stacksplitdfa; ++struct aa_policydb *nullpdb; ++ ++static int __init aa_setup_dfa_engine(void) ++{ ++ int error = -ENOMEM; ++ ++ nullpdb = aa_alloc_pdb(GFP_KERNEL); ++ if (!nullpdb) ++ return -ENOMEM; ++ ++ nulldfa = aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src), ++ TO_ACCEPT1_FLAG(YYTD_DATA32) | ++ TO_ACCEPT2_FLAG(YYTD_DATA32)); ++ if (IS_ERR(nulldfa)) { ++ error = PTR_ERR(nulldfa); ++ goto fail; ++ } ++ nullpdb->dfa = aa_get_dfa(nulldfa); ++ nullpdb->perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL); ++ if (!nullpdb->perms) ++ goto fail; ++ nullpdb->size = 2; ++ ++ stacksplitdfa = aa_dfa_unpack(stacksplitdfa_src, ++ sizeof(stacksplitdfa_src), ++ TO_ACCEPT1_FLAG(YYTD_DATA32) | ++ TO_ACCEPT2_FLAG(YYTD_DATA32)); ++ if (IS_ERR(stacksplitdfa)) { ++ error = PTR_ERR(stacksplitdfa); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ aa_put_pdb(nullpdb); ++ aa_put_dfa(nulldfa); ++ nullpdb = NULL; ++ nulldfa = NULL; ++ stacksplitdfa = NULL; ++ ++ return error; ++} ++ ++static void __init aa_teardown_dfa_engine(void) ++{ ++ aa_put_dfa(stacksplitdfa); ++ aa_put_dfa(nulldfa); ++ aa_put_pdb(nullpdb); ++ nullpdb = NULL; ++ stacksplitdfa = NULL; ++ nulldfa = NULL; ++} ++ + static int __init apparmor_init(void) + { + int error; +diff --git a/security/apparmor/match.c b/security/apparmor/match.c +index 3667b79e9366b0..6f6cdb86f32b5d 100644 +--- a/security/apparmor/match.c ++++ b/security/apparmor/match.c +@@ -21,50 +21,6 @@ + + #define base_idx(X) ((X) & 0xffffff) + +-static char nulldfa_src[] = { +- #include "nulldfa.in" +-}; +-struct aa_dfa *nulldfa; +- +-static char stacksplitdfa_src[] = { +- #include "stacksplitdfa.in" +-}; +-struct aa_dfa *stacksplitdfa; +- +-int __init aa_setup_dfa_engine(void) +-{ +- int error; +- +- nulldfa = aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src), +- TO_ACCEPT1_FLAG(YYTD_DATA32) | +- TO_ACCEPT2_FLAG(YYTD_DATA32)); +- if (IS_ERR(nulldfa)) { +- error = PTR_ERR(nulldfa); +- nulldfa = NULL; +- return error; +- } +- +- stacksplitdfa = aa_dfa_unpack(stacksplitdfa_src, +- sizeof(stacksplitdfa_src), +- TO_ACCEPT1_FLAG(YYTD_DATA32) | +- TO_ACCEPT2_FLAG(YYTD_DATA32)); +- if (IS_ERR(stacksplitdfa)) { +- aa_put_dfa(nulldfa); +- nulldfa = NULL; +- error = PTR_ERR(stacksplitdfa); +- stacksplitdfa = NULL; +- return error; +- } +- +- return 0; +-} +- +-void __init aa_teardown_dfa_engine(void) +-{ +- aa_put_dfa(stacksplitdfa); +- aa_put_dfa(nulldfa); +-} +- + /** + * unpack_table - unpack a dfa table (one of accept, default, base, next check) + * @blob: data to unpack (NOT NULL) +diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c +index cb0fdbdb82d944..49fe8da6fea459 100644 +--- a/security/apparmor/mount.c ++++ b/security/apparmor/mount.c +@@ -332,8 +332,8 @@ static int match_mnt_path_str(const struct cred *subj_cred, + } + + error = -EACCES; +- pos = do_match_mnt(&rules->policy, +- rules->policy.start[AA_CLASS_MOUNT], ++ pos = do_match_mnt(rules->policy, ++ rules->policy->start[AA_CLASS_MOUNT], + mntpnt, devname, type, flags, data, binary, &perms); + if (pos) { + info = mnt_info_table[pos]; +@@ -620,10 +620,10 @@ static int profile_umount(const struct cred *subj_cred, + if (error) + goto audit; + +- state = aa_dfa_match(rules->policy.dfa, +- rules->policy.start[AA_CLASS_MOUNT], ++ state = aa_dfa_match(rules->policy->dfa, ++ rules->policy->start[AA_CLASS_MOUNT], + name); +- perms = *aa_lookup_perms(&rules->policy, state); ++ perms = *aa_lookup_perms(rules->policy, state); + if (AA_MAY_UMOUNT & ~perms.allow) + error = -EACCES; + +@@ -694,12 +694,12 @@ static struct aa_label *build_pivotroot(const struct cred *subj_cred, + goto audit; + + error = -EACCES; +- state = aa_dfa_match(rules->policy.dfa, +- rules->policy.start[AA_CLASS_MOUNT], ++ state = aa_dfa_match(rules->policy->dfa, ++ rules->policy->start[AA_CLASS_MOUNT], + new_name); +- state = aa_dfa_null_transition(rules->policy.dfa, state); +- state = aa_dfa_match(rules->policy.dfa, state, old_name); +- perms = *aa_lookup_perms(&rules->policy, state); ++ state = aa_dfa_null_transition(rules->policy->dfa, state); ++ state = aa_dfa_match(rules->policy->dfa, state, old_name); ++ perms = *aa_lookup_perms(rules->policy, state); + + if (AA_MAY_PIVOTROOT & perms.allow) + error = 0; +diff --git a/security/apparmor/net.c b/security/apparmor/net.c +index 704c171232ab46..3e632700d06fb3 100644 +--- a/security/apparmor/net.c ++++ b/security/apparmor/net.c +@@ -127,9 +127,9 @@ int aa_profile_af_perm(struct aa_profile *profile, + + buffer[0] = cpu_to_be16(family); + buffer[1] = cpu_to_be16((u16) type); +- state = aa_dfa_match_len(rules->policy.dfa, state, (char *) &buffer, ++ state = aa_dfa_match_len(rules->policy->dfa, state, (char *) &buffer, + 4); +- perms = *aa_lookup_perms(&rules->policy, state); ++ perms = *aa_lookup_perms(rules->policy, state); + aa_apply_modes_to_perms(profile, &perms); + + return aa_check_perms(profile, &perms, request, ad, audit_net_cb); +@@ -190,8 +190,10 @@ int aa_sock_file_perm(const struct cred *subj_cred, struct aa_label *label, + const char *op, u32 request, struct socket *sock) + { + AA_BUG(!label); +- AA_BUG(!sock); +- AA_BUG(!sock->sk); ++ ++ /* sock && sock->sk can be NULL for sockets being set up or torn down */ ++ if (!sock || !sock->sk) ++ return 0; + + return aa_label_sk_perm(subj_cred, label, op, request, sock->sk); + } +diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c +index d9d3b3d776e11b..009fa7cfb6688a 100644 +--- a/security/apparmor/policy.c ++++ b/security/apparmor/policy.c +@@ -98,6 +98,41 @@ const char *const aa_profile_mode_names[] = { + }; + + ++static void aa_free_pdb(struct aa_policydb *policy) ++{ ++ if (policy) { ++ aa_put_dfa(policy->dfa); ++ if (policy->perms) ++ kvfree(policy->perms); ++ aa_free_str_table(&policy->trans); ++ } ++} ++ ++/** ++ * aa_pdb_free_kref - free aa_policydb by kref (called by aa_put_pdb) ++ * @kr: kref callback for freeing of a dfa (NOT NULL) ++ */ ++void aa_pdb_free_kref(struct kref *kref) ++{ ++ struct aa_policydb *pdb = container_of(kref, struct aa_policydb, count); ++ ++ aa_free_pdb(pdb); ++} ++ ++ ++struct aa_policydb *aa_alloc_pdb(gfp_t gfp) ++{ ++ struct aa_policydb *pdb = kzalloc(sizeof(struct aa_policydb), gfp); ++ ++ if (!pdb) ++ return NULL; ++ ++ kref_init(&pdb->count); ++ ++ return pdb; ++} ++ ++ + /** + * __add_profile - add a profiles to list and label tree + * @list: list to add it to (NOT NULL) +@@ -200,15 +235,15 @@ static void free_attachment(struct aa_attachment *attach) + for (i = 0; i < attach->xattr_count; i++) + kfree_sensitive(attach->xattrs[i]); + kfree_sensitive(attach->xattrs); +- aa_destroy_policydb(&attach->xmatch); ++ aa_put_pdb(attach->xmatch); + } + + static void free_ruleset(struct aa_ruleset *rules) + { + int i; + +- aa_destroy_policydb(&rules->file); +- aa_destroy_policydb(&rules->policy); ++ aa_put_pdb(rules->file); ++ aa_put_pdb(rules->policy); + aa_free_cap_rules(&rules->caps); + aa_free_rlimit_rules(&rules->rlimits); + +@@ -590,16 +625,8 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name, + /* TODO: ideally we should inherit abi from parent */ + profile->label.flags |= FLAG_NULL; + rules = list_first_entry(&profile->rules, typeof(*rules), list); +- rules->file.dfa = aa_get_dfa(nulldfa); +- rules->file.perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL); +- if (!rules->file.perms) +- goto fail; +- rules->file.size = 2; +- rules->policy.dfa = aa_get_dfa(nulldfa); +- rules->policy.perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL); +- if (!rules->policy.perms) +- goto fail; +- rules->policy.size = 2; ++ rules->file = aa_get_pdb(nullpdb); ++ rules->policy = aa_get_pdb(nullpdb); + + if (parent) { + profile->path_flags = parent->path_flags; +@@ -610,11 +637,6 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name, + } + + return profile; +- +-fail: +- aa_free_profile(profile); +- +- return NULL; + } + + /** +diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c +index d752bfa9b3f37e..9b25624285e676 100644 +--- a/security/apparmor/policy_unpack.c ++++ b/security/apparmor/policy_unpack.c +@@ -683,8 +683,10 @@ static ssize_t unpack_perms_table(struct aa_ext *e, struct aa_perms **perms) + if (!aa_unpack_array(e, NULL, &size)) + goto fail_reset; + *perms = kcalloc(size, sizeof(struct aa_perms), GFP_KERNEL); +- if (!*perms) +- goto fail_reset; ++ if (!*perms) { ++ e->pos = pos; ++ return -ENOMEM; ++ } + for (i = 0; i < size; i++) { + if (!unpack_perm(e, version, &(*perms)[i])) + goto fail; +@@ -705,24 +707,29 @@ fail_reset: + return -EPROTO; + } + +-static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, ++static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy, + bool required_dfa, bool required_trans, + const char **info) + { ++ struct aa_policydb *pdb; + void *pos = e->pos; + int i, flags, error = -EPROTO; + ssize_t size; + +- size = unpack_perms_table(e, &policy->perms); ++ pdb = aa_alloc_pdb(GFP_KERNEL); ++ if (!pdb) ++ return -ENOMEM; ++ ++ size = unpack_perms_table(e, &pdb->perms); + if (size < 0) { + error = size; +- policy->perms = NULL; ++ pdb->perms = NULL; + *info = "failed to unpack - perms"; + goto fail; + } +- policy->size = size; ++ pdb->size = size; + +- if (policy->perms) { ++ if (pdb->perms) { + /* perms table present accept is index */ + flags = TO_ACCEPT1_FLAG(YYTD_DATA32); + } else { +@@ -731,13 +738,13 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, + TO_ACCEPT2_FLAG(YYTD_DATA32); + } + +- policy->dfa = unpack_dfa(e, flags); +- if (IS_ERR(policy->dfa)) { +- error = PTR_ERR(policy->dfa); +- policy->dfa = NULL; ++ pdb->dfa = unpack_dfa(e, flags); ++ if (IS_ERR(pdb->dfa)) { ++ error = PTR_ERR(pdb->dfa); ++ pdb->dfa = NULL; + *info = "failed to unpack - dfa"; + goto fail; +- } else if (!policy->dfa) { ++ } else if (!pdb->dfa) { + if (required_dfa) { + *info = "missing required dfa"; + goto fail; +@@ -751,18 +758,18 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, + * sadly start was given different names for file and policydb + * but since it is optional we can try both + */ +- if (!aa_unpack_u32(e, &policy->start[0], "start")) ++ if (!aa_unpack_u32(e, &pdb->start[0], "start")) + /* default start state */ +- policy->start[0] = DFA_START; +- if (!aa_unpack_u32(e, &policy->start[AA_CLASS_FILE], "dfa_start")) { ++ pdb->start[0] = DFA_START; ++ if (!aa_unpack_u32(e, &pdb->start[AA_CLASS_FILE], "dfa_start")) { + /* default start state for xmatch and file dfa */ +- policy->start[AA_CLASS_FILE] = DFA_START; ++ pdb->start[AA_CLASS_FILE] = DFA_START; + } /* setup class index */ + for (i = AA_CLASS_FILE + 1; i <= AA_CLASS_LAST; i++) { +- policy->start[i] = aa_dfa_next(policy->dfa, policy->start[0], ++ pdb->start[i] = aa_dfa_next(pdb->dfa, pdb->start[0], + i); + } +- if (!unpack_trans_table(e, &policy->trans) && required_trans) { ++ if (!unpack_trans_table(e, &pdb->trans) && required_trans) { + *info = "failed to unpack profile transition table"; + goto fail; + } +@@ -770,9 +777,11 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, + /* TODO: move compat mapping here, requires dfa merging first */ + /* TODO: move verify here, it has to be done after compat mappings */ + out: ++ *policy = pdb; + return 0; + + fail: ++ aa_put_pdb(pdb); + e->pos = pos; + return error; + } +@@ -860,15 +869,15 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) + } + + /* neither xmatch_len not xmatch_perms are optional if xmatch is set */ +- if (profile->attach.xmatch.dfa) { ++ if (profile->attach.xmatch->dfa) { + if (!aa_unpack_u32(e, &tmp, NULL)) { + info = "missing xmatch len"; + goto fail; + } + profile->attach.xmatch_len = tmp; +- profile->attach.xmatch.start[AA_CLASS_XMATCH] = DFA_START; +- if (!profile->attach.xmatch.perms) { +- error = aa_compat_map_xmatch(&profile->attach.xmatch); ++ profile->attach.xmatch->start[AA_CLASS_XMATCH] = DFA_START; ++ if (!profile->attach.xmatch->perms) { ++ error = aa_compat_map_xmatch(profile->attach.xmatch); + if (error) { + info = "failed to convert xmatch permission table"; + goto fail; +@@ -985,16 +994,16 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) + if (error) + goto fail; + /* Fixup: drop when we get rid of start array */ +- if (aa_dfa_next(rules->policy.dfa, rules->policy.start[0], ++ if (aa_dfa_next(rules->policy->dfa, rules->policy->start[0], + AA_CLASS_FILE)) +- rules->policy.start[AA_CLASS_FILE] = +- aa_dfa_next(rules->policy.dfa, +- rules->policy.start[0], ++ rules->policy->start[AA_CLASS_FILE] = ++ aa_dfa_next(rules->policy->dfa, ++ rules->policy->start[0], + AA_CLASS_FILE); + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) + goto fail; +- if (!rules->policy.perms) { +- error = aa_compat_map_policy(&rules->policy, ++ if (!rules->policy->perms) { ++ error = aa_compat_map_policy(rules->policy, + e->version); + if (error) { + info = "failed to remap policydb permission table"; +@@ -1002,44 +1011,25 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) + } + } + } else { +- rules->policy.dfa = aa_get_dfa(nulldfa); +- rules->policy.perms = kcalloc(2, sizeof(struct aa_perms), +- GFP_KERNEL); +- if (!rules->policy.perms) +- goto fail; +- rules->policy.size = 2; ++ rules->policy = aa_get_pdb(nullpdb); + } + /* get file rules */ + error = unpack_pdb(e, &rules->file, false, true, &info); + if (error) { + goto fail; +- } else if (rules->file.dfa) { +- if (!rules->file.perms) { +- error = aa_compat_map_file(&rules->file); ++ } else if (rules->file->dfa) { ++ if (!rules->file->perms) { ++ error = aa_compat_map_file(rules->file); + if (error) { + info = "failed to remap file permission table"; + goto fail; + } + } +- } else if (rules->policy.dfa && +- rules->policy.start[AA_CLASS_FILE]) { +- rules->file.dfa = aa_get_dfa(rules->policy.dfa); +- rules->file.start[AA_CLASS_FILE] = rules->policy.start[AA_CLASS_FILE]; +- rules->file.perms = kcalloc(rules->policy.size, +- sizeof(struct aa_perms), +- GFP_KERNEL); +- if (!rules->file.perms) +- goto fail; +- memcpy(rules->file.perms, rules->policy.perms, +- rules->policy.size * sizeof(struct aa_perms)); +- rules->file.size = rules->policy.size; ++ } else if (rules->policy->dfa && ++ rules->policy->start[AA_CLASS_FILE]) { ++ rules->file = aa_get_pdb(rules->policy); + } else { +- rules->file.dfa = aa_get_dfa(nulldfa); +- rules->file.perms = kcalloc(2, sizeof(struct aa_perms), +- GFP_KERNEL); +- if (!rules->file.perms) +- goto fail; +- rules->file.size = 2; ++ rules->file = aa_get_pdb(nullpdb); + } + error = -EPROTO; + if (aa_unpack_nameX(e, AA_STRUCT, "data")) { +@@ -1247,26 +1237,32 @@ static int verify_profile(struct aa_profile *profile) + if (!rules) + return 0; + +- if ((rules->file.dfa && !verify_dfa_accept_index(rules->file.dfa, +- rules->file.size)) || +- (rules->policy.dfa && +- !verify_dfa_accept_index(rules->policy.dfa, rules->policy.size))) { ++ if (rules->file->dfa && !verify_dfa_accept_index(rules->file->dfa, ++ rules->file->size)) { ++ audit_iface(profile, NULL, NULL, ++ "Unpack: file Invalid named transition", NULL, ++ -EPROTO); ++ return -EPROTO; ++ } ++ if (rules->policy->dfa && ++ !verify_dfa_accept_index(rules->policy->dfa, rules->policy->size)) { + audit_iface(profile, NULL, NULL, +- "Unpack: Invalid named transition", NULL, -EPROTO); ++ "Unpack: policy Invalid named transition", NULL, ++ -EPROTO); + return -EPROTO; + } + +- if (!verify_perms(&rules->file)) { ++ if (!verify_perms(rules->file)) { + audit_iface(profile, NULL, NULL, + "Unpack: Invalid perm index", NULL, -EPROTO); + return -EPROTO; + } +- if (!verify_perms(&rules->policy)) { ++ if (!verify_perms(rules->policy)) { + audit_iface(profile, NULL, NULL, + "Unpack: Invalid perm index", NULL, -EPROTO); + return -EPROTO; + } +- if (!verify_perms(&profile->attach.xmatch)) { ++ if (!verify_perms(profile->attach.xmatch)) { + audit_iface(profile, NULL, NULL, + "Unpack: Invalid perm index", NULL, -EPROTO); + return -EPROTO; +diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c +index dcc94c3153d511..a7eee815f12156 100644 +--- a/security/apparmor/resource.c ++++ b/security/apparmor/resource.c +@@ -201,6 +201,11 @@ void __aa_transition_rlimits(struct aa_label *old_l, struct aa_label *new_l) + rules->rlimits.limits[j].rlim_max); + /* soft limit should not exceed hard limit */ + rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max); ++ if (j == RLIMIT_CPU && ++ rlim->rlim_cur != RLIM_INFINITY && ++ IS_ENABLED(CONFIG_POSIX_TIMERS)) ++ (void) update_rlimit_cpu(current->group_leader, ++ rlim->rlim_cur); + } + } + } +diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c +index 1e35c9f807b2b6..109ad155ffc2a6 100644 +--- a/security/smack/smackfs.c ++++ b/security/smack/smackfs.c +@@ -68,6 +68,7 @@ enum smk_inos { + static DEFINE_MUTEX(smack_cipso_lock); + static DEFINE_MUTEX(smack_ambient_lock); + static DEFINE_MUTEX(smk_net4addr_lock); ++static DEFINE_MUTEX(smk_cipso_doi_lock); + #if IS_ENABLED(CONFIG_IPV6) + static DEFINE_MUTEX(smk_net6addr_lock); + #endif /* CONFIG_IPV6 */ +@@ -139,7 +140,7 @@ struct smack_parsed_rule { + int smk_access2; + }; + +-static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; ++static u32 smk_cipso_doi_value = CIPSO_V4_DOI_UNKNOWN; + + /* + * Values for parsing cipso rules +@@ -679,43 +680,60 @@ static const struct file_operations smk_load_ops = { + }; + + /** +- * smk_cipso_doi - initialize the CIPSO domain ++ * smk_cipso_doi - set netlabel maps ++ * @ndoi: new value for our CIPSO DOI ++ * @gfp_flags: kmalloc allocation context + */ +-static void smk_cipso_doi(void) ++static int ++smk_cipso_doi(u32 ndoi, gfp_t gfp_flags) + { +- int rc; ++ int rc = 0; + struct cipso_v4_doi *doip; + struct netlbl_audit nai; + +- smk_netlabel_audit_set(&nai); ++ mutex_lock(&smk_cipso_doi_lock); + +- rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai); +- if (rc != 0) +- printk(KERN_WARNING "%s:%d remove rc = %d\n", +- __func__, __LINE__, rc); ++ if (smk_cipso_doi_value == ndoi) ++ goto clr_doi_lock; ++ ++ smk_netlabel_audit_set(&nai); + +- doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL | __GFP_NOFAIL); ++ doip = kmalloc(sizeof(struct cipso_v4_doi), gfp_flags); ++ if (!doip) { ++ rc = -ENOMEM; ++ goto clr_doi_lock; ++ } + doip->map.std = NULL; +- doip->doi = smk_cipso_doi_value; ++ doip->doi = ndoi; + doip->type = CIPSO_V4_MAP_PASS; + doip->tags[0] = CIPSO_V4_TAG_RBITMAP; + for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++) + doip->tags[rc] = CIPSO_V4_TAG_INVALID; + + rc = netlbl_cfg_cipsov4_add(doip, &nai); +- if (rc != 0) { +- printk(KERN_WARNING "%s:%d cipso add rc = %d\n", +- __func__, __LINE__, rc); ++ if (rc) { + kfree(doip); +- return; ++ goto clr_doi_lock; + } +- rc = netlbl_cfg_cipsov4_map_add(doip->doi, NULL, NULL, NULL, &nai); +- if (rc != 0) { +- printk(KERN_WARNING "%s:%d map add rc = %d\n", +- __func__, __LINE__, rc); +- netlbl_cfg_cipsov4_del(doip->doi, &nai); +- return; ++ ++ if (smk_cipso_doi_value != CIPSO_V4_DOI_UNKNOWN) { ++ rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai); ++ if (rc && rc != -ENOENT) ++ goto clr_ndoi_def; ++ ++ netlbl_cfg_cipsov4_del(smk_cipso_doi_value, &nai); + } ++ ++ rc = netlbl_cfg_cipsov4_map_add(ndoi, NULL, NULL, NULL, &nai); ++ if (rc) { ++ smk_cipso_doi_value = CIPSO_V4_DOI_UNKNOWN; // no default map ++clr_ndoi_def: netlbl_cfg_cipsov4_del(ndoi, &nai); ++ } else ++ smk_cipso_doi_value = ndoi; ++ ++clr_doi_lock: ++ mutex_unlock(&smk_cipso_doi_lock); ++ return rc; + } + + /** +@@ -1580,7 +1598,7 @@ static ssize_t smk_read_doi(struct file *filp, char __user *buf, + if (*ppos != 0) + return 0; + +- sprintf(temp, "%d", smk_cipso_doi_value); ++ sprintf(temp, "%lu", (unsigned long)smk_cipso_doi_value); + rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); + + return rc; +@@ -1599,7 +1617,7 @@ static ssize_t smk_write_doi(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) + { + char temp[80]; +- int i; ++ unsigned long u; + + if (!smack_privileged(CAP_MAC_ADMIN)) + return -EPERM; +@@ -1612,14 +1630,13 @@ static ssize_t smk_write_doi(struct file *file, const char __user *buf, + + temp[count] = '\0'; + +- if (sscanf(temp, "%d", &i) != 1) ++ if (kstrtoul(temp, 10, &u)) + return -EINVAL; + +- smk_cipso_doi_value = i; +- +- smk_cipso_doi(); ++ if (u == CIPSO_V4_DOI_UNKNOWN || u > U32_MAX) ++ return -EINVAL; + +- return count; ++ return smk_cipso_doi(u, GFP_KERNEL) ? : count; + } + + static const struct file_operations smk_doi_ops = { +@@ -2996,6 +3013,7 @@ static int __init init_smk_fs(void) + { + int err; + int rc; ++ struct netlbl_audit nai; + + if (smack_enabled == 0) + return 0; +@@ -3014,7 +3032,10 @@ static int __init init_smk_fs(void) + } + } + +- smk_cipso_doi(); ++ smk_netlabel_audit_set(&nai); ++ (void) netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai); ++ (void) smk_cipso_doi(SMACK_CIPSO_DOI_DEFAULT, ++ GFP_KERNEL | __GFP_NOFAIL); + smk_unlbl_ambient(NULL); + + rc = smack_populate_secattr(&smack_known_floor); +diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c +index 157efd1530fbf3..fd141185ce2b99 100644 +--- a/sound/pci/hda/patch_conexant.c ++++ b/sound/pci/hda/patch_conexant.c +@@ -1127,6 +1127,7 @@ static const struct hda_quirk cxt5066_fixups[] = { + SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", CXT_FIXUP_THINKPAD_ACPI), + SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004), + SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205), ++ SND_PCI_QUIRK(0x1d05, 0x3012, "MECHREVO Wujie 15X Pro", CXT_FIXUP_HEADSET_MIC), + HDA_CODEC_QUIRK(0x2782, 0x12c3, "Sirius Gen1", CXT_PINCFG_TOP_SPEAKER), + HDA_CODEC_QUIRK(0x2782, 0x12c5, "Sirius Gen2", CXT_PINCFG_TOP_SPEAKER), + {} +diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c +index b6068d289f5f9d..5aeacbcb1f6ad9 100644 +--- a/sound/soc/amd/yc/acp6x-mach.c ++++ b/sound/soc/amd/yc/acp6x-mach.c +@@ -689,7 +689,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { + DMI_MATCH(DMI_BOARD_NAME, "XyloD5_RBU"), + } + }, +- ++ { ++ .driver_data = &acp6x_card, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Vivobook_ASUSLaptop M6501RR_M6501RR"), ++ } ++ }, + {} + }; + +diff --git a/sound/soc/codecs/aw88261.c b/sound/soc/codecs/aw88261.c +index a697b5006b45b1..f2a9c33ff4a649 100644 +--- a/sound/soc/codecs/aw88261.c ++++ b/sound/soc/codecs/aw88261.c +@@ -424,9 +424,10 @@ static int aw88261_dev_reg_update(struct aw88261 *aw88261, + if (ret) + break; + ++ /* keep all three bits from current hw status */ + read_val &= (~AW88261_AMPPD_MASK) | (~AW88261_PWDN_MASK) | + (~AW88261_HMUTE_MASK); +- reg_val &= (AW88261_AMPPD_MASK | AW88261_PWDN_MASK | AW88261_HMUTE_MASK); ++ reg_val &= (AW88261_AMPPD_MASK & AW88261_PWDN_MASK & AW88261_HMUTE_MASK); + reg_val |= read_val; + + /* enable uls hmute */ +diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c +index 43792e175d75f1..864c6a858628d1 100644 +--- a/sound/soc/codecs/es8328.c ++++ b/sound/soc/codecs/es8328.c +@@ -750,17 +750,23 @@ static int es8328_resume(struct snd_soc_component *component) + es8328->supplies); + if (ret) { + dev_err(component->dev, "unable to enable regulators\n"); +- return ret; ++ goto err_clk; + } + + regcache_mark_dirty(regmap); + ret = regcache_sync(regmap); + if (ret) { + dev_err(component->dev, "unable to sync regcache\n"); +- return ret; ++ goto err_regulators; + } + + return 0; ++ ++err_regulators: ++ regulator_bulk_disable(ARRAY_SIZE(es8328->supplies), es8328->supplies); ++err_clk: ++ clk_disable_unprepare(es8328->clk); ++ return ret; + } + + static int es8328_component_probe(struct snd_soc_component *component) +diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c +index 5b8e78e516302e..f2a1306d042b7c 100644 +--- a/sound/soc/codecs/max98390.c ++++ b/sound/soc/codecs/max98390.c +@@ -1076,6 +1076,9 @@ static int max98390_i2c_probe(struct i2c_client *i2c) + + reset_gpio = devm_gpiod_get_optional(&i2c->dev, + "reset", GPIOD_OUT_HIGH); ++ if (IS_ERR(reset_gpio)) ++ return dev_err_probe(&i2c->dev, PTR_ERR(reset_gpio), ++ "Failed to get reset gpio\n"); + + /* Power on device */ + if (reset_gpio) { +diff --git a/sound/soc/codecs/nau8821.c b/sound/soc/codecs/nau8821.c +index 48ed75c3a7db2b..3cf531258911bb 100644 +--- a/sound/soc/codecs/nau8821.c ++++ b/sound/soc/codecs/nau8821.c +@@ -1067,20 +1067,24 @@ static void nau8821_eject_jack(struct nau8821 *nau8821) + snd_soc_component_disable_pin(component, "MICBIAS"); + snd_soc_dapm_sync(dapm); + ++ /* Disable & mask both insertion & ejection IRQs */ ++ regmap_update_bits(regmap, NAU8821_R12_INTERRUPT_DIS_CTRL, ++ NAU8821_IRQ_INSERT_DIS | NAU8821_IRQ_EJECT_DIS, ++ NAU8821_IRQ_INSERT_DIS | NAU8821_IRQ_EJECT_DIS); ++ regmap_update_bits(regmap, NAU8821_R0F_INTERRUPT_MASK, ++ NAU8821_IRQ_INSERT_EN | NAU8821_IRQ_EJECT_EN, ++ NAU8821_IRQ_INSERT_EN | NAU8821_IRQ_EJECT_EN); ++ + /* Clear all interruption status */ + nau8821_irq_status_clear(regmap, 0); + +- /* Enable the insertion interruption, disable the ejection inter- +- * ruption, and then bypass de-bounce circuit. +- */ ++ /* Enable & unmask the insertion IRQ */ + regmap_update_bits(regmap, NAU8821_R12_INTERRUPT_DIS_CTRL, +- NAU8821_IRQ_EJECT_DIS | NAU8821_IRQ_INSERT_DIS, +- NAU8821_IRQ_EJECT_DIS); +- /* Mask unneeded IRQs: 1 - disable, 0 - enable */ ++ NAU8821_IRQ_INSERT_DIS, 0); + regmap_update_bits(regmap, NAU8821_R0F_INTERRUPT_MASK, +- NAU8821_IRQ_EJECT_EN | NAU8821_IRQ_INSERT_EN, +- NAU8821_IRQ_EJECT_EN); ++ NAU8821_IRQ_INSERT_EN, 0); + ++ /* Bypass de-bounce circuit */ + regmap_update_bits(regmap, NAU8821_R0D_JACK_DET_CTRL, + NAU8821_JACK_DET_DB_BYPASS, NAU8821_JACK_DET_DB_BYPASS); + +@@ -1104,22 +1108,17 @@ static void nau8821_eject_jack(struct nau8821 *nau8821) + NAU8821_IRQ_KEY_RELEASE_DIS | + NAU8821_IRQ_KEY_PRESS_DIS); + } +- + } + + static void nau8821_jdet_work(struct work_struct *work) + { + struct nau8821 *nau8821 = +- container_of(work, struct nau8821, jdet_work); ++ container_of(work, struct nau8821, jdet_work.work); + struct snd_soc_dapm_context *dapm = nau8821->dapm; + struct snd_soc_component *component = snd_soc_dapm_to_component(dapm); + struct regmap *regmap = nau8821->regmap; + int jack_status_reg, mic_detected, event = 0, event_mask = 0; + +- snd_soc_component_force_enable_pin(component, "MICBIAS"); +- snd_soc_dapm_sync(dapm); +- msleep(20); +- + regmap_read(regmap, NAU8821_R58_I2C_DEVICE_ID, &jack_status_reg); + mic_detected = !(jack_status_reg & NAU8821_KEYDET); + if (mic_detected) { +@@ -1149,6 +1148,7 @@ static void nau8821_jdet_work(struct work_struct *work) + snd_soc_component_disable_pin(component, "MICBIAS"); + snd_soc_dapm_sync(dapm); + } ++ + event_mask |= SND_JACK_HEADSET; + snd_soc_jack_report(nau8821->jack, event, event_mask); + } +@@ -1158,6 +1158,15 @@ static void nau8821_setup_inserted_irq(struct nau8821 *nau8821) + { + struct regmap *regmap = nau8821->regmap; + ++ /* Disable & mask insertion IRQ */ ++ regmap_update_bits(regmap, NAU8821_R12_INTERRUPT_DIS_CTRL, ++ NAU8821_IRQ_INSERT_DIS, NAU8821_IRQ_INSERT_DIS); ++ regmap_update_bits(regmap, NAU8821_R0F_INTERRUPT_MASK, ++ NAU8821_IRQ_INSERT_EN, NAU8821_IRQ_INSERT_EN); ++ ++ /* Clear insert IRQ status */ ++ nau8821_irq_status_clear(regmap, NAU8821_JACK_INSERT_DETECTED); ++ + /* Enable internal VCO needed for interruptions */ + if (nau8821->dapm->bias_level < SND_SOC_BIAS_PREPARE) + nau8821_configure_sysclk(nau8821, NAU8821_CLK_INTERNAL, 0); +@@ -1177,17 +1186,19 @@ static void nau8821_setup_inserted_irq(struct nau8821 *nau8821) + regmap_update_bits(regmap, NAU8821_R0D_JACK_DET_CTRL, + NAU8821_JACK_DET_DB_BYPASS, 0); + ++ /* Unmask & enable the ejection IRQs */ + regmap_update_bits(regmap, NAU8821_R0F_INTERRUPT_MASK, +- NAU8821_IRQ_EJECT_EN, 0); ++ NAU8821_IRQ_EJECT_EN, 0); + regmap_update_bits(regmap, NAU8821_R12_INTERRUPT_DIS_CTRL, +- NAU8821_IRQ_EJECT_DIS, 0); ++ NAU8821_IRQ_EJECT_DIS, 0); + } + + static irqreturn_t nau8821_interrupt(int irq, void *data) + { + struct nau8821 *nau8821 = (struct nau8821 *)data; + struct regmap *regmap = nau8821->regmap; +- int active_irq, clear_irq = 0, event = 0, event_mask = 0; ++ struct snd_soc_component *component; ++ int active_irq, event = 0, event_mask = 0; + + if (regmap_read(regmap, NAU8821_R10_IRQ_STATUS, &active_irq)) { + dev_err(nau8821->dev, "failed to read irq status\n"); +@@ -1198,49 +1209,41 @@ static irqreturn_t nau8821_interrupt(int irq, void *data) + + if ((active_irq & NAU8821_JACK_EJECT_IRQ_MASK) == + NAU8821_JACK_EJECT_DETECTED) { +- cancel_work_sync(&nau8821->jdet_work); ++ cancel_delayed_work_sync(&nau8821->jdet_work); + regmap_update_bits(regmap, NAU8821_R71_ANALOG_ADC_1, + NAU8821_MICDET_MASK, NAU8821_MICDET_DIS); + nau8821_eject_jack(nau8821); + event_mask |= SND_JACK_HEADSET; +- clear_irq = NAU8821_JACK_EJECT_IRQ_MASK; + } else if (active_irq & NAU8821_KEY_SHORT_PRESS_IRQ) { + event |= NAU8821_BUTTON; + event_mask |= NAU8821_BUTTON; +- clear_irq = NAU8821_KEY_SHORT_PRESS_IRQ; ++ nau8821_irq_status_clear(regmap, NAU8821_KEY_SHORT_PRESS_IRQ); + } else if (active_irq & NAU8821_KEY_RELEASE_IRQ) { + event_mask = NAU8821_BUTTON; +- clear_irq = NAU8821_KEY_RELEASE_IRQ; ++ nau8821_irq_status_clear(regmap, NAU8821_KEY_RELEASE_IRQ); + } else if ((active_irq & NAU8821_JACK_INSERT_IRQ_MASK) == + NAU8821_JACK_INSERT_DETECTED) { +- cancel_work_sync(&nau8821->jdet_work); ++ cancel_delayed_work_sync(&nau8821->jdet_work); + regmap_update_bits(regmap, NAU8821_R71_ANALOG_ADC_1, + NAU8821_MICDET_MASK, NAU8821_MICDET_EN); + if (nau8821_is_jack_inserted(regmap)) { +- /* detect microphone and jack type */ +- schedule_work(&nau8821->jdet_work); ++ /* Detect microphone and jack type */ ++ component = snd_soc_dapm_to_component(nau8821->dapm); ++ snd_soc_component_force_enable_pin(component, "MICBIAS"); ++ snd_soc_dapm_sync(nau8821->dapm); ++ schedule_delayed_work(&nau8821->jdet_work, msecs_to_jiffies(20)); + /* Turn off insertion interruption at manual mode */ +- regmap_update_bits(regmap, +- NAU8821_R12_INTERRUPT_DIS_CTRL, +- NAU8821_IRQ_INSERT_DIS, +- NAU8821_IRQ_INSERT_DIS); +- regmap_update_bits(regmap, +- NAU8821_R0F_INTERRUPT_MASK, +- NAU8821_IRQ_INSERT_EN, +- NAU8821_IRQ_INSERT_EN); + nau8821_setup_inserted_irq(nau8821); + } else { + dev_warn(nau8821->dev, + "Inserted IRQ fired but not connected\n"); + nau8821_eject_jack(nau8821); + } ++ } else { ++ /* Clear the rightmost interrupt */ ++ nau8821_irq_status_clear(regmap, active_irq); + } + +- if (!clear_irq) +- clear_irq = active_irq; +- /* clears the rightmost interruption */ +- regmap_write(regmap, NAU8821_R11_INT_CLR_KEY_STATUS, clear_irq); +- + if (event_mask) + snd_soc_jack_report(nau8821->jack, event, event_mask); + +@@ -1664,8 +1667,14 @@ int nau8821_enable_jack_detect(struct snd_soc_component *component, + int ret; + + nau8821->jack = jack; ++ ++ if (nau8821->jdet_active) ++ return 0; ++ + /* Initiate jack detection work queue */ +- INIT_WORK(&nau8821->jdet_work, nau8821_jdet_work); ++ INIT_DELAYED_WORK(&nau8821->jdet_work, nau8821_jdet_work); ++ nau8821->jdet_active = true; ++ + ret = devm_request_threaded_irq(nau8821->dev, nau8821->irq, NULL, + nau8821_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "nau8821", nau8821); +diff --git a/sound/soc/codecs/nau8821.h b/sound/soc/codecs/nau8821.h +index 00a888ed07ceb9..ce0880cdd18994 100644 +--- a/sound/soc/codecs/nau8821.h ++++ b/sound/soc/codecs/nau8821.h +@@ -559,7 +559,8 @@ struct nau8821 { + struct regmap *regmap; + struct snd_soc_dapm_context *dapm; + struct snd_soc_jack *jack; +- struct work_struct jdet_work; ++ struct delayed_work jdet_work; ++ bool jdet_active; + int irq; + int clk_id; + int micbias_voltage; +diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c +index 4f50b07848fd8f..68a5ca176d6f0b 100644 +--- a/sound/soc/codecs/wm8962.c ++++ b/sound/soc/codecs/wm8962.c +@@ -67,6 +67,8 @@ struct wm8962_priv { + struct mutex dsp2_ena_lock; + u16 dsp2_ena; + ++ int mic_status; ++ + struct delayed_work mic_work; + struct snd_soc_jack *jack; + +@@ -1759,7 +1761,7 @@ SND_SOC_BYTES("EQR Coefficients", WM8962_EQ24, 18), + + + SOC_SINGLE("3D Switch", WM8962_THREED1, 0, 1, 0), +-SND_SOC_BYTES_MASK("3D Coefficients", WM8962_THREED1, 4, WM8962_THREED_ENA), ++SND_SOC_BYTES_MASK("3D Coefficients", WM8962_THREED1, 4, WM8962_THREED_ENA | WM8962_ADC_MONOMIX), + + SOC_SINGLE("DF1 Switch", WM8962_DF1, 0, 1, 0), + SND_SOC_BYTES_MASK("DF1 Coefficients", WM8962_DF1, 7, WM8962_DF1_ENA), +@@ -3073,8 +3075,16 @@ static void wm8962_mic_work(struct work_struct *work) + if (reg & WM8962_MICSHORT_STS) { + status |= SND_JACK_BTN_0; + irq_pol |= WM8962_MICSCD_IRQ_POL; ++ ++ /* Don't report a microphone if it's shorted right after ++ * plugging in, as this may be a TRS plug in a TRRS socket. ++ */ ++ if (!(wm8962->mic_status & WM8962_MICDET_STS)) ++ status = 0; + } + ++ wm8962->mic_status = status; ++ + snd_soc_jack_report(wm8962->jack, status, + SND_JACK_MICROPHONE | SND_JACK_BTN_0); + +diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c +index 3a5ab8b5367289..90a0a24c05d845 100644 +--- a/sound/soc/fsl/fsl_xcvr.c ++++ b/sound/soc/fsl/fsl_xcvr.c +@@ -206,13 +206,10 @@ static int fsl_xcvr_mode_put(struct snd_kcontrol *kcontrol, + + xcvr->mode = snd_soc_enum_item_to_val(e, item[0]); + +- down_read(&card->snd_card->controls_rwsem); + fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name, + (xcvr->mode == FSL_XCVR_MODE_ARC)); + fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name, + (xcvr->mode == FSL_XCVR_MODE_EARC)); +- up_read(&card->snd_card->controls_rwsem); +- + /* Allow playback for SPDIF only */ + rtd = snd_soc_get_pcm_runtime(card, card->dai_link); + rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count = +diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c +index 7ae93cbaea9a77..15ef6b6bec2bb7 100644 +--- a/sound/soc/rockchip/rockchip_i2s_tdm.c ++++ b/sound/soc/rockchip/rockchip_i2s_tdm.c +@@ -24,6 +24,7 @@ + + #define DRV_NAME "rockchip-i2s-tdm" + ++#define DEFAULT_MCLK_FS 256 + #define CH_GRP_MAX 4 /* The max channel 8 / 2 */ + #define MULTIPLEX_CH_MAX 10 + +@@ -695,6 +696,15 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream, + mclk_rate = i2s_tdm->mclk_rx_freq; + } + ++ /* ++ * When the dai/component driver doesn't need to set mclk-fs for a specific ++ * clock, it can skip the call to set_sysclk() for that clock. ++ * In that case, simply use the clock rate from the params and multiply it by ++ * the default mclk-fs value. ++ */ ++ if (!mclk_rate) ++ mclk_rate = DEFAULT_MCLK_FS * params_rate(params); ++ + err = clk_set_rate(mclk, mclk_rate); + if (err) + return err; +diff --git a/sound/soc/sof/ipc4-control.c b/sound/soc/sof/ipc4-control.c +index 84145209dec493..3835179b22b426 100644 +--- a/sound/soc/sof/ipc4-control.c ++++ b/sound/soc/sof/ipc4-control.c +@@ -66,7 +66,7 @@ static int sof_ipc4_set_get_kcontrol_data(struct snd_sof_control *scontrol, + * configuration + */ + memcpy(scontrol->ipc_control_data, scontrol->old_ipc_control_data, +- scontrol->max_size); ++ scontrol->size); + kfree(scontrol->old_ipc_control_data); + scontrol->old_ipc_control_data = NULL; + /* Send the last known good configuration to firmware */ +@@ -364,19 +364,35 @@ static int sof_ipc4_set_get_bytes_data(struct snd_sof_dev *sdev, + int ret = 0; + + /* Send the new data to the firmware only if it is powered up */ +- if (set && !pm_runtime_active(sdev->dev)) +- return 0; ++ if (set) { ++ if (!pm_runtime_active(sdev->dev)) ++ return 0; ++ ++ if (!data->size) { ++ dev_dbg(sdev->dev, "%s: No data to be sent.\n", ++ scontrol->name); ++ return 0; ++ } ++ } + + msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type); + + msg->data_ptr = data->data; +- msg->data_size = data->size; ++ if (set) ++ msg->data_size = data->size; ++ else ++ msg->data_size = scontrol->max_size - sizeof(*data); + + ret = sof_ipc4_set_get_kcontrol_data(scontrol, set, lock); +- if (ret < 0) ++ if (ret < 0) { + dev_err(sdev->dev, "Failed to %s for %s\n", + set ? "set bytes update" : "get bytes", + scontrol->name); ++ } else if (!set) { ++ /* Update the sizes according to the received payload data */ ++ data->size = msg->data_size; ++ scontrol->size = sizeof(*cdata) + sizeof(*data) + data->size; ++ } + + msg->data_ptr = NULL; + msg->data_size = 0; +@@ -392,6 +408,7 @@ static int sof_ipc4_bytes_put(struct snd_sof_control *scontrol, + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct sof_abi_hdr *data = cdata->data; + size_t size; ++ int ret; + + if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { + dev_err_ratelimited(scomp->dev, +@@ -413,9 +430,12 @@ static int sof_ipc4_bytes_put(struct snd_sof_control *scontrol, + /* copy from kcontrol */ + memcpy(data, ucontrol->value.bytes.data, size); + +- sof_ipc4_set_get_bytes_data(sdev, scontrol, true, true); ++ ret = sof_ipc4_set_get_bytes_data(sdev, scontrol, true, true); ++ if (!ret) ++ /* Update the cdata size */ ++ scontrol->size = sizeof(*cdata) + size; + +- return 0; ++ return ret; + } + + static int sof_ipc4_bytes_get(struct snd_sof_control *scontrol, +@@ -511,7 +531,7 @@ static int sof_ipc4_bytes_ext_put(struct snd_sof_control *scontrol, + if (!scontrol->old_ipc_control_data) { + /* Create a backup of the current, valid bytes control */ + scontrol->old_ipc_control_data = kmemdup(scontrol->ipc_control_data, +- scontrol->max_size, GFP_KERNEL); ++ scontrol->size, GFP_KERNEL); + if (!scontrol->old_ipc_control_data) + return -ENOMEM; + } +@@ -519,12 +539,15 @@ static int sof_ipc4_bytes_ext_put(struct snd_sof_control *scontrol, + /* Copy the whole binary data which includes the ABI header and the payload */ + if (copy_from_user(data, tlvd->tlv, header.length)) { + memcpy(scontrol->ipc_control_data, scontrol->old_ipc_control_data, +- scontrol->max_size); ++ scontrol->size); + kfree(scontrol->old_ipc_control_data); + scontrol->old_ipc_control_data = NULL; + return -EFAULT; + } + ++ /* Update the cdata size */ ++ scontrol->size = sizeof(*cdata) + header.length; ++ + return sof_ipc4_set_get_bytes_data(sdev, scontrol, true, true); + } + +diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c +index c380ddf68a5898..cc17d4e74c82fe 100644 +--- a/sound/soc/sof/ipc4-topology.c ++++ b/sound/soc/sof/ipc4-topology.c +@@ -2184,22 +2184,41 @@ static int sof_ipc4_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_ + struct sof_ipc4_msg *msg; + int ret; + +- if (scontrol->max_size < (sizeof(*control_data) + sizeof(struct sof_abi_hdr))) { +- dev_err(sdev->dev, "insufficient size for a bytes control %s: %zu.\n", ++ /* ++ * The max_size is coming from topology and indicates the maximum size ++ * of sof_abi_hdr plus the payload, which excludes the local only ++ * 'struct sof_ipc4_control_data' ++ */ ++ if (scontrol->max_size < sizeof(struct sof_abi_hdr)) { ++ dev_err(sdev->dev, ++ "insufficient maximum size for a bytes control %s: %zu.\n", + scontrol->name, scontrol->max_size); + return -EINVAL; + } + +- if (scontrol->priv_size > scontrol->max_size - sizeof(*control_data)) { +- dev_err(sdev->dev, "scontrol %s bytes data size %zu exceeds max %zu.\n", +- scontrol->name, scontrol->priv_size, +- scontrol->max_size - sizeof(*control_data)); ++ if (scontrol->priv_size > scontrol->max_size) { ++ dev_err(sdev->dev, ++ "bytes control %s initial data size %zu exceeds max %zu.\n", ++ scontrol->name, scontrol->priv_size, scontrol->max_size); ++ return -EINVAL; ++ } ++ ++ if (scontrol->priv_size < sizeof(struct sof_abi_hdr)) { ++ dev_err(sdev->dev, ++ "bytes control %s initial data size %zu is insufficient.\n", ++ scontrol->name, scontrol->priv_size); + return -EINVAL; + } + +- scontrol->size = sizeof(struct sof_ipc4_control_data) + scontrol->priv_size; ++ /* ++ * The used size behind the cdata pointer, which can be smaller than ++ * the maximum size ++ */ ++ scontrol->size = sizeof(*control_data) + scontrol->priv_size; + +- scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL); ++ /* Allocate the cdata: local struct size + maximum payload size */ ++ scontrol->ipc_control_data = kzalloc(sizeof(*control_data) + scontrol->max_size, ++ GFP_KERNEL); + if (!scontrol->ipc_control_data) + return -ENOMEM; + +diff --git a/sound/soc/sunxi/sun50i-dmic.c b/sound/soc/sunxi/sun50i-dmic.c +index 2599683a582dcd..9071bc48357595 100644 +--- a/sound/soc/sunxi/sun50i-dmic.c ++++ b/sound/soc/sunxi/sun50i-dmic.c +@@ -324,6 +324,9 @@ static int sun50i_dmic_probe(struct platform_device *pdev) + + host->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &sun50i_dmic_regmap_config); ++ if (IS_ERR(host->regmap)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(host->regmap), ++ "failed to initialise regmap\n"); + + /* Clocks */ + host->bus_clk = devm_clk_get(&pdev->dev, "bus"); +diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c +index 17ae74b067c5ef..1092b964167e97 100644 +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -278,8 +278,8 @@ static inline bool has_tx_length_quirk(struct snd_usb_audio *chip) + return chip->quirk_flags & QUIRK_FLAG_TX_LENGTH; + } + +-static void prepare_silent_urb(struct snd_usb_endpoint *ep, +- struct snd_urb_ctx *ctx) ++static int prepare_silent_urb(struct snd_usb_endpoint *ep, ++ struct snd_urb_ctx *ctx) + { + struct urb *urb = ctx->urb; + unsigned int offs = 0; +@@ -292,28 +292,34 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep, + extra = sizeof(packet_length); + + for (i = 0; i < ctx->packets; ++i) { +- unsigned int offset; +- unsigned int length; +- int counts; +- +- counts = snd_usb_endpoint_next_packet_size(ep, ctx, i, 0); +- length = counts * ep->stride; /* number of silent bytes */ +- offset = offs * ep->stride + extra * i; +- urb->iso_frame_desc[i].offset = offset; ++ int length; ++ ++ length = snd_usb_endpoint_next_packet_size(ep, ctx, i, 0); ++ if (length < 0) ++ return length; ++ length *= ep->stride; /* number of silent bytes */ ++ if (offs + length + extra > ctx->buffer_size) ++ break; ++ urb->iso_frame_desc[i].offset = offs; + urb->iso_frame_desc[i].length = length + extra; + if (extra) { + packet_length = cpu_to_le32(length); +- memcpy(urb->transfer_buffer + offset, ++ memcpy(urb->transfer_buffer + offs, + &packet_length, sizeof(packet_length)); ++ offs += extra; + } +- memset(urb->transfer_buffer + offset + extra, ++ memset(urb->transfer_buffer + offs, + ep->silence_value, length); +- offs += counts; ++ offs += length; + } + +- urb->number_of_packets = ctx->packets; +- urb->transfer_buffer_length = offs * ep->stride + ctx->packets * extra; ++ if (!offs) ++ return -EPIPE; ++ ++ urb->number_of_packets = i; ++ urb->transfer_buffer_length = offs; + ctx->queued = 0; ++ return 0; + } + + /* +@@ -335,8 +341,7 @@ static int prepare_outbound_urb(struct snd_usb_endpoint *ep, + if (data_subs && ep->prepare_data_urb) + return ep->prepare_data_urb(data_subs, urb, in_stream_lock); + /* no data provider, so send silence */ +- prepare_silent_urb(ep, ctx); +- break; ++ return prepare_silent_urb(ep, ctx); + + case SND_USB_ENDPOINT_TYPE_SYNC: + if (snd_usb_get_speed(ep->chip->dev) >= USB_SPEED_HIGH) { +@@ -489,6 +494,7 @@ int snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep, + + /* copy over the length information */ + if (implicit_fb) { ++ ctx->packets = packet->packets; + for (i = 0; i < packet->packets; i++) + ctx->packet_size[i] = packet->packet_size[i]; + } +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index cde5b5c165096a..ff2bbe761ee3a8 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -2047,6 +2047,8 @@ struct usb_audio_quirk_flags_table { + + static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + /* Device matches */ ++ DEVICE_FLG(0x001f, 0x0b21, /* AB13X USB Audio */ ++ QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY), + DEVICE_FLG(0x03f0, 0x654a, /* HP 320 FHD Webcam */ + QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), + DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */ +diff --git a/tools/bpf/bpftool/net.c b/tools/bpf/bpftool/net.c +index c2ca82fc21e21a..225d3678b4ed1d 100644 +--- a/tools/bpf/bpftool/net.c ++++ b/tools/bpf/bpftool/net.c +@@ -150,7 +150,7 @@ static int netlink_recv(int sock, __u32 nl_pid, __u32 seq, + bool multipart = true; + struct nlmsgerr *err; + struct nlmsghdr *nh; +- char buf[4096]; ++ char buf[8192]; + int len, ret; + + while (multipart) { +@@ -195,6 +195,9 @@ static int netlink_recv(int sock, __u32 nl_pid, __u32 seq, + return ret; + } + } ++ ++ if (len) ++ p_err("Invalid message or trailing data in Netlink response: %d bytes left", len); + } + ret = 0; + done: +diff --git a/tools/include/linux/bitfield.h b/tools/include/linux/bitfield.h +index 6093fa6db2600b..ddf81f24956ba0 100644 +--- a/tools/include/linux/bitfield.h ++++ b/tools/include/linux/bitfield.h +@@ -8,6 +8,7 @@ + #define _LINUX_BITFIELD_H + + #include ++#include + #include + + /* +diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c +index cf4db51b99eb5d..beb91c78ca7a47 100644 +--- a/tools/lib/bpf/btf_dump.c ++++ b/tools/lib/bpf/btf_dump.c +@@ -1758,9 +1758,18 @@ static int btf_dump_get_bitfield_value(struct btf_dump *d, + __u16 left_shift_bits, right_shift_bits; + const __u8 *bytes = data; + __u8 nr_copy_bits; ++ __u8 start_bit, nr_bytes; + __u64 num = 0; + int i; + ++ /* Calculate how many bytes cover the bitfield */ ++ start_bit = bits_offset % 8; ++ nr_bytes = (start_bit + bit_sz + 7) / 8; ++ ++ /* Bound check */ ++ if (data + nr_bytes > d->typed_dump->data_end) ++ return -E2BIG; ++ + /* Maximum supported bitfield size is 64 bits */ + if (t->size > 8) { + pr_warn("unexpected bitfield size %d\n", t->size); +diff --git a/tools/lib/bpf/netlink.c b/tools/lib/bpf/netlink.c +index 68a2def171751c..6f16c4f7b3a433 100644 +--- a/tools/lib/bpf/netlink.c ++++ b/tools/lib/bpf/netlink.c +@@ -143,7 +143,7 @@ static int libbpf_netlink_recv(int sock, __u32 nl_pid, int seq, + struct nlmsghdr *nh; + int len, ret; + +- ret = alloc_iov(&iov, 4096); ++ ret = alloc_iov(&iov, 8192); + if (ret) + goto done; + +@@ -212,6 +212,8 @@ start: + } + } + } ++ if (len) ++ pr_warn("Invalid message or trailing data in Netlink response: %d bytes left\n", len); + } + ret = 0; + done: +diff --git a/tools/lib/perf/Makefile b/tools/lib/perf/Makefile +index 3a9b2140aa048e..703a8ff0b34301 100644 +--- a/tools/lib/perf/Makefile ++++ b/tools/lib/perf/Makefile +@@ -54,13 +54,6 @@ endif + + TEST_ARGS := $(if $(V),-v) + +-# Set compile option CFLAGS +-ifdef EXTRA_CFLAGS +- CFLAGS := $(EXTRA_CFLAGS) +-else +- CFLAGS := -g -Wall +-endif +- + INCLUDES = \ + -I$(srctree)/tools/lib/perf/include \ + -I$(srctree)/tools/lib/ \ +@@ -70,11 +63,12 @@ INCLUDES = \ + -I$(srctree)/tools/include/uapi + + # Append required CFLAGS +-override CFLAGS += $(EXTRA_WARNINGS) +-override CFLAGS += -Werror -Wall ++override CFLAGS := $(INCLUDES) $(CFLAGS) ++override CFLAGS += -g -Werror -Wall + override CFLAGS += -fPIC +-override CFLAGS += $(INCLUDES) + override CFLAGS += -fvisibility=hidden ++override CFLAGS += $(EXTRA_WARNINGS) ++override CFLAGS += $(EXTRA_CFLAGS) + + all: + +diff --git a/tools/lib/subcmd/help.c b/tools/lib/subcmd/help.c +index ddaeb4eb3e2497..db94aa685b73b8 100644 +--- a/tools/lib/subcmd/help.c ++++ b/tools/lib/subcmd/help.c +@@ -97,11 +97,13 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) + ei++; + } + } +- if (ci != cj) { +- while (ci < cmds->cnt) { +- cmds->names[cj++] = cmds->names[ci]; +- cmds->names[ci++] = NULL; ++ while (ci < cmds->cnt) { ++ if (ci != cj) { ++ cmds->names[cj] = cmds->names[ci]; ++ cmds->names[ci] = NULL; + } ++ ci++; ++ cj++; + } + for (ci = cj; ci < cmds->cnt; ci++) + assert(cmds->names[ci] == NULL); +diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile +index 83b100c1e7f684..e9a0f89e9c39a9 100644 +--- a/tools/objtool/Makefile ++++ b/tools/objtool/Makefile +@@ -7,6 +7,8 @@ srctree := $(patsubst %/,%,$(dir $(CURDIR))) + srctree := $(patsubst %/,%,$(dir $(srctree))) + endif + ++RM ?= rm -f ++ + LIBSUBCMD_DIR = $(srctree)/tools/lib/subcmd/ + ifneq ($(OUTPUT),) + LIBSUBCMD_OUTPUT = $(abspath $(OUTPUT))/libsubcmd +diff --git a/tools/perf/tests/shell/stat.sh b/tools/perf/tests/shell/stat.sh +index 62f13dfeae8e4d..a76ccf2deb563c 100755 +--- a/tools/perf/tests/shell/stat.sh ++++ b/tools/perf/tests/shell/stat.sh +@@ -18,7 +18,7 @@ test_default_stat() { + + test_stat_record_report() { + echo "stat record and report test" +- if ! perf stat record -o - true | perf stat report -i - 2>&1 | \ ++ if ! perf stat record -e task-clock -o - true | perf stat report -i - 2>&1 | \ + grep -E -q "Performance counter stats for 'pipe':" + then + echo "stat record and report test [Failed]" +@@ -30,7 +30,7 @@ test_stat_record_report() { + + test_stat_record_script() { + echo "stat record and script test" +- if ! perf stat record -o - true | perf script -i - 2>&1 | \ ++ if ! perf stat record -e task-clock -o - true | perf script -i - 2>&1 | \ + grep -E -q "CPU[[:space:]]+THREAD[[:space:]]+VAL[[:space:]]+ENA[[:space:]]+RUN[[:space:]]+TIME[[:space:]]+EVENT" + then + echo "stat record and script test [Failed]" +@@ -159,7 +159,7 @@ test_hybrid() { + fi + + # Run default Perf stat +- cycles_events=$(perf stat -- true 2>&1 | grep -E "/cycles/[uH]*| cycles[:uH]* " -c) ++ cycles_events=$(perf stat -a -- sleep 0.1 2>&1 | grep -E "/cpu-cycles/[uH]*| cpu-cycles[:uH]* " | wc -l) + + # The expectation is that default output will have a cycles events on each + # hybrid PMU. In situations with no cycles PMU events, like virtualized, this +diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c +index 8719b3cb564661..99310f8423967f 100644 +--- a/tools/perf/util/evsel_fprintf.c ++++ b/tools/perf/util/evsel_fprintf.c +@@ -181,8 +181,12 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment, + if (print_dso && (!sym || !sym->inlined)) + printed += map__fprintf_dsoname_dsoff(map, print_dsoff, addr, fp); + +- if (print_srcline) +- printed += map__fprintf_srcline(map, addr, "\n ", fp); ++ if (print_srcline) { ++ if (node->srcline) ++ printed += fprintf(fp, "\n %s", node->srcline); ++ else ++ printed += map__fprintf_srcline(map, addr, "\n ", fp); ++ } + + if (sym && sym->inlined) + printed += fprintf(fp, " (inlined)"); +diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c +index 6013335a8daea5..bd027fdf6af179 100644 +--- a/tools/perf/util/unwind-libdw.c ++++ b/tools/perf/util/unwind-libdw.c +@@ -133,8 +133,8 @@ static int entry(u64 ip, struct unwind_info *ui) + } + + e->ip = ip; +- e->ms.maps = al.maps; +- e->ms.map = al.map; ++ e->ms.maps = maps__get(al.maps); ++ e->ms.map = map__get(al.map); + e->ms.sym = al.sym; + + pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n", +@@ -319,6 +319,9 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, + if (err) + pr_debug("unwind: failed with '%s'\n", dwfl_errmsg(-1)); + ++ for (i = 0; i < ui->idx; i++) ++ map_symbol__exit(&ui->entries[i].ms); ++ + dwfl_end(ui->dwfl); + free(ui); + return 0; +diff --git a/tools/power/cpupower/lib/cpuidle.c b/tools/power/cpupower/lib/cpuidle.c +index c15d0de12357fb..e7b8c566383701 100644 +--- a/tools/power/cpupower/lib/cpuidle.c ++++ b/tools/power/cpupower/lib/cpuidle.c +@@ -148,6 +148,7 @@ unsigned long long cpuidle_state_get_one_value(unsigned int cpu, + if (len == 0) + return 0; + ++ errno = 0; + value = strtoull(linebuf, &endp, 0); + + if (endp == linebuf || errno == ERANGE) +diff --git a/tools/power/x86/intel-speed-select/isst-config.c b/tools/power/x86/intel-speed-select/isst-config.c +index 5fcc2a92957e79..a5d512866a940d 100644 +--- a/tools/power/x86/intel-speed-select/isst-config.c ++++ b/tools/power/x86/intel-speed-select/isst-config.c +@@ -936,9 +936,11 @@ int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int lev + ret = write(fd, "member", strlen("member")); + if (ret == -1) { + printf("Can't update to member\n"); ++ close(fd); + return ret; + } + ++ close(fd); + return 0; + } + +diff --git a/tools/spi/.gitignore b/tools/spi/.gitignore +index 14ddba3d21957b..038261b34ed83c 100644 +--- a/tools/spi/.gitignore ++++ b/tools/spi/.gitignore +@@ -1,3 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0-only + spidev_fdx + spidev_test ++include/ +diff --git a/tools/testing/selftests/bpf/veristat.c b/tools/testing/selftests/bpf/veristat.c +index 611b5a0a6f7e3e..fab89a84119f85 100644 +--- a/tools/testing/selftests/bpf/veristat.c ++++ b/tools/testing/selftests/bpf/veristat.c +@@ -1372,7 +1372,7 @@ static void output_stats(const struct verif_stats *s, enum resfmt fmt, bool last + if (last && fmt == RESFMT_TABLE) { + output_header_underlines(); + printf("Done. Processed %d files, %d programs. Skipped %d files, %d programs.\n", +- env.files_processed, env.files_skipped, env.progs_processed, env.progs_skipped); ++ env.files_processed, env.progs_processed, env.files_skipped, env.progs_skipped); + } + } + +diff --git a/tools/testing/selftests/drivers/net/mlxsw/tc_restrictions.sh b/tools/testing/selftests/drivers/net/mlxsw/tc_restrictions.sh +index 0441a18f098b10..aac8ef490feb80 100755 +--- a/tools/testing/selftests/drivers/net/mlxsw/tc_restrictions.sh ++++ b/tools/testing/selftests/drivers/net/mlxsw/tc_restrictions.sh +@@ -317,7 +317,7 @@ police_limits_test() + + tc filter add dev $swp1 ingress pref 1 proto ip handle 101 \ + flower skip_sw \ +- action police rate 0.5kbit burst 1m conform-exceed drop/ok ++ action police rate 0.5kbit burst 2k conform-exceed drop/ok + check_fail $? "Incorrect success to add police action with too low rate" + + tc filter add dev $swp1 ingress pref 1 proto ip handle 101 \ +@@ -327,7 +327,7 @@ police_limits_test() + + tc filter add dev $swp1 ingress pref 1 proto ip handle 101 \ + flower skip_sw \ +- action police rate 1.5kbit burst 1m conform-exceed drop/ok ++ action police rate 1.5kbit burst 2k conform-exceed drop/ok + check_err $? "Failed to add police action with low rate" + + tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower +diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c +index 9c9c82fd18a7ea..f2042de4bab8e2 100644 +--- a/tools/testing/selftests/memfd/memfd_test.c ++++ b/tools/testing/selftests/memfd/memfd_test.c +@@ -18,6 +18,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + +@@ -39,14 +42,26 @@ + F_SEAL_EXEC) + + #define MFD_NOEXEC_SEAL 0x0008U ++union semun { ++ int val; ++ struct semid_ds *buf; ++ unsigned short int *array; ++ struct seminfo *__buf; ++}; ++ ++/* ++ * we use semaphores on nested wait tasks due the use of CLONE_NEWPID: the ++ * child will be PID 1 and can't send SIGSTOP to themselves due special ++ * treatment of the init task, so the SIGSTOP/SIGCONT synchronization ++ * approach can't be used here. ++ */ ++#define SEM_KEY 0xdeadbeef + + /* + * Default is not to test hugetlbfs + */ + static size_t mfd_def_size = MFD_DEF_SIZE; + static const char *memfd_str = MEMFD_STR; +-static int newpid_thread_fn2(void *arg); +-static void join_newpid_thread(pid_t pid); + + static ssize_t fd2name(int fd, char *buf, size_t bufsize) + { +@@ -195,7 +210,6 @@ static unsigned int mfd_assert_get_seals(int fd) + static void mfd_assert_has_seals(int fd, unsigned int seals) + { + char buf[PATH_MAX]; +- int nbytes; + unsigned int s; + fd2name(fd, buf, PATH_MAX); + +@@ -715,7 +729,6 @@ static void mfd_assert_mode(int fd, int mode) + { + struct stat st; + char buf[PATH_MAX]; +- int nbytes; + + fd2name(fd, buf, PATH_MAX); + +@@ -734,7 +747,6 @@ static void mfd_assert_mode(int fd, int mode) + static void mfd_assert_chmod(int fd, int mode) + { + char buf[PATH_MAX]; +- int nbytes; + + fd2name(fd, buf, PATH_MAX); + +@@ -750,7 +762,6 @@ static void mfd_fail_chmod(int fd, int mode) + { + struct stat st; + char buf[PATH_MAX]; +- int nbytes; + + fd2name(fd, buf, PATH_MAX); + +@@ -1297,9 +1308,6 @@ static void test_sysctl_set_sysctl2(void) + + static int sysctl_simple_child(void *arg) + { +- int fd; +- int pid; +- + printf("%s sysctl 0\n", memfd_str); + test_sysctl_set_sysctl0(); + +@@ -1342,8 +1350,22 @@ static int sysctl_nested(void *arg) + + static int sysctl_nested_wait(void *arg) + { +- /* Wait for a SIGCONT. */ +- kill(getpid(), SIGSTOP); ++ int sem = semget(SEM_KEY, 1, 0600); ++ struct sembuf sembuf; ++ ++ if (sem < 0) { ++ perror("semget:"); ++ abort(); ++ } ++ sembuf.sem_num = 0; ++ sembuf.sem_flg = 0; ++ sembuf.sem_op = 0; ++ ++ if (semop(sem, &sembuf, 1) < 0) { ++ perror("semop:"); ++ abort(); ++ } ++ + return sysctl_nested(arg); + } + +@@ -1364,8 +1386,9 @@ static void test_sysctl_sysctl2_failset(void) + + static int sysctl_nested_child(void *arg) + { +- int fd; +- int pid; ++ int pid, sem; ++ union semun semun; ++ struct sembuf sembuf; + + printf("%s nested sysctl 0\n", memfd_str); + sysctl_assert_write("0"); +@@ -1399,23 +1422,53 @@ static int sysctl_nested_child(void *arg) + test_sysctl_sysctl2_failset); + join_thread(pid); + ++ sem = semget(SEM_KEY, 1, IPC_CREAT | 0600); ++ if (sem < 0) { ++ perror("semget:"); ++ return 1; ++ } ++ semun.val = 1; ++ sembuf.sem_op = -1; ++ sembuf.sem_flg = 0; ++ sembuf.sem_num = 0; ++ + /* Verify that the rules are actually inherited after fork. */ + printf("%s nested sysctl 0 -> 1 after fork\n", memfd_str); + sysctl_assert_write("0"); + ++ if (semctl(sem, 0, SETVAL, semun) < 0) { ++ perror("semctl:"); ++ return 1; ++ } ++ + pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait, + test_sysctl_sysctl1_failset); + sysctl_assert_write("1"); +- kill(pid, SIGCONT); ++ ++ /* Allow child to continue */ ++ if (semop(sem, &sembuf, 1) < 0) { ++ perror("semop:"); ++ return 1; ++ } + join_thread(pid); + + printf("%s nested sysctl 0 -> 2 after fork\n", memfd_str); + sysctl_assert_write("0"); + ++ if (semctl(sem, 0, SETVAL, semun) < 0) { ++ perror("semctl:"); ++ return 1; ++ } ++ + pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait, + test_sysctl_sysctl2_failset); + sysctl_assert_write("2"); +- kill(pid, SIGCONT); ++ ++ /* Allow child to continue */ ++ if (semop(sem, &sembuf, 1) < 0) { ++ perror("semop:"); ++ return 1; ++ } + join_thread(pid); + + /* +@@ -1425,28 +1478,62 @@ static int sysctl_nested_child(void *arg) + */ + printf("%s nested sysctl 2 -> 1 after fork\n", memfd_str); + sysctl_assert_write("2"); ++ ++ if (semctl(sem, 0, SETVAL, semun) < 0) { ++ perror("semctl:"); ++ return 1; ++ } ++ + pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait, + test_sysctl_sysctl2); + sysctl_assert_write("1"); +- kill(pid, SIGCONT); ++ ++ /* Allow child to continue */ ++ if (semop(sem, &sembuf, 1) < 0) { ++ perror("semop:"); ++ return 1; ++ } + join_thread(pid); + + printf("%s nested sysctl 2 -> 0 after fork\n", memfd_str); + sysctl_assert_write("2"); ++ ++ if (semctl(sem, 0, SETVAL, semun) < 0) { ++ perror("semctl:"); ++ return 1; ++ } ++ + pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait, + test_sysctl_sysctl2); + sysctl_assert_write("0"); +- kill(pid, SIGCONT); ++ ++ /* Allow child to continue */ ++ if (semop(sem, &sembuf, 1) < 0) { ++ perror("semop:"); ++ return 1; ++ } + join_thread(pid); + + printf("%s nested sysctl 1 -> 0 after fork\n", memfd_str); + sysctl_assert_write("1"); ++ ++ if (semctl(sem, 0, SETVAL, semun) < 0) { ++ perror("semctl:"); ++ return 1; ++ } ++ + pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait, + test_sysctl_sysctl1); + sysctl_assert_write("0"); +- kill(pid, SIGCONT); ++ /* Allow child to continue */ ++ if (semop(sem, &sembuf, 1) < 0) { ++ perror("semop:"); ++ return 1; ++ } + join_thread(pid); + ++ semctl(sem, 0, IPC_RMID); ++ + return 0; + } + +diff --git a/tools/testing/selftests/mm/charge_reserved_hugetlb.sh b/tools/testing/selftests/mm/charge_reserved_hugetlb.sh +index dc3fc438b3d9e1..7cf581f4f44fb5 100755 +--- a/tools/testing/selftests/mm/charge_reserved_hugetlb.sh ++++ b/tools/testing/selftests/mm/charge_reserved_hugetlb.sh +@@ -288,7 +288,7 @@ function run_test() { + setup_cgroup "hugetlb_cgroup_test" "$cgroup_limit" "$reservation_limit" + + mkdir -p /mnt/huge +- mount -t hugetlbfs -o pagesize=${MB}M,size=256M none /mnt/huge ++ mount -t hugetlbfs -o pagesize=${MB}M none /mnt/huge + + write_hugetlbfs_and_get_usage "hugetlb_cgroup_test" "$size" "$populate" \ + "$write" "/mnt/huge/test" "$method" "$private" "$expect_failure" \ +@@ -342,7 +342,7 @@ function run_multiple_cgroup_test() { + setup_cgroup "hugetlb_cgroup_test2" "$cgroup_limit2" "$reservation_limit2" + + mkdir -p /mnt/huge +- mount -t hugetlbfs -o pagesize=${MB}M,size=256M none /mnt/huge ++ mount -t hugetlbfs -o pagesize=${MB}M none /mnt/huge + + write_hugetlbfs_and_get_usage "hugetlb_cgroup_test1" "$size1" \ + "$populate1" "$write1" "/mnt/huge/test1" "$method" "$private" \ +diff --git a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh +index eb307ca37bfa69..002551451a7287 100755 +--- a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh ++++ b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh +@@ -559,6 +559,21 @@ vxlan_encapped_ping_do() + local inner_tos=$1; shift + local outer_tos=$1; shift + ++ local ipv4hdr=$(: ++ )"45:"$( : IP version + IHL ++ )"$inner_tos:"$( : IP TOS ++ )"00:54:"$( : IP total length ++ )"99:83:"$( : IP identification ++ )"40:00:"$( : IP flags + frag off ++ )"40:"$( : IP TTL ++ )"01:"$( : IP proto ++ )"CHECKSUM:"$( : IP header csum ++ )"c0:00:02:03:"$( : IP saddr: 192.0.2.3 ++ )"c0:00:02:01"$( : IP daddr: 192.0.2.1 ++ ) ++ local checksum=$(payload_template_calc_checksum "$ipv4hdr") ++ ipv4hdr=$(payload_template_expand_checksum "$ipv4hdr" $checksum) ++ + $MZ $dev -c $count -d 100msec -q \ + -b $next_hop_mac -B $dest_ip \ + -t udp tos=$outer_tos,sp=23456,dp=$VXPORT,p=$(: +@@ -569,16 +584,7 @@ vxlan_encapped_ping_do() + )"$dest_mac:"$( : ETH daddr + )"$(mac_get w2):"$( : ETH saddr + )"08:00:"$( : ETH type +- )"45:"$( : IP version + IHL +- )"$inner_tos:"$( : IP TOS +- )"00:54:"$( : IP total length +- )"99:83:"$( : IP identification +- )"40:00:"$( : IP flags + frag off +- )"40:"$( : IP TTL +- )"01:"$( : IP proto +- )"00:00:"$( : IP header csum +- )"c0:00:02:03:"$( : IP saddr: 192.0.2.3 +- )"c0:00:02:01:"$( : IP daddr: 192.0.2.1 ++ )"$ipv4hdr:"$( : IPv4 header + )"08:"$( : ICMP type + )"00:"$( : ICMP code + )"8b:f2:"$( : ICMP csum +diff --git a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh +index bd3f7d492af2bb..28284a5aa07a97 100755 +--- a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh ++++ b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh +@@ -695,7 +695,7 @@ vxlan_encapped_ping_do() + )"6"$( : IP version + )"$inner_tos"$( : Traffic class + )"0:00:00:"$( : Flow label +- )"00:08:"$( : Payload length ++ )"00:03:"$( : Payload length + )"3a:"$( : Next header + )"04:"$( : Hop limit + )"$saddr:"$( : IP saddr