From: Sasha Levin Date: Mon, 3 Jun 2024 11:42:15 +0000 (-0400) Subject: Fixes for 5.10 X-Git-Tag: v6.1.93~55 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4b3fdb18ee99cfa3581cf642edac0e71dc333305;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.10 Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/arm64-asm-bug-add-.align-2-to-the-end-of-__bug_entry.patch b/queue-5.10/arm64-asm-bug-add-.align-2-to-the-end-of-__bug_entry.patch new file mode 100644 index 00000000000..726afbe6e5e --- /dev/null +++ b/queue-5.10/arm64-asm-bug-add-.align-2-to-the-end-of-__bug_entry.patch @@ -0,0 +1,160 @@ +From 404078ce2d7362c0bd8d373e77dc26521fd61850 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 May 2024 21:34:37 +0800 +Subject: arm64: asm-bug: Add .align 2 to the end of __BUG_ENTRY + +From: Jiangfeng Xiao + +[ Upstream commit ffbf4fb9b5c12ff878a10ea17997147ea4ebea6f ] + +When CONFIG_DEBUG_BUGVERBOSE=n, we fail to add necessary padding bytes +to bug_table entries, and as a result the last entry in a bug table will +be ignored, potentially leading to an unexpected panic(). All prior +entries in the table will be handled correctly. + +The arm64 ABI requires that struct fields of up to 8 bytes are +naturally-aligned, with padding added within a struct such that struct +are suitably aligned within arrays. + +When CONFIG_DEBUG_BUGVERPOSE=y, the layout of a bug_entry is: + + struct bug_entry { + signed int bug_addr_disp; // 4 bytes + signed int file_disp; // 4 bytes + unsigned short line; // 2 bytes + unsigned short flags; // 2 bytes + } + +... with 12 bytes total, requiring 4-byte alignment. + +When CONFIG_DEBUG_BUGVERBOSE=n, the layout of a bug_entry is: + + struct bug_entry { + signed int bug_addr_disp; // 4 bytes + unsigned short flags; // 2 bytes + < implicit padding > // 2 bytes + } + +... with 8 bytes total, with 6 bytes of data and 2 bytes of trailing +padding, requiring 4-byte alginment. + +When we create a bug_entry in assembly, we align the start of the entry +to 4 bytes, which implicitly handles padding for any prior entries. +However, we do not align the end of the entry, and so when +CONFIG_DEBUG_BUGVERBOSE=n, the final entry lacks the trailing padding +bytes. + +For the main kernel image this is not a problem as find_bug() doesn't +depend on the trailing padding bytes when searching for entries: + + for (bug = __start___bug_table; bug < __stop___bug_table; ++bug) + if (bugaddr == bug_addr(bug)) + return bug; + +However for modules, module_bug_finalize() depends on the trailing +bytes when calculating the number of entries: + + mod->num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); + +... and as the last bug_entry lacks the necessary padding bytes, this entry +will not be counted, e.g. in the case of a single entry: + + sechdrs[i].sh_size == 6 + sizeof(struct bug_entry) == 8; + + sechdrs[i].sh_size / sizeof(struct bug_entry) == 0; + +Consequently module_find_bug() will miss the last bug_entry when it does: + + for (i = 0; i < mod->num_bugs; ++i, ++bug) + if (bugaddr == bug_addr(bug)) + goto out; + +... which can lead to a kenrel panic due to an unhandled bug. + +This can be demonstrated with the following module: + + static int __init buginit(void) + { + WARN(1, "hello\n"); + return 0; + } + + static void __exit bugexit(void) + { + } + + module_init(buginit); + module_exit(bugexit); + MODULE_LICENSE("GPL"); + +... which will trigger a kernel panic when loaded: + + ------------[ cut here ]------------ + hello + Unexpected kernel BRK exception at EL1 + Internal error: BRK handler: 00000000f2000800 [#1] PREEMPT SMP + Modules linked in: hello(O+) + CPU: 0 PID: 50 Comm: insmod Tainted: G O 6.9.1 #8 + Hardware name: linux,dummy-virt (DT) + pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) + pc : buginit+0x18/0x1000 [hello] + lr : buginit+0x18/0x1000 [hello] + sp : ffff800080533ae0 + x29: ffff800080533ae0 x28: 0000000000000000 x27: 0000000000000000 + x26: ffffaba8c4e70510 x25: ffff800080533c30 x24: ffffaba8c4a28a58 + x23: 0000000000000000 x22: 0000000000000000 x21: ffff3947c0eab3c0 + x20: ffffaba8c4e3f000 x19: ffffaba846464000 x18: 0000000000000006 + x17: 0000000000000000 x16: ffffaba8c2492834 x15: 0720072007200720 + x14: 0720072007200720 x13: ffffaba8c49b27c8 x12: 0000000000000312 + x11: 0000000000000106 x10: ffffaba8c4a0a7c8 x9 : ffffaba8c49b27c8 + x8 : 00000000ffffefff x7 : ffffaba8c4a0a7c8 x6 : 80000000fffff000 + x5 : 0000000000000107 x4 : 0000000000000000 x3 : 0000000000000000 + x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff3947c0eab3c0 + Call trace: + buginit+0x18/0x1000 [hello] + do_one_initcall+0x80/0x1c8 + do_init_module+0x60/0x218 + load_module+0x1ba4/0x1d70 + __do_sys_init_module+0x198/0x1d0 + __arm64_sys_init_module+0x1c/0x28 + invoke_syscall+0x48/0x114 + el0_svc_common.constprop.0+0x40/0xe0 + do_el0_svc+0x1c/0x28 + el0_svc+0x34/0xd8 + el0t_64_sync_handler+0x120/0x12c + el0t_64_sync+0x190/0x194 + Code: d0ffffe0 910003fd 91000000 9400000b (d4210000) + ---[ end trace 0000000000000000 ]--- + Kernel panic - not syncing: BRK handler: Fatal exception + +Fix this by always aligning the end of a bug_entry to 4 bytes, which is +correct regardless of CONFIG_DEBUG_BUGVERBOSE. + +Fixes: 9fb7410f955f ("arm64/BUG: Use BRK instruction for generic BUG traps") + +Signed-off-by: Yuanbin Xie +Signed-off-by: Jiangfeng Xiao +Reviewed-by: Mark Rutland +Link: https://lore.kernel.org/r/1716212077-43826-1-git-send-email-xiaojiangfeng@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/asm-bug.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/include/asm/asm-bug.h b/arch/arm64/include/asm/asm-bug.h +index 03f52f84a4f3f..bc2dcc8a00009 100644 +--- a/arch/arm64/include/asm/asm-bug.h ++++ b/arch/arm64/include/asm/asm-bug.h +@@ -28,6 +28,7 @@ + 14470: .long 14471f - 14470b; \ + _BUGVERBOSE_LOCATION(__FILE__, __LINE__) \ + .short flags; \ ++ .align 2; \ + .popsection; \ + 14471: + #else +-- +2.43.0 + diff --git a/queue-5.10/asoc-tas2552-add-tx-path-for-capturing-audio-out-dat.patch b/queue-5.10/asoc-tas2552-add-tx-path-for-capturing-audio-out-dat.patch new file mode 100644 index 00000000000..3fa22859caf --- /dev/null +++ b/queue-5.10/asoc-tas2552-add-tx-path-for-capturing-audio-out-dat.patch @@ -0,0 +1,76 @@ +From bbe54b0fd3b9234217cca86f0fd6e3c7e4d51bee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 18 May 2024 11:35:15 +0800 +Subject: ASoC: tas2552: Add TX path for capturing AUDIO-OUT data + +From: Shenghao Ding + +[ Upstream commit 7078ac4fd179a68d0bab448004fcd357e7a45f8d ] + +TAS2552 is a Smartamp with I/V sense data, add TX path +to support capturing I/V data. + +Fixes: 38803ce7b53b ("ASoC: codecs: tas*: merge .digital_mute() into .mute_stream()") +Signed-off-by: Shenghao Ding +Link: https://msgid.link/r/20240518033515.866-1-shenghao-ding@ti.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2552.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c +index bd00c35116cd5..f045876c12f17 100644 +--- a/sound/soc/codecs/tas2552.c ++++ b/sound/soc/codecs/tas2552.c +@@ -2,7 +2,8 @@ + /* + * tas2552.c - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier + * +- * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com ++ * Copyright (C) 2014 - 2024 Texas Instruments Incorporated - ++ * https://www.ti.com + * + * Author: Dan Murphy + */ +@@ -119,12 +120,14 @@ static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] = + &tas2552_input_mux_control), + + SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_OUT("ASI OUT", "DAC Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0), + SND_SOC_DAPM_POST("Post Event", tas2552_post_event), + +- SND_SOC_DAPM_OUTPUT("OUT") ++ SND_SOC_DAPM_OUTPUT("OUT"), ++ SND_SOC_DAPM_INPUT("DMIC") + }; + + static const struct snd_soc_dapm_route tas2552_audio_map[] = { +@@ -134,6 +137,7 @@ static const struct snd_soc_dapm_route tas2552_audio_map[] = { + {"ClassD", NULL, "Input selection"}, + {"OUT", NULL, "ClassD"}, + {"ClassD", NULL, "PLL"}, ++ {"ASI OUT", NULL, "DMIC"} + }; + + #ifdef CONFIG_PM +@@ -538,6 +542,13 @@ static struct snd_soc_dai_driver tas2552_dai[] = { + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = TAS2552_FORMATS, + }, ++ .capture = { ++ .stream_name = "Capture", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = TAS2552_FORMATS, ++ }, + .ops = &tas2552_speaker_dai_ops, + }, + }; +-- +2.43.0 + diff --git a/queue-5.10/drm-bridge-tc358775-fix-support-for-jeida-18-and-jei.patch b/queue-5.10/drm-bridge-tc358775-fix-support-for-jeida-18-and-jei.patch new file mode 100644 index 00000000000..873e6b35a1d --- /dev/null +++ b/queue-5.10/drm-bridge-tc358775-fix-support-for-jeida-18-and-jei.patch @@ -0,0 +1,75 @@ +From 9cd6f6edf5de485cbcac1b8834025e371b501ddd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 25 Feb 2024 08:19:33 +0200 +Subject: drm/bridge: tc358775: fix support for jeida-18 and jeida-24 + +From: Michael Walle + +[ Upstream commit 30ea09a182cb37c4921b9d477ed18107befe6d78 ] + +The bridge always uses 24bpp internally. Therefore, for jeida-18 +mapping we need to discard the lowest two bits for each channel and thus +starting with LV_[RGB]2. jeida-24 has the same mapping but uses four +lanes instead of three, with the forth pair transmitting the lowest two +bits of each channel. Thus, the mapping between jeida-18 and jeida-24 +is actually the same, except that one channel is turned off (by +selecting the RGB666 format in VPCTRL). + +While at it, remove the bogus comment about the hardware default because +the default is overwritten in any case. + +Tested with a jeida-18 display (Evervision VGG644804). + +Fixes: b26975593b17 ("display/drm/bridge: TC358775 DSI/LVDS driver") +Signed-off-by: Michael Walle +Signed-off-by: Tony Lindgren +Reviewed-by: Robert Foss +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20240225062008.33191-5-tony@atomide.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/tc358775.c | 21 +++++++++------------ + 1 file changed, 9 insertions(+), 12 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c +index 55697fa4d7c8b..2e299cfe4e487 100644 +--- a/drivers/gpu/drm/bridge/tc358775.c ++++ b/drivers/gpu/drm/bridge/tc358775.c +@@ -453,10 +453,6 @@ static void tc_bridge_enable(struct drm_bridge *bridge) + dev_dbg(tc->dev, "bus_formats %04x bpc %d\n", + connector->display_info.bus_formats[0], + tc->bpc); +- /* +- * Default hardware register settings of tc358775 configured +- * with MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA jeida-24 format +- */ + if (connector->display_info.bus_formats[0] == + MEDIA_BUS_FMT_RGB888_1X7X4_SPWG) { + /* VESA-24 */ +@@ -467,14 +463,15 @@ static void tc_bridge_enable(struct drm_bridge *bridge) + d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_B6, LVI_B7, LVI_B1, LVI_B2)); + d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0)); + d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R6)); +- } else { /* MEDIA_BUS_FMT_RGB666_1X7X3_SPWG - JEIDA-18 */ +- d2l_write(tc->i2c, LV_MX0003, LV_MX(LVI_R0, LVI_R1, LVI_R2, LVI_R3)); +- d2l_write(tc->i2c, LV_MX0407, LV_MX(LVI_R4, LVI_L0, LVI_R5, LVI_G0)); +- d2l_write(tc->i2c, LV_MX0811, LV_MX(LVI_G1, LVI_G2, LVI_L0, LVI_L0)); +- d2l_write(tc->i2c, LV_MX1215, LV_MX(LVI_G3, LVI_G4, LVI_G5, LVI_B0)); +- d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_L0, LVI_L0, LVI_B1, LVI_B2)); +- d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0)); +- d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_L0)); ++ } else { ++ /* JEIDA-18 and JEIDA-24 */ ++ d2l_write(tc->i2c, LV_MX0003, LV_MX(LVI_R2, LVI_R3, LVI_R4, LVI_R5)); ++ d2l_write(tc->i2c, LV_MX0407, LV_MX(LVI_R6, LVI_R1, LVI_R7, LVI_G2)); ++ d2l_write(tc->i2c, LV_MX0811, LV_MX(LVI_G3, LVI_G4, LVI_G0, LVI_G1)); ++ d2l_write(tc->i2c, LV_MX1215, LV_MX(LVI_G5, LVI_G6, LVI_G7, LVI_B2)); ++ d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_B0, LVI_B1, LVI_B3, LVI_B4)); ++ d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B5, LVI_B6, LVI_B7, LVI_L0)); ++ d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R0)); + } + + d2l_write(tc->i2c, VFUEN, VFUEN_EN); +-- +2.43.0 + diff --git a/queue-5.10/drm-msm-dpu-always-flush-the-slave-intf-on-the-ctl.patch b/queue-5.10/drm-msm-dpu-always-flush-the-slave-intf-on-the-ctl.patch new file mode 100644 index 00000000000..6771cb95a14 --- /dev/null +++ b/queue-5.10/drm-msm-dpu-always-flush-the-slave-intf-on-the-ctl.patch @@ -0,0 +1,49 @@ +From 484315cfc06fcc24748058cb9e64e13dacca55b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Apr 2024 01:57:43 +0200 +Subject: drm/msm/dpu: Always flush the slave INTF on the CTL + +From: Marijn Suijten + +[ Upstream commit 2b938c3ab0a69ec6ea587bbf6fc2aec3db4a8736 ] + +As we can clearly see in a downstream kernel [1], flushing the slave INTF +is skipped /only if/ the PPSPLIT topology is active. + +However, when DPU was originally submitted to mainline PPSPLIT was no +longer part of it (seems to have been ripped out before submission), but +this clause was incorrectly ported from the original SDE driver. Given +that there is no support for PPSPLIT (currently), flushing the slave +INTF should /never/ be skipped (as the `if (ppsplit && !master) goto +skip;` clause downstream never becomes true). + +[1]: https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers/-/blob/display-kernel.lnx.5.4.r1-rel/msm/sde/sde_encoder_phys_cmd.c?ref_type=heads#L1131-1139 + +Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support") +Signed-off-by: Marijn Suijten +Reviewed-by: Dmitry Baryshkov +Patchwork: https://patchwork.freedesktop.org/patch/589901/ +Link: https://lore.kernel.org/r/20240417-drm-msm-initial-dualpipe-dsc-fixes-v1-3-78ae3ee9a697@somainline.org +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 3 --- + 1 file changed, 3 deletions(-) + +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 8493d68ad8417..e1a97c10c0e41 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 +@@ -448,9 +448,6 @@ static void dpu_encoder_phys_cmd_enable_helper( + + _dpu_encoder_phys_cmd_pingpong_config(phys_enc); + +- if (!dpu_encoder_phys_cmd_is_master(phys_enc)) +- return; +- + ctl = phys_enc->hw_ctl; + ctl->ops.get_bitmask_intf(ctl, &flush_mask, phys_enc->intf_idx); + ctl->ops.update_pending_flush(ctl, flush_mask); +-- +2.43.0 + diff --git a/queue-5.10/input-ims-pcu-fix-printf-string-overflow.patch b/queue-5.10/input-ims-pcu-fix-printf-string-overflow.patch new file mode 100644 index 00000000000..ccac0a4b055 --- /dev/null +++ b/queue-5.10/input-ims-pcu-fix-printf-string-overflow.patch @@ -0,0 +1,43 @@ +From b8d7248fe94c6d3877562939cfd8d34dbbe7df7d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Mar 2024 13:28:56 -0700 +Subject: Input: ims-pcu - fix printf string overflow + +From: Arnd Bergmann + +[ Upstream commit bf32bceedd0453c70d9d022e2e29f98e446d7161 ] + +clang warns about a string overflow in this driver + +drivers/input/misc/ims-pcu.c:1802:2: error: 'snprintf' will always be truncated; specified size is 10, but format string expands to at least 12 [-Werror,-Wformat-truncation] +drivers/input/misc/ims-pcu.c:1814:2: error: 'snprintf' will always be truncated; specified size is 10, but format string expands to at least 12 [-Werror,-Wformat-truncation] + +Make the buffer a little longer to ensure it always fits. + +Fixes: 628329d52474 ("Input: add IMS Passenger Control Unit driver") +Signed-off-by: Arnd Bergmann +Link: https://lore.kernel.org/r/20240326223825.4084412-7-arnd@kernel.org +Signed-off-by: Dmitry Torokhov +Signed-off-by: Sasha Levin +--- + drivers/input/misc/ims-pcu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c +index 08b9b5cdb943e..e5cb20e7f57b1 100644 +--- a/drivers/input/misc/ims-pcu.c ++++ b/drivers/input/misc/ims-pcu.c +@@ -42,8 +42,8 @@ struct ims_pcu_backlight { + #define IMS_PCU_PART_NUMBER_LEN 15 + #define IMS_PCU_SERIAL_NUMBER_LEN 8 + #define IMS_PCU_DOM_LEN 8 +-#define IMS_PCU_FW_VERSION_LEN (9 + 1) +-#define IMS_PCU_BL_VERSION_LEN (9 + 1) ++#define IMS_PCU_FW_VERSION_LEN 16 ++#define IMS_PCU_BL_VERSION_LEN 16 + #define IMS_PCU_BL_RESET_REASON_LEN (2 + 1) + + #define IMS_PCU_PCU_B_DEVICE_ID 5 +-- +2.43.0 + diff --git a/queue-5.10/input-ioc3kbd-add-device-table.patch b/queue-5.10/input-ioc3kbd-add-device-table.patch new file mode 100644 index 00000000000..b1e0c1ba195 --- /dev/null +++ b/queue-5.10/input-ioc3kbd-add-device-table.patch @@ -0,0 +1,45 @@ +From 7b6590bf50b9c927294a3c9db230e1b23bca24fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Mar 2024 12:46:14 -0700 +Subject: Input: ioc3kbd - add device table + +From: Karel Balej + +[ Upstream commit d40e9edcf3eb925c259df9f9dd7319a4fcbc675b ] + +Without the device table the driver will not auto-load when compiled as +a module. + +Fixes: 273db8f03509 ("Input: add IOC3 serio driver") +Signed-off-by: Karel Balej +Link: https://lore.kernel.org/r/20240313115832.8052-1-balejk@matfyz.cz +Signed-off-by: Dmitry Torokhov +Signed-off-by: Sasha Levin +--- + drivers/input/serio/ioc3kbd.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/input/serio/ioc3kbd.c b/drivers/input/serio/ioc3kbd.c +index 50552dc7b4f5e..676b0bda3d720 100644 +--- a/drivers/input/serio/ioc3kbd.c ++++ b/drivers/input/serio/ioc3kbd.c +@@ -200,9 +200,16 @@ static void ioc3kbd_remove(struct platform_device *pdev) + serio_unregister_port(d->aux); + } + ++static const struct platform_device_id ioc3kbd_id_table[] = { ++ { "ioc3-kbd", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(platform, ioc3kbd_id_table); ++ + static struct platform_driver ioc3kbd_driver = { + .probe = ioc3kbd_probe, + .remove_new = ioc3kbd_remove, ++ .id_table = ioc3kbd_id_table, + .driver = { + .name = "ioc3-kbd", + }, +-- +2.43.0 + diff --git a/queue-5.10/input-ioc3kbd-convert-to-platform-remove-callback-re.patch b/queue-5.10/input-ioc3kbd-convert-to-platform-remove-callback-re.patch new file mode 100644 index 00000000000..00453cbd347 --- /dev/null +++ b/queue-5.10/input-ioc3kbd-convert-to-platform-remove-callback-re.patch @@ -0,0 +1,64 @@ +From 6bad48478a7e6a17c2c12aade16c12b9ef385553 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Sep 2023 14:58:13 +0200 +Subject: Input: ioc3kbd - convert to platform remove callback returning void +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 150e792dee9ca8416f3d375e48f2f4d7f701fc6b ] + +The .remove() callback for a platform driver returns an int which makes +many driver authors wrongly assume it's possible to do error handling by +returning an error code. However the value returned is ignored (apart +from emitting a warning) and this typically results in resource leaks. +To improve here there is a quest to make the remove callback return +void. In the first step of this quest all drivers are converted to +.remove_new() which already returns void. Eventually after all drivers +are converted, .remove_new() will be renamed to .remove(). + +Trivially convert this driver from always returning zero in the remove +callback to the void returning variant. + +Signed-off-by: Uwe Kleine-König +Link: https://lore.kernel.org/r/20230920125829.1478827-37-u.kleine-koenig@pengutronix.de +Signed-off-by: Dmitry Torokhov +Stable-dep-of: d40e9edcf3eb ("Input: ioc3kbd - add device table") +Signed-off-by: Sasha Levin +--- + drivers/input/serio/ioc3kbd.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/input/serio/ioc3kbd.c b/drivers/input/serio/ioc3kbd.c +index d51bfe912db5b..50552dc7b4f5e 100644 +--- a/drivers/input/serio/ioc3kbd.c ++++ b/drivers/input/serio/ioc3kbd.c +@@ -190,7 +190,7 @@ static int ioc3kbd_probe(struct platform_device *pdev) + return 0; + } + +-static int ioc3kbd_remove(struct platform_device *pdev) ++static void ioc3kbd_remove(struct platform_device *pdev) + { + struct ioc3kbd_data *d = platform_get_drvdata(pdev); + +@@ -198,13 +198,11 @@ static int ioc3kbd_remove(struct platform_device *pdev) + + serio_unregister_port(d->kbd); + serio_unregister_port(d->aux); +- +- return 0; + } + + static struct platform_driver ioc3kbd_driver = { + .probe = ioc3kbd_probe, +- .remove = ioc3kbd_remove, ++ .remove_new = ioc3kbd_remove, + .driver = { + .name = "ioc3-kbd", + }, +-- +2.43.0 + diff --git a/queue-5.10/input-pm8xxx-vibrator-correct-vib_max_levels-calcula.patch b/queue-5.10/input-pm8xxx-vibrator-correct-vib_max_levels-calcula.patch new file mode 100644 index 00000000000..311c37312b6 --- /dev/null +++ b/queue-5.10/input-pm8xxx-vibrator-correct-vib_max_levels-calcula.patch @@ -0,0 +1,55 @@ +From af471761bef7bfe67e92a22197a0bde7704ca000 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Apr 2024 16:03:40 -0700 +Subject: Input: pm8xxx-vibrator - correct VIB_MAX_LEVELS calculation + +From: Fenglin Wu + +[ Upstream commit 48c0687a322d54ac7e7a685c0b6db78d78f593af ] + +The output voltage is inclusive hence the max level calculation is +off-by-one-step. Correct it. + +iWhile we are at it also add a define for the step size instead of +using the magic value. + +Fixes: 11205bb63e5c ("Input: add support for pm8xxx based vibrator driver") +Signed-off-by: Fenglin Wu +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20240412-pm8xxx-vibrator-new-design-v10-1-0ec0ad133866@quicinc.com +Signed-off-by: Dmitry Torokhov +Signed-off-by: Sasha Levin +--- + drivers/input/misc/pm8xxx-vibrator.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c +index 53ad25eaf1a28..8bfe5c7b1244c 100644 +--- a/drivers/input/misc/pm8xxx-vibrator.c ++++ b/drivers/input/misc/pm8xxx-vibrator.c +@@ -14,7 +14,8 @@ + + #define VIB_MAX_LEVEL_mV (3100) + #define VIB_MIN_LEVEL_mV (1200) +-#define VIB_MAX_LEVELS (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV) ++#define VIB_PER_STEP_mV (100) ++#define VIB_MAX_LEVELS (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV + VIB_PER_STEP_mV) + + #define MAX_FF_SPEED 0xff + +@@ -118,10 +119,10 @@ static void pm8xxx_work_handler(struct work_struct *work) + vib->active = true; + vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) + + VIB_MIN_LEVEL_mV; +- vib->level /= 100; ++ vib->level /= VIB_PER_STEP_mV; + } else { + vib->active = false; +- vib->level = VIB_MIN_LEVEL_mV / 100; ++ vib->level = VIB_MIN_LEVEL_mV / VIB_PER_STEP_mV; + } + + pm8xxx_vib_set(vib, vib->active); +-- +2.43.0 + diff --git a/queue-5.10/ipv6-sr-fix-memleak-in-seg6_hmac_init_algo.patch b/queue-5.10/ipv6-sr-fix-memleak-in-seg6_hmac_init_algo.patch new file mode 100644 index 00000000000..672eeee7bea --- /dev/null +++ b/queue-5.10/ipv6-sr-fix-memleak-in-seg6_hmac_init_algo.patch @@ -0,0 +1,125 @@ +From 2b375a4627fddb53dbc9c9cb8df51e3b1a9c726b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 May 2024 08:54:35 +0800 +Subject: ipv6: sr: fix memleak in seg6_hmac_init_algo + +From: Hangbin Liu + +[ Upstream commit efb9f4f19f8e37fde43dfecebc80292d179f56c6 ] + +seg6_hmac_init_algo returns without cleaning up the previous allocations +if one fails, so it's going to leak all that memory and the crypto tfms. + +Update seg6_hmac_exit to only free the memory when allocated, so we can +reuse the code directly. + +Fixes: bf355b8d2c30 ("ipv6: sr: add core files for SR HMAC support") +Reported-by: Sabrina Dubroca +Closes: https://lore.kernel.org/netdev/Zj3bh-gE7eT6V6aH@hog/ +Signed-off-by: Hangbin Liu +Reviewed-by: Simon Horman +Reviewed-by: Sabrina Dubroca +Link: https://lore.kernel.org/r/20240517005435.2600277-1-liuhangbin@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv6/seg6_hmac.c | 42 ++++++++++++++++++++++++++++-------------- + 1 file changed, 28 insertions(+), 14 deletions(-) + +diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c +index 552bce1fdfb94..2e2b94ae63552 100644 +--- a/net/ipv6/seg6_hmac.c ++++ b/net/ipv6/seg6_hmac.c +@@ -355,6 +355,7 @@ static int seg6_hmac_init_algo(void) + struct crypto_shash *tfm; + struct shash_desc *shash; + int i, alg_count, cpu; ++ int ret = -ENOMEM; + + alg_count = ARRAY_SIZE(hmac_algos); + +@@ -365,12 +366,14 @@ static int seg6_hmac_init_algo(void) + algo = &hmac_algos[i]; + algo->tfms = alloc_percpu(struct crypto_shash *); + if (!algo->tfms) +- return -ENOMEM; ++ goto error_out; + + for_each_possible_cpu(cpu) { + tfm = crypto_alloc_shash(algo->name, 0, 0); +- if (IS_ERR(tfm)) +- return PTR_ERR(tfm); ++ if (IS_ERR(tfm)) { ++ ret = PTR_ERR(tfm); ++ goto error_out; ++ } + p_tfm = per_cpu_ptr(algo->tfms, cpu); + *p_tfm = tfm; + } +@@ -382,18 +385,22 @@ static int seg6_hmac_init_algo(void) + + algo->shashs = alloc_percpu(struct shash_desc *); + if (!algo->shashs) +- return -ENOMEM; ++ goto error_out; + + for_each_possible_cpu(cpu) { + shash = kzalloc_node(shsize, GFP_KERNEL, + cpu_to_node(cpu)); + if (!shash) +- return -ENOMEM; ++ goto error_out; + *per_cpu_ptr(algo->shashs, cpu) = shash; + } + } + + return 0; ++ ++error_out: ++ seg6_hmac_exit(); ++ return ret; + } + + int __init seg6_hmac_init(void) +@@ -413,22 +420,29 @@ int __net_init seg6_hmac_net_init(struct net *net) + void seg6_hmac_exit(void) + { + struct seg6_hmac_algo *algo = NULL; ++ struct crypto_shash *tfm; ++ struct shash_desc *shash; + int i, alg_count, cpu; + + alg_count = ARRAY_SIZE(hmac_algos); + for (i = 0; i < alg_count; i++) { + algo = &hmac_algos[i]; +- for_each_possible_cpu(cpu) { +- struct crypto_shash *tfm; +- struct shash_desc *shash; + +- shash = *per_cpu_ptr(algo->shashs, cpu); +- kfree(shash); +- tfm = *per_cpu_ptr(algo->tfms, cpu); +- crypto_free_shash(tfm); ++ if (algo->shashs) { ++ for_each_possible_cpu(cpu) { ++ shash = *per_cpu_ptr(algo->shashs, cpu); ++ kfree(shash); ++ } ++ free_percpu(algo->shashs); ++ } ++ ++ if (algo->tfms) { ++ for_each_possible_cpu(cpu) { ++ tfm = *per_cpu_ptr(algo->tfms, cpu); ++ crypto_free_shash(tfm); ++ } ++ free_percpu(algo->tfms); + } +- free_percpu(algo->tfms); +- free_percpu(algo->shashs); + } + } + EXPORT_SYMBOL(seg6_hmac_exit); +-- +2.43.0 + diff --git a/queue-5.10/media-cec-abort-if-the-current-transmit-was-canceled.patch b/queue-5.10/media-cec-abort-if-the-current-transmit-was-canceled.patch new file mode 100644 index 00000000000..819edf6caca --- /dev/null +++ b/queue-5.10/media-cec-abort-if-the-current-transmit-was-canceled.patch @@ -0,0 +1,125 @@ +From 18441ea31cb04328ab04aac122c1f4f95abd0e71 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Mar 2022 14:01:44 +0000 +Subject: media: cec: abort if the current transmit was canceled + +From: Hans Verkuil + +[ Upstream commit 590a8e564c6eff7e77a84e728612f1269e3c0685 ] + +If a transmit-in-progress was canceled, then, once the transmit +is done, mark it as aborted and refrain from retrying the transmit. + +To signal this situation the new transmit_in_progress_aborted field is +set to true. + +The old implementation would just set adap->transmitting to NULL and +set adap->transmit_in_progress to false, but on the hardware level +the transmit was still ongoing. However, the framework would think +the transmit was aborted, and if a new transmit was issued, then +it could overwrite the HW buffer containing the old transmit with the +new transmit, leading to garbled data on the CEC bus. + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs") +Signed-off-by: Sasha Levin +--- + drivers/media/cec/core/cec-adap.c | 14 +++++++++++--- + include/media/cec.h | 6 ++++++ + 2 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index 6415a80c9040e..fd4af157f4ce7 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -421,7 +421,7 @@ static void cec_flush(struct cec_adapter *adap) + cec_data_cancel(data, CEC_TX_STATUS_ABORTED); + } + if (adap->transmitting) +- cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED); ++ adap->transmit_in_progress_aborted = true; + + /* Cancel the pending timeout work. */ + list_for_each_entry_safe(data, n, &adap->wait_queue, list) { +@@ -572,6 +572,7 @@ int cec_thread_func(void *_adap) + if (data->attempts == 0) + data->attempts = attempts; + ++ adap->transmit_in_progress_aborted = false; + /* Tell the adapter to transmit, cancel on error */ + if (adap->ops->adap_transmit(adap, data->attempts, + signal_free_time, &data->msg)) +@@ -599,6 +600,8 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, + struct cec_msg *msg; + unsigned int attempts_made = arb_lost_cnt + nack_cnt + + low_drive_cnt + error_cnt; ++ bool done = status & (CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_OK); ++ bool aborted = adap->transmit_in_progress_aborted; + + dprintk(2, "%s: status 0x%02x\n", __func__, status); + if (attempts_made < 1) +@@ -619,6 +622,7 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, + goto wake_thread; + } + adap->transmit_in_progress = false; ++ adap->transmit_in_progress_aborted = false; + + msg = &data->msg; + +@@ -639,8 +643,7 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, + * the hardware didn't signal that it retried itself (by setting + * CEC_TX_STATUS_MAX_RETRIES), then we will retry ourselves. + */ +- if (data->attempts > attempts_made && +- !(status & (CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_OK))) { ++ if (!aborted && data->attempts > attempts_made && !done) { + /* Retry this message */ + data->attempts -= attempts_made; + if (msg->timeout) +@@ -655,6 +658,8 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, + goto wake_thread; + } + ++ if (aborted && !done) ++ status |= CEC_TX_STATUS_ABORTED; + data->attempts = 0; + + /* Always set CEC_TX_STATUS_MAX_RETRIES on error */ +@@ -1576,6 +1581,9 @@ static void cec_activate_cnt_dec(struct cec_adapter *adap) + WARN_ON(adap->ops->adap_enable(adap, false)); + adap->last_initiator = 0xff; + adap->transmit_in_progress = false; ++ adap->transmit_in_progress_aborted = false; ++ if (adap->transmitting) ++ cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED); + mutex_unlock(&adap->devnode.lock); + } + +diff --git a/include/media/cec.h b/include/media/cec.h +index 97c5f5bfcbd00..31d704f367074 100644 +--- a/include/media/cec.h ++++ b/include/media/cec.h +@@ -163,6 +163,11 @@ struct cec_adap_ops { + * @wait_queue: queue of transmits waiting for a reply + * @transmitting: CEC messages currently being transmitted + * @transmit_in_progress: true if a transmit is in progress ++ * @transmit_in_progress_aborted: true if a transmit is in progress is to be ++ * aborted. This happens if the logical address is ++ * invalidated while the transmit is ongoing. In that ++ * case the transmit will finish, but will not retransmit ++ * and be marked as ABORTED. + * @kthread_config: kthread used to configure a CEC adapter + * @config_completion: used to signal completion of the config kthread + * @kthread: main CEC processing thread +@@ -218,6 +223,7 @@ struct cec_adapter { + struct list_head wait_queue; + struct cec_data *transmitting; + bool transmit_in_progress; ++ bool transmit_in_progress_aborted; + + struct task_struct *kthread_config; + struct completion config_completion; +-- +2.43.0 + diff --git a/queue-5.10/media-cec-adap.c-drop-activate_cnt-use-state-info-in.patch b/queue-5.10/media-cec-adap.c-drop-activate_cnt-use-state-info-in.patch new file mode 100644 index 00000000000..9f89a598af9 --- /dev/null +++ b/queue-5.10/media-cec-adap.c-drop-activate_cnt-use-state-info-in.patch @@ -0,0 +1,314 @@ +From 26052739d14571572a27d4790b5b18ceeeb45b31 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 May 2022 10:53:05 +0200 +Subject: media: cec-adap.c: drop activate_cnt, use state info instead + +From: Hans Verkuil + +[ Upstream commit f9222f8ca18bcb1d55dd749b493b29fd8092fb82 ] + +Using an activation counter to decide when the enable or disable the +cec adapter is not the best approach and can lead to race conditions. + +Change this to determining the current status of the adapter, and +enable or disable the adapter accordingly. + +It now only needs to be called whenever there is a chance that the +state changes, and it can handle enabling/disabling monitoring as +well if needed. + +This simplifies the code and it should be a more robust approach as well. + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs") +Signed-off-by: Sasha Levin +--- + drivers/media/cec/core/cec-adap.c | 152 ++++++++++++------------------ + include/media/cec.h | 4 +- + 2 files changed, 61 insertions(+), 95 deletions(-) + +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index 07ff4b0c8461e..920c108b84aaf 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -1548,47 +1548,59 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block) + } + + /* +- * Helper functions to enable/disable the CEC adapter. ++ * Helper function to enable/disable the CEC adapter. + * +- * These functions are called with adap->lock held. ++ * This function is called with adap->lock held. + */ +-static int cec_activate_cnt_inc(struct cec_adapter *adap) ++static int cec_adap_enable(struct cec_adapter *adap) + { +- int ret; ++ bool enable; ++ int ret = 0; ++ ++ enable = adap->monitor_all_cnt || adap->monitor_pin_cnt || ++ adap->log_addrs.num_log_addrs; ++ if (adap->needs_hpd) ++ enable = enable && adap->phys_addr != CEC_PHYS_ADDR_INVALID; + +- if (adap->activate_cnt++) ++ if (enable == adap->is_enabled) + return 0; + + /* serialize adap_enable */ + mutex_lock(&adap->devnode.lock); +- adap->last_initiator = 0xff; +- adap->transmit_in_progress = false; +- ret = call_op(adap, adap_enable, true); +- if (ret) +- adap->activate_cnt--; ++ if (enable) { ++ adap->last_initiator = 0xff; ++ adap->transmit_in_progress = false; ++ ret = adap->ops->adap_enable(adap, true); ++ if (!ret) { ++ /* ++ * Enable monitor-all/pin modes if needed. We warn, but ++ * continue if this fails as this is not a critical error. ++ */ ++ if (adap->monitor_all_cnt) ++ WARN_ON(call_op(adap, adap_monitor_all_enable, true)); ++ if (adap->monitor_pin_cnt) ++ WARN_ON(call_op(adap, adap_monitor_pin_enable, true)); ++ } ++ } else { ++ /* Disable monitor-all/pin modes if needed (needs_hpd == 1) */ ++ if (adap->monitor_all_cnt) ++ WARN_ON(call_op(adap, adap_monitor_all_enable, false)); ++ if (adap->monitor_pin_cnt) ++ WARN_ON(call_op(adap, adap_monitor_pin_enable, false)); ++ WARN_ON(adap->ops->adap_enable(adap, false)); ++ adap->last_initiator = 0xff; ++ adap->transmit_in_progress = false; ++ adap->transmit_in_progress_aborted = false; ++ if (adap->transmitting) ++ cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED, 0); ++ } ++ if (!ret) ++ adap->is_enabled = enable; ++ wake_up_interruptible(&adap->kthread_waitq); + mutex_unlock(&adap->devnode.lock); + return ret; + } + +-static void cec_activate_cnt_dec(struct cec_adapter *adap) +-{ +- if (WARN_ON(!adap->activate_cnt)) +- return; +- +- if (--adap->activate_cnt) +- return; +- +- /* serialize adap_enable */ +- mutex_lock(&adap->devnode.lock); +- WARN_ON(call_op(adap, adap_enable, false)); +- adap->last_initiator = 0xff; +- adap->transmit_in_progress = false; +- adap->transmit_in_progress_aborted = false; +- if (adap->transmitting) +- cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED, 0); +- mutex_unlock(&adap->devnode.lock); +-} +- + /* Set a new physical address and send an event notifying userspace of this. + * + * This function is called with adap->lock held. +@@ -1609,33 +1621,16 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) + adap->phys_addr = CEC_PHYS_ADDR_INVALID; + cec_post_state_event(adap); + cec_adap_unconfigure(adap); +- if (becomes_invalid && adap->needs_hpd) { +- /* Disable monitor-all/pin modes if needed */ +- if (adap->monitor_all_cnt) +- WARN_ON(call_op(adap, adap_monitor_all_enable, false)); +- if (adap->monitor_pin_cnt) +- WARN_ON(call_op(adap, adap_monitor_pin_enable, false)); +- cec_activate_cnt_dec(adap); +- wake_up_interruptible(&adap->kthread_waitq); +- } +- if (becomes_invalid) ++ if (becomes_invalid) { ++ cec_adap_enable(adap); + return; +- } +- +- if (is_invalid && adap->needs_hpd) { +- if (cec_activate_cnt_inc(adap)) +- return; +- /* +- * Re-enable monitor-all/pin modes if needed. We warn, but +- * continue if this fails as this is not a critical error. +- */ +- if (adap->monitor_all_cnt) +- WARN_ON(call_op(adap, adap_monitor_all_enable, true)); +- if (adap->monitor_pin_cnt) +- WARN_ON(call_op(adap, adap_monitor_pin_enable, true)); ++ } + } + + adap->phys_addr = phys_addr; ++ if (is_invalid) ++ cec_adap_enable(adap); ++ + cec_post_state_event(adap); + if (adap->log_addrs.num_log_addrs) + cec_claim_log_addrs(adap, block); +@@ -1692,6 +1687,7 @@ int __cec_s_log_addrs(struct cec_adapter *adap, + struct cec_log_addrs *log_addrs, bool block) + { + u16 type_mask = 0; ++ int err; + int i; + + if (adap->devnode.unregistered) +@@ -1707,8 +1703,7 @@ int __cec_s_log_addrs(struct cec_adapter *adap, + adap->log_addrs.osd_name[0] = '\0'; + adap->log_addrs.vendor_id = CEC_VENDOR_ID_NONE; + adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0; +- if (!adap->needs_hpd) +- cec_activate_cnt_dec(adap); ++ cec_adap_enable(adap); + return 0; + } + +@@ -1842,17 +1837,12 @@ int __cec_s_log_addrs(struct cec_adapter *adap, + sizeof(log_addrs->features[i])); + } + +- if (!adap->needs_hpd && !adap->is_configuring && !adap->is_configured) { +- int ret = cec_activate_cnt_inc(adap); +- +- if (ret) +- return ret; +- } + log_addrs->log_addr_mask = adap->log_addrs.log_addr_mask; + adap->log_addrs = *log_addrs; +- if (adap->phys_addr != CEC_PHYS_ADDR_INVALID) ++ err = cec_adap_enable(adap); ++ if (!err && adap->phys_addr != CEC_PHYS_ADDR_INVALID) + cec_claim_log_addrs(adap, block); +- return 0; ++ return err; + } + + int cec_s_log_addrs(struct cec_adapter *adap, +@@ -2155,20 +2145,9 @@ int cec_monitor_all_cnt_inc(struct cec_adapter *adap) + if (adap->monitor_all_cnt++) + return 0; + +- if (!adap->needs_hpd) { +- ret = cec_activate_cnt_inc(adap); +- if (ret) { +- adap->monitor_all_cnt--; +- return ret; +- } +- } +- +- ret = call_op(adap, adap_monitor_all_enable, true); +- if (ret) { ++ ret = cec_adap_enable(adap); ++ if (ret) + adap->monitor_all_cnt--; +- if (!adap->needs_hpd) +- cec_activate_cnt_dec(adap); +- } + return ret; + } + +@@ -2179,8 +2158,7 @@ void cec_monitor_all_cnt_dec(struct cec_adapter *adap) + if (--adap->monitor_all_cnt) + return; + WARN_ON(call_op(adap, adap_monitor_all_enable, false)); +- if (!adap->needs_hpd) +- cec_activate_cnt_dec(adap); ++ cec_adap_enable(adap); + } + + /* +@@ -2195,20 +2173,9 @@ int cec_monitor_pin_cnt_inc(struct cec_adapter *adap) + if (adap->monitor_pin_cnt++) + return 0; + +- if (!adap->needs_hpd) { +- ret = cec_activate_cnt_inc(adap); +- if (ret) { +- adap->monitor_pin_cnt--; +- return ret; +- } +- } +- +- ret = call_op(adap, adap_monitor_pin_enable, true); +- if (ret) { ++ ret = cec_adap_enable(adap); ++ if (ret) + adap->monitor_pin_cnt--; +- if (!adap->needs_hpd) +- cec_activate_cnt_dec(adap); +- } + return ret; + } + +@@ -2219,8 +2186,7 @@ void cec_monitor_pin_cnt_dec(struct cec_adapter *adap) + if (--adap->monitor_pin_cnt) + return; + WARN_ON(call_op(adap, adap_monitor_pin_enable, false)); +- if (!adap->needs_hpd) +- cec_activate_cnt_dec(adap); ++ cec_adap_enable(adap); + } + + #ifdef CONFIG_DEBUG_FS +@@ -2234,7 +2200,7 @@ int cec_adap_status(struct seq_file *file, void *priv) + struct cec_data *data; + + mutex_lock(&adap->lock); +- seq_printf(file, "activation count: %u\n", adap->activate_cnt); ++ seq_printf(file, "enabled: %d\n", adap->is_enabled); + seq_printf(file, "configured: %d\n", adap->is_configured); + seq_printf(file, "configuring: %d\n", adap->is_configuring); + seq_printf(file, "phys_addr: %x.%x.%x.%x\n", +diff --git a/include/media/cec.h b/include/media/cec.h +index 31d704f367074..df3e8738d512b 100644 +--- a/include/media/cec.h ++++ b/include/media/cec.h +@@ -180,6 +180,7 @@ struct cec_adap_ops { + * @needs_hpd: if true, then the HDMI HotPlug Detect pin must be high + * in order to transmit or receive CEC messages. This is usually a HW + * limitation. ++ * @is_enabled: the CEC adapter is enabled + * @is_configuring: the CEC adapter is configuring (i.e. claiming LAs) + * @is_configured: the CEC adapter is configured (i.e. has claimed LAs) + * @cec_pin_is_high: if true then the CEC pin is high. Only used with the +@@ -190,7 +191,6 @@ struct cec_adap_ops { + * Drivers that need this can set this field to true after the + * cec_allocate_adapter() call. + * @last_initiator: the initiator of the last transmitted message. +- * @activate_cnt: number of times that CEC is activated + * @monitor_all_cnt: number of filehandles monitoring all msgs + * @monitor_pin_cnt: number of filehandles monitoring pin changes + * @follower_cnt: number of filehandles in follower mode +@@ -238,12 +238,12 @@ struct cec_adapter { + + u16 phys_addr; + bool needs_hpd; ++ bool is_enabled; + bool is_configuring; + bool is_configured; + bool cec_pin_is_high; + bool adap_controls_phys_addr; + u8 last_initiator; +- u32 activate_cnt; + u32 monitor_all_cnt; + u32 monitor_pin_cnt; + u32 follower_cnt; +-- +2.43.0 + diff --git a/queue-5.10/media-cec-call-enable_adap-on-s_log_addrs.patch b/queue-5.10/media-cec-call-enable_adap-on-s_log_addrs.patch new file mode 100644 index 00000000000..2128b574227 --- /dev/null +++ b/queue-5.10/media-cec-call-enable_adap-on-s_log_addrs.patch @@ -0,0 +1,389 @@ +From dc0a182c46a4e04faf3d33c5d81942f592b089b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Mar 2022 13:55:08 +0000 +Subject: media: cec: call enable_adap on s_log_addrs + +From: Hans Verkuil + +[ Upstream commit 3813c932ed970dd4f413498ccecb03c73c4f1784 ] + +Don't enable/disable the adapter if the first fh is opened or the +last fh is closed, instead do this when the adapter is configured +or unconfigured, and also when we enter Monitor All or Monitor Pin +mode for the first time or we exit the Monitor All/Pin mode for the +last time. + +However, if needs_hpd is true, then do this when the physical +address is set or cleared: in that case the adapter typically is +powered by the HPD, so it really is disabled when the HPD is low. +This case (needs_hpd is true) was already handled in this way, so +this wasn't changed. + +The problem with the old behavior was that if the HPD goes low when +no fh is open, and a transmit was in progress, then the adapter would +be disabled, typically stopping the transmit immediately which +leaves a partial message on the bus, which isn't nice and can confuse +some adapters. + +It makes much more sense to disable it only when the adapter is +unconfigured and we're not monitoring the bus, since then you really +won't be using it anymore. + +To keep track of this store a CEC activation count and call adap_enable +only when it goes from 0 to 1 or back to 0. + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs") +Signed-off-by: Sasha Levin +--- + drivers/media/cec/core/cec-adap.c | 174 ++++++++++++++++++++++-------- + drivers/media/cec/core/cec-api.c | 18 +--- + include/media/cec.h | 2 + + 3 files changed, 130 insertions(+), 64 deletions(-) + +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index d2a6fd8b65014..6415a80c9040e 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -1532,6 +1532,7 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block) + "ceccfg-%s", adap->name); + if (IS_ERR(adap->kthread_config)) { + adap->kthread_config = NULL; ++ adap->is_configuring = false; + } else if (block) { + mutex_unlock(&adap->lock); + wait_for_completion(&adap->config_completion); +@@ -1539,59 +1540,90 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block) + } + } + ++/* ++ * Helper functions to enable/disable the CEC adapter. ++ * ++ * These functions are called with adap->lock held. ++ */ ++static int cec_activate_cnt_inc(struct cec_adapter *adap) ++{ ++ int ret; ++ ++ if (adap->activate_cnt++) ++ return 0; ++ ++ /* serialize adap_enable */ ++ mutex_lock(&adap->devnode.lock); ++ adap->last_initiator = 0xff; ++ adap->transmit_in_progress = false; ++ ret = adap->ops->adap_enable(adap, true); ++ if (ret) ++ adap->activate_cnt--; ++ mutex_unlock(&adap->devnode.lock); ++ return ret; ++} ++ ++static void cec_activate_cnt_dec(struct cec_adapter *adap) ++{ ++ if (WARN_ON(!adap->activate_cnt)) ++ return; ++ ++ if (--adap->activate_cnt) ++ return; ++ ++ /* serialize adap_enable */ ++ mutex_lock(&adap->devnode.lock); ++ WARN_ON(adap->ops->adap_enable(adap, false)); ++ adap->last_initiator = 0xff; ++ adap->transmit_in_progress = false; ++ mutex_unlock(&adap->devnode.lock); ++} ++ + /* Set a new physical address and send an event notifying userspace of this. + * + * This function is called with adap->lock held. + */ + void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) + { ++ bool becomes_invalid = phys_addr == CEC_PHYS_ADDR_INVALID; ++ bool is_invalid = adap->phys_addr == CEC_PHYS_ADDR_INVALID; ++ + if (phys_addr == adap->phys_addr) + return; +- if (phys_addr != CEC_PHYS_ADDR_INVALID && adap->devnode.unregistered) ++ if (!becomes_invalid && adap->devnode.unregistered) + return; + + dprintk(1, "new physical address %x.%x.%x.%x\n", + cec_phys_addr_exp(phys_addr)); +- if (phys_addr == CEC_PHYS_ADDR_INVALID || +- adap->phys_addr != CEC_PHYS_ADDR_INVALID) { ++ if (becomes_invalid || !is_invalid) { + adap->phys_addr = CEC_PHYS_ADDR_INVALID; + cec_post_state_event(adap); + cec_adap_unconfigure(adap); +- /* Disabling monitor all mode should always succeed */ +- if (adap->monitor_all_cnt) +- WARN_ON(call_op(adap, adap_monitor_all_enable, false)); +- /* serialize adap_enable */ +- mutex_lock(&adap->devnode.lock); +- if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) { +- WARN_ON(adap->ops->adap_enable(adap, false)); +- adap->transmit_in_progress = false; ++ if (becomes_invalid && adap->needs_hpd) { ++ /* Disable monitor-all/pin modes if needed */ ++ if (adap->monitor_all_cnt) ++ WARN_ON(call_op(adap, adap_monitor_all_enable, false)); ++ if (adap->monitor_pin_cnt) ++ WARN_ON(call_op(adap, adap_monitor_pin_enable, false)); ++ cec_activate_cnt_dec(adap); + wake_up_interruptible(&adap->kthread_waitq); + } +- mutex_unlock(&adap->devnode.lock); +- if (phys_addr == CEC_PHYS_ADDR_INVALID) ++ if (becomes_invalid) + return; + } + +- /* serialize adap_enable */ +- mutex_lock(&adap->devnode.lock); +- adap->last_initiator = 0xff; +- adap->transmit_in_progress = false; +- +- if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) { +- if (adap->ops->adap_enable(adap, true)) { +- mutex_unlock(&adap->devnode.lock); ++ if (is_invalid && adap->needs_hpd) { ++ if (cec_activate_cnt_inc(adap)) + return; +- } +- } +- +- if (adap->monitor_all_cnt && +- call_op(adap, adap_monitor_all_enable, true)) { +- if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) +- WARN_ON(adap->ops->adap_enable(adap, false)); +- mutex_unlock(&adap->devnode.lock); +- return; ++ /* ++ * Re-enable monitor-all/pin modes if needed. We warn, but ++ * continue if this fails as this is not a critical error. ++ */ ++ if (adap->monitor_all_cnt) ++ WARN_ON(call_op(adap, adap_monitor_all_enable, true)); ++ if (adap->monitor_pin_cnt) ++ WARN_ON(call_op(adap, adap_monitor_pin_enable, true)); + } +- mutex_unlock(&adap->devnode.lock); + + adap->phys_addr = phys_addr; + cec_post_state_event(adap); +@@ -1656,6 +1688,8 @@ int __cec_s_log_addrs(struct cec_adapter *adap, + return -ENODEV; + + if (!log_addrs || log_addrs->num_log_addrs == 0) { ++ if (!adap->is_configuring && !adap->is_configured) ++ return 0; + cec_adap_unconfigure(adap); + adap->log_addrs.num_log_addrs = 0; + for (i = 0; i < CEC_MAX_LOG_ADDRS; i++) +@@ -1663,6 +1697,8 @@ int __cec_s_log_addrs(struct cec_adapter *adap, + adap->log_addrs.osd_name[0] = '\0'; + adap->log_addrs.vendor_id = CEC_VENDOR_ID_NONE; + adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0; ++ if (!adap->needs_hpd) ++ cec_activate_cnt_dec(adap); + return 0; + } + +@@ -1796,6 +1832,12 @@ int __cec_s_log_addrs(struct cec_adapter *adap, + sizeof(log_addrs->features[i])); + } + ++ if (!adap->needs_hpd && !adap->is_configuring && !adap->is_configured) { ++ int ret = cec_activate_cnt_inc(adap); ++ ++ if (ret) ++ return ret; ++ } + log_addrs->log_addr_mask = adap->log_addrs.log_addr_mask; + adap->log_addrs = *log_addrs; + if (adap->phys_addr != CEC_PHYS_ADDR_INVALID) +@@ -2099,20 +2141,37 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, + */ + int cec_monitor_all_cnt_inc(struct cec_adapter *adap) + { +- int ret = 0; ++ int ret; + +- if (adap->monitor_all_cnt == 0) +- ret = call_op(adap, adap_monitor_all_enable, 1); +- if (ret == 0) +- adap->monitor_all_cnt++; ++ if (adap->monitor_all_cnt++) ++ return 0; ++ ++ if (!adap->needs_hpd) { ++ ret = cec_activate_cnt_inc(adap); ++ if (ret) { ++ adap->monitor_all_cnt--; ++ return ret; ++ } ++ } ++ ++ ret = call_op(adap, adap_monitor_all_enable, true); ++ if (ret) { ++ adap->monitor_all_cnt--; ++ if (!adap->needs_hpd) ++ cec_activate_cnt_dec(adap); ++ } + return ret; + } + + void cec_monitor_all_cnt_dec(struct cec_adapter *adap) + { +- adap->monitor_all_cnt--; +- if (adap->monitor_all_cnt == 0) +- WARN_ON(call_op(adap, adap_monitor_all_enable, 0)); ++ if (WARN_ON(!adap->monitor_all_cnt)) ++ return; ++ if (--adap->monitor_all_cnt) ++ return; ++ WARN_ON(call_op(adap, adap_monitor_all_enable, false)); ++ if (!adap->needs_hpd) ++ cec_activate_cnt_dec(adap); + } + + /* +@@ -2122,20 +2181,37 @@ void cec_monitor_all_cnt_dec(struct cec_adapter *adap) + */ + int cec_monitor_pin_cnt_inc(struct cec_adapter *adap) + { +- int ret = 0; ++ int ret; + +- if (adap->monitor_pin_cnt == 0) +- ret = call_op(adap, adap_monitor_pin_enable, 1); +- if (ret == 0) +- adap->monitor_pin_cnt++; ++ if (adap->monitor_pin_cnt++) ++ return 0; ++ ++ if (!adap->needs_hpd) { ++ ret = cec_activate_cnt_inc(adap); ++ if (ret) { ++ adap->monitor_pin_cnt--; ++ return ret; ++ } ++ } ++ ++ ret = call_op(adap, adap_monitor_pin_enable, true); ++ if (ret) { ++ adap->monitor_pin_cnt--; ++ if (!adap->needs_hpd) ++ cec_activate_cnt_dec(adap); ++ } + return ret; + } + + void cec_monitor_pin_cnt_dec(struct cec_adapter *adap) + { +- adap->monitor_pin_cnt--; +- if (adap->monitor_pin_cnt == 0) +- WARN_ON(call_op(adap, adap_monitor_pin_enable, 0)); ++ if (WARN_ON(!adap->monitor_pin_cnt)) ++ return; ++ if (--adap->monitor_pin_cnt) ++ return; ++ WARN_ON(call_op(adap, adap_monitor_pin_enable, false)); ++ if (!adap->needs_hpd) ++ cec_activate_cnt_dec(adap); + } + + #ifdef CONFIG_DEBUG_FS +@@ -2149,6 +2225,7 @@ int cec_adap_status(struct seq_file *file, void *priv) + struct cec_data *data; + + mutex_lock(&adap->lock); ++ seq_printf(file, "activation count: %u\n", adap->activate_cnt); + seq_printf(file, "configured: %d\n", adap->is_configured); + seq_printf(file, "configuring: %d\n", adap->is_configuring); + seq_printf(file, "phys_addr: %x.%x.%x.%x\n", +@@ -2163,6 +2240,9 @@ int cec_adap_status(struct seq_file *file, void *priv) + if (adap->monitor_all_cnt) + seq_printf(file, "file handles in Monitor All mode: %u\n", + adap->monitor_all_cnt); ++ if (adap->monitor_pin_cnt) ++ seq_printf(file, "file handles in Monitor Pin mode: %u\n", ++ adap->monitor_pin_cnt); + if (adap->tx_timeouts) { + seq_printf(file, "transmit timeouts: %u\n", + adap->tx_timeouts); +diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c +index 899017a0e514e..0be4e822211e7 100644 +--- a/drivers/media/cec/core/cec-api.c ++++ b/drivers/media/cec/core/cec-api.c +@@ -586,18 +586,6 @@ static int cec_open(struct inode *inode, struct file *filp) + return err; + } + +- /* serialize adap_enable */ +- mutex_lock(&devnode->lock); +- if (list_empty(&devnode->fhs) && +- !adap->needs_hpd && +- adap->phys_addr == CEC_PHYS_ADDR_INVALID) { +- err = adap->ops->adap_enable(adap, true); +- if (err) { +- mutex_unlock(&devnode->lock); +- kfree(fh); +- return err; +- } +- } + filp->private_data = fh; + + /* Queue up initial state events */ +@@ -625,6 +613,7 @@ static int cec_open(struct inode *inode, struct file *filp) + } + #endif + ++ mutex_lock(&devnode->lock); + mutex_lock(&devnode->lock_fhs); + list_add(&fh->list, &devnode->fhs); + mutex_unlock(&devnode->lock_fhs); +@@ -656,15 +645,10 @@ static int cec_release(struct inode *inode, struct file *filp) + cec_monitor_all_cnt_dec(adap); + mutex_unlock(&adap->lock); + +- /* serialize adap_enable */ + mutex_lock(&devnode->lock); + mutex_lock(&devnode->lock_fhs); + list_del(&fh->list); + mutex_unlock(&devnode->lock_fhs); +- if (cec_is_registered(adap) && list_empty(&devnode->fhs) && +- !adap->needs_hpd && adap->phys_addr == CEC_PHYS_ADDR_INVALID) { +- WARN_ON(adap->ops->adap_enable(adap, false)); +- } + mutex_unlock(&devnode->lock); + + /* Unhook pending transmits from this filehandle. */ +diff --git a/include/media/cec.h b/include/media/cec.h +index 77346f757036d..97c5f5bfcbd00 100644 +--- a/include/media/cec.h ++++ b/include/media/cec.h +@@ -185,6 +185,7 @@ struct cec_adap_ops { + * Drivers that need this can set this field to true after the + * cec_allocate_adapter() call. + * @last_initiator: the initiator of the last transmitted message. ++ * @activate_cnt: number of times that CEC is activated + * @monitor_all_cnt: number of filehandles monitoring all msgs + * @monitor_pin_cnt: number of filehandles monitoring pin changes + * @follower_cnt: number of filehandles in follower mode +@@ -236,6 +237,7 @@ struct cec_adapter { + bool cec_pin_is_high; + bool adap_controls_phys_addr; + u8 last_initiator; ++ u32 activate_cnt; + u32 monitor_all_cnt; + u32 monitor_pin_cnt; + u32 follower_cnt; +-- +2.43.0 + diff --git a/queue-5.10/media-cec-cec-adap-always-cancel-work-in-cec_transmi.patch b/queue-5.10/media-cec-cec-adap-always-cancel-work-in-cec_transmi.patch new file mode 100644 index 00000000000..b591fc0a67a --- /dev/null +++ b/queue-5.10/media-cec-cec-adap-always-cancel-work-in-cec_transmi.patch @@ -0,0 +1,39 @@ +From 5c8c58fb9e3cbef99983feb93853b326586ef163 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Feb 2024 12:24:38 +0000 +Subject: media: cec: cec-adap: always cancel work in cec_transmit_msg_fh + +From: Hans Verkuil + +[ Upstream commit 9fe2816816a3c765dff3b88af5b5c3d9bbb911ce ] + +Do not check for !data->completed, just always call +cancel_delayed_work_sync(). This fixes a small race condition. + +Signed-off-by: Hans Verkuil +Reported-by: Yang, Chenyuan +Closes: https://lore.kernel.org/linux-media/PH7PR11MB57688E64ADE4FE82E658D86DA09EA@PH7PR11MB5768.namprd11.prod.outlook.com/ +Fixes: 490d84f6d73c ("media: cec: forgot to cancel delayed work") +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/cec/core/cec-adap.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index 2f7ab5df1c584..78027f0310acd 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -913,8 +913,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, + */ + mutex_unlock(&adap->lock); + wait_for_completion_killable(&data->c); +- if (!data->completed) +- cancel_delayed_work_sync(&data->work); ++ cancel_delayed_work_sync(&data->work); + mutex_lock(&adap->lock); + + /* Cancel the transmit if it was interrupted */ +-- +2.43.0 + diff --git a/queue-5.10/media-cec-cec-api-add-locking-in-cec_release.patch b/queue-5.10/media-cec-cec-api-add-locking-in-cec_release.patch new file mode 100644 index 00000000000..e91ff701b68 --- /dev/null +++ b/queue-5.10/media-cec-cec-api-add-locking-in-cec_release.patch @@ -0,0 +1,46 @@ +From bfb378aba7791a3c77529ad53f8026c234bcfe56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Feb 2024 12:25:55 +0000 +Subject: media: cec: cec-api: add locking in cec_release() + +From: Hans Verkuil + +[ Upstream commit 42bcaacae924bf18ae387c3f78c202df0b739292 ] + +When cec_release() uses fh->msgs it has to take fh->lock, +otherwise the list can get corrupted. + +Signed-off-by: Hans Verkuil +Reported-by: Yang, Chenyuan +Closes: https://lore.kernel.org/linux-media/PH7PR11MB57688E64ADE4FE82E658D86DA09EA@PH7PR11MB5768.namprd11.prod.outlook.com/ +Fixes: ca684386e6e2 ("[media] cec: add HDMI CEC framework (api)") +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/cec/core/cec-api.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c +index f922a2196b2b7..893641ebc644b 100644 +--- a/drivers/media/cec/core/cec-api.c ++++ b/drivers/media/cec/core/cec-api.c +@@ -672,6 +672,8 @@ static int cec_release(struct inode *inode, struct file *filp) + list_del(&data->xfer_list); + } + mutex_unlock(&adap->lock); ++ ++ mutex_lock(&fh->lock); + while (!list_empty(&fh->msgs)) { + struct cec_msg_entry *entry = + list_first_entry(&fh->msgs, struct cec_msg_entry, list); +@@ -689,6 +691,7 @@ static int cec_release(struct inode *inode, struct file *filp) + kfree(entry); + } + } ++ mutex_unlock(&fh->lock); + kfree(fh); + + cec_put_device(devnode); +-- +2.43.0 + diff --git a/queue-5.10/media-cec-core-avoid-confusing-transmit-timed-out-me.patch b/queue-5.10/media-cec-core-avoid-confusing-transmit-timed-out-me.patch new file mode 100644 index 00000000000..19a742ff98e --- /dev/null +++ b/queue-5.10/media-cec-core-avoid-confusing-transmit-timed-out-me.patch @@ -0,0 +1,73 @@ +From 70a0b1de0a165e52a7aab50cf24e21c55c50373a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Apr 2024 11:13:47 +0100 +Subject: media: cec: core: avoid confusing "transmit timed out" message + +From: Hans Verkuil + +[ Upstream commit cbe499977bc36fedae89f0a0d7deb4ccde9798fe ] + +If, when waiting for a transmit to finish, the wait is interrupted, +then you might get a "transmit timed out" message, even though the +transmit was interrupted and did not actually time out. + +Set transmit_in_progress_aborted to true if the +wait_for_completion_killable() call was interrupted and ensure +that the transmit is properly marked as ABORTED. + +Signed-off-by: Hans Verkuil +Reported-by: Yang, Chenyuan +Closes: https://lore.kernel.org/linux-media/PH7PR11MB57688E64ADE4FE82E658D86DA09EA@PH7PR11MB5768.namprd11.prod.outlook.com/ +Fixes: 590a8e564c6e ("media: cec: abort if the current transmit was canceled") +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/cec/core/cec-adap.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index 42d66ae27b19f..a5853c82d5e4f 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -502,6 +502,15 @@ int cec_thread_func(void *_adap) + goto unlock; + } + ++ if (adap->transmit_in_progress && ++ adap->transmit_in_progress_aborted) { ++ if (adap->transmitting) ++ cec_data_cancel(adap->transmitting, ++ CEC_TX_STATUS_ABORTED, 0); ++ adap->transmit_in_progress = false; ++ adap->transmit_in_progress_aborted = false; ++ goto unlock; ++ } + if (adap->transmit_in_progress && timeout) { + /* + * If we timeout, then log that. Normally this does +@@ -755,6 +764,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, + { + struct cec_data *data; + bool is_raw = msg_is_raw(msg); ++ int err; + + if (adap->devnode.unregistered) + return -ENODEV; +@@ -917,10 +927,13 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, + * Release the lock and wait, retake the lock afterwards. + */ + mutex_unlock(&adap->lock); +- wait_for_completion_killable(&data->c); ++ err = wait_for_completion_killable(&data->c); + cancel_delayed_work_sync(&data->work); + mutex_lock(&adap->lock); + ++ if (err) ++ adap->transmit_in_progress_aborted = true; ++ + /* Cancel the transmit if it was interrupted */ + if (!data->completed) { + if (data->msg.tx_status & CEC_TX_STATUS_OK) +-- +2.43.0 + diff --git a/queue-5.10/media-cec-core-avoid-recursive-cec_claim_log_addrs.patch b/queue-5.10/media-cec-core-avoid-recursive-cec_claim_log_addrs.patch new file mode 100644 index 00000000000..b631e2ec445 --- /dev/null +++ b/queue-5.10/media-cec-core-avoid-recursive-cec_claim_log_addrs.patch @@ -0,0 +1,81 @@ +From 3e2892b57b2d3703b7848e418943c0ccfa8e6d57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Feb 2024 16:17:33 +0000 +Subject: media: cec: core: avoid recursive cec_claim_log_addrs + +From: Hans Verkuil + +[ Upstream commit 47c82aac10a6954d68f29f10d9758d016e8e5af1 ] + +Keep track if cec_claim_log_addrs() is running, and return -EBUSY +if it is when calling CEC_ADAP_S_LOG_ADDRS. + +This prevents a case where cec_claim_log_addrs() could be called +while it was still in progress. + +Signed-off-by: Hans Verkuil +Reported-by: Yang, Chenyuan +Closes: https://lore.kernel.org/linux-media/PH7PR11MB57688E64ADE4FE82E658D86DA09EA@PH7PR11MB5768.namprd11.prod.outlook.com/ +Fixes: ca684386e6e2 ("[media] cec: add HDMI CEC framework (api)") +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/cec/core/cec-adap.c | 6 +++++- + drivers/media/cec/core/cec-api.c | 2 +- + include/media/cec.h | 1 + + 3 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index 920c108b84aaf..42d66ae27b19f 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -1528,9 +1528,12 @@ static int cec_config_thread_func(void *arg) + */ + static void cec_claim_log_addrs(struct cec_adapter *adap, bool block) + { +- if (WARN_ON(adap->is_configuring || adap->is_configured)) ++ if (WARN_ON(adap->is_claiming_log_addrs || ++ adap->is_configuring || adap->is_configured)) + return; + ++ adap->is_claiming_log_addrs = true; ++ + init_completion(&adap->config_completion); + + /* Ready to kick off the thread */ +@@ -1545,6 +1548,7 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block) + wait_for_completion(&adap->config_completion); + mutex_lock(&adap->lock); + } ++ adap->is_claiming_log_addrs = false; + } + + /* +diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c +index feaf100a44c2d..8bdf58abdf965 100644 +--- a/drivers/media/cec/core/cec-api.c ++++ b/drivers/media/cec/core/cec-api.c +@@ -178,7 +178,7 @@ static long cec_adap_s_log_addrs(struct cec_adapter *adap, struct cec_fh *fh, + CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU | + CEC_LOG_ADDRS_FL_CDC_ONLY; + mutex_lock(&adap->lock); +- if (!adap->is_configuring && ++ if (!adap->is_claiming_log_addrs && !adap->is_configuring && + (!log_addrs.num_log_addrs || !adap->is_configured) && + !cec_is_busy(adap, fh)) { + err = __cec_s_log_addrs(adap, &log_addrs, block); +diff --git a/include/media/cec.h b/include/media/cec.h +index df3e8738d512b..23202bf439b47 100644 +--- a/include/media/cec.h ++++ b/include/media/cec.h +@@ -239,6 +239,7 @@ struct cec_adapter { + u16 phys_addr; + bool needs_hpd; + bool is_enabled; ++ bool is_claiming_log_addrs; + bool is_configuring; + bool is_configured; + bool cec_pin_is_high; +-- +2.43.0 + diff --git a/queue-5.10/media-cec-correctly-pass-on-reply-results.patch b/queue-5.10/media-cec-correctly-pass-on-reply-results.patch new file mode 100644 index 00000000000..637a0f6b03c --- /dev/null +++ b/queue-5.10/media-cec-correctly-pass-on-reply-results.patch @@ -0,0 +1,166 @@ +From bbc91d41136df8053b26495e984568b0158f68f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 13 Nov 2021 11:02:36 +0000 +Subject: media: cec: correctly pass on reply results + +From: Hans Verkuil + +[ Upstream commit f9d0ecbf56f4b90745a6adc5b59281ad8f70ab54 ] + +The results of non-blocking transmits were not correctly communicated +to userspace. + +Specifically: + +1) if a non-blocking transmit was canceled, then rx_status wasn't set to 0 + as it should. +2) if the non-blocking transmit succeeded, but the corresponding reply + never arrived (aborted or timed out), then tx_status wasn't set to 0 + as it should, and rx_status was hardcoded to ABORTED instead of the + actual reason, such as TIMEOUT. In addition, adap->ops->received() was + never called, so drivers that want to do message processing themselves + would not be informed of the failed reply. + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs") +Signed-off-by: Sasha Levin +--- + drivers/media/cec/core/cec-adap.c | 48 +++++++++++++++++++------------ + 1 file changed, 30 insertions(+), 18 deletions(-) + +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index fd4af157f4ce7..41f4def8a31ca 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -366,38 +366,48 @@ static void cec_data_completed(struct cec_data *data) + /* + * A pending CEC transmit needs to be cancelled, either because the CEC + * adapter is disabled or the transmit takes an impossibly long time to +- * finish. ++ * finish, or the reply timed out. + * + * This function is called with adap->lock held. + */ +-static void cec_data_cancel(struct cec_data *data, u8 tx_status) ++static void cec_data_cancel(struct cec_data *data, u8 tx_status, u8 rx_status) + { ++ struct cec_adapter *adap = data->adap; ++ + /* + * It's either the current transmit, or it is a pending + * transmit. Take the appropriate action to clear it. + */ +- if (data->adap->transmitting == data) { +- data->adap->transmitting = NULL; ++ if (adap->transmitting == data) { ++ adap->transmitting = NULL; + } else { + list_del_init(&data->list); + if (!(data->msg.tx_status & CEC_TX_STATUS_OK)) +- if (!WARN_ON(!data->adap->transmit_queue_sz)) +- data->adap->transmit_queue_sz--; ++ if (!WARN_ON(!adap->transmit_queue_sz)) ++ adap->transmit_queue_sz--; + } + + if (data->msg.tx_status & CEC_TX_STATUS_OK) { + data->msg.rx_ts = ktime_get_ns(); +- data->msg.rx_status = CEC_RX_STATUS_ABORTED; ++ data->msg.rx_status = rx_status; ++ if (!data->blocking) ++ data->msg.tx_status = 0; + } else { + data->msg.tx_ts = ktime_get_ns(); + data->msg.tx_status |= tx_status | + CEC_TX_STATUS_MAX_RETRIES; + data->msg.tx_error_cnt++; + data->attempts = 0; ++ if (!data->blocking) ++ data->msg.rx_status = 0; + } + + /* Queue transmitted message for monitoring purposes */ +- cec_queue_msg_monitor(data->adap, &data->msg, 1); ++ cec_queue_msg_monitor(adap, &data->msg, 1); ++ ++ if (!data->blocking && data->msg.sequence && adap->ops->received) ++ /* Allow drivers to process the message first */ ++ adap->ops->received(adap, &data->msg); + + cec_data_completed(data); + } +@@ -418,7 +428,7 @@ static void cec_flush(struct cec_adapter *adap) + while (!list_empty(&adap->transmit_queue)) { + data = list_first_entry(&adap->transmit_queue, + struct cec_data, list); +- cec_data_cancel(data, CEC_TX_STATUS_ABORTED); ++ cec_data_cancel(data, CEC_TX_STATUS_ABORTED, 0); + } + if (adap->transmitting) + adap->transmit_in_progress_aborted = true; +@@ -426,7 +436,7 @@ static void cec_flush(struct cec_adapter *adap) + /* Cancel the pending timeout work. */ + list_for_each_entry_safe(data, n, &adap->wait_queue, list) { + if (cancel_delayed_work(&data->work)) +- cec_data_cancel(data, CEC_TX_STATUS_OK); ++ cec_data_cancel(data, CEC_TX_STATUS_OK, CEC_RX_STATUS_ABORTED); + /* + * If cancel_delayed_work returned false, then + * the cec_wait_timeout function is running, +@@ -516,7 +526,7 @@ int cec_thread_func(void *_adap) + adap->transmitting->msg.msg); + /* Just give up on this. */ + cec_data_cancel(adap->transmitting, +- CEC_TX_STATUS_TIMEOUT); ++ CEC_TX_STATUS_TIMEOUT, 0); + } else { + pr_warn("cec-%s: transmit timed out\n", adap->name); + } +@@ -576,7 +586,7 @@ int cec_thread_func(void *_adap) + /* Tell the adapter to transmit, cancel on error */ + if (adap->ops->adap_transmit(adap, data->attempts, + signal_free_time, &data->msg)) +- cec_data_cancel(data, CEC_TX_STATUS_ABORTED); ++ cec_data_cancel(data, CEC_TX_STATUS_ABORTED, 0); + else + adap->transmit_in_progress = true; + +@@ -738,9 +748,7 @@ static void cec_wait_timeout(struct work_struct *work) + + /* Mark the message as timed out */ + list_del_init(&data->list); +- data->msg.rx_ts = ktime_get_ns(); +- data->msg.rx_status = CEC_RX_STATUS_TIMEOUT; +- cec_data_completed(data); ++ cec_data_cancel(data, CEC_TX_STATUS_OK, CEC_RX_STATUS_TIMEOUT); + unlock: + mutex_unlock(&adap->lock); + } +@@ -923,8 +931,12 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, + mutex_lock(&adap->lock); + + /* Cancel the transmit if it was interrupted */ +- if (!data->completed) +- cec_data_cancel(data, CEC_TX_STATUS_ABORTED); ++ if (!data->completed) { ++ if (data->msg.tx_status & CEC_TX_STATUS_OK) ++ cec_data_cancel(data, CEC_TX_STATUS_OK, CEC_RX_STATUS_ABORTED); ++ else ++ cec_data_cancel(data, CEC_TX_STATUS_ABORTED, 0); ++ } + + /* The transmit completed (possibly with an error) */ + *msg = data->msg; +@@ -1583,7 +1595,7 @@ static void cec_activate_cnt_dec(struct cec_adapter *adap) + adap->transmit_in_progress = false; + adap->transmit_in_progress_aborted = false; + if (adap->transmitting) +- cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED); ++ cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED, 0); + mutex_unlock(&adap->devnode.lock); + } + +-- +2.43.0 + diff --git a/queue-5.10/media-cec-fix-a-deadlock-situation.patch b/queue-5.10/media-cec-fix-a-deadlock-situation.patch new file mode 100644 index 00000000000..48c30767b59 --- /dev/null +++ b/queue-5.10/media-cec-fix-a-deadlock-situation.patch @@ -0,0 +1,271 @@ +From afc180e1cb4b1241d198a3175a13b10cf307dcba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 1 Dec 2021 13:41:26 +0100 +Subject: media: cec: fix a deadlock situation + +From: Hans Verkuil + +[ Upstream commit a9e6107616bb8108aa4fc22584a05e69761a91f7 ] + +The cec_devnode struct has a lock meant to serialize access +to the fields of this struct. This lock is taken during +device node (un)registration and when opening or releasing a +filehandle to the device node. When the last open filehandle +is closed the cec adapter might be disabled by calling the +adap_enable driver callback with the devnode.lock held. + +However, if during that callback a message or event arrives +then the driver will call one of the cec_queue_event() +variants in cec-adap.c, and those will take the same devnode.lock +to walk the open filehandle list. + +This obviously causes a deadlock. + +This is quite easy to reproduce with the cec-gpio driver since that +uses the cec-pin framework which generated lots of events and uses +a kernel thread for the processing, so when adap_enable is called +the thread is still running and can generate events. + +But I suspect that it might also happen with other drivers if an +interrupt arrives signaling e.g. a received message before adap_enable +had a chance to disable the interrupts. + +This patch adds a new mutex to serialize access to the fhs list. +When adap_enable() is called the devnode.lock mutex is held, but +not devnode.lock_fhs. The event functions in cec-adap.c will now +use devnode.lock_fhs instead of devnode.lock, ensuring that it is +safe to call those functions from the adap_enable callback. + +This specific issue only happens if the last open filehandle is closed +and the physical address is invalid. This is not something that +happens during normal operation, but it does happen when monitoring +CEC traffic (e.g. cec-ctl --monitor) with an unconfigured CEC adapter. + +Signed-off-by: Hans Verkuil +Cc: # for v5.13 and up +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs") +Signed-off-by: Sasha Levin +--- + drivers/media/cec/core/cec-adap.c | 38 +++++++++++++++++-------------- + drivers/media/cec/core/cec-api.c | 6 +++++ + drivers/media/cec/core/cec-core.c | 3 +++ + include/media/cec.h | 11 +++++++-- + 4 files changed, 39 insertions(+), 19 deletions(-) + +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index 78027f0310acd..d2a6fd8b65014 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -161,10 +161,10 @@ static void cec_queue_event(struct cec_adapter *adap, + u64 ts = ktime_get_ns(); + struct cec_fh *fh; + +- mutex_lock(&adap->devnode.lock); ++ mutex_lock(&adap->devnode.lock_fhs); + list_for_each_entry(fh, &adap->devnode.fhs, list) + cec_queue_event_fh(fh, ev, ts); +- mutex_unlock(&adap->devnode.lock); ++ mutex_unlock(&adap->devnode.lock_fhs); + } + + /* Notify userspace that the CEC pin changed state at the given time. */ +@@ -178,11 +178,12 @@ void cec_queue_pin_cec_event(struct cec_adapter *adap, bool is_high, + }; + struct cec_fh *fh; + +- mutex_lock(&adap->devnode.lock); +- list_for_each_entry(fh, &adap->devnode.fhs, list) ++ mutex_lock(&adap->devnode.lock_fhs); ++ list_for_each_entry(fh, &adap->devnode.fhs, list) { + if (fh->mode_follower == CEC_MODE_MONITOR_PIN) + cec_queue_event_fh(fh, &ev, ktime_to_ns(ts)); +- mutex_unlock(&adap->devnode.lock); ++ } ++ mutex_unlock(&adap->devnode.lock_fhs); + } + EXPORT_SYMBOL_GPL(cec_queue_pin_cec_event); + +@@ -195,10 +196,10 @@ void cec_queue_pin_hpd_event(struct cec_adapter *adap, bool is_high, ktime_t ts) + }; + struct cec_fh *fh; + +- mutex_lock(&adap->devnode.lock); ++ mutex_lock(&adap->devnode.lock_fhs); + list_for_each_entry(fh, &adap->devnode.fhs, list) + cec_queue_event_fh(fh, &ev, ktime_to_ns(ts)); +- mutex_unlock(&adap->devnode.lock); ++ mutex_unlock(&adap->devnode.lock_fhs); + } + EXPORT_SYMBOL_GPL(cec_queue_pin_hpd_event); + +@@ -211,10 +212,10 @@ void cec_queue_pin_5v_event(struct cec_adapter *adap, bool is_high, ktime_t ts) + }; + struct cec_fh *fh; + +- mutex_lock(&adap->devnode.lock); ++ mutex_lock(&adap->devnode.lock_fhs); + list_for_each_entry(fh, &adap->devnode.fhs, list) + cec_queue_event_fh(fh, &ev, ktime_to_ns(ts)); +- mutex_unlock(&adap->devnode.lock); ++ mutex_unlock(&adap->devnode.lock_fhs); + } + EXPORT_SYMBOL_GPL(cec_queue_pin_5v_event); + +@@ -286,12 +287,12 @@ static void cec_queue_msg_monitor(struct cec_adapter *adap, + u32 monitor_mode = valid_la ? CEC_MODE_MONITOR : + CEC_MODE_MONITOR_ALL; + +- mutex_lock(&adap->devnode.lock); ++ mutex_lock(&adap->devnode.lock_fhs); + list_for_each_entry(fh, &adap->devnode.fhs, list) { + if (fh->mode_follower >= monitor_mode) + cec_queue_msg_fh(fh, msg); + } +- mutex_unlock(&adap->devnode.lock); ++ mutex_unlock(&adap->devnode.lock_fhs); + } + + /* +@@ -302,12 +303,12 @@ static void cec_queue_msg_followers(struct cec_adapter *adap, + { + struct cec_fh *fh; + +- mutex_lock(&adap->devnode.lock); ++ mutex_lock(&adap->devnode.lock_fhs); + list_for_each_entry(fh, &adap->devnode.fhs, list) { + if (fh->mode_follower == CEC_MODE_FOLLOWER) + cec_queue_msg_fh(fh, msg); + } +- mutex_unlock(&adap->devnode.lock); ++ mutex_unlock(&adap->devnode.lock_fhs); + } + + /* Notify userspace of an adapter state change. */ +@@ -1559,6 +1560,7 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) + /* Disabling monitor all mode should always succeed */ + if (adap->monitor_all_cnt) + WARN_ON(call_op(adap, adap_monitor_all_enable, false)); ++ /* serialize adap_enable */ + mutex_lock(&adap->devnode.lock); + if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) { + WARN_ON(adap->ops->adap_enable(adap, false)); +@@ -1570,14 +1572,16 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) + return; + } + ++ /* serialize adap_enable */ + mutex_lock(&adap->devnode.lock); + adap->last_initiator = 0xff; + adap->transmit_in_progress = false; + +- if ((adap->needs_hpd || list_empty(&adap->devnode.fhs)) && +- adap->ops->adap_enable(adap, true)) { +- mutex_unlock(&adap->devnode.lock); +- return; ++ if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) { ++ if (adap->ops->adap_enable(adap, true)) { ++ mutex_unlock(&adap->devnode.lock); ++ return; ++ } + } + + if (adap->monitor_all_cnt && +diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c +index 893641ebc644b..899017a0e514e 100644 +--- a/drivers/media/cec/core/cec-api.c ++++ b/drivers/media/cec/core/cec-api.c +@@ -586,6 +586,7 @@ static int cec_open(struct inode *inode, struct file *filp) + return err; + } + ++ /* serialize adap_enable */ + mutex_lock(&devnode->lock); + if (list_empty(&devnode->fhs) && + !adap->needs_hpd && +@@ -624,7 +625,9 @@ static int cec_open(struct inode *inode, struct file *filp) + } + #endif + ++ mutex_lock(&devnode->lock_fhs); + list_add(&fh->list, &devnode->fhs); ++ mutex_unlock(&devnode->lock_fhs); + mutex_unlock(&devnode->lock); + + return 0; +@@ -653,8 +656,11 @@ static int cec_release(struct inode *inode, struct file *filp) + cec_monitor_all_cnt_dec(adap); + mutex_unlock(&adap->lock); + ++ /* serialize adap_enable */ + mutex_lock(&devnode->lock); ++ mutex_lock(&devnode->lock_fhs); + list_del(&fh->list); ++ mutex_unlock(&devnode->lock_fhs); + if (cec_is_registered(adap) && list_empty(&devnode->fhs) && + !adap->needs_hpd && adap->phys_addr == CEC_PHYS_ADDR_INVALID) { + WARN_ON(adap->ops->adap_enable(adap, false)); +diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c +index ece236291f358..61139b0a08699 100644 +--- a/drivers/media/cec/core/cec-core.c ++++ b/drivers/media/cec/core/cec-core.c +@@ -167,8 +167,10 @@ static void cec_devnode_unregister(struct cec_adapter *adap) + return; + } + ++ mutex_lock(&devnode->lock_fhs); + list_for_each_entry(fh, &devnode->fhs, list) + wake_up_interruptible(&fh->wait); ++ mutex_unlock(&devnode->lock_fhs); + + devnode->registered = false; + devnode->unregistered = true; +@@ -272,6 +274,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, + + /* adap->devnode initialization */ + INIT_LIST_HEAD(&adap->devnode.fhs); ++ mutex_init(&adap->devnode.lock_fhs); + mutex_init(&adap->devnode.lock); + + adap->kthread = kthread_run(cec_thread_func, adap, "cec-%s", name); +diff --git a/include/media/cec.h b/include/media/cec.h +index 208c9613c07eb..77346f757036d 100644 +--- a/include/media/cec.h ++++ b/include/media/cec.h +@@ -26,13 +26,17 @@ + * @dev: cec device + * @cdev: cec character device + * @minor: device node minor number ++ * @lock: lock to serialize open/release and registration + * @registered: the device was correctly registered + * @unregistered: the device was unregistered ++ * @lock_fhs: lock to control access to @fhs + * @fhs: the list of open filehandles (cec_fh) +- * @lock: lock to control access to this structure + * + * This structure represents a cec-related device node. + * ++ * To add or remove filehandles from @fhs the @lock must be taken first, ++ * followed by @lock_fhs. It is safe to access @fhs if either lock is held. ++ * + * The @parent is a physical device. It must be set by core or device drivers + * before registering the node. + */ +@@ -43,10 +47,13 @@ struct cec_devnode { + + /* device info */ + int minor; ++ /* serialize open/release and registration */ ++ struct mutex lock; + bool registered; + bool unregistered; ++ /* protect access to fhs */ ++ struct mutex lock_fhs; + struct list_head fhs; +- struct mutex lock; + }; + + struct cec_adapter; +-- +2.43.0 + diff --git a/queue-5.10/media-cec-use-call_op-and-check-for-unregistered.patch b/queue-5.10/media-cec-use-call_op-and-check-for-unregistered.patch new file mode 100644 index 00000000000..ddd854c2d68 --- /dev/null +++ b/queue-5.10/media-cec-use-call_op-and-check-for-unregistered.patch @@ -0,0 +1,312 @@ +From e6cc59c37dbe766dae9af5c58a023beffdbea040 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Mar 2022 08:51:20 +0000 +Subject: media: cec: use call_op and check for !unregistered + +From: Hans Verkuil + +[ Upstream commit e2ed5024ac2bc27d4bfc99fd58f5ab54de8fa965 ] + +Use call_(void_)op consistently in the CEC core framework. Ditto +for the cec pin ops. And check if !adap->devnode.unregistered before +calling each op. This avoids calls to ops when the device has been +unregistered and the underlying hardware may be gone. + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs") +Signed-off-by: Sasha Levin +--- + drivers/media/cec/core/cec-adap.c | 37 ++++++++++----------------- + drivers/media/cec/core/cec-api.c | 6 +++-- + drivers/media/cec/core/cec-core.c | 4 +-- + drivers/media/cec/core/cec-pin-priv.h | 11 ++++++++ + drivers/media/cec/core/cec-pin.c | 23 ++++++++--------- + drivers/media/cec/core/cec-priv.h | 10 ++++++++ + 6 files changed, 51 insertions(+), 40 deletions(-) + +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index 41f4def8a31ca..07ff4b0c8461e 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -39,15 +39,6 @@ static void cec_fill_msg_report_features(struct cec_adapter *adap, + */ + #define CEC_XFER_TIMEOUT_MS (5 * 400 + 100) + +-#define call_op(adap, op, arg...) \ +- (adap->ops->op ? adap->ops->op(adap, ## arg) : 0) +- +-#define call_void_op(adap, op, arg...) \ +- do { \ +- if (adap->ops->op) \ +- adap->ops->op(adap, ## arg); \ +- } while (0) +- + static int cec_log_addr2idx(const struct cec_adapter *adap, u8 log_addr) + { + int i; +@@ -405,9 +396,9 @@ static void cec_data_cancel(struct cec_data *data, u8 tx_status, u8 rx_status) + /* Queue transmitted message for monitoring purposes */ + cec_queue_msg_monitor(adap, &data->msg, 1); + +- if (!data->blocking && data->msg.sequence && adap->ops->received) ++ if (!data->blocking && data->msg.sequence) + /* Allow drivers to process the message first */ +- adap->ops->received(adap, &data->msg); ++ call_op(adap, received, &data->msg); + + cec_data_completed(data); + } +@@ -584,8 +575,8 @@ int cec_thread_func(void *_adap) + + adap->transmit_in_progress_aborted = false; + /* Tell the adapter to transmit, cancel on error */ +- if (adap->ops->adap_transmit(adap, data->attempts, +- signal_free_time, &data->msg)) ++ if (call_op(adap, adap_transmit, data->attempts, ++ signal_free_time, &data->msg)) + cec_data_cancel(data, CEC_TX_STATUS_ABORTED, 0); + else + adap->transmit_in_progress = true; +@@ -1311,7 +1302,7 @@ static int cec_config_log_addr(struct cec_adapter *adap, + * Message not acknowledged, so this logical + * address is free to use. + */ +- err = adap->ops->adap_log_addr(adap, log_addr); ++ err = call_op(adap, adap_log_addr, log_addr); + if (err) + return err; + +@@ -1328,9 +1319,8 @@ static int cec_config_log_addr(struct cec_adapter *adap, + */ + static void cec_adap_unconfigure(struct cec_adapter *adap) + { +- if (!adap->needs_hpd || +- adap->phys_addr != CEC_PHYS_ADDR_INVALID) +- WARN_ON(adap->ops->adap_log_addr(adap, CEC_LOG_ADDR_INVALID)); ++ if (!adap->needs_hpd || adap->phys_addr != CEC_PHYS_ADDR_INVALID) ++ WARN_ON(call_op(adap, adap_log_addr, CEC_LOG_ADDR_INVALID)); + adap->log_addrs.log_addr_mask = 0; + adap->is_configured = false; + cec_flush(adap); +@@ -1573,7 +1563,7 @@ static int cec_activate_cnt_inc(struct cec_adapter *adap) + mutex_lock(&adap->devnode.lock); + adap->last_initiator = 0xff; + adap->transmit_in_progress = false; +- ret = adap->ops->adap_enable(adap, true); ++ ret = call_op(adap, adap_enable, true); + if (ret) + adap->activate_cnt--; + mutex_unlock(&adap->devnode.lock); +@@ -1590,7 +1580,7 @@ static void cec_activate_cnt_dec(struct cec_adapter *adap) + + /* serialize adap_enable */ + mutex_lock(&adap->devnode.lock); +- WARN_ON(adap->ops->adap_enable(adap, false)); ++ WARN_ON(call_op(adap, adap_enable, false)); + adap->last_initiator = 0xff; + adap->transmit_in_progress = false; + adap->transmit_in_progress_aborted = false; +@@ -1964,11 +1954,10 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, + msg->msg[1] != CEC_MSG_CDC_MESSAGE) + return 0; + +- if (adap->ops->received) { +- /* Allow drivers to process the message first */ +- if (adap->ops->received(adap, msg) != -ENOMSG) +- return 0; +- } ++ /* Allow drivers to process the message first */ ++ if (adap->ops->received && !adap->devnode.unregistered && ++ adap->ops->received(adap, msg) != -ENOMSG) ++ return 0; + + /* + * REPORT_PHYSICAL_ADDR, CEC_MSG_USER_CONTROL_PRESSED and +diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c +index 0be4e822211e7..feaf100a44c2d 100644 +--- a/drivers/media/cec/core/cec-api.c ++++ b/drivers/media/cec/core/cec-api.c +@@ -595,7 +595,8 @@ static int cec_open(struct inode *inode, struct file *filp) + adap->conn_info.type != CEC_CONNECTOR_TYPE_NO_CONNECTOR; + cec_queue_event_fh(fh, &ev, 0); + #ifdef CONFIG_CEC_PIN +- if (adap->pin && adap->pin->ops->read_hpd) { ++ if (adap->pin && adap->pin->ops->read_hpd && ++ !adap->devnode.unregistered) { + err = adap->pin->ops->read_hpd(adap); + if (err >= 0) { + ev.event = err ? CEC_EVENT_PIN_HPD_HIGH : +@@ -603,7 +604,8 @@ static int cec_open(struct inode *inode, struct file *filp) + cec_queue_event_fh(fh, &ev, 0); + } + } +- if (adap->pin && adap->pin->ops->read_5v) { ++ if (adap->pin && adap->pin->ops->read_5v && ++ !adap->devnode.unregistered) { + err = adap->pin->ops->read_5v(adap); + if (err >= 0) { + ev.event = err ? CEC_EVENT_PIN_5V_HIGH : +diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c +index 61139b0a08699..0a3345e1a0f3a 100644 +--- a/drivers/media/cec/core/cec-core.c ++++ b/drivers/media/cec/core/cec-core.c +@@ -204,7 +204,7 @@ static ssize_t cec_error_inj_write(struct file *file, + line = strsep(&p, "\n"); + if (!*line || *line == '#') + continue; +- if (!adap->ops->error_inj_parse_line(adap, line)) { ++ if (!call_op(adap, error_inj_parse_line, line)) { + kfree(buf); + return -EINVAL; + } +@@ -217,7 +217,7 @@ static int cec_error_inj_show(struct seq_file *sf, void *unused) + { + struct cec_adapter *adap = sf->private; + +- return adap->ops->error_inj_show(adap, sf); ++ return call_op(adap, error_inj_show, sf); + } + + static int cec_error_inj_open(struct inode *inode, struct file *file) +diff --git a/drivers/media/cec/core/cec-pin-priv.h b/drivers/media/cec/core/cec-pin-priv.h +index f423db8855d9e..5577c62e4131f 100644 +--- a/drivers/media/cec/core/cec-pin-priv.h ++++ b/drivers/media/cec/core/cec-pin-priv.h +@@ -12,6 +12,17 @@ + #include + #include + ++#define call_pin_op(pin, op, arg...) \ ++ ((pin && pin->ops->op && !pin->adap->devnode.unregistered) ? \ ++ pin->ops->op(pin->adap, ## arg) : 0) ++ ++#define call_void_pin_op(pin, op, arg...) \ ++ do { \ ++ if (pin && pin->ops->op && \ ++ !pin->adap->devnode.unregistered) \ ++ pin->ops->op(pin->adap, ## arg); \ ++ } while (0) ++ + enum cec_pin_state { + /* CEC is off */ + CEC_ST_OFF, +diff --git a/drivers/media/cec/core/cec-pin.c b/drivers/media/cec/core/cec-pin.c +index f8452a1f9fc6c..447fdada20e98 100644 +--- a/drivers/media/cec/core/cec-pin.c ++++ b/drivers/media/cec/core/cec-pin.c +@@ -135,7 +135,7 @@ static void cec_pin_update(struct cec_pin *pin, bool v, bool force) + + static bool cec_pin_read(struct cec_pin *pin) + { +- bool v = pin->ops->read(pin->adap); ++ bool v = call_pin_op(pin, read); + + cec_pin_update(pin, v, false); + return v; +@@ -143,13 +143,13 @@ static bool cec_pin_read(struct cec_pin *pin) + + static void cec_pin_low(struct cec_pin *pin) + { +- pin->ops->low(pin->adap); ++ call_void_pin_op(pin, low); + cec_pin_update(pin, false, false); + } + + static bool cec_pin_high(struct cec_pin *pin) + { +- pin->ops->high(pin->adap); ++ call_void_pin_op(pin, high); + return cec_pin_read(pin); + } + +@@ -1086,7 +1086,7 @@ static int cec_pin_thread_func(void *_adap) + CEC_PIN_IRQ_UNCHANGED)) { + case CEC_PIN_IRQ_DISABLE: + if (irq_enabled) { +- pin->ops->disable_irq(adap); ++ call_void_pin_op(pin, disable_irq); + irq_enabled = false; + } + cec_pin_high(pin); +@@ -1097,7 +1097,7 @@ static int cec_pin_thread_func(void *_adap) + case CEC_PIN_IRQ_ENABLE: + if (irq_enabled) + break; +- pin->enable_irq_failed = !pin->ops->enable_irq(adap); ++ pin->enable_irq_failed = !call_pin_op(pin, enable_irq); + if (pin->enable_irq_failed) { + cec_pin_to_idle(pin); + hrtimer_start(&pin->timer, ns_to_ktime(0), +@@ -1112,8 +1112,8 @@ static int cec_pin_thread_func(void *_adap) + if (kthread_should_stop()) + break; + } +- if (pin->ops->disable_irq && irq_enabled) +- pin->ops->disable_irq(adap); ++ if (irq_enabled) ++ call_void_pin_op(pin, disable_irq); + hrtimer_cancel(&pin->timer); + cec_pin_read(pin); + cec_pin_to_idle(pin); +@@ -1208,7 +1208,7 @@ static void cec_pin_adap_status(struct cec_adapter *adap, + seq_printf(file, "state: %s\n", states[pin->state].name); + seq_printf(file, "tx_bit: %d\n", pin->tx_bit); + seq_printf(file, "rx_bit: %d\n", pin->rx_bit); +- seq_printf(file, "cec pin: %d\n", pin->ops->read(adap)); ++ seq_printf(file, "cec pin: %d\n", call_pin_op(pin, read)); + seq_printf(file, "cec pin events dropped: %u\n", + pin->work_pin_events_dropped_cnt); + seq_printf(file, "irq failed: %d\n", pin->enable_irq_failed); +@@ -1261,8 +1261,7 @@ static void cec_pin_adap_status(struct cec_adapter *adap, + pin->rx_data_bit_too_long_cnt = 0; + pin->rx_low_drive_cnt = 0; + pin->tx_low_drive_cnt = 0; +- if (pin->ops->status) +- pin->ops->status(adap, file); ++ call_void_pin_op(pin, status, file); + } + + static int cec_pin_adap_monitor_all_enable(struct cec_adapter *adap, +@@ -1278,7 +1277,7 @@ static void cec_pin_adap_free(struct cec_adapter *adap) + { + struct cec_pin *pin = adap->pin; + +- if (pin->ops->free) ++ if (pin && pin->ops->free) + pin->ops->free(adap); + adap->pin = NULL; + kfree(pin); +@@ -1288,7 +1287,7 @@ static int cec_pin_received(struct cec_adapter *adap, struct cec_msg *msg) + { + struct cec_pin *pin = adap->pin; + +- if (pin->ops->received) ++ if (pin->ops->received && !adap->devnode.unregistered) + return pin->ops->received(adap, msg); + return -ENOMSG; + } +diff --git a/drivers/media/cec/core/cec-priv.h b/drivers/media/cec/core/cec-priv.h +index 9bbd05053d420..b78df931aa74b 100644 +--- a/drivers/media/cec/core/cec-priv.h ++++ b/drivers/media/cec/core/cec-priv.h +@@ -17,6 +17,16 @@ + pr_info("cec-%s: " fmt, adap->name, ## arg); \ + } while (0) + ++#define call_op(adap, op, arg...) \ ++ ((adap->ops->op && !adap->devnode.unregistered) ? \ ++ adap->ops->op(adap, ## arg) : 0) ++ ++#define call_void_op(adap, op, arg...) \ ++ do { \ ++ if (adap->ops->op && !adap->devnode.unregistered) \ ++ adap->ops->op(adap, ## arg); \ ++ } while (0) ++ + /* devnode to cec_adapter */ + #define to_cec_adapter(node) container_of(node, struct cec_adapter, devnode) + +-- +2.43.0 + diff --git a/queue-5.10/media-core-headers-fix-kernel-doc-warnings.patch b/queue-5.10/media-core-headers-fix-kernel-doc-warnings.patch new file mode 100644 index 00000000000..ee9ffdcb6aa --- /dev/null +++ b/queue-5.10/media-core-headers-fix-kernel-doc-warnings.patch @@ -0,0 +1,276 @@ +From 0456bc48703200f8aa568c29abe1db0fe0be679c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Mar 2021 12:48:20 +0100 +Subject: media: core headers: fix kernel-doc warnings + +From: Hans Verkuil + +[ Upstream commit f12b81e47f48940a6ec82ff308a7d97cd2307442 ] + +This patch fixes the following kernel-doc warnings: + +include/uapi/linux/videodev2.h:996: warning: Function parameter or member 'm' not described in 'v4l2_plane' +include/uapi/linux/videodev2.h:996: warning: Function parameter or member 'reserved' not described in 'v4l2_plane' +include/uapi/linux/videodev2.h:1057: warning: Function parameter or member 'm' not described in 'v4l2_buffer' +include/uapi/linux/videodev2.h:1057: warning: Function parameter or member 'reserved2' not described in 'v4l2_buffer' +include/uapi/linux/videodev2.h:1057: warning: Function parameter or member 'reserved' not described in 'v4l2_buffer' +include/uapi/linux/videodev2.h:1068: warning: Function parameter or member 'tv' not described in 'v4l2_timeval_to_ns' +include/uapi/linux/videodev2.h:1068: warning: Excess function parameter 'ts' description in 'v4l2_timeval_to_ns' +include/uapi/linux/videodev2.h:1138: warning: Function parameter or member 'reserved' not described in 'v4l2_exportbuffer' +include/uapi/linux/videodev2.h:2237: warning: Function parameter or member 'reserved' not described in 'v4l2_plane_pix_format' +include/uapi/linux/videodev2.h:2270: warning: Function parameter or member 'hsv_enc' not described in 'v4l2_pix_format_mplane' +include/uapi/linux/videodev2.h:2270: warning: Function parameter or member 'reserved' not described in 'v4l2_pix_format_mplane' +include/uapi/linux/videodev2.h:2281: warning: Function parameter or member 'reserved' not described in 'v4l2_sdr_format' +include/uapi/linux/videodev2.h:2315: warning: Function parameter or member 'fmt' not described in 'v4l2_format' + +include/uapi/linux/v4l2-subdev.h:53: warning: Function parameter or member 'reserved' not described in 'v4l2_subdev_format' +include/uapi/linux/v4l2-subdev.h:66: warning: Function parameter or member 'reserved' not described in 'v4l2_subdev_crop' +include/uapi/linux/v4l2-subdev.h:89: warning: Function parameter or member 'reserved' not described in 'v4l2_subdev_mbus_code_enum' +include/uapi/linux/v4l2-subdev.h:108: warning: Function parameter or member 'min_width' not described in 'v4l2_subdev_frame_size_enum' +include/uapi/linux/v4l2-subdev.h:108: warning: Function parameter or member 'max_width' not described in 'v4l2_subdev_frame_size_enum' +include/uapi/linux/v4l2-subdev.h:108: warning: Function parameter or member 'min_height' not described in 'v4l2_subdev_frame_size_enum' +include/uapi/linux/v4l2-subdev.h:108: warning: Function parameter or member 'max_height' not described in 'v4l2_subdev_frame_size_enum' +include/uapi/linux/v4l2-subdev.h:108: warning: Function parameter or member 'reserved' not described in 'v4l2_subdev_frame_size_enum' +include/uapi/linux/v4l2-subdev.h:119: warning: Function parameter or member 'reserved' not described in 'v4l2_subdev_frame_interval' +include/uapi/linux/v4l2-subdev.h:140: warning: Function parameter or member 'reserved' not described in 'v4l2_subdev_frame_interval_enum' + +include/uapi/linux/cec.h:406: warning: Function parameter or member 'raw' not described in 'cec_connector_info' +include/uapi/linux/cec.h:470: warning: Function parameter or member 'flags' not described in 'cec_event' + +include/media/v4l2-h264.h:82: warning: Function parameter or member 'reflist' not described in 'v4l2_h264_build_p_ref_list' +include/media/v4l2-h264.h:82: warning: expecting prototype for v4l2_h264_build_b_ref_lists(). Prototype was for v4l2_h264_build_p_ref_list() +instead + +include/media/cec.h:50: warning: Function parameter or member 'lock' not described in 'cec_devnode' + +include/media/v4l2-jpeg.h:122: warning: Function parameter or member 'num_dht' not described in 'v4l2_jpeg_header' +include/media/v4l2-jpeg.h:122: warning: Function parameter or member 'num_dqt' not described in 'v4l2_jpeg_header' + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs") +Signed-off-by: Sasha Levin +--- + include/media/cec.h | 2 +- + include/media/v4l2-h264.h | 6 +++--- + include/media/v4l2-jpeg.h | 2 ++ + include/uapi/linux/cec.h | 3 ++- + include/uapi/linux/v4l2-subdev.h | 12 +++++++++++- + include/uapi/linux/videodev2.h | 15 ++++++++++++++- + 6 files changed, 33 insertions(+), 7 deletions(-) + +diff --git a/include/media/cec.h b/include/media/cec.h +index cd35ae6b7560f..208c9613c07eb 100644 +--- a/include/media/cec.h ++++ b/include/media/cec.h +@@ -28,8 +28,8 @@ + * @minor: device node minor number + * @registered: the device was correctly registered + * @unregistered: the device was unregistered +- * @fhs_lock: lock to control access to the filehandle list + * @fhs: the list of open filehandles (cec_fh) ++ * @lock: lock to control access to this structure + * + * This structure represents a cec-related device node. + * +diff --git a/include/media/v4l2-h264.h b/include/media/v4l2-h264.h +index f08ba181263d1..1cc89d2e693a3 100644 +--- a/include/media/v4l2-h264.h ++++ b/include/media/v4l2-h264.h +@@ -66,11 +66,11 @@ v4l2_h264_build_b_ref_lists(const struct v4l2_h264_reflist_builder *builder, + u8 *b0_reflist, u8 *b1_reflist); + + /** +- * v4l2_h264_build_b_ref_lists() - Build the P reference list ++ * v4l2_h264_build_p_ref_list() - Build the P reference list + * + * @builder: reference list builder context +- * @p_reflist: 16-bytes array used to store the P reference list. Each entry +- * is an index in the DPB ++ * @reflist: 16-bytes array used to store the P reference list. Each entry ++ * is an index in the DPB + * + * This functions builds the P reference lists. This procedure is describe in + * section '8.2.4 Decoding process for reference picture lists construction' +diff --git a/include/media/v4l2-jpeg.h b/include/media/v4l2-jpeg.h +index ddba2a56c3214..3a3344a976782 100644 +--- a/include/media/v4l2-jpeg.h ++++ b/include/media/v4l2-jpeg.h +@@ -91,7 +91,9 @@ struct v4l2_jpeg_scan_header { + * struct v4l2_jpeg_header - parsed JPEG header + * @sof: pointer to frame header and size + * @sos: pointer to scan header and size ++ * @num_dht: number of entries in @dht + * @dht: pointers to huffman tables and sizes ++ * @num_dqt: number of entries in @dqt + * @dqt: pointers to quantization tables and sizes + * @frame: parsed frame header + * @scan: pointer to parsed scan header, optional +diff --git a/include/uapi/linux/cec.h b/include/uapi/linux/cec.h +index 7d1a06c524696..dc8879d179fdf 100644 +--- a/include/uapi/linux/cec.h ++++ b/include/uapi/linux/cec.h +@@ -396,6 +396,7 @@ struct cec_drm_connector_info { + * associated with the CEC adapter. + * @type: connector type (if any) + * @drm: drm connector info ++ * @raw: array to pad the union + */ + struct cec_connector_info { + __u32 type; +@@ -453,7 +454,7 @@ struct cec_event_lost_msgs { + * struct cec_event - CEC event structure + * @ts: the timestamp of when the event was sent. + * @event: the event. +- * array. ++ * @flags: event flags. + * @state_change: the event payload for CEC_EVENT_STATE_CHANGE. + * @lost_msgs: the event payload for CEC_EVENT_LOST_MSGS. + * @raw: array to pad the union. +diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h +index a38454d9e0f54..658106f5b5dc9 100644 +--- a/include/uapi/linux/v4l2-subdev.h ++++ b/include/uapi/linux/v4l2-subdev.h +@@ -44,6 +44,7 @@ enum v4l2_subdev_format_whence { + * @which: format type (from enum v4l2_subdev_format_whence) + * @pad: pad number, as reported by the media API + * @format: media bus format (format code and frame size) ++ * @reserved: drivers and applications must zero this array + */ + struct v4l2_subdev_format { + __u32 which; +@@ -57,6 +58,7 @@ struct v4l2_subdev_format { + * @which: format type (from enum v4l2_subdev_format_whence) + * @pad: pad number, as reported by the media API + * @rect: pad crop rectangle boundaries ++ * @reserved: drivers and applications must zero this array + */ + struct v4l2_subdev_crop { + __u32 which; +@@ -78,6 +80,7 @@ struct v4l2_subdev_crop { + * @code: format code (MEDIA_BUS_FMT_ definitions) + * @which: format type (from enum v4l2_subdev_format_whence) + * @flags: flags set by the driver, (V4L2_SUBDEV_MBUS_CODE_*) ++ * @reserved: drivers and applications must zero this array + */ + struct v4l2_subdev_mbus_code_enum { + __u32 pad; +@@ -90,10 +93,15 @@ struct v4l2_subdev_mbus_code_enum { + + /** + * struct v4l2_subdev_frame_size_enum - Media bus format enumeration +- * @pad: pad number, as reported by the media API + * @index: format index during enumeration ++ * @pad: pad number, as reported by the media API + * @code: format code (MEDIA_BUS_FMT_ definitions) ++ * @min_width: minimum frame width, in pixels ++ * @max_width: maximum frame width, in pixels ++ * @min_height: minimum frame height, in pixels ++ * @max_height: maximum frame height, in pixels + * @which: format type (from enum v4l2_subdev_format_whence) ++ * @reserved: drivers and applications must zero this array + */ + struct v4l2_subdev_frame_size_enum { + __u32 index; +@@ -111,6 +119,7 @@ struct v4l2_subdev_frame_size_enum { + * struct v4l2_subdev_frame_interval - Pad-level frame rate + * @pad: pad number, as reported by the media API + * @interval: frame interval in seconds ++ * @reserved: drivers and applications must zero this array + */ + struct v4l2_subdev_frame_interval { + __u32 pad; +@@ -127,6 +136,7 @@ struct v4l2_subdev_frame_interval { + * @height: frame height in pixels + * @interval: frame interval in seconds + * @which: format type (from enum v4l2_subdev_format_whence) ++ * @reserved: drivers and applications must zero this array + */ + struct v4l2_subdev_frame_interval_enum { + __u32 index; +diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h +index 55b8c4b824797..1bbd81f031fe0 100644 +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -976,8 +976,10 @@ struct v4l2_requestbuffers { + * pointing to this plane + * @fd: when memory is V4L2_MEMORY_DMABUF, a userspace file + * descriptor associated with this plane ++ * @m: union of @mem_offset, @userptr and @fd + * @data_offset: offset in the plane to the start of data; usually 0, + * unless there is a header in front of the data ++ * @reserved: drivers and applications must zero this array + * + * Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer + * with two planes can have one plane for Y, and another for interleaved CbCr +@@ -1019,10 +1021,14 @@ struct v4l2_plane { + * a userspace file descriptor associated with this buffer + * @planes: for multiplanar buffers; userspace pointer to the array of plane + * info structs for this buffer ++ * @m: union of @offset, @userptr, @planes and @fd + * @length: size in bytes of the buffer (NOT its payload) for single-plane + * buffers (when type != *_MPLANE); number of elements in the + * planes array for multi-plane buffers ++ * @reserved2: drivers and applications must zero this field + * @request_fd: fd of the request that this buffer should use ++ * @reserved: for backwards compatibility with applications that do not know ++ * about @request_fd + * + * Contains data exchanged by application and driver using one of the Streaming + * I/O methods. +@@ -1060,7 +1066,7 @@ struct v4l2_buffer { + #ifndef __KERNEL__ + /** + * v4l2_timeval_to_ns - Convert timeval to nanoseconds +- * @ts: pointer to the timeval variable to be converted ++ * @tv: pointer to the timeval variable to be converted + * + * Returns the scalar nanosecond representation of the timeval + * parameter. +@@ -1121,6 +1127,7 @@ static inline __u64 v4l2_timeval_to_ns(const struct timeval *tv) + * @flags: flags for newly created file, currently only O_CLOEXEC is + * supported, refer to manual of open syscall for more details + * @fd: file descriptor associated with DMABUF (set by driver) ++ * @reserved: drivers and applications must zero this array + * + * Contains data used for exporting a video buffer as DMABUF file descriptor. + * The buffer is identified by a 'cookie' returned by VIDIOC_QUERYBUF +@@ -2215,6 +2222,7 @@ struct v4l2_mpeg_vbi_fmt_ivtv { + * this plane will be used + * @bytesperline: distance in bytes between the leftmost pixels in two + * adjacent lines ++ * @reserved: drivers and applications must zero this array + */ + struct v4l2_plane_pix_format { + __u32 sizeimage; +@@ -2233,8 +2241,10 @@ struct v4l2_plane_pix_format { + * @num_planes: number of planes for this format + * @flags: format flags (V4L2_PIX_FMT_FLAG_*) + * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding ++ * @hsv_enc: enum v4l2_hsv_encoding, HSV encoding + * @quantization: enum v4l2_quantization, colorspace quantization + * @xfer_func: enum v4l2_xfer_func, colorspace transfer function ++ * @reserved: drivers and applications must zero this array + */ + struct v4l2_pix_format_mplane { + __u32 width; +@@ -2259,6 +2269,7 @@ struct v4l2_pix_format_mplane { + * struct v4l2_sdr_format - SDR format definition + * @pixelformat: little endian four character code (fourcc) + * @buffersize: maximum size in bytes required for data ++ * @reserved: drivers and applications must zero this array + */ + struct v4l2_sdr_format { + __u32 pixelformat; +@@ -2285,6 +2296,8 @@ struct v4l2_meta_format { + * @vbi: raw VBI capture or output parameters + * @sliced: sliced VBI capture or output parameters + * @raw_data: placeholder for future extensions and custom formats ++ * @fmt: union of @pix, @pix_mp, @win, @vbi, @sliced, @sdr, @meta ++ * and @raw_data + */ + struct v4l2_format { + __u32 type; +-- +2.43.0 + diff --git a/queue-5.10/media-flexcop-usb-clean-up-endpoint-sanity-checks.patch b/queue-5.10/media-flexcop-usb-clean-up-endpoint-sanity-checks.patch new file mode 100644 index 00000000000..1c01a67dbb1 --- /dev/null +++ b/queue-5.10/media-flexcop-usb-clean-up-endpoint-sanity-checks.patch @@ -0,0 +1,56 @@ +From f80dd34278ac0342fc7fcb42e6954e582cf6ff6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Aug 2022 17:14:54 +0200 +Subject: media: flexcop-usb: clean up endpoint sanity checks + +From: Johan Hovold + +[ Upstream commit 3de50478b5cc2e0c2479a5f2b967f331f7597d23 ] + +Add a temporary variable to make the endpoint sanity checks a bit more +readable. + +While at it, fix a typo in the usb_set_interface() comment. + +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20220822151456.27178-2-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: f62dc8f6bf82 ("media: flexcop-usb: fix sanity check of bNumEndpoints") +Signed-off-by: Sasha Levin +--- + drivers/media/usb/b2c2/flexcop-usb.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c +index 2299d5cca8ffb..6d199b32e3170 100644 +--- a/drivers/media/usb/b2c2/flexcop-usb.c ++++ b/drivers/media/usb/b2c2/flexcop-usb.c +@@ -502,17 +502,21 @@ static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb) + + static int flexcop_usb_init(struct flexcop_usb *fc_usb) + { +- /* use the alternate setting with the larges buffer */ +- int ret = usb_set_interface(fc_usb->udev, 0, 1); ++ struct usb_host_interface *alt; ++ int ret; + ++ /* use the alternate setting with the largest buffer */ ++ ret = usb_set_interface(fc_usb->udev, 0, 1); + if (ret) { + err("set interface failed."); + return ret; + } + +- if (fc_usb->uintf->cur_altsetting->desc.bNumEndpoints < 1) ++ alt = fc_usb->uintf->cur_altsetting; ++ ++ if (alt->desc.bNumEndpoints < 1) + return -ENODEV; +- if (!usb_endpoint_is_isoc_in(&fc_usb->uintf->cur_altsetting->endpoint[0].desc)) ++ if (!usb_endpoint_is_isoc_in(&alt->endpoint[0].desc)) + return -ENODEV; + + switch (fc_usb->udev->speed) { +-- +2.43.0 + diff --git a/queue-5.10/media-flexcop-usb-fix-sanity-check-of-bnumendpoints.patch b/queue-5.10/media-flexcop-usb-fix-sanity-check-of-bnumendpoints.patch new file mode 100644 index 00000000000..3eefafb09cf --- /dev/null +++ b/queue-5.10/media-flexcop-usb-fix-sanity-check-of-bnumendpoints.patch @@ -0,0 +1,40 @@ +From c9782023df6440cd048dc761cb431a95597f6a5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Jun 2022 06:50:24 +0100 +Subject: media: flexcop-usb: fix sanity check of bNumEndpoints + +From: Dongliang Mu + +[ Upstream commit f62dc8f6bf82d1b307fc37d8d22cc79f67856c2f ] + +Commit d725d20e81c2 ("media: flexcop-usb: sanity checking of endpoint type +") adds a sanity check for endpoint[1], but fails to modify the sanity +check of bNumEndpoints. + +Fix this by modifying the sanity check of bNumEndpoints to 2. + +Link: https://lore.kernel.org/linux-media/20220602055027.849014-1-dzm91@hust.edu.cn +Fixes: d725d20e81c2 ("media: flexcop-usb: sanity checking of endpoint type") +Signed-off-by: Dongliang Mu +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/usb/b2c2/flexcop-usb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c +index 6d199b32e3170..6ded5a6181aa2 100644 +--- a/drivers/media/usb/b2c2/flexcop-usb.c ++++ b/drivers/media/usb/b2c2/flexcop-usb.c +@@ -514,7 +514,7 @@ static int flexcop_usb_init(struct flexcop_usb *fc_usb) + + alt = fc_usb->uintf->cur_altsetting; + +- if (alt->desc.bNumEndpoints < 1) ++ if (alt->desc.bNumEndpoints < 2) + return -ENODEV; + if (!usb_endpoint_is_isoc_in(&alt->endpoint[0].desc)) + return -ENODEV; +-- +2.43.0 + diff --git a/queue-5.10/media-stk1160-fix-bounds-checking-in-stk1160_copy_vi.patch b/queue-5.10/media-stk1160-fix-bounds-checking-in-stk1160_copy_vi.patch new file mode 100644 index 00000000000..ce4fbda0207 --- /dev/null +++ b/queue-5.10/media-stk1160-fix-bounds-checking-in-stk1160_copy_vi.patch @@ -0,0 +1,84 @@ +From 95f4f3ed09e3cea74d69f42c0b9fc6e1e6cdc943 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Apr 2024 12:32:44 +0300 +Subject: media: stk1160: fix bounds checking in stk1160_copy_video() + +From: Dan Carpenter + +[ Upstream commit faa4364bef2ec0060de381ff028d1d836600a381 ] + +The subtract in this condition is reversed. The ->length is the length +of the buffer. The ->bytesused is how many bytes we have copied thus +far. When the condition is reversed that means the result of the +subtraction is always negative but since it's unsigned then the result +is a very high positive value. That means the overflow check is never +true. + +Additionally, the ->bytesused doesn't actually work for this purpose +because we're not writing to "buf->mem + buf->bytesused". Instead, the +math to calculate the destination where we are writing is a bit +involved. You calculate the number of full lines already written, +multiply by two, skip a line if necessary so that we start on an odd +numbered line, and add the offset into the line. + +To fix this buffer overflow, just take the actual destination where we +are writing, if the offset is already out of bounds print an error and +return. Otherwise, write up to buf->length bytes. + +Fixes: 9cb2173e6ea8 ("[media] media: Add stk1160 new driver (easycap replacement)") +Signed-off-by: Dan Carpenter +Reviewed-by: Ricardo Ribalda +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/usb/stk1160/stk1160-video.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c +index 4cf540d1b2501..2a5a90311e0cc 100644 +--- a/drivers/media/usb/stk1160/stk1160-video.c ++++ b/drivers/media/usb/stk1160/stk1160-video.c +@@ -99,7 +99,7 @@ void stk1160_buffer_done(struct stk1160 *dev) + static inline + void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) + { +- int linesdone, lineoff, lencopy; ++ int linesdone, lineoff, lencopy, offset; + int bytesperline = dev->width * 2; + struct stk1160_buffer *buf = dev->isoc_ctl.buf; + u8 *dst = buf->mem; +@@ -139,8 +139,13 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) + * Check if we have enough space left in the buffer. + * In that case, we force loop exit after copy. + */ +- if (lencopy > buf->bytesused - buf->length) { +- lencopy = buf->bytesused - buf->length; ++ offset = dst - (u8 *)buf->mem; ++ if (offset > buf->length) { ++ dev_warn_ratelimited(dev->dev, "out of bounds offset\n"); ++ return; ++ } ++ if (lencopy > buf->length - offset) { ++ lencopy = buf->length - offset; + remain = lencopy; + } + +@@ -182,8 +187,13 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) + * Check if we have enough space left in the buffer. + * In that case, we force loop exit after copy. + */ +- if (lencopy > buf->bytesused - buf->length) { +- lencopy = buf->bytesused - buf->length; ++ offset = dst - (u8 *)buf->mem; ++ if (offset > buf->length) { ++ dev_warn_ratelimited(dev->dev, "offset out of bounds\n"); ++ return; ++ } ++ if (lencopy > buf->length - offset) { ++ lencopy = buf->length - offset; + remain = lencopy; + } + +-- +2.43.0 + diff --git a/queue-5.10/mmc-sdhci_am654-add-itapdlysel-in-sdhci_j721e_4bit_s.patch b/queue-5.10/mmc-sdhci_am654-add-itapdlysel-in-sdhci_j721e_4bit_s.patch new file mode 100644 index 00000000000..5bfe4d1f39f --- /dev/null +++ b/queue-5.10/mmc-sdhci_am654-add-itapdlysel-in-sdhci_j721e_4bit_s.patch @@ -0,0 +1,60 @@ +From 0d60332ca2ce3cacbe640836314d6cf75afa073c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Mar 2024 17:38:36 -0500 +Subject: mmc: sdhci_am654: Add ITAPDLYSEL in sdhci_j721e_4bit_set_clock + +From: Judith Mendez + +[ Upstream commit 9dff65bb5e09903c27d9cff947dff4d22b6ea6a1 ] + +Add ITAPDLYSEL to sdhci_j721e_4bit_set_clock function. +This allows to set the correct ITAPDLY for timings that +do not carry out tuning. + +Fixes: 1accbced1c32 ("mmc: sdhci_am654: Add Support for 4 bit IP on J721E") +Signed-off-by: Judith Mendez +Acked-by: Adrian Hunter +Link: https://lore.kernel.org/r/20240320223837.959900-7-jm@ti.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/sdhci_am654.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c +index 1968381b93100..879ead07f8022 100644 +--- a/drivers/mmc/host/sdhci_am654.c ++++ b/drivers/mmc/host/sdhci_am654.c +@@ -319,6 +319,7 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host, + unsigned char timing = host->mmc->ios.timing; + u32 otap_del_sel; + u32 itap_del_ena; ++ u32 itap_del_sel; + u32 mask, val; + + /* Setup DLL Output TAP delay */ +@@ -328,13 +329,18 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host, + val = (0x1 << OTAPDLYENA_SHIFT) | + (otap_del_sel << OTAPDLYSEL_SHIFT); + ++ /* Setup Input TAP delay */ + itap_del_ena = sdhci_am654->itap_del_ena[timing]; ++ itap_del_sel = sdhci_am654->itap_del_sel[timing]; + +- mask |= ITAPDLYENA_MASK; +- val |= (itap_del_ena << ITAPDLYENA_SHIFT); ++ mask |= ITAPDLYENA_MASK | ITAPDLYSEL_MASK; ++ val |= (itap_del_ena << ITAPDLYENA_SHIFT) | ++ (itap_del_sel << ITAPDLYSEL_SHIFT); + ++ regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, ++ 1 << ITAPCHGWIN_SHIFT); + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val); +- ++ regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0); + regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK, + sdhci_am654->clkbuf_sel); + +-- +2.43.0 + diff --git a/queue-5.10/mmc-sdhci_am654-add-otap-itap-delay-enable.patch b/queue-5.10/mmc-sdhci_am654-add-otap-itap-delay-enable.patch new file mode 100644 index 00000000000..6f4d1eb8fd0 --- /dev/null +++ b/queue-5.10/mmc-sdhci_am654-add-otap-itap-delay-enable.patch @@ -0,0 +1,168 @@ +From 8f3e71db5da96340560134bad1fdaff9d099ac7b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Mar 2024 17:38:33 -0500 +Subject: mmc: sdhci_am654: Add OTAP/ITAP delay enable + +From: Judith Mendez + +[ Upstream commit 387c1bf7dce0dfea02080c8bdb066b5209e92155 ] + +Currently the OTAP/ITAP delay enable functionality is incorrect in +the am654_set_clock function. The OTAP delay is not enabled when +timing < SDR25 bus speed mode. The ITAP delay is not enabled for +timings that do not carry out tuning. + +Add this OTAP/ITAP delay functionality according to the datasheet +[1] OTAPDLYENA and ITAPDLYENA for MMC0. + +[1] https://www.ti.com/lit/ds/symlink/am62p.pdf + +Fixes: 8ee5fc0e0b3b ("mmc: sdhci_am654: Update OTAPDLY writes") +Signed-off-by: Judith Mendez +Acked-by: Adrian Hunter +Link: https://lore.kernel.org/r/20240320223837.959900-4-jm@ti.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/sdhci_am654.c | 40 ++++++++++++++++++++++------------ + 1 file changed, 26 insertions(+), 14 deletions(-) + +diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c +index 847cd4e434721..1968381b93100 100644 +--- a/drivers/mmc/host/sdhci_am654.c ++++ b/drivers/mmc/host/sdhci_am654.c +@@ -142,6 +142,7 @@ struct sdhci_am654_data { + struct regmap *base; + int otap_del_sel[ARRAY_SIZE(td)]; + int itap_del_sel[ARRAY_SIZE(td)]; ++ u32 itap_del_ena[ARRAY_SIZE(td)]; + int clkbuf_sel; + int trm_icp; + int drv_strength; +@@ -238,11 +239,13 @@ static void sdhci_am654_setup_dll(struct sdhci_host *host, unsigned int clock) + } + + static void sdhci_am654_write_itapdly(struct sdhci_am654_data *sdhci_am654, +- u32 itapdly) ++ u32 itapdly, u32 enable) + { + /* Set ITAPCHGWIN before writing to ITAPDLY */ + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, + 1 << ITAPCHGWIN_SHIFT); ++ regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYENA_MASK, ++ enable << ITAPDLYENA_SHIFT); + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYSEL_MASK, + itapdly << ITAPDLYSEL_SHIFT); + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0); +@@ -259,8 +262,8 @@ static void sdhci_am654_setup_delay_chain(struct sdhci_am654_data *sdhci_am654, + mask = SELDLYTXCLK_MASK | SELDLYRXCLK_MASK; + regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask, val); + +- sdhci_am654_write_itapdly(sdhci_am654, +- sdhci_am654->itap_del_sel[timing]); ++ sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing], ++ sdhci_am654->itap_del_ena[timing]); + } + + static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) +@@ -269,7 +272,6 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) + struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); + unsigned char timing = host->mmc->ios.timing; + u32 otap_del_sel; +- u32 otap_del_ena; + u32 mask, val; + + regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0); +@@ -278,10 +280,9 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) + + /* Setup DLL Output TAP delay */ + otap_del_sel = sdhci_am654->otap_del_sel[timing]; +- otap_del_ena = (timing > MMC_TIMING_UHS_SDR25) ? 1 : 0; + + mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; +- val = (otap_del_ena << OTAPDLYENA_SHIFT) | ++ val = (0x1 << OTAPDLYENA_SHIFT) | + (otap_del_sel << OTAPDLYSEL_SHIFT); + + /* Write to STRBSEL for HS400 speed mode */ +@@ -299,7 +300,8 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) + if (timing > MMC_TIMING_UHS_SDR25 && clock >= CLOCK_TOO_SLOW_HZ) { + sdhci_am654_setup_dll(host, clock); + sdhci_am654->dll_enable = true; +- sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing]); ++ sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing], ++ sdhci_am654->itap_del_ena[timing]); + } else { + sdhci_am654_setup_delay_chain(sdhci_am654, timing); + sdhci_am654->dll_enable = false; +@@ -316,6 +318,7 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host, + struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); + unsigned char timing = host->mmc->ios.timing; + u32 otap_del_sel; ++ u32 itap_del_ena; + u32 mask, val; + + /* Setup DLL Output TAP delay */ +@@ -324,6 +327,12 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host, + mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; + val = (0x1 << OTAPDLYENA_SHIFT) | + (otap_del_sel << OTAPDLYSEL_SHIFT); ++ ++ itap_del_ena = sdhci_am654->itap_del_ena[timing]; ++ ++ mask |= ITAPDLYENA_MASK; ++ val |= (itap_del_ena << ITAPDLYENA_SHIFT); ++ + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val); + + regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK, +@@ -477,6 +486,7 @@ static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host, + { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); ++ unsigned char timing = host->mmc->ios.timing; + struct window fail_window[ITAPDLY_LENGTH]; + u8 curr_pass, itap; + u8 fail_index = 0; +@@ -485,11 +495,10 @@ static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host, + memset(fail_window, 0, sizeof(fail_window)); + + /* Enable ITAPDLY */ +- regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYENA_MASK, +- 1 << ITAPDLYENA_SHIFT); ++ sdhci_am654->itap_del_ena[timing] = 0x1; + + for (itap = 0; itap < ITAPDLY_LENGTH; itap++) { +- sdhci_am654_write_itapdly(sdhci_am654, itap); ++ sdhci_am654_write_itapdly(sdhci_am654, itap, sdhci_am654->itap_del_ena[timing]); + + curr_pass = !mmc_send_tuning(host->mmc, opcode, NULL); + +@@ -513,7 +522,7 @@ static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host, + itap = sdhci_am654_calculate_itap(host, fail_window, fail_index, + sdhci_am654->dll_enable); + +- sdhci_am654_write_itapdly(sdhci_am654, itap); ++ sdhci_am654_write_itapdly(sdhci_am654, itap, sdhci_am654->itap_del_ena[timing]); + + return 0; + } +@@ -665,9 +674,12 @@ static int sdhci_am654_get_otap_delay(struct sdhci_host *host, + host->mmc->caps2 &= ~td[i].capability; + } + +- if (td[i].itap_binding) +- device_property_read_u32(dev, td[i].itap_binding, +- &sdhci_am654->itap_del_sel[i]); ++ if (td[i].itap_binding) { ++ ret = device_property_read_u32(dev, td[i].itap_binding, ++ &sdhci_am654->itap_del_sel[i]); ++ if (!ret) ++ sdhci_am654->itap_del_ena[i] = 0x1; ++ } + } + + return 0; +-- +2.43.0 + diff --git a/queue-5.10/mmc-sdhci_am654-add-tuning-algorithm-for-delay-chain.patch b/queue-5.10/mmc-sdhci_am654-add-tuning-algorithm-for-delay-chain.patch new file mode 100644 index 00000000000..9bcc498ca30 --- /dev/null +++ b/queue-5.10/mmc-sdhci_am654-add-tuning-algorithm-for-delay-chain.patch @@ -0,0 +1,195 @@ +From 80b0af2faa31963d326cd9f96954ac370f3e1701 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Mar 2024 17:38:31 -0500 +Subject: mmc: sdhci_am654: Add tuning algorithm for delay chain + +From: Judith Mendez + +[ Upstream commit 6231d99dd4119312ad41abf9383e18fec66cbe4b ] + +Currently the sdhci_am654 driver only supports one tuning +algorithm which should be used only when DLL is enabled. The +ITAPDLY is selected from the largest passing window and the +buffer is viewed as a circular buffer. + +The new algorithm should be used when the delay chain +is enabled. The ITAPDLY is selected from the largest passing +window and the buffer is not viewed as a circular buffer. + +This implementation is based off of the following paper: [1]. + +Also add support for multiple failing windows. + +[1] https://www.ti.com/lit/an/spract9/spract9.pdf + +Fixes: 13ebeae68ac9 ("mmc: sdhci_am654: Add support for software tuning") +Signed-off-by: Judith Mendez +Acked-by: Adrian Hunter +Link: https://lore.kernel.org/r/20240320223837.959900-2-jm@ti.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/sdhci_am654.c | 112 +++++++++++++++++++++++++++------ + 1 file changed, 92 insertions(+), 20 deletions(-) + +diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c +index eb52e0c5a0202..2e302c2b0ac12 100644 +--- a/drivers/mmc/host/sdhci_am654.c ++++ b/drivers/mmc/host/sdhci_am654.c +@@ -149,10 +149,17 @@ struct sdhci_am654_data { + int strb_sel; + u32 flags; + u32 quirks; ++ bool dll_enable; + + #define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0) + }; + ++struct window { ++ u8 start; ++ u8 end; ++ u8 length; ++}; ++ + struct sdhci_am654_driver_data { + const struct sdhci_pltfm_data *pdata; + u32 flags; +@@ -294,10 +301,13 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) + + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val); + +- if (timing > MMC_TIMING_UHS_SDR25 && clock >= CLOCK_TOO_SLOW_HZ) ++ if (timing > MMC_TIMING_UHS_SDR25 && clock >= CLOCK_TOO_SLOW_HZ) { + sdhci_am654_setup_dll(host, clock); +- else ++ sdhci_am654->dll_enable = true; ++ } else { + sdhci_am654_setup_delay_chain(sdhci_am654, timing); ++ sdhci_am654->dll_enable = false; ++ } + + regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK, + sdhci_am654->clkbuf_sel); +@@ -415,39 +425,101 @@ static u32 sdhci_am654_cqhci_irq(struct sdhci_host *host, u32 intmask) + return 0; + } + +-#define ITAP_MAX 32 ++#define ITAPDLY_LENGTH 32 ++#define ITAPDLY_LAST_INDEX (ITAPDLY_LENGTH - 1) ++ ++static u32 sdhci_am654_calculate_itap(struct sdhci_host *host, struct window ++ *fail_window, u8 num_fails, bool circular_buffer) ++{ ++ u8 itap = 0, start_fail = 0, end_fail = 0, pass_length = 0; ++ u8 first_fail_start = 0, last_fail_end = 0; ++ struct device *dev = mmc_dev(host->mmc); ++ struct window pass_window = {0, 0, 0}; ++ int prev_fail_end = -1; ++ u8 i; ++ ++ if (!num_fails) ++ return ITAPDLY_LAST_INDEX >> 1; ++ ++ if (fail_window->length == ITAPDLY_LENGTH) { ++ dev_err(dev, "No passing ITAPDLY, return 0\n"); ++ return 0; ++ } ++ ++ first_fail_start = fail_window->start; ++ last_fail_end = fail_window[num_fails - 1].end; ++ ++ for (i = 0; i < num_fails; i++) { ++ start_fail = fail_window[i].start; ++ end_fail = fail_window[i].end; ++ pass_length = start_fail - (prev_fail_end + 1); ++ ++ if (pass_length > pass_window.length) { ++ pass_window.start = prev_fail_end + 1; ++ pass_window.length = pass_length; ++ } ++ prev_fail_end = end_fail; ++ } ++ ++ if (!circular_buffer) ++ pass_length = ITAPDLY_LAST_INDEX - last_fail_end; ++ else ++ pass_length = ITAPDLY_LAST_INDEX - last_fail_end + first_fail_start; ++ ++ if (pass_length > pass_window.length) { ++ pass_window.start = last_fail_end + 1; ++ pass_window.length = pass_length; ++ } ++ ++ if (!circular_buffer) ++ itap = pass_window.start + (pass_window.length >> 1); ++ else ++ itap = (pass_window.start + (pass_window.length >> 1)) % ITAPDLY_LENGTH; ++ ++ return (itap > ITAPDLY_LAST_INDEX) ? ITAPDLY_LAST_INDEX >> 1 : itap; ++} ++ + static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host, + u32 opcode) + { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); +- int cur_val, prev_val = 1, fail_len = 0, pass_window = 0, pass_len; +- u32 itap; ++ struct window fail_window[ITAPDLY_LENGTH]; ++ u8 curr_pass, itap; ++ u8 fail_index = 0; ++ u8 prev_pass = 1; ++ ++ memset(fail_window, 0, sizeof(fail_window)); + + /* Enable ITAPDLY */ + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYENA_MASK, + 1 << ITAPDLYENA_SHIFT); + +- for (itap = 0; itap < ITAP_MAX; itap++) { ++ for (itap = 0; itap < ITAPDLY_LENGTH; itap++) { + sdhci_am654_write_itapdly(sdhci_am654, itap); + +- cur_val = !mmc_send_tuning(host->mmc, opcode, NULL); +- if (cur_val && !prev_val) +- pass_window = itap; ++ curr_pass = !mmc_send_tuning(host->mmc, opcode, NULL); + +- if (!cur_val) +- fail_len++; ++ if (!curr_pass && prev_pass) ++ fail_window[fail_index].start = itap; + +- prev_val = cur_val; ++ if (!curr_pass) { ++ fail_window[fail_index].end = itap; ++ fail_window[fail_index].length++; ++ } ++ ++ if (curr_pass && !prev_pass) ++ fail_index++; ++ ++ prev_pass = curr_pass; + } +- /* +- * Having determined the length of the failing window and start of +- * the passing window calculate the length of the passing window and +- * set the final value halfway through it considering the range as a +- * circular buffer +- */ +- pass_len = ITAP_MAX - fail_len; +- itap = (pass_window + (pass_len >> 1)) % ITAP_MAX; ++ ++ if (fail_window[fail_index].length != 0) ++ fail_index++; ++ ++ itap = sdhci_am654_calculate_itap(host, fail_window, fail_index, ++ sdhci_am654->dll_enable); ++ + sdhci_am654_write_itapdly(sdhci_am654, itap); + + return 0; +-- +2.43.0 + diff --git a/queue-5.10/mmc-sdhci_am654-drop-lookup-for-deprecated-ti-otap-d.patch b/queue-5.10/mmc-sdhci_am654-drop-lookup-for-deprecated-ti-otap-d.patch new file mode 100644 index 00000000000..b9bd7bf3e27 --- /dev/null +++ b/queue-5.10/mmc-sdhci_am654-drop-lookup-for-deprecated-ti-otap-d.patch @@ -0,0 +1,102 @@ +From 0e1ca613331404a45dc7229eb8044cdfe7471f63 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Nov 2023 11:32:14 +0530 +Subject: mmc: sdhci_am654: Drop lookup for deprecated ti,otap-del-sel + +From: Vignesh Raghavendra + +[ Upstream commit 5cb2f9286a31f33dc732c57540838ad9339393ab ] + +ti,otap-del-sel has been deprecated since v5.7 and there are no users of +this property and no documentation in the DT bindings either. +Drop the fallback code looking for this property, this makes +sdhci_am654_get_otap_delay() much easier to read as all the TAP values +can be handled via a single iterator loop. + +Signed-off-by: Vignesh Raghavendra +Acked-by: Adrian Hunter +Link: https://lore.kernel.org/r/20231122060215.2074799-1-vigneshr@ti.com +Signed-off-by: Ulf Hansson +Stable-dep-of: 387c1bf7dce0 ("mmc: sdhci_am654: Add OTAP/ITAP delay enable") +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/sdhci_am654.c | 37 ++++++---------------------------- + 1 file changed, 6 insertions(+), 31 deletions(-) + +diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c +index 13bff543f7c06..847cd4e434721 100644 +--- a/drivers/mmc/host/sdhci_am654.c ++++ b/drivers/mmc/host/sdhci_am654.c +@@ -140,7 +140,6 @@ static const struct timing_data td[] = { + + struct sdhci_am654_data { + struct regmap *base; +- bool legacy_otapdly; + int otap_del_sel[ARRAY_SIZE(td)]; + int itap_del_sel[ARRAY_SIZE(td)]; + int clkbuf_sel; +@@ -278,11 +277,7 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) + sdhci_set_clock(host, clock); + + /* Setup DLL Output TAP delay */ +- if (sdhci_am654->legacy_otapdly) +- otap_del_sel = sdhci_am654->otap_del_sel[0]; +- else +- otap_del_sel = sdhci_am654->otap_del_sel[timing]; +- ++ otap_del_sel = sdhci_am654->otap_del_sel[timing]; + otap_del_ena = (timing > MMC_TIMING_UHS_SDR25) ? 1 : 0; + + mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; +@@ -324,10 +319,7 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host, + u32 mask, val; + + /* Setup DLL Output TAP delay */ +- if (sdhci_am654->legacy_otapdly) +- otap_del_sel = sdhci_am654->otap_del_sel[0]; +- else +- otap_del_sel = sdhci_am654->otap_del_sel[timing]; ++ otap_del_sel = sdhci_am654->otap_del_sel[timing]; + + mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; + val = (0x1 << OTAPDLYENA_SHIFT) | +@@ -652,32 +644,15 @@ static int sdhci_am654_get_otap_delay(struct sdhci_host *host, + int i; + int ret; + +- ret = device_property_read_u32(dev, td[MMC_TIMING_LEGACY].otap_binding, +- &sdhci_am654->otap_del_sel[MMC_TIMING_LEGACY]); +- if (ret) { +- /* +- * ti,otap-del-sel-legacy is mandatory, look for old binding +- * if not found. +- */ +- ret = device_property_read_u32(dev, "ti,otap-del-sel", +- &sdhci_am654->otap_del_sel[0]); +- if (ret) { +- dev_err(dev, "Couldn't find otap-del-sel\n"); +- +- return ret; +- } +- +- dev_info(dev, "Using legacy binding ti,otap-del-sel\n"); +- sdhci_am654->legacy_otapdly = true; +- +- return 0; +- } +- + for (i = MMC_TIMING_LEGACY; i <= MMC_TIMING_MMC_HS400; i++) { + + ret = device_property_read_u32(dev, td[i].otap_binding, + &sdhci_am654->otap_del_sel[i]); + if (ret) { ++ if (i == MMC_TIMING_LEGACY) { ++ dev_err(dev, "Couldn't find mandatory ti,otap-del-sel-legacy\n"); ++ return ret; ++ } + dev_dbg(dev, "Couldn't find %s\n", + td[i].otap_binding); + /* +-- +2.43.0 + diff --git a/queue-5.10/mmc-sdhci_am654-fix-itapdly-for-hs400-timing.patch b/queue-5.10/mmc-sdhci_am654-fix-itapdly-for-hs400-timing.patch new file mode 100644 index 00000000000..91c9516703c --- /dev/null +++ b/queue-5.10/mmc-sdhci_am654-fix-itapdly-for-hs400-timing.patch @@ -0,0 +1,59 @@ +From b8633da72511f88b5e6c6e9662c397cc025ddd62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Mar 2024 17:38:37 -0500 +Subject: mmc: sdhci_am654: Fix ITAPDLY for HS400 timing + +From: Judith Mendez + +[ Upstream commit d3182932bb070e7518411fd165e023f82afd7d25 ] + +While STRB is currently used for DATA and CRC responses, the CMD +responses from the device to the host still require ITAPDLY for +HS400 timing. + +Currently what is stored for HS400 is the ITAPDLY from High Speed +mode which is incorrect. The ITAPDLY for HS400 speed mode should +be the same as ITAPDLY as HS200 timing after tuning is executed. +Add the functionality to save ITAPDLY from HS200 tuning and save +as HS400 ITAPDLY. + +Fixes: a161c45f2979 ("mmc: sdhci_am654: Enable DLL only for some speed modes") +Signed-off-by: Judith Mendez +Acked-by: Adrian Hunter +Link: https://lore.kernel.org/r/20240320223837.959900-8-jm@ti.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/sdhci_am654.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c +index 879ead07f8022..9d74ee989cb72 100644 +--- a/drivers/mmc/host/sdhci_am654.c ++++ b/drivers/mmc/host/sdhci_am654.c +@@ -300,6 +300,12 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) + if (timing > MMC_TIMING_UHS_SDR25 && clock >= CLOCK_TOO_SLOW_HZ) { + sdhci_am654_setup_dll(host, clock); + sdhci_am654->dll_enable = true; ++ ++ if (timing == MMC_TIMING_MMC_HS400) { ++ sdhci_am654->itap_del_ena[timing] = 0x1; ++ sdhci_am654->itap_del_sel[timing] = sdhci_am654->itap_del_sel[timing - 1]; ++ } ++ + sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing], + sdhci_am654->itap_del_ena[timing]); + } else { +@@ -530,6 +536,9 @@ static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host, + + sdhci_am654_write_itapdly(sdhci_am654, itap, sdhci_am654->itap_del_ena[timing]); + ++ /* Save ITAPDLY */ ++ sdhci_am654->itap_del_sel[timing] = itap; ++ + return 0; + } + +-- +2.43.0 + diff --git a/queue-5.10/mmc-sdhci_am654-write-itapdly-for-ddr52-timing.patch b/queue-5.10/mmc-sdhci_am654-write-itapdly-for-ddr52-timing.patch new file mode 100644 index 00000000000..a58dfec0a15 --- /dev/null +++ b/queue-5.10/mmc-sdhci_am654-write-itapdly-for-ddr52-timing.patch @@ -0,0 +1,39 @@ +From c57330ac305c53ba0f09a1e6b9b38322cdfb4d94 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Mar 2024 17:38:32 -0500 +Subject: mmc: sdhci_am654: Write ITAPDLY for DDR52 timing + +From: Judith Mendez + +[ Upstream commit d465234493bb6ad1b9c10a0c9ef9881b8d85081a ] + +For DDR52 timing, DLL is enabled but tuning is not carried +out, therefore the ITAPDLY value in PHY CTRL 4 register is +not correct. Fix this by writing ITAPDLY after enabling DLL. + +Fixes: a161c45f2979 ("mmc: sdhci_am654: Enable DLL only for some speed modes") +Signed-off-by: Judith Mendez +Reviewed-by: Andrew Davis +Acked-by: Adrian Hunter +Link: https://lore.kernel.org/r/20240320223837.959900-3-jm@ti.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/sdhci_am654.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c +index 2e302c2b0ac12..13bff543f7c06 100644 +--- a/drivers/mmc/host/sdhci_am654.c ++++ b/drivers/mmc/host/sdhci_am654.c +@@ -304,6 +304,7 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) + if (timing > MMC_TIMING_UHS_SDR25 && clock >= CLOCK_TOO_SLOW_HZ) { + sdhci_am654_setup_dll(host, clock); + sdhci_am654->dll_enable = true; ++ sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing]); + } else { + sdhci_am654_setup_delay_chain(sdhci_am654, timing); + sdhci_am654->dll_enable = false; +-- +2.43.0 + diff --git a/queue-5.10/net-fec-avoid-lock-evasion-when-reading-pps_enable.patch b/queue-5.10/net-fec-avoid-lock-evasion-when-reading-pps_enable.patch new file mode 100644 index 00000000000..05847ecdba9 --- /dev/null +++ b/queue-5.10/net-fec-avoid-lock-evasion-when-reading-pps_enable.patch @@ -0,0 +1,62 @@ +From a79ad2e7f60efada05719ec31752d55f47e0c640 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 May 2024 10:38:00 +0800 +Subject: net: fec: avoid lock evasion when reading pps_enable + +From: Wei Fang + +[ Upstream commit 3b1c92f8e5371700fada307cc8fd2c51fa7bc8c1 ] + +The assignment of pps_enable is protected by tmreg_lock, but the read +operation of pps_enable is not. So the Coverity tool reports a lock +evasion warning which may cause data race to occur when running in a +multithread environment. Although this issue is almost impossible to +occur, we'd better fix it, at least it seems more logically reasonable, +and it also prevents Coverity from continuing to issue warnings. + +Fixes: 278d24047891 ("net: fec: ptp: Enable PPS output based on ptp clock") +Signed-off-by: Wei Fang +Link: https://lore.kernel.org/r/20240521023800.17102-1-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_ptp.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index c5ae673005908..780fbb3e1ed06 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -103,14 +103,13 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable) + u64 ns; + val = 0; + +- if (fep->pps_enable == enable) +- return 0; +- +- fep->pps_channel = DEFAULT_PPS_CHANNEL; +- fep->reload_period = PPS_OUPUT_RELOAD_PERIOD; +- + spin_lock_irqsave(&fep->tmreg_lock, flags); + ++ if (fep->pps_enable == enable) { ++ spin_unlock_irqrestore(&fep->tmreg_lock, flags); ++ return 0; ++ } ++ + if (enable) { + /* clear capture or output compare interrupt status if have. + */ +@@ -441,6 +440,9 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, + int ret = 0; + + if (rq->type == PTP_CLK_REQ_PPS) { ++ fep->pps_channel = DEFAULT_PPS_CHANNEL; ++ fep->reload_period = PPS_OUPUT_RELOAD_PERIOD; ++ + ret = fec_ptp_enable_pps(fep, on); + + return ret; +-- +2.43.0 + diff --git a/queue-5.10/nfc-nci-fix-handling-of-zero-length-payload-packets-.patch b/queue-5.10/nfc-nci-fix-handling-of-zero-length-payload-packets-.patch new file mode 100644 index 00000000000..5a3bd7630a9 --- /dev/null +++ b/queue-5.10/nfc-nci-fix-handling-of-zero-length-payload-packets-.patch @@ -0,0 +1,42 @@ +From c91fbcc7d49e4813f3d4fd148f9fbc728c970d62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 May 2024 00:34:42 +0900 +Subject: nfc: nci: Fix handling of zero-length payload packets in + nci_rx_work() + +From: Ryosuke Yasuoka + +[ Upstream commit 6671e352497ca4bb07a96c48e03907065ff77d8a ] + +When nci_rx_work() receives a zero-length payload packet, it should not +discard the packet and exit the loop. Instead, it should continue +processing subsequent packets. + +Fixes: d24b03535e5e ("nfc: nci: Fix uninit-value in nci_dev_up and nci_ntf_packet") +Signed-off-by: Ryosuke Yasuoka +Reviewed-by: Simon Horman +Reviewed-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20240521153444.535399-1-ryasuoka@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/nfc/nci/core.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index ada7f32d03e48..a7e6b8b272505 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -1517,8 +1517,7 @@ static void nci_rx_work(struct work_struct *work) + + if (!nci_valid_size(skb)) { + kfree_skb(skb); +- kcov_remote_stop(); +- break; ++ continue; + } + + /* Process frame */ +-- +2.43.0 + diff --git a/queue-5.10/nfc-nci-fix-kcov-check-in-nci_rx_work.patch b/queue-5.10/nfc-nci-fix-kcov-check-in-nci_rx_work.patch new file mode 100644 index 00000000000..91af6d0303e --- /dev/null +++ b/queue-5.10/nfc-nci-fix-kcov-check-in-nci_rx_work.patch @@ -0,0 +1,45 @@ +From 404a205cc5df2ce4f4e56166badc3c3e3c681be6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 May 2024 19:36:49 +0900 +Subject: nfc: nci: Fix kcov check in nci_rx_work() + +From: Tetsuo Handa + +[ Upstream commit 19e35f24750ddf860c51e51c68cf07ea181b4881 ] + +Commit 7e8cdc97148c ("nfc: Add KCOV annotations") added +kcov_remote_start_common()/kcov_remote_stop() pair into nci_rx_work(), +with an assumption that kcov_remote_stop() is called upon continue of +the for loop. But commit d24b03535e5e ("nfc: nci: Fix uninit-value in +nci_dev_up and nci_ntf_packet") forgot to call kcov_remote_stop() before +break of the for loop. + +Reported-by: syzbot +Closes: https://syzkaller.appspot.com/bug?extid=0438378d6f157baae1a2 +Fixes: d24b03535e5e ("nfc: nci: Fix uninit-value in nci_dev_up and nci_ntf_packet") +Suggested-by: Andrey Konovalov +Signed-off-by: Tetsuo Handa +Reviewed-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/6d10f829-5a0c-405a-b39a-d7266f3a1a0b@I-love.SAKURA.ne.jp +Signed-off-by: Jakub Kicinski +Stable-dep-of: 6671e352497c ("nfc: nci: Fix handling of zero-length payload packets in nci_rx_work()") +Signed-off-by: Sasha Levin +--- + net/nfc/nci/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index 7b3f3d6285004..ada7f32d03e48 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -1517,6 +1517,7 @@ static void nci_rx_work(struct work_struct *work) + + if (!nci_valid_size(skb)) { + kfree_skb(skb); ++ kcov_remote_stop(); + break; + } + +-- +2.43.0 + diff --git a/queue-5.10/nfc-nci-fix-uninit-value-in-nci_rx_work.patch b/queue-5.10/nfc-nci-fix-uninit-value-in-nci_rx_work.patch new file mode 100644 index 00000000000..cd2340a1822 --- /dev/null +++ b/queue-5.10/nfc-nci-fix-uninit-value-in-nci_rx_work.patch @@ -0,0 +1,63 @@ +From 3d13ce5fe4463b901a223e04f6ac6514e76676b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 19 May 2024 18:43:03 +0900 +Subject: nfc: nci: Fix uninit-value in nci_rx_work + +From: Ryosuke Yasuoka + +[ Upstream commit e4a87abf588536d1cdfb128595e6e680af5cf3ed ] + +syzbot reported the following uninit-value access issue [1] + +nci_rx_work() parses received packet from ndev->rx_q. It should be +validated header size, payload size and total packet size before +processing the packet. If an invalid packet is detected, it should be +silently discarded. + +Fixes: d24b03535e5e ("nfc: nci: Fix uninit-value in nci_dev_up and nci_ntf_packet") +Reported-and-tested-by: syzbot+d7b4dc6cd50410152534@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=d7b4dc6cd50410152534 [1] +Signed-off-by: Ryosuke Yasuoka +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/nfc/nci/core.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index d8002065baaef..7b3f3d6285004 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -1452,6 +1452,19 @@ int nci_core_ntf_packet(struct nci_dev *ndev, __u16 opcode, + ndev->ops->n_core_ops); + } + ++static bool nci_valid_size(struct sk_buff *skb) ++{ ++ BUILD_BUG_ON(NCI_CTRL_HDR_SIZE != NCI_DATA_HDR_SIZE); ++ unsigned int hdr_size = NCI_CTRL_HDR_SIZE; ++ ++ if (skb->len < hdr_size || ++ !nci_plen(skb->data) || ++ skb->len < hdr_size + nci_plen(skb->data)) { ++ return false; ++ } ++ return true; ++} ++ + /* ---- NCI TX Data worker thread ---- */ + + static void nci_tx_work(struct work_struct *work) +@@ -1502,7 +1515,7 @@ static void nci_rx_work(struct work_struct *work) + nfc_send_to_raw_sock(ndev->nfc_dev, skb, + RAW_PAYLOAD_NCI, NFC_DIRECTION_RX); + +- if (!nci_plen(skb->data)) { ++ if (!nci_valid_size(skb)) { + kfree_skb(skb); + break; + } +-- +2.43.0 + diff --git a/queue-5.10/null_blk-fix-the-warning-modpost-missing-module_desc.patch b/queue-5.10/null_blk-fix-the-warning-modpost-missing-module_desc.patch new file mode 100644 index 00000000000..972af3ca1f2 --- /dev/null +++ b/queue-5.10/null_blk-fix-the-warning-modpost-missing-module_desc.patch @@ -0,0 +1,34 @@ +From 284bfde64da056e205e085bda608e515291a0445 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 May 2024 09:55:38 +0200 +Subject: null_blk: Fix the WARNING: modpost: missing MODULE_DESCRIPTION() + +From: Zhu Yanjun + +[ Upstream commit 9e6727f824edcdb8fdd3e6e8a0862eb49546e1cd ] + +No functional changes intended. + +Fixes: f2298c0403b0 ("null_blk: multi queue aware block test driver") +Signed-off-by: Zhu Yanjun +Reviewed-by: Chaitanya Kulkarni +Link: https://lore.kernel.org/r/20240506075538.6064-1-yanjun.zhu@linux.dev +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/null_blk/main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c +index ee1c3f476a3a0..862a9420df526 100644 +--- a/drivers/block/null_blk/main.c ++++ b/drivers/block/null_blk/main.c +@@ -2040,4 +2040,5 @@ module_init(null_init); + module_exit(null_exit); + + MODULE_AUTHOR("Jens Axboe "); ++MODULE_DESCRIPTION("multi queue aware block test driver"); + MODULE_LICENSE("GPL"); +-- +2.43.0 + diff --git a/queue-5.10/openvswitch-set-the-skbuff-pkt_type-for-proper-pmtud.patch b/queue-5.10/openvswitch-set-the-skbuff-pkt_type-for-proper-pmtud.patch new file mode 100644 index 00000000000..62381edc3de --- /dev/null +++ b/queue-5.10/openvswitch-set-the-skbuff-pkt_type-for-proper-pmtud.patch @@ -0,0 +1,101 @@ +From 62d52fb0fd2896218550c72f39dcc177ab07dfa2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 May 2024 16:09:41 -0400 +Subject: openvswitch: Set the skbuff pkt_type for proper pmtud support. + +From: Aaron Conole + +[ Upstream commit 30a92c9e3d6b073932762bef2ac66f4ee784c657 ] + +Open vSwitch is originally intended to switch at layer 2, only dealing with +Ethernet frames. With the introduction of l3 tunnels support, it crossed +into the realm of needing to care a bit about some routing details when +making forwarding decisions. If an oversized packet would need to be +fragmented during this forwarding decision, there is a chance for pmtu +to get involved and generate a routing exception. This is gated by the +skbuff->pkt_type field. + +When a flow is already loaded into the openvswitch module this field is +set up and transitioned properly as a packet moves from one port to +another. In the case that a packet execute is invoked after a flow is +newly installed this field is not properly initialized. This causes the +pmtud mechanism to omit sending the required exception messages across +the tunnel boundary and a second attempt needs to be made to make sure +that the routing exception is properly setup. To fix this, we set the +outgoing packet's pkt_type to PACKET_OUTGOING, since it can only get +to the openvswitch module via a port device or packet command. + +Even for bridge ports as users, the pkt_type needs to be reset when +doing the transmit as the packet is truly outgoing and routing needs +to get involved post packet transformations, in the case of +VXLAN/GENEVE/udp-tunnel packets. In general, the pkt_type on output +gets ignored, since we go straight to the driver, but in the case of +tunnel ports they go through IP routing layer. + +This issue is periodically encountered in complex setups, such as large +openshift deployments, where multiple sets of tunnel traversal occurs. +A way to recreate this is with the ovn-heater project that can setup +a networking environment which mimics such large deployments. We need +larger environments for this because we need to ensure that flow +misses occur. In these environment, without this patch, we can see: + + ./ovn_cluster.sh start + podman exec ovn-chassis-1 ip r a 170.168.0.5/32 dev eth1 mtu 1200 + podman exec ovn-chassis-1 ip netns exec sw01p1 ip r flush cache + podman exec ovn-chassis-1 ip netns exec sw01p1 \ + ping 21.0.0.3 -M do -s 1300 -c2 + PING 21.0.0.3 (21.0.0.3) 1300(1328) bytes of data. + From 21.0.0.3 icmp_seq=2 Frag needed and DF set (mtu = 1142) + + --- 21.0.0.3 ping statistics --- + ... + +Using tcpdump, we can also see the expected ICMP FRAG_NEEDED message is not +sent into the server. + +With this patch, setting the pkt_type, we see the following: + + podman exec ovn-chassis-1 ip netns exec sw01p1 \ + ping 21.0.0.3 -M do -s 1300 -c2 + PING 21.0.0.3 (21.0.0.3) 1300(1328) bytes of data. + From 21.0.0.3 icmp_seq=1 Frag needed and DF set (mtu = 1222) + ping: local error: message too long, mtu=1222 + + --- 21.0.0.3 ping statistics --- + ... + +In this case, the first ping request receives the FRAG_NEEDED message and +a local routing exception is created. + +Tested-by: Jaime Caamano +Reported-at: https://issues.redhat.com/browse/FDP-164 +Fixes: 58264848a5a7 ("openvswitch: Add vxlan tunneling support.") +Signed-off-by: Aaron Conole +Acked-by: Eelco Chaudron +Link: https://lore.kernel.org/r/20240516200941.16152-1-aconole@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/openvswitch/actions.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c +index 80fee9d118eec..4095456f413df 100644 +--- a/net/openvswitch/actions.c ++++ b/net/openvswitch/actions.c +@@ -923,6 +923,12 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port, + pskb_trim(skb, ovs_mac_header_len(key)); + } + ++ /* Need to set the pkt_type to involve the routing layer. The ++ * packet movement through the OVS datapath doesn't generally ++ * use routing, but this is needed for tunnel cases. ++ */ ++ skb->pkt_type = PACKET_OUTGOING; ++ + if (likely(!mru || + (skb->len <= mru + vport->dev->hard_header_len))) { + ovs_vport_send(vport, skb, ovs_key_mac_proto(key)); +-- +2.43.0 + diff --git a/queue-5.10/params-lift-param_set_uint_minmax-to-common-code.patch b/queue-5.10/params-lift-param_set_uint_minmax-to-common-code.patch new file mode 100644 index 00000000000..f3d58c16a6d --- /dev/null +++ b/queue-5.10/params-lift-param_set_uint_minmax-to-common-code.patch @@ -0,0 +1,99 @@ +From 7ab9191f9b7519de7489afbd0da823ec1d4e687f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Jun 2021 14:19:33 -0700 +Subject: params: lift param_set_uint_minmax to common code + +From: Sagi Grimberg + +[ Upstream commit 2a14c9ae15a38148484a128b84bff7e9ffd90d68 ] + +It is a useful helper hence move it to common code so others can enjoy +it. + +Suggested-by: Christoph Hellwig +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Hannes Reinecke +Signed-off-by: Sagi Grimberg +Signed-off-by: Christoph Hellwig +Stable-dep-of: 3ebc46ca8675 ("tcp: Fix shift-out-of-bounds in dctcp_update_alpha().") +Signed-off-by: Sasha Levin +--- + include/linux/moduleparam.h | 2 ++ + kernel/params.c | 18 ++++++++++++++++++ + net/sunrpc/xprtsock.c | 18 ------------------ + 3 files changed, 20 insertions(+), 18 deletions(-) + +diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h +index 6388eb9734a51..f25a1c4843903 100644 +--- a/include/linux/moduleparam.h ++++ b/include/linux/moduleparam.h +@@ -431,6 +431,8 @@ extern int param_get_int(char *buffer, const struct kernel_param *kp); + extern const struct kernel_param_ops param_ops_uint; + extern int param_set_uint(const char *val, const struct kernel_param *kp); + extern int param_get_uint(char *buffer, const struct kernel_param *kp); ++int param_set_uint_minmax(const char *val, const struct kernel_param *kp, ++ unsigned int min, unsigned int max); + #define param_check_uint(name, p) __param_check(name, p, unsigned int) + + extern const struct kernel_param_ops param_ops_long; +diff --git a/kernel/params.c b/kernel/params.c +index 164d79330849a..eb00abef7076a 100644 +--- a/kernel/params.c ++++ b/kernel/params.c +@@ -243,6 +243,24 @@ STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul); + STANDARD_PARAM_DEF(ullong, unsigned long long, "%llu", kstrtoull); + STANDARD_PARAM_DEF(hexint, unsigned int, "%#08x", kstrtouint); + ++int param_set_uint_minmax(const char *val, const struct kernel_param *kp, ++ unsigned int min, unsigned int max) ++{ ++ unsigned int num; ++ int ret; ++ ++ if (!val) ++ return -EINVAL; ++ ret = kstrtouint(val, 0, &num); ++ if (ret) ++ return ret; ++ if (num < min || num > max) ++ return -EINVAL; ++ *((unsigned int *)kp->arg) = num; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(param_set_uint_minmax); ++ + int param_set_charp(const char *val, const struct kernel_param *kp) + { + if (strlen(val) > 1024) { +diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c +index ae5b5380f0f03..0666f981618a2 100644 +--- a/net/sunrpc/xprtsock.c ++++ b/net/sunrpc/xprtsock.c +@@ -3166,24 +3166,6 @@ void cleanup_socket_xprt(void) + xprt_unregister_transport(&xs_bc_tcp_transport); + } + +-static int param_set_uint_minmax(const char *val, +- const struct kernel_param *kp, +- unsigned int min, unsigned int max) +-{ +- unsigned int num; +- int ret; +- +- if (!val) +- return -EINVAL; +- ret = kstrtouint(val, 0, &num); +- if (ret) +- return ret; +- if (num < min || num > max) +- return -EINVAL; +- *((unsigned int *)kp->arg) = num; +- return 0; +-} +- + static int param_set_portnr(const char *val, const struct kernel_param *kp) + { + return param_set_uint_minmax(val, kp, +-- +2.43.0 + diff --git a/queue-5.10/powerpc-pseries-add-failure-related-checks-for-h_get.patch b/queue-5.10/powerpc-pseries-add-failure-related-checks-for-h_get.patch new file mode 100644 index 00000000000..12f253270c3 --- /dev/null +++ b/queue-5.10/powerpc-pseries-add-failure-related-checks-for-h_get.patch @@ -0,0 +1,86 @@ +From f276ed018331b56de7121edab2f5398c082ab693 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Apr 2024 14:50:47 +0530 +Subject: powerpc/pseries: Add failure related checks for h_get_mpp and + h_get_ppp + +From: Shrikanth Hegde + +[ Upstream commit 6d4341638516bf97b9a34947e0bd95035a8230a5 ] + +Couple of Minor fixes: + +- hcall return values are long. Fix that for h_get_mpp, h_get_ppp and +parse_ppp_data + +- If hcall fails, values set should be at-least zero. It shouldn't be +uninitialized values. Fix that for h_get_mpp and h_get_ppp + +Signed-off-by: Shrikanth Hegde +Signed-off-by: Michael Ellerman +Link: https://msgid.link/20240412092047.455483-3-sshegde@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/include/asm/hvcall.h | 2 +- + arch/powerpc/platforms/pseries/lpar.c | 6 +++--- + arch/powerpc/platforms/pseries/lparcfg.c | 6 +++--- + 3 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h +index 00c8cda1c9c31..1a60188f74ad8 100644 +--- a/arch/powerpc/include/asm/hvcall.h ++++ b/arch/powerpc/include/asm/hvcall.h +@@ -494,7 +494,7 @@ struct hvcall_mpp_data { + unsigned long backing_mem; + }; + +-int h_get_mpp(struct hvcall_mpp_data *); ++long h_get_mpp(struct hvcall_mpp_data *mpp_data); + + struct hvcall_mpp_x_data { + unsigned long coalesced_bytes; +diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c +index 4a3425fb19398..aed67f1a1bc56 100644 +--- a/arch/powerpc/platforms/pseries/lpar.c ++++ b/arch/powerpc/platforms/pseries/lpar.c +@@ -1883,10 +1883,10 @@ void __trace_hcall_exit(long opcode, long retval, unsigned long *retbuf) + * h_get_mpp + * H_GET_MPP hcall returns info in 7 parms + */ +-int h_get_mpp(struct hvcall_mpp_data *mpp_data) ++long h_get_mpp(struct hvcall_mpp_data *mpp_data) + { +- int rc; +- unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; ++ unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = {0}; ++ long rc; + + rc = plpar_hcall9(H_GET_MPP, retbuf); + +diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c +index a7d4e25ae82a1..e0c5fc9ab242e 100644 +--- a/arch/powerpc/platforms/pseries/lparcfg.c ++++ b/arch/powerpc/platforms/pseries/lparcfg.c +@@ -112,8 +112,8 @@ struct hvcall_ppp_data { + */ + static unsigned int h_get_ppp(struct hvcall_ppp_data *ppp_data) + { +- unsigned long rc; +- unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; ++ unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = {0}; ++ long rc; + + rc = plpar_hcall9(H_GET_PPP, retbuf); + +@@ -192,7 +192,7 @@ static void parse_ppp_data(struct seq_file *m) + struct hvcall_ppp_data ppp_data; + struct device_node *root; + const __be32 *perf_level; +- int rc; ++ long rc; + + rc = h_get_ppp(&ppp_data); + if (rc) +-- +2.43.0 + diff --git a/queue-5.10/regulator-bd71828-don-t-overwrite-runtime-voltages.patch b/queue-5.10/regulator-bd71828-don-t-overwrite-runtime-voltages.patch new file mode 100644 index 00000000000..d3a800df4fe --- /dev/null +++ b/queue-5.10/regulator-bd71828-don-t-overwrite-runtime-voltages.patch @@ -0,0 +1,186 @@ +From 5652070e0948609dba092b3896fde386462ba449 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 May 2024 11:54:41 +0300 +Subject: regulator: bd71828: Don't overwrite runtime voltages + +From: Matti Vaittinen + +[ Upstream commit 0f9f7c63c415e287cd57b5c98be61eb320dedcfc ] + +Some of the regulators on the BD71828 have common voltage setting for +RUN/SUSPEND/IDLE/LPSR states. The enable control can be set for each +state though. + +The driver allows setting the voltage values for these states via +device-tree. As a side effect, setting the voltages for +SUSPEND/IDLE/LPSR will also change the RUN level voltage which is not +desired and can break the system. + +The comment in code reflects this behaviour, but it is likely to not +make people any happier. The right thing to do is to allow setting the +enable/disable state at SUSPEND/IDLE/LPSR via device-tree, but to +disallow setting state specific voltages for those regulators. + +BUCK1 is a bit different. It only shares the SUSPEND and LPSR state +voltages. The former behaviour of allowing to silently overwrite the +SUSPEND state voltage by LPSR state voltage is also changed here so that +the SUSPEND voltage is prioritized over LPSR voltage. + +Prevent setting PMIC state specific voltages for regulators which do not +support it. + +Signed-off-by: Matti Vaittinen +Fixes: 522498f8cb8c ("regulator: bd71828: Basic support for ROHM bd71828 PMIC regulators") +Link: https://msgid.link/r/e1883ae1e3ae5668f1030455d4750923561f3d68.1715848512.git.mazziesaccount@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/bd71828-regulator.c | 58 +-------------------------- + 1 file changed, 2 insertions(+), 56 deletions(-) + +diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c +index 85c0b90009639..fc08f6f61655e 100644 +--- a/drivers/regulator/bd71828-regulator.c ++++ b/drivers/regulator/bd71828-regulator.c +@@ -234,14 +234,11 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + .suspend_reg = BD71828_REG_BUCK1_SUSP_VOLT, + .suspend_mask = BD71828_MASK_BUCK1267_VOLT, + .suspend_on_mask = BD71828_MASK_SUSP_EN, +- .lpsr_on_mask = BD71828_MASK_LPSR_EN, + /* + * LPSR voltage is same as SUSPEND voltage. Allow +- * setting it so that regulator can be set enabled at +- * LPSR state ++ * only enabling/disabling regulator for LPSR state + */ +- .lpsr_reg = BD71828_REG_BUCK1_SUSP_VOLT, +- .lpsr_mask = BD71828_MASK_BUCK1267_VOLT, ++ .lpsr_on_mask = BD71828_MASK_LPSR_EN, + }, + .reg_inits = buck1_inits, + .reg_init_amnt = ARRAY_SIZE(buck1_inits), +@@ -312,13 +309,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_BUCK3_VOLT, +- .idle_reg = BD71828_REG_BUCK3_VOLT, +- .suspend_reg = BD71828_REG_BUCK3_VOLT, +- .lpsr_reg = BD71828_REG_BUCK3_VOLT, + .run_mask = BD71828_MASK_BUCK3_VOLT, +- .idle_mask = BD71828_MASK_BUCK3_VOLT, +- .suspend_mask = BD71828_MASK_BUCK3_VOLT, +- .lpsr_mask = BD71828_MASK_BUCK3_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -353,13 +344,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_BUCK4_VOLT, +- .idle_reg = BD71828_REG_BUCK4_VOLT, +- .suspend_reg = BD71828_REG_BUCK4_VOLT, +- .lpsr_reg = BD71828_REG_BUCK4_VOLT, + .run_mask = BD71828_MASK_BUCK4_VOLT, +- .idle_mask = BD71828_MASK_BUCK4_VOLT, +- .suspend_mask = BD71828_MASK_BUCK4_VOLT, +- .lpsr_mask = BD71828_MASK_BUCK4_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -394,13 +379,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_BUCK5_VOLT, +- .idle_reg = BD71828_REG_BUCK5_VOLT, +- .suspend_reg = BD71828_REG_BUCK5_VOLT, +- .lpsr_reg = BD71828_REG_BUCK5_VOLT, + .run_mask = BD71828_MASK_BUCK5_VOLT, +- .idle_mask = BD71828_MASK_BUCK5_VOLT, +- .suspend_mask = BD71828_MASK_BUCK5_VOLT, +- .lpsr_mask = BD71828_MASK_BUCK5_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -509,13 +488,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO1_VOLT, +- .idle_reg = BD71828_REG_LDO1_VOLT, +- .suspend_reg = BD71828_REG_LDO1_VOLT, +- .lpsr_reg = BD71828_REG_LDO1_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, +- .idle_mask = BD71828_MASK_LDO_VOLT, +- .suspend_mask = BD71828_MASK_LDO_VOLT, +- .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -549,13 +522,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO2_VOLT, +- .idle_reg = BD71828_REG_LDO2_VOLT, +- .suspend_reg = BD71828_REG_LDO2_VOLT, +- .lpsr_reg = BD71828_REG_LDO2_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, +- .idle_mask = BD71828_MASK_LDO_VOLT, +- .suspend_mask = BD71828_MASK_LDO_VOLT, +- .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -589,13 +556,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO3_VOLT, +- .idle_reg = BD71828_REG_LDO3_VOLT, +- .suspend_reg = BD71828_REG_LDO3_VOLT, +- .lpsr_reg = BD71828_REG_LDO3_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, +- .idle_mask = BD71828_MASK_LDO_VOLT, +- .suspend_mask = BD71828_MASK_LDO_VOLT, +- .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -630,13 +591,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO4_VOLT, +- .idle_reg = BD71828_REG_LDO4_VOLT, +- .suspend_reg = BD71828_REG_LDO4_VOLT, +- .lpsr_reg = BD71828_REG_LDO4_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, +- .idle_mask = BD71828_MASK_LDO_VOLT, +- .suspend_mask = BD71828_MASK_LDO_VOLT, +- .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -671,13 +626,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO5_VOLT, +- .idle_reg = BD71828_REG_LDO5_VOLT, +- .suspend_reg = BD71828_REG_LDO5_VOLT, +- .lpsr_reg = BD71828_REG_LDO5_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, +- .idle_mask = BD71828_MASK_LDO_VOLT, +- .suspend_mask = BD71828_MASK_LDO_VOLT, +- .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -736,9 +685,6 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + .suspend_reg = BD71828_REG_LDO7_VOLT, + .lpsr_reg = BD71828_REG_LDO7_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, +- .idle_mask = BD71828_MASK_LDO_VOLT, +- .suspend_mask = BD71828_MASK_LDO_VOLT, +- .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +-- +2.43.0 + diff --git a/queue-5.10/riscv-cleanup-stacktrace.patch b/queue-5.10/riscv-cleanup-stacktrace.patch new file mode 100644 index 00000000000..2778dfa40d0 --- /dev/null +++ b/queue-5.10/riscv-cleanup-stacktrace.patch @@ -0,0 +1,123 @@ +From 937215a95b66766cc984c02d2a9f70d160523364 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Nov 2020 14:42:21 +0800 +Subject: riscv: Cleanup stacktrace +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kefeng Wang + +[ Upstream commit 99c168fccbfedbc10ce1cb2dcb9eb790c478d833 ] + +1. add asm/stacktrace.h for walk_stackframe and struct stackframe +2. remove unnecessary blank lines in stacktrace.c +3. fix warning "no previous prototype for ‘fill_callchain’" + +Signed-off-by: Kefeng Wang +Signed-off-by: Palmer Dabbelt +Stable-dep-of: a2a4d4a6a0bf ("riscv: stacktrace: fixed walk_stackframe()") +Signed-off-by: Sasha Levin +--- + arch/riscv/include/asm/stacktrace.h | 17 +++++++++++++++++ + arch/riscv/kernel/perf_callchain.c | 10 ++-------- + arch/riscv/kernel/stacktrace.c | 9 ++------- + 3 files changed, 21 insertions(+), 15 deletions(-) + create mode 100644 arch/riscv/include/asm/stacktrace.h + +diff --git a/arch/riscv/include/asm/stacktrace.h b/arch/riscv/include/asm/stacktrace.h +new file mode 100644 +index 0000000000000..f09c1e31bde9c +--- /dev/null ++++ b/arch/riscv/include/asm/stacktrace.h +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef _ASM_RISCV_STACKTRACE_H ++#define _ASM_RISCV_STACKTRACE_H ++ ++#include ++#include ++ ++struct stackframe { ++ unsigned long fp; ++ unsigned long ra; ++}; ++ ++extern void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, ++ bool (*fn)(unsigned long, void *), void *arg); ++ ++#endif /* _ASM_RISCV_STACKTRACE_H */ +diff --git a/arch/riscv/kernel/perf_callchain.c b/arch/riscv/kernel/perf_callchain.c +index fb02811df7143..8b4bd418b3434 100644 +--- a/arch/riscv/kernel/perf_callchain.c ++++ b/arch/riscv/kernel/perf_callchain.c +@@ -4,11 +4,7 @@ + #include + #include + +-/* Kernel callchain */ +-struct stackframe { +- unsigned long fp; +- unsigned long ra; +-}; ++#include + + /* + * Get the return address for a single stackframe and return a pointer to the +@@ -75,13 +71,11 @@ void perf_callchain_user(struct perf_callchain_entry_ctx *entry, + fp = user_backtrace(entry, fp, 0); + } + +-bool fill_callchain(unsigned long pc, void *entry) ++static bool fill_callchain(unsigned long pc, void *entry) + { + return perf_callchain_store(entry, pc) == 0; + } + +-void notrace walk_stackframe(struct task_struct *task, +- struct pt_regs *regs, bool (*fn)(unsigned long, void *), void *arg); + void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) + { +diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c +index 9c34735c1e771..cd14309fff0d9 100644 +--- a/arch/riscv/kernel/stacktrace.c ++++ b/arch/riscv/kernel/stacktrace.c +@@ -12,15 +12,12 @@ + #include + #include + ++#include ++ + register unsigned long sp_in_global __asm__("sp"); + + #ifdef CONFIG_FRAME_POINTER + +-struct stackframe { +- unsigned long fp; +- unsigned long ra; +-}; +- + void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, + bool (*fn)(unsigned long, void *), void *arg) + { +@@ -102,7 +99,6 @@ void notrace walk_stackframe(struct task_struct *task, + + #endif /* CONFIG_FRAME_POINTER */ + +- + static bool print_trace_address(unsigned long pc, void *arg) + { + const char *loglvl = arg; +@@ -136,7 +132,6 @@ unsigned long get_wchan(struct task_struct *task) + return pc; + } + +- + #ifdef CONFIG_STACKTRACE + + static bool __save_trace(unsigned long pc, void *arg, bool nosched) +-- +2.43.0 + diff --git a/queue-5.10/riscv-stacktrace-fixed-walk_stackframe.patch b/queue-5.10/riscv-stacktrace-fixed-walk_stackframe.patch new file mode 100644 index 00000000000..73a2278eb0a --- /dev/null +++ b/queue-5.10/riscv-stacktrace-fixed-walk_stackframe.patch @@ -0,0 +1,132 @@ +From 4e43cdd51db17bdafaf21fca0c3b534358c1b481 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 May 2024 22:13:13 +0300 +Subject: riscv: stacktrace: fixed walk_stackframe() + +From: Matthew Bystrin + +[ Upstream commit a2a4d4a6a0bf5eba66f8b0b32502cc20d82715a0 ] + +If the load access fault occures in a leaf function (with +CONFIG_FRAME_POINTER=y), when wrong stack trace will be displayed: + +[] regmap_mmio_read32le+0xe/0x1c +---[ end trace 0000000000000000 ]--- + +Registers dump: + ra 0xffffffff80485758 + sp 0xffffffc80200b9a0 + fp 0xffffffc80200b9b0 + pc 0xffffffff804853ba + +Stack dump: + 0xffffffc80200b9a0: 0xffffffc80200b9e0 0xffffffc80200b9e0 + 0xffffffc80200b9b0: 0xffffffff8116d7e8 0x0000000000000100 + 0xffffffc80200b9c0: 0xffffffd8055b9400 0xffffffd8055b9400 + 0xffffffc80200b9d0: 0xffffffc80200b9f0 0xffffffff8047c526 + 0xffffffc80200b9e0: 0xffffffc80200ba30 0xffffffff8047fe9a + +The assembler dump of the function preambula: + add sp,sp,-16 + sd s0,8(sp) + add s0,sp,16 + +In the fist stack frame, where ra is not stored on the stack we can +observe: + + 0(sp) 8(sp) + .---------------------------------------------. + sp->| frame->fp | frame->ra (saved fp) | + |---------------------------------------------| + fp->| .... | .... | + |---------------------------------------------| + | | | + +and in the code check is performed: + if (regs && (regs->epc == pc) && (frame->fp & 0x7)) + +I see no reason to check frame->fp value at all, because it is can be +uninitialized value on the stack. A better way is to check frame->ra to +be an address on the stack. After the stacktrace shows as expect: + +[] regmap_mmio_read32le+0xe/0x1c +[] regmap_mmio_read+0x24/0x52 +[] _regmap_bus_reg_read+0x1a/0x22 +[] _regmap_read+0x5c/0xea +[] _regmap_update_bits+0x76/0xc0 +... +---[ end trace 0000000000000000 ]--- +As pointed by Samuel Holland it is incorrect to remove check of the stackframe +entirely. + +Changes since v2 [2]: + - Add accidentally forgotten curly brace + +Changes since v1 [1]: + - Instead of just dropping frame->fp check, replace it with validation of + frame->ra, which should be a stack address. + - Move frame pointer validation into the separate function. + +[1] https://lore.kernel.org/linux-riscv/20240426072701.6463-1-dev.mbstr@gmail.com/ +[2] https://lore.kernel.org/linux-riscv/20240521131314.48895-1-dev.mbstr@gmail.com/ + +Fixes: f766f77a74f5 ("riscv/stacktrace: Fix stack output without ra on the stack top") +Signed-off-by: Matthew Bystrin +Reviewed-by: Samuel Holland +Link: https://lore.kernel.org/r/20240521191727.62012-1-dev.mbstr@gmail.com +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/stacktrace.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c +index ff877ee3fb942..c38b20caad7cc 100644 +--- a/arch/riscv/kernel/stacktrace.c ++++ b/arch/riscv/kernel/stacktrace.c +@@ -20,6 +20,16 @@ register unsigned long sp_in_global __asm__("sp"); + + extern asmlinkage void ret_from_exception(void); + ++static inline int fp_is_valid(unsigned long fp, unsigned long sp) ++{ ++ unsigned long low, high; ++ ++ low = sp + sizeof(struct stackframe); ++ high = ALIGN(sp, THREAD_SIZE); ++ ++ return !(fp < low || fp > high || fp & 0x07); ++} ++ + void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, + bool (*fn)(unsigned long, void *), void *arg) + { +@@ -42,21 +52,19 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, + } + + for (;;) { +- unsigned long low, high; + struct stackframe *frame; + + if (unlikely(!__kernel_text_address(pc) || fn(pc, arg))) + break; + +- /* Validate frame pointer */ +- low = sp + sizeof(struct stackframe); +- high = ALIGN(sp, THREAD_SIZE); +- if (unlikely(fp < low || fp > high || fp & 0x7)) ++ if (unlikely(!fp_is_valid(fp, sp))) + break; ++ + /* Unwind stack frame */ + frame = (struct stackframe *)fp - 1; + sp = fp; +- if (regs && (regs->epc == pc) && (frame->fp & 0x7)) { ++ if (regs && (regs->epc == pc) && fp_is_valid(frame->ra, sp)) { ++ /* We hit function where ra is not saved on the stack */ + fp = frame->ra; + pc = regs->ra; + } else { +-- +2.43.0 + diff --git a/queue-5.10/riscv-stacktrace-make-walk_stackframe-cross-pt_regs-.patch b/queue-5.10/riscv-stacktrace-make-walk_stackframe-cross-pt_regs-.patch new file mode 100644 index 00000000000..a2caa333925 --- /dev/null +++ b/queue-5.10/riscv-stacktrace-make-walk_stackframe-cross-pt_regs-.patch @@ -0,0 +1,126 @@ +From 0e9e6af8571bcc141fed0f560a07a33c19abf1ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 01:49:37 -0500 +Subject: riscv: stacktrace: Make walk_stackframe cross pt_regs frame + +From: Guo Ren + +[ Upstream commit 7ecdadf7f8c659524f6b2aebf6be7bf619764d90 ] + +The current walk_stackframe with FRAME_POINTER would stop unwinding at +ret_from_exception: + BUG: sleeping function called from invalid context at kernel/locking/rwsem.c:1518 + in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid: 1, name: init + CPU: 0 PID: 1 Comm: init Not tainted 5.10.113-00021-g15c15974895c-dirty #192 + Call Trace: + [] walk_stackframe+0x0/0xee + [] show_stack+0x32/0x4a + [] dump_stack_lvl+0x72/0x8e + [] dump_stack+0x14/0x1c + [] ___might_sleep+0x12e/0x138 + [] __might_sleep+0x10/0x18 + [] down_read+0x22/0xa4 + [] do_page_fault+0xb0/0x2fe + [] ret_from_exception+0x0/0xc + +The optimization would help walk_stackframe cross the pt_regs frame and +get more backtrace of debug info: + BUG: sleeping function called from invalid context at kernel/locking/rwsem.c:1518 + in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid: 1, name: init + CPU: 0 PID: 1 Comm: init Not tainted 5.10.113-00021-g15c15974895c-dirty #192 + Call Trace: + [] walk_stackframe+0x0/0xee + [] show_stack+0x32/0x4a + [] dump_stack_lvl+0x72/0x8e + [] dump_stack+0x14/0x1c + [] ___might_sleep+0x12e/0x138 + [] __might_sleep+0x10/0x18 + [] down_read+0x22/0xa4 + [] do_page_fault+0xb0/0x2fe + [] ret_from_exception+0x0/0xc + [] riscv_intc_irq+0x1a/0x72 + [] ret_from_exception+0x0/0xc + [] vma_link+0x54/0x160 + [] mmap_region+0x2cc/0x4d0 + [] do_mmap+0x2d8/0x3ac + [] vm_mmap_pgoff+0x70/0xb8 + [] vm_mmap+0x2a/0x36 + [] elf_map+0x72/0x84 + [] load_elf_binary+0x69a/0xec8 + [] bprm_execve+0x246/0x53a + [] kernel_execve+0xe8/0x124 + [] run_init_process+0xfa/0x10c + [] try_to_run_init_process+0x12/0x3c + [] kernel_init+0xb4/0xf8 + [] ret_from_exception+0x0/0xc + +Here is the error injection test code for the above output: + drivers/irqchip/irq-riscv-intc.c: + static asmlinkage void riscv_intc_irq(struct pt_regs *regs) + { + unsigned long cause = regs->cause & ~CAUSE_IRQ_FLAG; ++ u32 tmp; __get_user(tmp, (u32 *)0); + +Signed-off-by: Guo Ren +Signed-off-by: Guo Ren +Link: https://lore.kernel.org/r/20221109064937.3643993-3-guoren@kernel.org +[Palmer: use SYM_CODE_*] +Signed-off-by: Palmer Dabbelt +Stable-dep-of: a2a4d4a6a0bf ("riscv: stacktrace: fixed walk_stackframe()") +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/entry.S | 3 ++- + arch/riscv/kernel/stacktrace.c | 9 +++++++++ + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S +index 5214c578a6023..88bd7e5f74cee 100644 +--- a/arch/riscv/kernel/entry.S ++++ b/arch/riscv/kernel/entry.S +@@ -218,7 +218,7 @@ ret_from_syscall_rejected: + andi t0, t0, _TIF_SYSCALL_WORK + bnez t0, handle_syscall_trace_exit + +-ret_from_exception: ++SYM_CODE_START_NOALIGN(ret_from_exception) + REG_L s0, PT_STATUS(sp) + csrc CSR_STATUS, SR_IE + #ifdef CONFIG_TRACE_IRQFLAGS +@@ -232,6 +232,7 @@ ret_from_exception: + andi s0, s0, SR_SPP + #endif + bnez s0, resume_kernel ++SYM_CODE_END(ret_from_exception) + + resume_userspace: + /* Interrupts must be disabled here so flags are checked atomically */ +diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c +index cd14309fff0d9..ff877ee3fb942 100644 +--- a/arch/riscv/kernel/stacktrace.c ++++ b/arch/riscv/kernel/stacktrace.c +@@ -18,6 +18,8 @@ register unsigned long sp_in_global __asm__("sp"); + + #ifdef CONFIG_FRAME_POINTER + ++extern asmlinkage void ret_from_exception(void); ++ + void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, + bool (*fn)(unsigned long, void *), void *arg) + { +@@ -61,6 +63,13 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, + fp = frame->fp; + pc = ftrace_graph_ret_addr(current, NULL, frame->ra, + &frame->ra); ++ if (pc == (unsigned long)ret_from_exception) { ++ if (unlikely(!__kernel_text_address(pc) || !fn(arg, pc))) ++ break; ++ ++ pc = ((struct pt_regs *)sp)->epc; ++ fp = ((struct pt_regs *)sp)->s0; ++ } + } + + } +-- +2.43.0 + diff --git a/queue-5.10/rpcrdma-fix-handling-for-rdma_cm_event_device_remova.patch b/queue-5.10/rpcrdma-fix-handling-for-rdma_cm_event_device_remova.patch new file mode 100644 index 00000000000..37008bf1213 --- /dev/null +++ b/queue-5.10/rpcrdma-fix-handling-for-rdma_cm_event_device_remova.patch @@ -0,0 +1,51 @@ +From 95dc804381b56efa7f0143fdfe00ac485977767f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 May 2024 12:37:59 +0300 +Subject: rpcrdma: fix handling for RDMA_CM_EVENT_DEVICE_REMOVAL + +From: Dan Aloni + +[ Upstream commit 4836da219781ec510c4c0303df901aa643507a7a ] + +Under the scenario of IB device bonding, when bringing down one of the +ports, or all ports, we saw xprtrdma entering a non-recoverable state +where it is not even possible to complete the disconnect and shut it +down the mount, requiring a reboot. Following debug, we saw that +transport connect never ended after receiving the +RDMA_CM_EVENT_DEVICE_REMOVAL callback. + +The DEVICE_REMOVAL callback is irrespective of whether the CM_ID is +connected, and ESTABLISHED may not have happened. So need to work with +each of these states accordingly. + +Fixes: 2acc5cae2923 ('xprtrdma: Prevent dereferencing r_xprt->rx_ep after it is freed') +Cc: Sagi Grimberg +Signed-off-by: Dan Aloni +Reviewed-by: Sagi Grimberg +Reviewed-by: Chuck Lever +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/xprtrdma/verbs.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c +index d015576f3081a..9e9df38b29f74 100644 +--- a/net/sunrpc/xprtrdma/verbs.c ++++ b/net/sunrpc/xprtrdma/verbs.c +@@ -268,7 +268,11 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) + case RDMA_CM_EVENT_DEVICE_REMOVAL: + pr_info("rpcrdma: removing device %s for %pISpc\n", + ep->re_id->device->name, sap); +- fallthrough; ++ switch (xchg(&ep->re_connect_status, -ENODEV)) { ++ case 0: goto wake_connect_worker; ++ case 1: goto disconnected; ++ } ++ return 0; + case RDMA_CM_EVENT_ADDR_CHANGE: + ep->re_connect_status = -ENODEV; + goto disconnected; +-- +2.43.0 + diff --git a/queue-5.10/scsi-qla2xxx-replace-all-non-returning-strlcpy-with-.patch b/queue-5.10/scsi-qla2xxx-replace-all-non-returning-strlcpy-with-.patch new file mode 100644 index 00000000000..7941f8fa607 --- /dev/null +++ b/queue-5.10/scsi-qla2xxx-replace-all-non-returning-strlcpy-with-.patch @@ -0,0 +1,117 @@ +From 8c6f67b2d81ddea811a0c761ad5ed4bb6fb7108d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 May 2023 02:54:04 +0000 +Subject: scsi: qla2xxx: Replace all non-returning strlcpy() with strscpy() + +From: Azeem Shaikh + +[ Upstream commit 37f1663c91934f664fb850306708094a324c227c ] + +strlcpy() reads the entire source buffer first. This read may exceed the +destination size limit. This is both inefficient and can lead to linear +read overflows if a source string is not NUL-terminated [1]. In an effort +to remove strlcpy() completely [2], replace strlcpy() here with strscpy(). +No return values were used, so direct replacement is safe. + +[1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strlcpy +[2] https://github.com/KSPP/linux/issues/89 + +Signed-off-by: Azeem Shaikh +Link: https://lore.kernel.org/r/20230516025404.2843867-1-azeemshaikh38@gmail.com +Reviewed-by: Kees Cook +Signed-off-by: Martin K. Petersen +Stable-dep-of: c3408c4ae041 ("scsi: qla2xxx: Avoid possible run-time warning with long model_num") +Signed-off-by: Sasha Levin +--- + drivers/scsi/qla2xxx/qla_init.c | 8 ++++---- + drivers/scsi/qla2xxx/qla_mr.c | 20 ++++++++++---------- + 2 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index 3d56f971cdc4d..8d54f60998029 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -4644,7 +4644,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, + if (use_tbl && + ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && + index < QLA_MODEL_NAMES) +- strlcpy(ha->model_desc, ++ strscpy(ha->model_desc, + qla2x00_model_name[index * 2 + 1], + sizeof(ha->model_desc)); + } else { +@@ -4652,14 +4652,14 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, + if (use_tbl && + ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && + index < QLA_MODEL_NAMES) { +- strlcpy(ha->model_number, ++ strscpy(ha->model_number, + qla2x00_model_name[index * 2], + sizeof(ha->model_number)); +- strlcpy(ha->model_desc, ++ strscpy(ha->model_desc, + qla2x00_model_name[index * 2 + 1], + sizeof(ha->model_desc)); + } else { +- strlcpy(ha->model_number, def, ++ strscpy(ha->model_number, def, + sizeof(ha->model_number)); + } + } +diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c +index 7178646ee0f06..cc8994a7c9942 100644 +--- a/drivers/scsi/qla2xxx/qla_mr.c ++++ b/drivers/scsi/qla2xxx/qla_mr.c +@@ -691,7 +691,7 @@ qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) + struct qla_hw_data *ha = vha->hw; + + if (pci_is_pcie(ha->pdev)) +- strlcpy(str, "PCIe iSA", str_len); ++ strscpy(str, "PCIe iSA", str_len); + return str; + } + +@@ -1849,21 +1849,21 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) + phost_info = &preg_hsi->hsi; + memset(preg_hsi, 0, sizeof(struct register_host_info)); + phost_info->os_type = OS_TYPE_LINUX; +- strlcpy(phost_info->sysname, p_sysid->sysname, ++ strscpy(phost_info->sysname, p_sysid->sysname, + sizeof(phost_info->sysname)); +- strlcpy(phost_info->nodename, p_sysid->nodename, ++ strscpy(phost_info->nodename, p_sysid->nodename, + sizeof(phost_info->nodename)); + if (!strcmp(phost_info->nodename, "(none)")) + ha->mr.host_info_resend = true; +- strlcpy(phost_info->release, p_sysid->release, ++ strscpy(phost_info->release, p_sysid->release, + sizeof(phost_info->release)); +- strlcpy(phost_info->version, p_sysid->version, ++ strscpy(phost_info->version, p_sysid->version, + sizeof(phost_info->version)); +- strlcpy(phost_info->machine, p_sysid->machine, ++ strscpy(phost_info->machine, p_sysid->machine, + sizeof(phost_info->machine)); +- strlcpy(phost_info->domainname, p_sysid->domainname, ++ strscpy(phost_info->domainname, p_sysid->domainname, + sizeof(phost_info->domainname)); +- strlcpy(phost_info->hostdriver, QLA2XXX_VERSION, ++ strscpy(phost_info->hostdriver, QLA2XXX_VERSION, + sizeof(phost_info->hostdriver)); + preg_hsi->utc = (uint64_t)ktime_get_real_seconds(); + ql_dbg(ql_dbg_init, vha, 0x0149, +@@ -1909,9 +1909,9 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) + if (fx_type == FXDISC_GET_CONFIG_INFO) { + struct config_info_data *pinfo = + (struct config_info_data *) fdisc->u.fxiocb.rsp_addr; +- strlcpy(vha->hw->model_number, pinfo->model_num, ++ strscpy(vha->hw->model_number, pinfo->model_num, + ARRAY_SIZE(vha->hw->model_number)); +- strlcpy(vha->hw->model_desc, pinfo->model_description, ++ strscpy(vha->hw->model_desc, pinfo->model_description, + ARRAY_SIZE(vha->hw->model_desc)); + memcpy(&vha->hw->mr.symbolic_name, pinfo->symbolic_name, + sizeof(vha->hw->mr.symbolic_name)); +-- +2.43.0 + diff --git a/queue-5.10/series b/queue-5.10/series index 83c08a3962a..25bc2a16e5b 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -191,3 +191,56 @@ libsubcmd-fix-parse-options-memory-leak.patch perf-stat-don-t-display-metric-header-for-non-leader.patch s390-ipl-fix-incorrect-initialization-of-len-fields-.patch s390-ipl-fix-incorrect-initialization-of-nvme-dump-b.patch +input-ims-pcu-fix-printf-string-overflow.patch +input-ioc3kbd-convert-to-platform-remove-callback-re.patch +input-ioc3kbd-add-device-table.patch +mmc-sdhci_am654-add-tuning-algorithm-for-delay-chain.patch +mmc-sdhci_am654-write-itapdly-for-ddr52-timing.patch +mmc-sdhci_am654-drop-lookup-for-deprecated-ti-otap-d.patch +mmc-sdhci_am654-add-otap-itap-delay-enable.patch +mmc-sdhci_am654-add-itapdlysel-in-sdhci_j721e_4bit_s.patch +mmc-sdhci_am654-fix-itapdly-for-hs400-timing.patch +input-pm8xxx-vibrator-correct-vib_max_levels-calcula.patch +drm-msm-dpu-always-flush-the-slave-intf-on-the-ctl.patch +um-fix-return-value-in-ubd_init.patch +um-add-winch-to-winch_handlers-before-registering-wi.patch +um-vector-fix-bpfflash-parameter-evaluation.patch +drm-bridge-tc358775-fix-support-for-jeida-18-and-jei.patch +media-stk1160-fix-bounds-checking-in-stk1160_copy_vi.patch +scsi-qla2xxx-replace-all-non-returning-strlcpy-with-.patch +media-flexcop-usb-clean-up-endpoint-sanity-checks.patch +media-flexcop-usb-fix-sanity-check-of-bnumendpoints.patch +powerpc-pseries-add-failure-related-checks-for-h_get.patch +um-fix-the-wmissing-prototypes-warning-for-__switch_.patch +media-cec-cec-adap-always-cancel-work-in-cec_transmi.patch +media-cec-cec-api-add-locking-in-cec_release.patch +media-core-headers-fix-kernel-doc-warnings.patch +media-cec-fix-a-deadlock-situation.patch +media-cec-call-enable_adap-on-s_log_addrs.patch +media-cec-abort-if-the-current-transmit-was-canceled.patch +media-cec-correctly-pass-on-reply-results.patch +media-cec-use-call_op-and-check-for-unregistered.patch +media-cec-adap.c-drop-activate_cnt-use-state-info-in.patch +media-cec-core-avoid-recursive-cec_claim_log_addrs.patch +media-cec-core-avoid-confusing-transmit-timed-out-me.patch +null_blk-fix-the-warning-modpost-missing-module_desc.patch +regulator-bd71828-don-t-overwrite-runtime-voltages.patch +x86-kconfig-select-arch_want_frame_pointers-again-wh.patch +nfc-nci-fix-uninit-value-in-nci_rx_work.patch +asoc-tas2552-add-tx-path-for-capturing-audio-out-dat.patch +sunrpc-fix-nfsacl-rpc-retry-on-soft-mount.patch +rpcrdma-fix-handling-for-rdma_cm_event_device_remova.patch +ipv6-sr-fix-memleak-in-seg6_hmac_init_algo.patch +params-lift-param_set_uint_minmax-to-common-code.patch +tcp-fix-shift-out-of-bounds-in-dctcp_update_alpha.patch +openvswitch-set-the-skbuff-pkt_type-for-proper-pmtud.patch +arm64-asm-bug-add-.align-2-to-the-end-of-__bug_entry.patch +virtio-delete-vq-in-vp_find_vqs_msix-when-request_ir.patch +riscv-cleanup-stacktrace.patch +riscv-stacktrace-make-walk_stackframe-cross-pt_regs-.patch +riscv-stacktrace-fixed-walk_stackframe.patch +net-fec-avoid-lock-evasion-when-reading-pps_enable.patch +tls-fix-missing-memory-barrier-in-tls_init.patch +tcp-remove-64-kbyte-limit-for-initial-tp-rcv_wnd-val.patch +nfc-nci-fix-kcov-check-in-nci_rx_work.patch +nfc-nci-fix-handling-of-zero-length-payload-packets-.patch diff --git a/queue-5.10/sunrpc-fix-nfsacl-rpc-retry-on-soft-mount.patch b/queue-5.10/sunrpc-fix-nfsacl-rpc-retry-on-soft-mount.patch new file mode 100644 index 00000000000..58980e0f823 --- /dev/null +++ b/queue-5.10/sunrpc-fix-nfsacl-rpc-retry-on-soft-mount.patch @@ -0,0 +1,55 @@ +From ad6f7359741d3f4d86cb22ad0aac851b5e733867 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Apr 2024 13:49:38 +0300 +Subject: sunrpc: fix NFSACL RPC retry on soft mount + +From: Dan Aloni + +[ Upstream commit 0dc9f430027b8bd9073fdafdfcdeb1a073ab5594 ] + +It used to be quite awhile ago since 1b63a75180c6 ('SUNRPC: Refactor +rpc_clone_client()'), in 2012, that `cl_timeout` was copied in so that +all mount parameters propagate to NFSACL clients. However since that +change, if mount options as follows are given: + + soft,timeo=50,retrans=16,vers=3 + +The resultant NFSACL client receives: + + cl_softrtry: 1 + cl_timeout: to_initval=60000, to_maxval=60000, to_increment=0, to_retries=2, to_exponential=0 + +These values lead to NFSACL operations not being retried under the +condition of transient network outages with soft mount. Instead, getacl +call fails after 60 seconds with EIO. + +The simple fix is to pass the existing client's `cl_timeout` as the new +client timeout. + +Cc: Chuck Lever +Cc: Benjamin Coddington +Link: https://lore.kernel.org/all/20231105154857.ryakhmgaptq3hb6b@gmail.com/T/ +Fixes: 1b63a75180c6 ('SUNRPC: Refactor rpc_clone_client()') +Signed-off-by: Dan Aloni +Reviewed-by: Benjamin Coddington +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/clnt.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c +index a5ce9b937c42e..196a3b11d1509 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -970,6 +970,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, + .authflavor = old->cl_auth->au_flavor, + .cred = old->cl_cred, + .stats = old->cl_stats, ++ .timeout = old->cl_timeout, + }; + struct rpc_clnt *clnt; + int err; +-- +2.43.0 + diff --git a/queue-5.10/tcp-fix-shift-out-of-bounds-in-dctcp_update_alpha.patch b/queue-5.10/tcp-fix-shift-out-of-bounds-in-dctcp_update_alpha.patch new file mode 100644 index 00000000000..3f6ed854893 --- /dev/null +++ b/queue-5.10/tcp-fix-shift-out-of-bounds-in-dctcp_update_alpha.patch @@ -0,0 +1,125 @@ +From 895110ca036e6968f01ed57201c3e138d73770d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 May 2024 18:16:26 +0900 +Subject: tcp: Fix shift-out-of-bounds in dctcp_update_alpha(). + +From: Kuniyuki Iwashima + +[ Upstream commit 3ebc46ca8675de6378e3f8f40768e180bb8afa66 ] + +In dctcp_update_alpha(), we use a module parameter dctcp_shift_g +as follows: + + alpha -= min_not_zero(alpha, alpha >> dctcp_shift_g); + ... + delivered_ce <<= (10 - dctcp_shift_g); + +It seems syzkaller started fuzzing module parameters and triggered +shift-out-of-bounds [0] by setting 100 to dctcp_shift_g: + + memcpy((void*)0x20000080, + "/sys/module/tcp_dctcp/parameters/dctcp_shift_g\000", 47); + res = syscall(__NR_openat, /*fd=*/0xffffffffffffff9cul, /*file=*/0x20000080ul, + /*flags=*/2ul, /*mode=*/0ul); + memcpy((void*)0x20000000, "100\000", 4); + syscall(__NR_write, /*fd=*/r[0], /*val=*/0x20000000ul, /*len=*/4ul); + +Let's limit the max value of dctcp_shift_g by param_set_uint_minmax(). + +With this patch: + + # echo 10 > /sys/module/tcp_dctcp/parameters/dctcp_shift_g + # cat /sys/module/tcp_dctcp/parameters/dctcp_shift_g + 10 + # echo 11 > /sys/module/tcp_dctcp/parameters/dctcp_shift_g + -bash: echo: write error: Invalid argument + +[0]: +UBSAN: shift-out-of-bounds in net/ipv4/tcp_dctcp.c:143:12 +shift exponent 100 is too large for 32-bit type 'u32' (aka 'unsigned int') +CPU: 0 PID: 8083 Comm: syz-executor345 Not tainted 6.9.0-05151-g1b294a1f3561 #2 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS +1.13.0-1ubuntu1.1 04/01/2014 +Call Trace: + + __dump_stack lib/dump_stack.c:88 [inline] + dump_stack_lvl+0x201/0x300 lib/dump_stack.c:114 + ubsan_epilogue lib/ubsan.c:231 [inline] + __ubsan_handle_shift_out_of_bounds+0x346/0x3a0 lib/ubsan.c:468 + dctcp_update_alpha+0x540/0x570 net/ipv4/tcp_dctcp.c:143 + tcp_in_ack_event net/ipv4/tcp_input.c:3802 [inline] + tcp_ack+0x17b1/0x3bc0 net/ipv4/tcp_input.c:3948 + tcp_rcv_state_process+0x57a/0x2290 net/ipv4/tcp_input.c:6711 + tcp_v4_do_rcv+0x764/0xc40 net/ipv4/tcp_ipv4.c:1937 + sk_backlog_rcv include/net/sock.h:1106 [inline] + __release_sock+0x20f/0x350 net/core/sock.c:2983 + release_sock+0x61/0x1f0 net/core/sock.c:3549 + mptcp_subflow_shutdown+0x3d0/0x620 net/mptcp/protocol.c:2907 + mptcp_check_send_data_fin+0x225/0x410 net/mptcp/protocol.c:2976 + __mptcp_close+0x238/0xad0 net/mptcp/protocol.c:3072 + mptcp_close+0x2a/0x1a0 net/mptcp/protocol.c:3127 + inet_release+0x190/0x1f0 net/ipv4/af_inet.c:437 + __sock_release net/socket.c:659 [inline] + sock_close+0xc0/0x240 net/socket.c:1421 + __fput+0x41b/0x890 fs/file_table.c:422 + task_work_run+0x23b/0x300 kernel/task_work.c:180 + exit_task_work include/linux/task_work.h:38 [inline] + do_exit+0x9c8/0x2540 kernel/exit.c:878 + do_group_exit+0x201/0x2b0 kernel/exit.c:1027 + __do_sys_exit_group kernel/exit.c:1038 [inline] + __se_sys_exit_group kernel/exit.c:1036 [inline] + __x64_sys_exit_group+0x3f/0x40 kernel/exit.c:1036 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xe4/0x240 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x67/0x6f +RIP: 0033:0x7f6c2b5005b6 +Code: Unable to access opcode bytes at 0x7f6c2b50058c. +RSP: 002b:00007ffe883eb948 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7 +RAX: ffffffffffffffda RBX: 00007f6c2b5862f0 RCX: 00007f6c2b5005b6 +RDX: 0000000000000001 RSI: 000000000000003c RDI: 0000000000000001 +RBP: 0000000000000001 R08: 00000000000000e7 R09: ffffffffffffffc0 +R10: 0000000000000006 R11: 0000000000000246 R12: 00007f6c2b5862f0 +R13: 0000000000000001 R14: 0000000000000000 R15: 0000000000000001 + + +Reported-by: syzkaller +Reported-by: Yue Sun +Reported-by: xingwei lee +Closes: https://lore.kernel.org/netdev/CAEkJfYNJM=cw-8x7_Vmj1J6uYVCWMbbvD=EFmDPVBGpTsqOxEA@mail.gmail.com/ +Fixes: e3118e8359bb ("net: tcp: add DCTCP congestion control algorithm") +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/20240517091626.32772-1-kuniyu@amazon.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_dctcp.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_dctcp.c b/net/ipv4/tcp_dctcp.c +index 79f705450c162..be2c97e907ae2 100644 +--- a/net/ipv4/tcp_dctcp.c ++++ b/net/ipv4/tcp_dctcp.c +@@ -55,7 +55,18 @@ struct dctcp { + }; + + static unsigned int dctcp_shift_g __read_mostly = 4; /* g = 1/2^4 */ +-module_param(dctcp_shift_g, uint, 0644); ++ ++static int dctcp_shift_g_set(const char *val, const struct kernel_param *kp) ++{ ++ return param_set_uint_minmax(val, kp, 0, 10); ++} ++ ++static const struct kernel_param_ops dctcp_shift_g_ops = { ++ .set = dctcp_shift_g_set, ++ .get = param_get_uint, ++}; ++ ++module_param_cb(dctcp_shift_g, &dctcp_shift_g_ops, &dctcp_shift_g, 0644); + MODULE_PARM_DESC(dctcp_shift_g, "parameter g for updating dctcp_alpha"); + + static unsigned int dctcp_alpha_on_init __read_mostly = DCTCP_MAX_ALPHA; +-- +2.43.0 + diff --git a/queue-5.10/tcp-remove-64-kbyte-limit-for-initial-tp-rcv_wnd-val.patch b/queue-5.10/tcp-remove-64-kbyte-limit-for-initial-tp-rcv_wnd-val.patch new file mode 100644 index 00000000000..2ba4fad2eef --- /dev/null +++ b/queue-5.10/tcp-remove-64-kbyte-limit-for-initial-tp-rcv_wnd-val.patch @@ -0,0 +1,76 @@ +From d95db3294f123d366133d54b7f3c12a5ee0ac717 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 May 2024 21:42:20 +0800 +Subject: tcp: remove 64 KByte limit for initial tp->rcv_wnd value + +From: Jason Xing + +[ Upstream commit 378979e94e953c2070acb4f0e0c98d29260bd09d ] + +Recently, we had some servers upgraded to the latest kernel and noticed +the indicator from the user side showed worse results than before. It is +caused by the limitation of tp->rcv_wnd. + +In 2018 commit a337531b942b ("tcp: up initial rmem to 128KB and SYN rwin +to around 64KB") limited the initial value of tp->rcv_wnd to 65535, most +CDN teams would not benefit from this change because they cannot have a +large window to receive a big packet, which will be slowed down especially +in long RTT. Small rcv_wnd means slow transfer speed, to some extent. It's +the side effect for the latency/time-sensitive users. + +To avoid future confusion, current change doesn't affect the initial +receive window on the wire in a SYN or SYN+ACK packet which are set within +65535 bytes according to RFC 7323 also due to the limit in +__tcp_transmit_skb(): + + th->window = htons(min(tp->rcv_wnd, 65535U)); + +In one word, __tcp_transmit_skb() already ensures that constraint is +respected, no matter how large tp->rcv_wnd is. The change doesn't violate +RFC. + +Let me provide one example if with or without the patch: +Before: +client --- SYN: rwindow=65535 ---> server +client <--- SYN+ACK: rwindow=65535 ---- server +client --- ACK: rwindow=65536 ---> server +Note: for the last ACK, the calculation is 512 << 7. + +After: +client --- SYN: rwindow=65535 ---> server +client <--- SYN+ACK: rwindow=65535 ---- server +client --- ACK: rwindow=175232 ---> server +Note: I use the following command to make it work: +ip route change default via [ip] dev eth0 metric 100 initrwnd 120 +For the last ACK, the calculation is 1369 << 7. + +When we apply such a patch, having a large rcv_wnd if the user tweak this +knob can help transfer data more rapidly and save some rtts. + +Fixes: a337531b942b ("tcp: up initial rmem to 128KB and SYN rwin to around 64KB") +Signed-off-by: Jason Xing +Reviewed-by: Eric Dumazet +Acked-by: Neal Cardwell +Link: https://lore.kernel.org/r/20240521134220.12510-1-kerneljasonxing@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_output.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 68f1633c477ae..efc57fa04f860 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -229,7 +229,7 @@ void tcp_select_initial_window(const struct sock *sk, int __space, __u32 mss, + if (sock_net(sk)->ipv4.sysctl_tcp_workaround_signed_windows) + (*rcv_wnd) = min(space, MAX_TCP_WINDOW); + else +- (*rcv_wnd) = min_t(u32, space, U16_MAX); ++ (*rcv_wnd) = space; + + if (init_rcv_wnd) + *rcv_wnd = min(*rcv_wnd, init_rcv_wnd * mss); +-- +2.43.0 + diff --git a/queue-5.10/tls-fix-missing-memory-barrier-in-tls_init.patch b/queue-5.10/tls-fix-missing-memory-barrier-in-tls_init.patch new file mode 100644 index 00000000000..72addb3171a --- /dev/null +++ b/queue-5.10/tls-fix-missing-memory-barrier-in-tls_init.patch @@ -0,0 +1,73 @@ +From e86ada08dec2f044b34a6ed3fc8a6addd32dc58d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 May 2024 19:34:38 +0900 +Subject: tls: fix missing memory barrier in tls_init + +From: Dae R. Jeong + +[ Upstream commit 91e61dd7a0af660408e87372d8330ceb218be302 ] + +In tls_init(), a write memory barrier is missing, and store-store +reordering may cause NULL dereference in tls_{setsockopt,getsockopt}. + +CPU0 CPU1 +----- ----- +// In tls_init() +// In tls_ctx_create() +ctx = kzalloc() +ctx->sk_proto = READ_ONCE(sk->sk_prot) -(1) + +// In update_sk_prot() +WRITE_ONCE(sk->sk_prot, tls_prots) -(2) + + // In sock_common_setsockopt() + READ_ONCE(sk->sk_prot)->setsockopt() + + // In tls_{setsockopt,getsockopt}() + ctx->sk_proto->setsockopt() -(3) + +In the above scenario, when (1) and (2) are reordered, (3) can observe +the NULL value of ctx->sk_proto, causing NULL dereference. + +To fix it, we rely on rcu_assign_pointer() which implies the release +barrier semantic. By moving rcu_assign_pointer() after ctx->sk_proto is +initialized, we can ensure that ctx->sk_proto are visible when +changing sk->sk_prot. + +Fixes: d5bee7374b68 ("net/tls: Annotate access to sk_prot with READ_ONCE/WRITE_ONCE") +Signed-off-by: Yewon Choi +Signed-off-by: Dae R. Jeong +Link: https://lore.kernel.org/netdev/ZU4OJG56g2V9z_H7@dragonet/T/ +Link: https://lore.kernel.org/r/Zkx4vjSFp0mfpjQ2@libra05 +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/tls/tls_main.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c +index 2bbacd9b97e56..ebf856cf821da 100644 +--- a/net/tls/tls_main.c ++++ b/net/tls/tls_main.c +@@ -633,9 +633,17 @@ struct tls_context *tls_ctx_create(struct sock *sk) + return NULL; + + mutex_init(&ctx->tx_lock); +- rcu_assign_pointer(icsk->icsk_ulp_data, ctx); + ctx->sk_proto = READ_ONCE(sk->sk_prot); + ctx->sk = sk; ++ /* Release semantic of rcu_assign_pointer() ensures that ++ * ctx->sk_proto is visible before changing sk->sk_prot in ++ * update_sk_prot(), and prevents reading uninitialized value in ++ * tls_{getsockopt, setsockopt}. Note that we do not need a ++ * read barrier in tls_{getsockopt,setsockopt} as there is an ++ * address dependency between sk->sk_proto->{getsockopt,setsockopt} ++ * and ctx->sk_proto. ++ */ ++ rcu_assign_pointer(icsk->icsk_ulp_data, ctx); + return ctx; + } + +-- +2.43.0 + diff --git a/queue-5.10/um-add-winch-to-winch_handlers-before-registering-wi.patch b/queue-5.10/um-add-winch-to-winch_handlers-before-registering-wi.patch new file mode 100644 index 00000000000..9dea238f708 --- /dev/null +++ b/queue-5.10/um-add-winch-to-winch_handlers-before-registering-wi.patch @@ -0,0 +1,68 @@ +From 907c883f23a76e1023c80ba1da0791e3a55446b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Mar 2024 11:49:26 +0100 +Subject: um: Add winch to winch_handlers before registering winch IRQ + +From: Roberto Sassu + +[ Upstream commit a0fbbd36c156b9f7b2276871d499c9943dfe5101 ] + +Registering a winch IRQ is racy, an interrupt may occur before the winch is +added to the winch_handlers list. + +If that happens, register_winch_irq() adds to that list a winch that is +scheduled to be (or has already been) freed, causing a panic later in +winch_cleanup(). + +Avoid the race by adding the winch to the winch_handlers list before +registering the IRQ, and rolling back if um_request_irq() fails. + +Fixes: 42a359e31a0e ("uml: SIGIO support cleanup") +Signed-off-by: Roberto Sassu +Reviewed-by: Johannes Berg +Signed-off-by: Richard Weinberger +Signed-off-by: Sasha Levin +--- + arch/um/drivers/line.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c +index 14ad9f495fe69..37e96ba0f5fb1 100644 +--- a/arch/um/drivers/line.c ++++ b/arch/um/drivers/line.c +@@ -668,24 +668,26 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_port *port, + goto cleanup; + } + +- *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list), +- .fd = fd, ++ *winch = ((struct winch) { .fd = fd, + .tty_fd = tty_fd, + .pid = pid, + .port = port, + .stack = stack }); + ++ spin_lock(&winch_handler_lock); ++ list_add(&winch->list, &winch_handlers); ++ spin_unlock(&winch_handler_lock); ++ + if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, + IRQF_SHARED, "winch", winch) < 0) { + printk(KERN_ERR "register_winch_irq - failed to register " + "IRQ\n"); ++ spin_lock(&winch_handler_lock); ++ list_del(&winch->list); ++ spin_unlock(&winch_handler_lock); + goto out_free; + } + +- spin_lock(&winch_handler_lock); +- list_add(&winch->list, &winch_handlers); +- spin_unlock(&winch_handler_lock); +- + return; + + out_free: +-- +2.43.0 + diff --git a/queue-5.10/um-fix-return-value-in-ubd_init.patch b/queue-5.10/um-fix-return-value-in-ubd_init.patch new file mode 100644 index 00000000000..35638ad8b6e --- /dev/null +++ b/queue-5.10/um-fix-return-value-in-ubd_init.patch @@ -0,0 +1,46 @@ +From f230d80ed04e39fb2614035c54fb29f49b1f0abe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Mar 2024 17:12:59 +0800 +Subject: um: Fix return value in ubd_init() + +From: Duoming Zhou + +[ Upstream commit 31a5990ed253a66712d7ddc29c92d297a991fdf2 ] + +When kmalloc_array() fails to allocate memory, the ubd_init() +should return -ENOMEM instead of -1. So, fix it. + +Fixes: f88f0bdfc32f ("um: UBD Improvements") +Signed-off-by: Duoming Zhou +Reviewed-by: Johannes Berg +Signed-off-by: Richard Weinberger +Signed-off-by: Sasha Levin +--- + arch/um/drivers/ubd_kern.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c +index b12c1b0d3e1d0..de28ce711687e 100644 +--- a/arch/um/drivers/ubd_kern.c ++++ b/arch/um/drivers/ubd_kern.c +@@ -1158,7 +1158,7 @@ static int __init ubd_init(void) + + if (irq_req_buffer == NULL) { + printk(KERN_ERR "Failed to initialize ubd buffering\n"); +- return -1; ++ return -ENOMEM; + } + io_req_buffer = kmalloc_array(UBD_REQ_BUFFER_SIZE, + sizeof(struct io_thread_req *), +@@ -1169,7 +1169,7 @@ static int __init ubd_init(void) + + if (io_req_buffer == NULL) { + printk(KERN_ERR "Failed to initialize ubd buffering\n"); +- return -1; ++ return -ENOMEM; + } + platform_driver_register(&ubd_driver); + mutex_lock(&ubd_lock); +-- +2.43.0 + diff --git a/queue-5.10/um-fix-the-wmissing-prototypes-warning-for-__switch_.patch b/queue-5.10/um-fix-the-wmissing-prototypes-warning-for-__switch_.patch new file mode 100644 index 00000000000..87f14d5d409 --- /dev/null +++ b/queue-5.10/um-fix-the-wmissing-prototypes-warning-for-__switch_.patch @@ -0,0 +1,48 @@ +From aa3e776a2fb6c8efc6d33c500174af5ffdcf9f10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Apr 2024 20:58:53 +0800 +Subject: um: Fix the -Wmissing-prototypes warning for __switch_mm + +From: Tiwei Bie + +[ Upstream commit 2cbade17b18c0f0fd9963f26c9fc9b057eb1cb3a ] + +The __switch_mm function is defined in the user code, and is called +by the kernel code. It should be declared in a shared header. + +Fixes: 4dc706c2f292 ("um: take um_mmu.h to asm/mmu.h, clean asm/mmu_context.h a bit") +Signed-off-by: Tiwei Bie +Signed-off-by: Richard Weinberger +Signed-off-by: Sasha Levin +--- + arch/um/include/asm/mmu.h | 2 -- + arch/um/include/shared/skas/mm_id.h | 2 ++ + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/um/include/asm/mmu.h b/arch/um/include/asm/mmu.h +index 5b072aba5b658..a7cb380c0b5c0 100644 +--- a/arch/um/include/asm/mmu.h ++++ b/arch/um/include/asm/mmu.h +@@ -15,8 +15,6 @@ typedef struct mm_context { + struct page *stub_pages[2]; + } mm_context_t; + +-extern void __switch_mm(struct mm_id * mm_idp); +- + /* Avoid tangled inclusion with asm/ldt.h */ + extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm); + extern void free_ldt(struct mm_context *mm); +diff --git a/arch/um/include/shared/skas/mm_id.h b/arch/um/include/shared/skas/mm_id.h +index e82e203f5f419..92dbf727e3842 100644 +--- a/arch/um/include/shared/skas/mm_id.h ++++ b/arch/um/include/shared/skas/mm_id.h +@@ -15,4 +15,6 @@ struct mm_id { + int kill; + }; + ++void __switch_mm(struct mm_id *mm_idp); ++ + #endif +-- +2.43.0 + diff --git a/queue-5.10/um-vector-fix-bpfflash-parameter-evaluation.patch b/queue-5.10/um-vector-fix-bpfflash-parameter-evaluation.patch new file mode 100644 index 00000000000..7552e6513fb --- /dev/null +++ b/queue-5.10/um-vector-fix-bpfflash-parameter-evaluation.patch @@ -0,0 +1,37 @@ +From 31e2f795ed5c4c47bd111de03c230300df9d8a09 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Mar 2024 10:06:36 +0100 +Subject: um: vector: fix bpfflash parameter evaluation + +From: Johannes Berg + +[ Upstream commit 584ed2f76ff5fe360d87a04d17b6520c7999e06b ] + +With W=1 the build complains about a pointer compared to +zero, clearly the result should've been compared. + +Fixes: 9807019a62dc ("um: Loadable BPF "Firmware" for vector drivers") +Signed-off-by: Johannes Berg +Reviewed-by: Tiwei Bie +Signed-off-by: Richard Weinberger +Signed-off-by: Sasha Levin +--- + arch/um/drivers/vector_kern.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c +index fc662f7cc2afb..c10432ef2d410 100644 +--- a/arch/um/drivers/vector_kern.c ++++ b/arch/um/drivers/vector_kern.c +@@ -142,7 +142,7 @@ static bool get_bpf_flash(struct arglist *def) + + if (allow != NULL) { + if (kstrtoul(allow, 10, &result) == 0) +- return (allow > 0); ++ return result > 0; + } + return false; + } +-- +2.43.0 + diff --git a/queue-5.10/virtio-delete-vq-in-vp_find_vqs_msix-when-request_ir.patch b/queue-5.10/virtio-delete-vq-in-vp_find_vqs_msix-when-request_ir.patch new file mode 100644 index 00000000000..95fb2cf6058 --- /dev/null +++ b/queue-5.10/virtio-delete-vq-in-vp_find_vqs_msix-when-request_ir.patch @@ -0,0 +1,94 @@ +From f0f91983a177a533df6d0ecf34a67fb106fbc4f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Apr 2024 17:08:45 +0200 +Subject: virtio: delete vq in vp_find_vqs_msix() when request_irq() fails + +From: Jiri Pirko + +[ Upstream commit 89875151fccdd024d571aa884ea97a0128b968b6 ] + +When request_irq() fails, error path calls vp_del_vqs(). There, as vq is +present in the list, free_irq() is called for the same vector. That +causes following splat: + +[ 0.414355] Trying to free already-free IRQ 27 +[ 0.414403] WARNING: CPU: 1 PID: 1 at kernel/irq/manage.c:1899 free_irq+0x1a1/0x2d0 +[ 0.414510] Modules linked in: +[ 0.414540] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.9.0-rc4+ #27 +[ 0.414540] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-1.fc39 04/01/2014 +[ 0.414540] RIP: 0010:free_irq+0x1a1/0x2d0 +[ 0.414540] Code: 1e 00 48 83 c4 08 48 89 e8 5b 5d 41 5c 41 5d 41 5e 41 5f c3 cc cc cc cc 90 8b 74 24 04 48 c7 c7 98 80 6c b1 e8 00 c9 f7 ff 90 <0f> 0b 90 90 48 89 ee 4c 89 ef e8 e0 20 b8 00 49 8b 47 40 48 8b 40 +[ 0.414540] RSP: 0000:ffffb71480013ae0 EFLAGS: 00010086 +[ 0.414540] RAX: 0000000000000000 RBX: ffffa099c2722000 RCX: 0000000000000000 +[ 0.414540] RDX: 0000000000000000 RSI: ffffb71480013998 RDI: 0000000000000001 +[ 0.414540] RBP: 0000000000000246 R08: 00000000ffffdfff R09: 0000000000000001 +[ 0.414540] R10: 00000000ffffdfff R11: ffffffffb18729c0 R12: ffffa099c1c91760 +[ 0.414540] R13: ffffa099c1c916a4 R14: ffffa099c1d2f200 R15: ffffa099c1c91600 +[ 0.414540] FS: 0000000000000000(0000) GS:ffffa099fec40000(0000) knlGS:0000000000000000 +[ 0.414540] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 0.414540] CR2: 0000000000000000 CR3: 0000000008e3e001 CR4: 0000000000370ef0 +[ 0.414540] Call Trace: +[ 0.414540] +[ 0.414540] ? __warn+0x80/0x120 +[ 0.414540] ? free_irq+0x1a1/0x2d0 +[ 0.414540] ? report_bug+0x164/0x190 +[ 0.414540] ? handle_bug+0x3b/0x70 +[ 0.414540] ? exc_invalid_op+0x17/0x70 +[ 0.414540] ? asm_exc_invalid_op+0x1a/0x20 +[ 0.414540] ? free_irq+0x1a1/0x2d0 +[ 0.414540] vp_del_vqs+0xc1/0x220 +[ 0.414540] vp_find_vqs_msix+0x305/0x470 +[ 0.414540] vp_find_vqs+0x3e/0x1a0 +[ 0.414540] vp_modern_find_vqs+0x1b/0x70 +[ 0.414540] init_vqs+0x387/0x600 +[ 0.414540] virtnet_probe+0x50a/0xc80 +[ 0.414540] virtio_dev_probe+0x1e0/0x2b0 +[ 0.414540] really_probe+0xc0/0x2c0 +[ 0.414540] ? __pfx___driver_attach+0x10/0x10 +[ 0.414540] __driver_probe_device+0x73/0x120 +[ 0.414540] driver_probe_device+0x1f/0xe0 +[ 0.414540] __driver_attach+0x88/0x180 +[ 0.414540] bus_for_each_dev+0x85/0xd0 +[ 0.414540] bus_add_driver+0xec/0x1f0 +[ 0.414540] driver_register+0x59/0x100 +[ 0.414540] ? __pfx_virtio_net_driver_init+0x10/0x10 +[ 0.414540] virtio_net_driver_init+0x90/0xb0 +[ 0.414540] do_one_initcall+0x58/0x230 +[ 0.414540] kernel_init_freeable+0x1a3/0x2d0 +[ 0.414540] ? __pfx_kernel_init+0x10/0x10 +[ 0.414540] kernel_init+0x1a/0x1c0 +[ 0.414540] ret_from_fork+0x31/0x50 +[ 0.414540] ? __pfx_kernel_init+0x10/0x10 +[ 0.414540] ret_from_fork_asm+0x1a/0x30 +[ 0.414540] + +Fix this by calling deleting the current vq when request_irq() fails. + +Fixes: 0b0f9dc52ed0 ("Revert "virtio_pci: use shared interrupts for virtqueues"") +Signed-off-by: Jiri Pirko +Message-Id: <20240426150845.3999481-1-jiri@resnulli.us> +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Sasha Levin +--- + drivers/virtio/virtio_pci_common.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c +index 1e890ef176873..a6f375417fd54 100644 +--- a/drivers/virtio/virtio_pci_common.c ++++ b/drivers/virtio/virtio_pci_common.c +@@ -339,8 +339,10 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs, + vring_interrupt, 0, + vp_dev->msix_names[msix_vec], + vqs[i]); +- if (err) ++ if (err) { ++ vp_del_vq(vqs[i]); + goto error_find; ++ } + } + return 0; + +-- +2.43.0 + diff --git a/queue-5.10/x86-kconfig-select-arch_want_frame_pointers-again-wh.patch b/queue-5.10/x86-kconfig-select-arch_want_frame_pointers-again-wh.patch new file mode 100644 index 00000000000..73532db6a01 --- /dev/null +++ b/queue-5.10/x86-kconfig-select-arch_want_frame_pointers-again-wh.patch @@ -0,0 +1,63 @@ +From ac56f3fafa4176b1b80ebad2124b4fb36db712d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Feb 2024 21:20:03 +0900 +Subject: x86/kconfig: Select ARCH_WANT_FRAME_POINTERS again when + UNWINDER_FRAME_POINTER=y + +From: Masahiro Yamada + +[ Upstream commit 66ee3636eddcc82ab82b539d08b85fb5ac1dff9b ] + +It took me some time to understand the purpose of the tricky code at +the end of arch/x86/Kconfig.debug. + +Without it, the following would be shown: + + WARNING: unmet direct dependencies detected for FRAME_POINTER + +because + + 81d387190039 ("x86/kconfig: Consolidate unwinders into multiple choice selection") + +removed 'select ARCH_WANT_FRAME_POINTERS'. + +The correct and more straightforward approach should have been to move +it where 'select FRAME_POINTER' is located. + +Several architectures properly handle the conditional selection of +ARCH_WANT_FRAME_POINTERS. For example, 'config UNWINDER_FRAME_POINTER' +in arch/arm/Kconfig.debug. + +Fixes: 81d387190039 ("x86/kconfig: Consolidate unwinders into multiple choice selection") +Signed-off-by: Masahiro Yamada +Signed-off-by: Borislav Petkov (AMD) +Acked-by: Josh Poimboeuf +Link: https://lore.kernel.org/r/20240204122003.53795-1-masahiroy@kernel.org +Signed-off-by: Sasha Levin +--- + arch/x86/Kconfig.debug | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug +index 27b5e2bc6a016..e6546aa448de1 100644 +--- a/arch/x86/Kconfig.debug ++++ b/arch/x86/Kconfig.debug +@@ -258,6 +258,7 @@ config UNWINDER_ORC + + config UNWINDER_FRAME_POINTER + bool "Frame pointer unwinder" ++ select ARCH_WANT_FRAME_POINTERS + select FRAME_POINTER + help + This option enables the frame pointer unwinder for unwinding kernel +@@ -281,7 +282,3 @@ config UNWINDER_GUESS + overhead. + + endchoice +- +-config FRAME_POINTER +- depends on !UNWINDER_ORC && !UNWINDER_GUESS +- bool +-- +2.43.0 +