From: Sasha Levin Date: Mon, 3 Jun 2024 11:42:14 +0000 (-0400) Subject: Fixes for 5.15 X-Git-Tag: v6.1.93~56 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=68289539d84a378673897e25426032205842dbe2;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/af_unix-update-unix_sk-sk-oob_skb-under-sk_receive_q.patch b/queue-5.15/af_unix-update-unix_sk-sk-oob_skb-under-sk_receive_q.patch new file mode 100644 index 00000000000..6dcb167bbb8 --- /dev/null +++ b/queue-5.15/af_unix-update-unix_sk-sk-oob_skb-under-sk_receive_q.patch @@ -0,0 +1,155 @@ +From c010dda6b5a1f8f31d7cc6444ee4b3280ffcbb6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 May 2024 22:48:35 +0900 +Subject: af_unix: Update unix_sk(sk)->oob_skb under sk_receive_queue lock. + +From: Kuniyuki Iwashima + +[ Upstream commit 9841991a446c87f90f66f4b9fee6fe934c1336a2 ] + +Billy Jheng Bing-Jhong reported a race between __unix_gc() and +queue_oob(). + +__unix_gc() tries to garbage-collect close()d inflight sockets, +and then if the socket has MSG_OOB in unix_sk(sk)->oob_skb, GC +will drop the reference and set NULL to it locklessly. + +However, the peer socket still can send MSG_OOB message and +queue_oob() can update unix_sk(sk)->oob_skb concurrently, leading +NULL pointer dereference. [0] + +To fix the issue, let's update unix_sk(sk)->oob_skb under the +sk_receive_queue's lock and take it everywhere we touch oob_skb. + +Note that we defer kfree_skb() in manage_oob() to silence lockdep +false-positive (See [1]). + +[0]: +BUG: kernel NULL pointer dereference, address: 0000000000000008 + PF: supervisor write access in kernel mode + PF: error_code(0x0002) - not-present page +PGD 8000000009f5e067 P4D 8000000009f5e067 PUD 9f5d067 PMD 0 +Oops: 0002 [#1] PREEMPT SMP PTI +CPU: 3 PID: 50 Comm: kworker/3:1 Not tainted 6.9.0-rc5-00191-gd091e579b864 #110 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014 +Workqueue: events delayed_fput +RIP: 0010:skb_dequeue (./include/linux/skbuff.h:2386 ./include/linux/skbuff.h:2402 net/core/skbuff.c:3847) +Code: 39 e3 74 3e 8b 43 10 48 89 ef 83 e8 01 89 43 10 49 8b 44 24 08 49 c7 44 24 08 00 00 00 00 49 8b 14 24 49 c7 04 24 00 00 00 00 <48> 89 42 08 48 89 10 e8 e7 c5 42 00 4c 89 e0 5b 5d 41 5c c3 cc cc +RSP: 0018:ffffc900001bfd48 EFLAGS: 00000002 +RAX: 0000000000000000 RBX: ffff8880088f5ae8 RCX: 00000000361289f9 +RDX: 0000000000000000 RSI: 0000000000000206 RDI: ffff8880088f5b00 +RBP: ffff8880088f5b00 R08: 0000000000080000 R09: 0000000000000001 +R10: 0000000000000003 R11: 0000000000000001 R12: ffff8880056b6a00 +R13: ffff8880088f5280 R14: 0000000000000001 R15: ffff8880088f5a80 +FS: 0000000000000000(0000) GS:ffff88807dd80000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000000000008 CR3: 0000000006314000 CR4: 00000000007506f0 +PKRU: 55555554 +Call Trace: + + unix_release_sock (net/unix/af_unix.c:654) + unix_release (net/unix/af_unix.c:1050) + __sock_release (net/socket.c:660) + sock_close (net/socket.c:1423) + __fput (fs/file_table.c:423) + delayed_fput (fs/file_table.c:444 (discriminator 3)) + process_one_work (kernel/workqueue.c:3259) + worker_thread (kernel/workqueue.c:3329 kernel/workqueue.c:3416) + kthread (kernel/kthread.c:388) + ret_from_fork (arch/x86/kernel/process.c:153) + ret_from_fork_asm (arch/x86/entry/entry_64.S:257) + +Modules linked in: +CR2: 0000000000000008 + +Link: https://lore.kernel.org/netdev/a00d3993-c461-43f2-be6d-07259c98509a@rbox.co/ [1] +Fixes: 1279f9d9dec2 ("af_unix: Call kfree_skb() for dead unix_(sk)->oob_skb in GC.") +Reported-by: Billy Jheng Bing-Jhong +Signed-off-by: Kuniyuki Iwashima +Link: https://lore.kernel.org/r/20240516134835.8332-1-kuniyu@amazon.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/unix/af_unix.c | 28 ++++++++++++++++++++++------ + 1 file changed, 22 insertions(+), 6 deletions(-) + +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 995a2a0b208a1..80f91b5ab4012 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -2005,13 +2005,15 @@ static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other + maybe_add_creds(skb, sock, other); + skb_get(skb); + ++ scm_stat_add(other, skb); ++ ++ spin_lock(&other->sk_receive_queue.lock); + if (ousk->oob_skb) + consume_skb(ousk->oob_skb); +- + WRITE_ONCE(ousk->oob_skb, skb); ++ __skb_queue_tail(&other->sk_receive_queue, skb); ++ spin_unlock(&other->sk_receive_queue.lock); + +- scm_stat_add(other, skb); +- skb_queue_tail(&other->sk_receive_queue, skb); + sk_send_sigurg(other); + unix_state_unlock(other); + other->sk_data_ready(other); +@@ -2516,8 +2518,10 @@ static int unix_stream_recv_urg(struct unix_stream_read_state *state) + + mutex_lock(&u->iolock); + unix_state_lock(sk); ++ spin_lock(&sk->sk_receive_queue.lock); + + if (sock_flag(sk, SOCK_URGINLINE) || !u->oob_skb) { ++ spin_unlock(&sk->sk_receive_queue.lock); + unix_state_unlock(sk); + mutex_unlock(&u->iolock); + return -EINVAL; +@@ -2529,6 +2533,8 @@ static int unix_stream_recv_urg(struct unix_stream_read_state *state) + WRITE_ONCE(u->oob_skb, NULL); + else + skb_get(oob_skb); ++ ++ spin_unlock(&sk->sk_receive_queue.lock); + unix_state_unlock(sk); + + chunk = state->recv_actor(oob_skb, 0, chunk, state); +@@ -2557,6 +2563,10 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk, + consume_skb(skb); + skb = NULL; + } else { ++ struct sk_buff *unlinked_skb = NULL; ++ ++ spin_lock(&sk->sk_receive_queue.lock); ++ + if (skb == u->oob_skb) { + if (copied) { + skb = NULL; +@@ -2568,13 +2578,19 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk, + } else if (flags & MSG_PEEK) { + skb = NULL; + } else { +- skb_unlink(skb, &sk->sk_receive_queue); ++ __skb_unlink(skb, &sk->sk_receive_queue); + WRITE_ONCE(u->oob_skb, NULL); +- if (!WARN_ON_ONCE(skb_unref(skb))) +- kfree_skb(skb); ++ unlinked_skb = skb; + skb = skb_peek(&sk->sk_receive_queue); + } + } ++ ++ spin_unlock(&sk->sk_receive_queue.lock); ++ ++ if (unlinked_skb) { ++ WARN_ON_ONCE(skb_unref(unlinked_skb)); ++ kfree_skb(unlinked_skb); ++ } + } + return skb; + } +-- +2.43.0 + diff --git a/queue-5.15/arm64-asm-bug-add-.align-2-to-the-end-of-__bug_entry.patch b/queue-5.15/arm64-asm-bug-add-.align-2-to-the-end-of-__bug_entry.patch new file mode 100644 index 00000000000..730e5b77f0f --- /dev/null +++ b/queue-5.15/arm64-asm-bug-add-.align-2-to-the-end-of-__bug_entry.patch @@ -0,0 +1,160 @@ +From cdfb649910af04d180778d0481f8f3190afde726 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.15/asoc-mediatek-mt8192-fix-register-configuration-for-.patch b/queue-5.15/asoc-mediatek-mt8192-fix-register-configuration-for-.patch new file mode 100644 index 00000000000..67cbb225e98 --- /dev/null +++ b/queue-5.15/asoc-mediatek-mt8192-fix-register-configuration-for-.patch @@ -0,0 +1,43 @@ +From 2e9daff115cfe65c4e13b5739800ada9ea60f77d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 May 2024 07:31:29 +0000 +Subject: ASoC: mediatek: mt8192: fix register configuration for tdm + +From: Hsin-Te Yuan + +[ Upstream commit a85ed162f0efcfdd664954414a05d1d560cc95dc ] + +For DSP_A, data is a BCK cycle behind LRCK trigger edge. For DSP_B, this +delay doesn't exist. Fix the delay configuration to match the standard. + +Fixes: 52fcd65414abfc ("ASoC: mediatek: mt8192: support tdm in platform driver") +Signed-off-by: Hsin-Te Yuan +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Chen-Yu Tsai +Link: https://lore.kernel.org/r/20240509-8192-tdm-v1-1-530b54645763@chromium.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/mediatek/mt8192/mt8192-dai-tdm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c +index f3bebed2428a7..360259e60de84 100644 +--- a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c ++++ b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c +@@ -566,10 +566,10 @@ static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream, + tdm_con |= 1 << DELAY_DATA_SFT; + tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT; + } else if (tdm_priv->tdm_out_mode == TDM_OUT_DSP_A) { +- tdm_con |= 0 << DELAY_DATA_SFT; ++ tdm_con |= 1 << DELAY_DATA_SFT; + tdm_con |= 0 << LRCK_TDM_WIDTH_SFT; + } else if (tdm_priv->tdm_out_mode == TDM_OUT_DSP_B) { +- tdm_con |= 1 << DELAY_DATA_SFT; ++ tdm_con |= 0 << DELAY_DATA_SFT; + tdm_con |= 0 << LRCK_TDM_WIDTH_SFT; + } + +-- +2.43.0 + diff --git a/queue-5.15/asoc-tas2552-add-tx-path-for-capturing-audio-out-dat.patch b/queue-5.15/asoc-tas2552-add-tx-path-for-capturing-audio-out-dat.patch new file mode 100644 index 00000000000..5c7de08f0c0 --- /dev/null +++ b/queue-5.15/asoc-tas2552-add-tx-path-for-capturing-audio-out-dat.patch @@ -0,0 +1,76 @@ +From 60f657404b1b59801b294abc343b855584909069 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 700baa6314aa8..ba36525a57898 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.15/drm-bridge-tc358775-fix-support-for-jeida-18-and-jei.patch b/queue-5.15/drm-bridge-tc358775-fix-support-for-jeida-18-and-jei.patch new file mode 100644 index 00000000000..f71d423f7de --- /dev/null +++ b/queue-5.15/drm-bridge-tc358775-fix-support-for-jeida-18-and-jei.patch @@ -0,0 +1,75 @@ +From 8e1c7b376e1ba999d2b510ce6605ad014d000a21 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.15/drm-msm-dpu-always-flush-the-slave-intf-on-the-ctl.patch b/queue-5.15/drm-msm-dpu-always-flush-the-slave-intf-on-the-ctl.patch new file mode 100644 index 00000000000..156ea760705 --- /dev/null +++ b/queue-5.15/drm-msm-dpu-always-flush-the-slave-intf-on-the-ctl.patch @@ -0,0 +1,49 @@ +From 1402e2f5b0b7c6c68abc3b221be0b7cd557bc647 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 aa01698d6b256..a05276f0d6982 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 +@@ -441,9 +441,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.update_pending_flush_intf(ctl, phys_enc->intf_idx); + } +-- +2.43.0 + diff --git a/queue-5.15/drm-msm-dsi-print-dual-dsi-adjusted-pclk-instead-of-.patch b/queue-5.15/drm-msm-dsi-print-dual-dsi-adjusted-pclk-instead-of-.patch new file mode 100644 index 00000000000..046b0b75c08 --- /dev/null +++ b/queue-5.15/drm-msm-dsi-print-dual-dsi-adjusted-pclk-instead-of-.patch @@ -0,0 +1,60 @@ +From 961385ae1ba58aba8f5a08015c32141989180c0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Apr 2024 01:57:41 +0200 +Subject: drm/msm/dsi: Print dual-DSI-adjusted pclk instead of original mode + pclk + +From: Marijn Suijten + +[ Upstream commit f12e0e12524a34bf145f7b80122e653ffe3d130a ] + +When dual-DSI (bonded DSI) was added in commit ed9976a09b48 +("drm/msm/dsi: adjust dsi timing for dual dsi mode") some DBG() prints +were not updated, leading to print the original mode->clock rather +than the adjusted (typically the mode clock divided by two, though more +recently also adjusted for DSC compression) msm_host->pixel_clk_rate +which is passed to clk_set_rate() just below. Fix that by printing the +actual pixel_clk_rate that is being set. + +Fixes: ed9976a09b48 ("drm/msm/dsi: adjust dsi timing for dual dsi mode") +Signed-off-by: Marijn Suijten +Reviewed-by: Dmitry Baryshkov +Patchwork: https://patchwork.freedesktop.org/patch/589896/ +Link: https://lore.kernel.org/r/20240417-drm-msm-initial-dualpipe-dsc-fixes-v1-1-78ae3ee9a697@somainline.org +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/dsi/dsi_host.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c +index 8d0612caf6c21..c563ecf6e7b94 100644 +--- a/drivers/gpu/drm/msm/dsi/dsi_host.c ++++ b/drivers/gpu/drm/msm/dsi/dsi_host.c +@@ -501,8 +501,8 @@ int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host) + unsigned long byte_intf_rate; + int ret; + +- DBG("Set clk rates: pclk=%d, byteclk=%lu", +- msm_host->mode->clock, msm_host->byte_clk_rate); ++ DBG("Set clk rates: pclk=%lu, byteclk=%lu", ++ msm_host->pixel_clk_rate, msm_host->byte_clk_rate); + + ret = dev_pm_opp_set_rate(&msm_host->pdev->dev, + msm_host->byte_clk_rate); +@@ -583,9 +583,9 @@ int dsi_link_clk_set_rate_v2(struct msm_dsi_host *msm_host) + { + int ret; + +- DBG("Set clk rates: pclk=%d, byteclk=%lu, esc_clk=%lu, dsi_src_clk=%lu", +- msm_host->mode->clock, msm_host->byte_clk_rate, +- msm_host->esc_clk_rate, msm_host->src_clk_rate); ++ DBG("Set clk rates: pclk=%lu, byteclk=%lu, esc_clk=%lu, dsi_src_clk=%lu", ++ msm_host->pixel_clk_rate, msm_host->byte_clk_rate, ++ msm_host->esc_clk_rate, msm_host->src_clk_rate); + + ret = clk_set_rate(msm_host->byte_clk, msm_host->byte_clk_rate); + if (ret) { +-- +2.43.0 + diff --git a/queue-5.15/fs-ntfs3-use-64-bit-variable-to-avoid-32-bit-overflo.patch b/queue-5.15/fs-ntfs3-use-64-bit-variable-to-avoid-32-bit-overflo.patch new file mode 100644 index 00000000000..226cca86ddb --- /dev/null +++ b/queue-5.15/fs-ntfs3-use-64-bit-variable-to-avoid-32-bit-overflo.patch @@ -0,0 +1,36 @@ +From 105518d141319d5b314274e1750584eb5ca6a1f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Apr 2024 09:45:09 +0300 +Subject: fs/ntfs3: Use 64 bit variable to avoid 32 bit overflow + +From: Konstantin Komarov + +[ Upstream commit e931f6b630ffb22d66caab202a52aa8cbb10c649 ] + +For example, in the expression: + vbo = 2 * vbo + skip + +Fixes: b46acd6a6a627 ("fs/ntfs3: Add NTFS journal") +Signed-off-by: Konstantin Komarov +Signed-off-by: Sasha Levin +--- + fs/ntfs3/fslog.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c +index 6ba1357f3ed4c..369ab64a0b844 100644 +--- a/fs/ntfs3/fslog.c ++++ b/fs/ntfs3/fslog.c +@@ -1181,7 +1181,8 @@ static int read_log_page(struct ntfs_log *log, u32 vbo, + static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first, + struct restart_info *info) + { +- u32 skip, vbo; ++ u32 skip; ++ u64 vbo; + struct RESTART_HDR *r_page = NULL; + + /* Determine which restart area we are looking for. */ +-- +2.43.0 + diff --git a/queue-5.15/fs-ntfs3-use-variable-length-array-instead-of-fixed-.patch b/queue-5.15/fs-ntfs3-use-variable-length-array-instead-of-fixed-.patch new file mode 100644 index 00000000000..6e436a1a948 --- /dev/null +++ b/queue-5.15/fs-ntfs3-use-variable-length-array-instead-of-fixed-.patch @@ -0,0 +1,38 @@ +From 59ef73372bf1308023f4a2188ccf632556747600 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Apr 2024 09:43:58 +0300 +Subject: fs/ntfs3: Use variable length array instead of fixed size + +From: Konstantin Komarov + +[ Upstream commit 1997cdc3e727526aa5d84b32f7cbb3f56459b7ef ] + +Should fix smatch warning: + ntfs_set_label() error: __builtin_memcpy() 'uni->name' too small (20 vs 256) + +Fixes: 4534a70b7056f ("fs/ntfs3: Add headers and misc files") +Reported-by: kernel test robot +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/r/202401091421.3RJ24Mn3-lkp@intel.com/ +Signed-off-by: Konstantin Komarov +Signed-off-by: Sasha Levin +--- + fs/ntfs3/ntfs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/ntfs3/ntfs.h b/fs/ntfs3/ntfs.h +index ba26a465b3091..324c0b036fdc1 100644 +--- a/fs/ntfs3/ntfs.h ++++ b/fs/ntfs3/ntfs.h +@@ -59,7 +59,7 @@ struct GUID { + struct cpu_str { + u8 len; + u8 unused; +- u16 name[10]; ++ u16 name[]; + }; + + struct le_str { +-- +2.43.0 + diff --git a/queue-5.15/ice-interpret-.set_channels-input-differently.patch b/queue-5.15/ice-interpret-.set_channels-input-differently.patch new file mode 100644 index 00000000000..77c97aa9410 --- /dev/null +++ b/queue-5.15/ice-interpret-.set_channels-input-differently.patch @@ -0,0 +1,90 @@ +From f486b1c8b90356d876cc2c0562035a92094585b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 May 2024 12:39:53 -0700 +Subject: ice: Interpret .set_channels() input differently + +From: Larysa Zaremba + +[ Upstream commit 05d6f442f31f901d27dbc64fd504a8ec7d5013de ] + +A bug occurs because a safety check guarding AF_XDP-related queues in +ethnl_set_channels(), does not trigger. This happens, because kernel and +ice driver interpret the ethtool command differently. + +How the bug occurs: +1. ethtool -l -> combined: 40 +2. Attach AF_XDP to queue 30 +3. ethtool -L rx 15 tx 15 + combined number is not specified, so command becomes {rx_count = 15, + tx_count = 15, combined_count = 40}. +4. ethnl_set_channels checks, if there are any AF_XDP of queues from the + new (combined_count + rx_count) to the old one, so from 55 to 40, check + does not trigger. +5. ice interprets `rx 15 tx 15` as 15 combined channels and deletes the + queue that AF_XDP is attached to. + +Interpret the command in a way that is more consistent with ethtool +manual [0] (--show-channels and --set-channels). + +Considering that in the ice driver only the difference between RX and TX +queues forms dedicated channels, change the correct way to set number of +channels to: + +ethtool -L combined 10 /* For symmetric queues */ +ethtool -L combined 8 tx 2 rx 0 /* For asymmetric queues */ + +[0] https://man7.org/linux/man-pages/man8/ethtool.8.html + +Fixes: 87324e747fde ("ice: Implement ethtool ops for channels") +Reviewed-by: Michal Swiatkowski +Signed-off-by: Larysa Zaremba +Tested-by: Chandan Kumar Rout +Tested-by: Pucha Himasekhar Reddy +Acked-by: Maciej Fijalkowski +Signed-off-by: Jacob Keller +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_ethtool.c | 19 ++----------------- + 1 file changed, 2 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index 60f73e775beeb..2440c82ea1fa4 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -3394,7 +3394,6 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch) + struct ice_pf *pf = vsi->back; + int new_rx = 0, new_tx = 0; + bool locked = false; +- u32 curr_combined; + int ret = 0; + + /* do not support changing channels in Safe Mode */ +@@ -3411,22 +3410,8 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch) + return -EOPNOTSUPP; + } + +- curr_combined = ice_get_combined_cnt(vsi); +- +- /* these checks are for cases where user didn't specify a particular +- * value on cmd line but we get non-zero value anyway via +- * get_channels(); look at ethtool.c in ethtool repository (the user +- * space part), particularly, do_schannels() routine +- */ +- if (ch->rx_count == vsi->num_rxq - curr_combined) +- ch->rx_count = 0; +- if (ch->tx_count == vsi->num_txq - curr_combined) +- ch->tx_count = 0; +- if (ch->combined_count == curr_combined) +- ch->combined_count = 0; +- +- if (!(ch->combined_count || (ch->rx_count && ch->tx_count))) { +- netdev_err(dev, "Please specify at least 1 Rx and 1 Tx channel\n"); ++ if (ch->rx_count && ch->tx_count) { ++ netdev_err(dev, "Dedicated RX or TX channels cannot be used simultaneously\n"); + return -EINVAL; + } + +-- +2.43.0 + diff --git a/queue-5.15/input-cyapa-add-missing-input-core-locking-to-suspen.patch b/queue-5.15/input-cyapa-add-missing-input-core-locking-to-suspen.patch new file mode 100644 index 00000000000..487e4cb7709 --- /dev/null +++ b/queue-5.15/input-cyapa-add-missing-input-core-locking-to-suspen.patch @@ -0,0 +1,126 @@ +From 289efbb5e9aeecd8d7af2644db2fdda9c55066c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Oct 2023 14:10:18 +0200 +Subject: Input: cyapa - add missing input core locking to suspend/resume + functions + +From: Marek Szyprowski + +[ Upstream commit 7b4e0b39182cf5e677c1fc092a3ec40e621c25b6 ] + +Grab input->mutex during suspend/resume functions like it is done in +other input drivers. This fixes the following warning during system +suspend/resume cycle on Samsung Exynos5250-based Snow Chromebook: + +------------[ cut here ]------------ +WARNING: CPU: 1 PID: 1680 at drivers/input/input.c:2291 input_device_enabled+0x68/0x6c +Modules linked in: ... +CPU: 1 PID: 1680 Comm: kworker/u4:12 Tainted: G W 6.6.0-rc5-next-20231009 #14109 +Hardware name: Samsung Exynos (Flattened Device Tree) +Workqueue: events_unbound async_run_entry_fn + unwind_backtrace from show_stack+0x10/0x14 + show_stack from dump_stack_lvl+0x58/0x70 + dump_stack_lvl from __warn+0x1a8/0x1cc + __warn from warn_slowpath_fmt+0x18c/0x1b4 + warn_slowpath_fmt from input_device_enabled+0x68/0x6c + input_device_enabled from cyapa_gen3_set_power_mode+0x13c/0x1dc + cyapa_gen3_set_power_mode from cyapa_reinitialize+0x10c/0x15c + cyapa_reinitialize from cyapa_resume+0x48/0x98 + cyapa_resume from dpm_run_callback+0x90/0x298 + dpm_run_callback from device_resume+0xb4/0x258 + device_resume from async_resume+0x20/0x64 + async_resume from async_run_entry_fn+0x40/0x15c + async_run_entry_fn from process_scheduled_works+0xbc/0x6a8 + process_scheduled_works from worker_thread+0x188/0x454 + worker_thread from kthread+0x108/0x140 + kthread from ret_from_fork+0x14/0x28 +Exception stack(0xf1625fb0 to 0xf1625ff8) +... +---[ end trace 0000000000000000 ]--- +... +------------[ cut here ]------------ +WARNING: CPU: 1 PID: 1680 at drivers/input/input.c:2291 input_device_enabled+0x68/0x6c +Modules linked in: ... +CPU: 1 PID: 1680 Comm: kworker/u4:12 Tainted: G W 6.6.0-rc5-next-20231009 #14109 +Hardware name: Samsung Exynos (Flattened Device Tree) +Workqueue: events_unbound async_run_entry_fn + unwind_backtrace from show_stack+0x10/0x14 + show_stack from dump_stack_lvl+0x58/0x70 + dump_stack_lvl from __warn+0x1a8/0x1cc + __warn from warn_slowpath_fmt+0x18c/0x1b4 + warn_slowpath_fmt from input_device_enabled+0x68/0x6c + input_device_enabled from cyapa_gen3_set_power_mode+0x13c/0x1dc + cyapa_gen3_set_power_mode from cyapa_reinitialize+0x10c/0x15c + cyapa_reinitialize from cyapa_resume+0x48/0x98 + cyapa_resume from dpm_run_callback+0x90/0x298 + dpm_run_callback from device_resume+0xb4/0x258 + device_resume from async_resume+0x20/0x64 + async_resume from async_run_entry_fn+0x40/0x15c + async_run_entry_fn from process_scheduled_works+0xbc/0x6a8 + process_scheduled_works from worker_thread+0x188/0x454 + worker_thread from kthread+0x108/0x140 + kthread from ret_from_fork+0x14/0x28 +Exception stack(0xf1625fb0 to 0xf1625ff8) +... +---[ end trace 0000000000000000 ]--- + +Fixes: d69f0a43c677 ("Input: use input_device_enabled()") +Signed-off-by: Marek Szyprowski +Reviewed-by: Andrzej Pietrasiewicz +Link: https://lore.kernel.org/r/20231009121018.1075318-1-m.szyprowski@samsung.com +Signed-off-by: Dmitry Torokhov +Signed-off-by: Sasha Levin +--- + drivers/input/mouse/cyapa.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c +index 77cc653edca22..e401934df4642 100644 +--- a/drivers/input/mouse/cyapa.c ++++ b/drivers/input/mouse/cyapa.c +@@ -1357,10 +1357,16 @@ static int __maybe_unused cyapa_suspend(struct device *dev) + u8 power_mode; + int error; + +- error = mutex_lock_interruptible(&cyapa->state_sync_lock); ++ error = mutex_lock_interruptible(&cyapa->input->mutex); + if (error) + return error; + ++ error = mutex_lock_interruptible(&cyapa->state_sync_lock); ++ if (error) { ++ mutex_unlock(&cyapa->input->mutex); ++ return error; ++ } ++ + /* + * Runtime PM is enable only when device is in operational mode and + * users in use, so need check it before disable it to +@@ -1395,6 +1401,8 @@ static int __maybe_unused cyapa_suspend(struct device *dev) + cyapa->irq_wake = (enable_irq_wake(client->irq) == 0); + + mutex_unlock(&cyapa->state_sync_lock); ++ mutex_unlock(&cyapa->input->mutex); ++ + return 0; + } + +@@ -1404,6 +1412,7 @@ static int __maybe_unused cyapa_resume(struct device *dev) + struct cyapa *cyapa = i2c_get_clientdata(client); + int error; + ++ mutex_lock(&cyapa->input->mutex); + mutex_lock(&cyapa->state_sync_lock); + + if (device_may_wakeup(dev) && cyapa->irq_wake) { +@@ -1422,6 +1431,7 @@ static int __maybe_unused cyapa_resume(struct device *dev) + enable_irq(client->irq); + + mutex_unlock(&cyapa->state_sync_lock); ++ mutex_unlock(&cyapa->input->mutex); + return 0; + } + +-- +2.43.0 + diff --git a/queue-5.15/input-ims-pcu-fix-printf-string-overflow.patch b/queue-5.15/input-ims-pcu-fix-printf-string-overflow.patch new file mode 100644 index 00000000000..10717f2e4ac --- /dev/null +++ b/queue-5.15/input-ims-pcu-fix-printf-string-overflow.patch @@ -0,0 +1,43 @@ +From f54158a701ed660c6f56ef5f6f1ae7209ca38e3d 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 6f38aa23a1ff6..b3215c97ee02d 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.15/input-ioc3kbd-add-device-table.patch b/queue-5.15/input-ioc3kbd-add-device-table.patch new file mode 100644 index 00000000000..5b2215f1b55 --- /dev/null +++ b/queue-5.15/input-ioc3kbd-add-device-table.patch @@ -0,0 +1,45 @@ +From 894ac559b4b2c340a5f9fe465d9ebf61c916216c 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.15/input-ioc3kbd-convert-to-platform-remove-callback-re.patch b/queue-5.15/input-ioc3kbd-convert-to-platform-remove-callback-re.patch new file mode 100644 index 00000000000..29138739af0 --- /dev/null +++ b/queue-5.15/input-ioc3kbd-convert-to-platform-remove-callback-re.patch @@ -0,0 +1,64 @@ +From 06d84d287a0209f2a5f3856363c2b97dce5951e5 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.15/input-pm8xxx-vibrator-correct-vib_max_levels-calcula.patch b/queue-5.15/input-pm8xxx-vibrator-correct-vib_max_levels-calcula.patch new file mode 100644 index 00000000000..ad0b462ebe6 --- /dev/null +++ b/queue-5.15/input-pm8xxx-vibrator-correct-vib_max_levels-calcula.patch @@ -0,0 +1,55 @@ +From 49332c210689cef8550e25cc0706f27ded611985 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.15/ipv6-sr-fix-memleak-in-seg6_hmac_init_algo.patch b/queue-5.15/ipv6-sr-fix-memleak-in-seg6_hmac_init_algo.patch new file mode 100644 index 00000000000..03aa40605fb --- /dev/null +++ b/queue-5.15/ipv6-sr-fix-memleak-in-seg6_hmac_init_algo.patch @@ -0,0 +1,125 @@ +From fa067db3bfdcc91147cbbbf2c78786fab10e64b6 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 b7d6b64cc5320..fdbc06f356d66 100644 +--- a/net/ipv6/seg6_hmac.c ++++ b/net/ipv6/seg6_hmac.c +@@ -354,6 +354,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); + +@@ -364,12 +365,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; + } +@@ -381,18 +384,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) +@@ -412,22 +419,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.15/ipv6-sr-fix-missing-sk_buff-release-in-seg6_input_co.patch b/queue-5.15/ipv6-sr-fix-missing-sk_buff-release-in-seg6_input_co.patch new file mode 100644 index 00000000000..50ec969b0fa --- /dev/null +++ b/queue-5.15/ipv6-sr-fix-missing-sk_buff-release-in-seg6_input_co.patch @@ -0,0 +1,76 @@ +From e63f775c008862ba9dff9e6dc16157dc7599d38b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 May 2024 18:45:41 +0200 +Subject: ipv6: sr: fix missing sk_buff release in seg6_input_core + +From: Andrea Mayer + +[ Upstream commit 5447f9708d9e4c17a647b16a9cb29e9e02820bd9 ] + +The seg6_input() function is responsible for adding the SRH into a +packet, delegating the operation to the seg6_input_core(). This function +uses the skb_cow_head() to ensure that there is sufficient headroom in +the sk_buff for accommodating the link-layer header. +In the event that the skb_cow_header() function fails, the +seg6_input_core() catches the error but it does not release the sk_buff, +which will result in a memory leak. + +This issue was introduced in commit af3b5158b89d ("ipv6: sr: fix BUG due +to headroom too small after SRH push") and persists even after commit +7a3f5b0de364 ("netfilter: add netfilter hooks to SRv6 data plane"), +where the entire seg6_input() code was refactored to deal with netfilter +hooks. + +The proposed patch addresses the identified memory leak by requiring the +seg6_input_core() function to release the sk_buff in the event that +skb_cow_head() fails. + +Fixes: af3b5158b89d ("ipv6: sr: fix BUG due to headroom too small after SRH push") +Signed-off-by: Andrea Mayer +Reviewed-by: Simon Horman +Reviewed-by: David Ahern +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ipv6/seg6_iptunnel.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c +index e756ba705fd9b..f98bb719190be 100644 +--- a/net/ipv6/seg6_iptunnel.c ++++ b/net/ipv6/seg6_iptunnel.c +@@ -327,10 +327,8 @@ static int seg6_input_core(struct net *net, struct sock *sk, + int err; + + err = seg6_do_srh(skb); +- if (unlikely(err)) { +- kfree_skb(skb); +- return err; +- } ++ if (unlikely(err)) ++ goto drop; + + slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate); + +@@ -355,7 +353,7 @@ static int seg6_input_core(struct net *net, struct sock *sk, + + err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); + if (unlikely(err)) +- return err; ++ goto drop; + + if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled)) + return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, +@@ -363,6 +361,9 @@ static int seg6_input_core(struct net *net, struct sock *sk, + skb_dst(skb)->dev, seg6_input_finish); + + return seg6_input_finish(dev_net(skb->dev), NULL, skb); ++drop: ++ kfree_skb(skb); ++ return err; + } + + static int seg6_input_nf(struct sk_buff *skb) +-- +2.43.0 + diff --git a/queue-5.15/media-cec-abort-if-the-current-transmit-was-canceled.patch b/queue-5.15/media-cec-abort-if-the-current-transmit-was-canceled.patch new file mode 100644 index 00000000000..2190b1ffbd0 --- /dev/null +++ b/queue-5.15/media-cec-abort-if-the-current-transmit-was-canceled.patch @@ -0,0 +1,125 @@ +From a1b100aa927f2a51ee8228ede70c26ec6100e7b3 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 730f169c93ba3..a0a19f37ef5ba 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.15/media-cec-adap.c-drop-activate_cnt-use-state-info-in.patch b/queue-5.15/media-cec-adap.c-drop-activate_cnt-use-state-info-in.patch new file mode 100644 index 00000000000..2c907d3f6f3 --- /dev/null +++ b/queue-5.15/media-cec-adap.c-drop-activate_cnt-use-state-info-in.patch @@ -0,0 +1,314 @@ +From 4fd270de414be25bdf20c00f442f2af91201a341 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 f53d0de176d85..11e091255795e 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.15/media-cec-call-enable_adap-on-s_log_addrs.patch b/queue-5.15/media-cec-call-enable_adap-on-s_log_addrs.patch new file mode 100644 index 00000000000..ea4ab58f5e9 --- /dev/null +++ b/queue-5.15/media-cec-call-enable_adap-on-s_log_addrs.patch @@ -0,0 +1,389 @@ +From c4dd77c36d9563bfeaac64571830b0cd20d556e6 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 1b72063f242e0..730f169c93ba3 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 4510a4bec659a..398eeacf1eb59 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.15/media-cec-cec-adap-always-cancel-work-in-cec_transmi.patch b/queue-5.15/media-cec-cec-adap-always-cancel-work-in-cec_transmi.patch new file mode 100644 index 00000000000..ee67f873626 --- /dev/null +++ b/queue-5.15/media-cec-cec-adap-always-cancel-work-in-cec_transmi.patch @@ -0,0 +1,39 @@ +From e5b0b39e5de63eb08f3cdcb9886f55577f619341 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 01ff1329e01c5..1b72063f242e0 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -914,8 +914,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.15/media-cec-cec-api-add-locking-in-cec_release.patch b/queue-5.15/media-cec-cec-api-add-locking-in-cec_release.patch new file mode 100644 index 00000000000..aedebfd7a2e --- /dev/null +++ b/queue-5.15/media-cec-cec-api-add-locking-in-cec_release.patch @@ -0,0 +1,46 @@ +From 643f1d2d811e0b921f6b8a265f2a32dc907518bd 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 52c30e4e20055..4510a4bec659a 100644 +--- a/drivers/media/cec/core/cec-api.c ++++ b/drivers/media/cec/core/cec-api.c +@@ -678,6 +678,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); +@@ -695,6 +697,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.15/media-cec-core-avoid-confusing-transmit-timed-out-me.patch b/queue-5.15/media-cec-core-avoid-confusing-transmit-timed-out-me.patch new file mode 100644 index 00000000000..53b5fb319c4 --- /dev/null +++ b/queue-5.15/media-cec-core-avoid-confusing-transmit-timed-out-me.patch @@ -0,0 +1,73 @@ +From ce291808d243d8189fab94fc8ee6c78dc273ddf8 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 40fea5d3ffe50..bf5386d0f5858 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.15/media-cec-core-avoid-recursive-cec_claim_log_addrs.patch b/queue-5.15/media-cec-core-avoid-recursive-cec_claim_log_addrs.patch new file mode 100644 index 00000000000..c93ca725e0d --- /dev/null +++ b/queue-5.15/media-cec-core-avoid-recursive-cec_claim_log_addrs.patch @@ -0,0 +1,81 @@ +From a6165396b0854f258218c638baacca1445660092 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 11e091255795e..40fea5d3ffe50 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 a44cd1484a13c..7f260f2cbb153 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.15/media-cec-correctly-pass-on-reply-results.patch b/queue-5.15/media-cec-correctly-pass-on-reply-results.patch new file mode 100644 index 00000000000..d5a8795f73e --- /dev/null +++ b/queue-5.15/media-cec-correctly-pass-on-reply-results.patch @@ -0,0 +1,166 @@ +From 5ce9f190d0c75eb10e55fbecfb0523902b75e201 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 a0a19f37ef5ba..297842398cf30 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.15/media-cec-use-call_op-and-check-for-unregistered.patch b/queue-5.15/media-cec-use-call_op-and-check-for-unregistered.patch new file mode 100644 index 00000000000..2739ec74f7a --- /dev/null +++ b/queue-5.15/media-cec-use-call_op-and-check-for-unregistered.patch @@ -0,0 +1,312 @@ +From 1f0fcefe9e295cfcf78e01627c269c5fe614f08f 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 297842398cf30..f53d0de176d85 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 398eeacf1eb59..a44cd1484a13c 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 ec67065d52021..34f1631b77098 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 fb101f15865c8..e7d63f6acb300 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 0eb90cc0ffb0f..99e69c49e0c9e 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.15/media-flexcop-usb-clean-up-endpoint-sanity-checks.patch b/queue-5.15/media-flexcop-usb-clean-up-endpoint-sanity-checks.patch new file mode 100644 index 00000000000..ba656fe066b --- /dev/null +++ b/queue-5.15/media-flexcop-usb-clean-up-endpoint-sanity-checks.patch @@ -0,0 +1,56 @@ +From cba7c41998eb019a0a17066756a24d8cb56d16b9 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 8ab1be03e7319..0b5c2f3a54ab4 100644 +--- a/drivers/media/usb/b2c2/flexcop-usb.c ++++ b/drivers/media/usb/b2c2/flexcop-usb.c +@@ -501,17 +501,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.15/media-flexcop-usb-fix-sanity-check-of-bnumendpoints.patch b/queue-5.15/media-flexcop-usb-fix-sanity-check-of-bnumendpoints.patch new file mode 100644 index 00000000000..aac76123373 --- /dev/null +++ b/queue-5.15/media-flexcop-usb-fix-sanity-check-of-bnumendpoints.patch @@ -0,0 +1,40 @@ +From cd65f17359db1bef1862903042cb055984f05310 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 0b5c2f3a54ab4..0354614351cbf 100644 +--- a/drivers/media/usb/b2c2/flexcop-usb.c ++++ b/drivers/media/usb/b2c2/flexcop-usb.c +@@ -513,7 +513,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.15/media-stk1160-fix-bounds-checking-in-stk1160_copy_vi.patch b/queue-5.15/media-stk1160-fix-bounds-checking-in-stk1160_copy_vi.patch new file mode 100644 index 00000000000..4429dced4aa --- /dev/null +++ b/queue-5.15/media-stk1160-fix-bounds-checking-in-stk1160_copy_vi.patch @@ -0,0 +1,84 @@ +From b46e4e7c9171c7c47bcb19d9bf53e534f399e2ba 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.15/mmc-sdhci_am654-add-itapdlysel-in-sdhci_j721e_4bit_s.patch b/queue-5.15/mmc-sdhci_am654-add-itapdlysel-in-sdhci_j721e_4bit_s.patch new file mode 100644 index 00000000000..929479a9551 --- /dev/null +++ b/queue-5.15/mmc-sdhci_am654-add-itapdlysel-in-sdhci_j721e_4bit_s.patch @@ -0,0 +1,60 @@ +From 63996757ce0ee5556ecc974a0399bc18b53ece6a 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 2c73396383733..9cdc5e7889b45 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.15/mmc-sdhci_am654-add-otap-itap-delay-enable.patch b/queue-5.15/mmc-sdhci_am654-add-otap-itap-delay-enable.patch new file mode 100644 index 00000000000..36d8d1cd56c --- /dev/null +++ b/queue-5.15/mmc-sdhci_am654-add-otap-itap-delay-enable.patch @@ -0,0 +1,168 @@ +From d71f1a4ba00d3c96853bd0b076bc5681976bd24b 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 8203fc15c507a..2c73396383733 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.15/mmc-sdhci_am654-add-tuning-algorithm-for-delay-chain.patch b/queue-5.15/mmc-sdhci_am654-add-tuning-algorithm-for-delay-chain.patch new file mode 100644 index 00000000000..96c4f5f129d --- /dev/null +++ b/queue-5.15/mmc-sdhci_am654-add-tuning-algorithm-for-delay-chain.patch @@ -0,0 +1,195 @@ +From df9bd8305bef1a6d1675940e61d167ab3ed7e6d7 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 210701e4fc137..ec77cf4d5dcdc 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.15/mmc-sdhci_am654-drop-lookup-for-deprecated-ti-otap-d.patch b/queue-5.15/mmc-sdhci_am654-drop-lookup-for-deprecated-ti-otap-d.patch new file mode 100644 index 00000000000..956b692d5f4 --- /dev/null +++ b/queue-5.15/mmc-sdhci_am654-drop-lookup-for-deprecated-ti-otap-d.patch @@ -0,0 +1,102 @@ +From 07771a73c3b67f2eb31651edcb31392ec283ef1d 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 e68fce4413c8a..8203fc15c507a 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.15/mmc-sdhci_am654-fix-itapdly-for-hs400-timing.patch b/queue-5.15/mmc-sdhci_am654-fix-itapdly-for-hs400-timing.patch new file mode 100644 index 00000000000..87d8dcdca57 --- /dev/null +++ b/queue-5.15/mmc-sdhci_am654-fix-itapdly-for-hs400-timing.patch @@ -0,0 +1,59 @@ +From a37a62cae67d883a350e05c191fbcfe4964b3997 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 9cdc5e7889b45..230b61902e39d 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.15/mmc-sdhci_am654-write-itapdly-for-ddr52-timing.patch b/queue-5.15/mmc-sdhci_am654-write-itapdly-for-ddr52-timing.patch new file mode 100644 index 00000000000..277993e6605 --- /dev/null +++ b/queue-5.15/mmc-sdhci_am654-write-itapdly-for-ddr52-timing.patch @@ -0,0 +1,39 @@ +From 8368c078ca58f982fbcf22a2c9ee1f80f3e29d06 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 ec77cf4d5dcdc..e68fce4413c8a 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.15/net-always-descend-into-dsa-folder-with-config_net_d.patch b/queue-5.15/net-always-descend-into-dsa-folder-with-config_net_d.patch new file mode 100644 index 00000000000..0b08f4a0d5b --- /dev/null +++ b/queue-5.15/net-always-descend-into-dsa-folder-with-config_net_d.patch @@ -0,0 +1,58 @@ +From 72d9721cafe70bc3dfd91754134f9608110b392d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 May 2024 09:56:30 -0700 +Subject: net: Always descend into dsa/ folder with CONFIG_NET_DSA enabled + +From: Florian Fainelli + +[ Upstream commit b1fa60ec252fba39130107074becd12d0b3f83ec ] + +Stephen reported that he was unable to get the dsa_loop driver to get +probed, and the reason ended up being because he had CONFIG_FIXED_PHY=y +in his kernel configuration. As Masahiro explained it: + + "obj-m += dsa/" means everything under dsa/ must be modular. + + If there is a built-in object under dsa/ with CONFIG_NET_DSA=m, + you cannot do "obj-$(CONFIG_NET_DSA) += dsa/". + + You need to change it back to "obj-y += dsa/". + +This was the case here whereby CONFIG_NET_DSA=m, and so the +obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdinfo.o rule is not executed and +the DSA loop mdio_board info structure is not registered with the +kernel, and eventually the device is simply not found. + +To preserve the intention of the original commit of limiting the amount +of folder descending, conditionally descend into drivers/net/dsa when +CONFIG_NET_DSA is enabled. + +Fixes: 227d72063fcc ("dsa: simplify Kconfig symbols and dependencies") +Reported-by: Stephen Langstaff +Signed-off-by: Florian Fainelli +Reviewed-by: Vladimir Oltean +Reviewed-by: Alexander Lobakin +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/Makefile | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/Makefile b/drivers/net/Makefile +index 50e60852f1286..e5ed9dff10a24 100644 +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -46,7 +46,9 @@ obj-$(CONFIG_ARCNET) += arcnet/ + obj-$(CONFIG_DEV_APPLETALK) += appletalk/ + obj-$(CONFIG_CAIF) += caif/ + obj-$(CONFIG_CAN) += can/ +-obj-$(CONFIG_NET_DSA) += dsa/ ++ifdef CONFIG_NET_DSA ++obj-y += dsa/ ++endif + obj-$(CONFIG_ETHERNET) += ethernet/ + obj-$(CONFIG_FDDI) += fddi/ + obj-$(CONFIG_HIPPI) += hippi/ +-- +2.43.0 + diff --git a/queue-5.15/net-fec-avoid-lock-evasion-when-reading-pps_enable.patch b/queue-5.15/net-fec-avoid-lock-evasion-when-reading-pps_enable.patch new file mode 100644 index 00000000000..04cad76a08c --- /dev/null +++ b/queue-5.15/net-fec-avoid-lock-evasion-when-reading-pps_enable.patch @@ -0,0 +1,62 @@ +From c78d01eacd2f0f129bf538863ff39c3317e7efc4 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.15/nfc-nci-fix-handling-of-zero-length-payload-packets-.patch b/queue-5.15/nfc-nci-fix-handling-of-zero-length-payload-packets-.patch new file mode 100644 index 00000000000..4ccdd818772 --- /dev/null +++ b/queue-5.15/nfc-nci-fix-handling-of-zero-length-payload-packets-.patch @@ -0,0 +1,42 @@ +From 0d0510989471fd77b8b5b3367d58a26ae7a6419b 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 a32e49278a3f4..4d718c6921e07 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -1531,8 +1531,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.15/nfc-nci-fix-kcov-check-in-nci_rx_work.patch b/queue-5.15/nfc-nci-fix-kcov-check-in-nci_rx_work.patch new file mode 100644 index 00000000000..bf68fb02906 --- /dev/null +++ b/queue-5.15/nfc-nci-fix-kcov-check-in-nci_rx_work.patch @@ -0,0 +1,45 @@ +From 4a50d3dc95f081de9c755283d52ed98b95fdc0d3 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 64c87b43035da..a32e49278a3f4 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -1531,6 +1531,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.15/nfc-nci-fix-uninit-value-in-nci_rx_work.patch b/queue-5.15/nfc-nci-fix-uninit-value-in-nci_rx_work.patch new file mode 100644 index 00000000000..9d231f3e5af --- /dev/null +++ b/queue-5.15/nfc-nci-fix-uninit-value-in-nci_rx_work.patch @@ -0,0 +1,63 @@ +From 3deb92bf45382aeaeb310961c081c2952a4879ba 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 2a821f2b2ffe8..64c87b43035da 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -1466,6 +1466,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) +@@ -1516,7 +1529,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.15/nfsv4-fixup-smatch-warning-for-ambiguous-return.patch b/queue-5.15/nfsv4-fixup-smatch-warning-for-ambiguous-return.patch new file mode 100644 index 00000000000..50c1551c9d6 --- /dev/null +++ b/queue-5.15/nfsv4-fixup-smatch-warning-for-ambiguous-return.patch @@ -0,0 +1,67 @@ +From 83b77fb229d4875c1258eb227869d805391fe23d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Apr 2024 14:49:29 -0400 +Subject: NFSv4: Fixup smatch warning for ambiguous return + +From: Benjamin Coddington + +[ Upstream commit 37ffe06537af3e3ec212e7cbe941046fce0a822f ] + +Dan Carpenter reports smatch warning for nfs4_try_migration() when a memory +allocation failure results in a zero return value. In this case, a +transient allocation failure error will likely be retried the next time the +server responds with NFS4ERR_MOVED. + +We can fixup the smatch warning with a small refactor: attempt all three +allocations before testing and returning on a failure. + +Reported-by: Dan Carpenter +Fixes: c3ed222745d9 ("NFSv4: Fix free of uninitialized nfs4_label on referral lookup.") +Signed-off-by: Benjamin Coddington +Reviewed-by: Dan Carpenter +Reviewed-by: Chuck Lever +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4state.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c +index d7868cc527805..d452fa85a567c 100644 +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -2102,6 +2102,7 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred + { + struct nfs_client *clp = server->nfs_client; + struct nfs4_fs_locations *locations = NULL; ++ struct nfs_fattr *fattr; + struct inode *inode; + struct page *page; + int status, result; +@@ -2111,19 +2112,16 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred + (unsigned long long)server->fsid.minor, + clp->cl_hostname); + +- result = 0; + page = alloc_page(GFP_KERNEL); + locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL); +- if (page == NULL || locations == NULL) { +- dprintk("<-- %s: no memory\n", __func__); +- goto out; +- } +- locations->fattr = nfs_alloc_fattr(); +- if (locations->fattr == NULL) { ++ fattr = nfs_alloc_fattr(); ++ if (page == NULL || locations == NULL || fattr == NULL) { + dprintk("<-- %s: no memory\n", __func__); ++ result = 0; + goto out; + } + ++ locations->fattr = fattr; + inode = d_inode(server->super->s_root); + result = nfs4_proc_get_locations(server, NFS_FH(inode), locations, + page, cred); +-- +2.43.0 + diff --git a/queue-5.15/null_blk-fix-the-warning-modpost-missing-module_desc.patch b/queue-5.15/null_blk-fix-the-warning-modpost-missing-module_desc.patch new file mode 100644 index 00000000000..ac511a6e44e --- /dev/null +++ b/queue-5.15/null_blk-fix-the-warning-modpost-missing-module_desc.patch @@ -0,0 +1,34 @@ +From 4cd3a50d5f0f18dd2e83cb72aeae8e0c7775c2d8 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 1fe5d33a5798d..ec78d9ad3e9bc 100644 +--- a/drivers/block/null_blk/main.c ++++ b/drivers/block/null_blk/main.c +@@ -2053,4 +2053,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.15/openvswitch-set-the-skbuff-pkt_type-for-proper-pmtud.patch b/queue-5.15/openvswitch-set-the-skbuff-pkt_type-for-proper-pmtud.patch new file mode 100644 index 00000000000..23caae851ab --- /dev/null +++ b/queue-5.15/openvswitch-set-the-skbuff-pkt_type-for-proper-pmtud.patch @@ -0,0 +1,101 @@ +From 2881ed9fed2a96ffca118407f854cca07993d3d0 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 aca6e2b599c86..85af0e9e0ac6d 100644 +--- a/net/openvswitch/actions.c ++++ b/net/openvswitch/actions.c +@@ -924,6 +924,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.15/powerpc-pseries-add-failure-related-checks-for-h_get.patch b/queue-5.15/powerpc-pseries-add-failure-related-checks-for-h_get.patch new file mode 100644 index 00000000000..fc98461d0e2 --- /dev/null +++ b/queue-5.15/powerpc-pseries-add-failure-related-checks-for-h_get.patch @@ -0,0 +1,86 @@ +From bb4092fd03b19325ad578d85d02ab56d1594cbb1 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 9bcf345cb208b..c25f160bb9978 100644 +--- a/arch/powerpc/include/asm/hvcall.h ++++ b/arch/powerpc/include/asm/hvcall.h +@@ -513,7 +513,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 6c196b9413553..c2fff9a339285 100644 +--- a/arch/powerpc/platforms/pseries/lpar.c ++++ b/arch/powerpc/platforms/pseries/lpar.c +@@ -1886,10 +1886,10 @@ notrace 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 a291b5a94d4da..fea4dfa54e3c2 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.15/regulator-bd71828-don-t-overwrite-runtime-voltages.patch b/queue-5.15/regulator-bd71828-don-t-overwrite-runtime-voltages.patch new file mode 100644 index 00000000000..8c22969e9cb --- /dev/null +++ b/queue-5.15/regulator-bd71828-don-t-overwrite-runtime-voltages.patch @@ -0,0 +1,186 @@ +From 480aa44c91c8bb905f9a3ce6adb10dd32ffe968d 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 a4f09a5a30cab..d07f0d120ca71 100644 +--- a/drivers/regulator/bd71828-regulator.c ++++ b/drivers/regulator/bd71828-regulator.c +@@ -207,14 +207,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), +@@ -289,13 +286,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, +@@ -330,13 +321,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, +@@ -371,13 +356,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, +@@ -494,13 +473,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, +@@ -534,13 +507,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, +@@ -574,13 +541,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, +@@ -615,13 +576,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, +@@ -656,13 +611,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, +@@ -721,9 +670,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.15/riscv-stacktrace-fixed-walk_stackframe.patch b/queue-5.15/riscv-stacktrace-fixed-walk_stackframe.patch new file mode 100644 index 00000000000..943b914e900 --- /dev/null +++ b/queue-5.15/riscv-stacktrace-fixed-walk_stackframe.patch @@ -0,0 +1,132 @@ +From b607957bc247e88f98dba5981ba89725e7e3d349 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 26f3916eea47c..94721c484d638 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)(void *, unsigned long), void *arg) + { +@@ -43,21 +53,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) || (level++ >= 0 && !fn(arg, pc)))) + 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.15/riscv-stacktrace-make-walk_stackframe-cross-pt_regs-.patch b/queue-5.15/riscv-stacktrace-make-walk_stackframe-cross-pt_regs-.patch new file mode 100644 index 00000000000..82a414e75c3 --- /dev/null +++ b/queue-5.15/riscv-stacktrace-make-walk_stackframe-cross-pt_regs-.patch @@ -0,0 +1,126 @@ +From 3a99d9425e5a389be7fef083c481e14c6de795e3 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 5ca2860cc06cd..851c967c49ccd 100644 +--- a/arch/riscv/kernel/entry.S ++++ b/arch/riscv/kernel/entry.S +@@ -231,7 +231,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 +@@ -245,6 +245,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 894ae66421a76..26f3916eea47c 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)(void *, unsigned long), void *arg) + { +@@ -62,6 +64,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.15/rpcrdma-fix-handling-for-rdma_cm_event_device_remova.patch b/queue-5.15/rpcrdma-fix-handling-for-rdma_cm_event_device_remova.patch new file mode 100644 index 00000000000..66eb8adeffa --- /dev/null +++ b/queue-5.15/rpcrdma-fix-handling-for-rdma_cm_event_device_remova.patch @@ -0,0 +1,51 @@ +From 11bbb043a966c00ea5537ab7a0ab535d755a0181 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 41095a278f798..34413d4ab0e52 100644 +--- a/net/sunrpc/xprtrdma/verbs.c ++++ b/net/sunrpc/xprtrdma/verbs.c +@@ -258,7 +258,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.15/scsi-qla2xxx-replace-all-non-returning-strlcpy-with-.patch b/queue-5.15/scsi-qla2xxx-replace-all-non-returning-strlcpy-with-.patch new file mode 100644 index 00000000000..1cdecbf02df --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-replace-all-non-returning-strlcpy-with-.patch @@ -0,0 +1,117 @@ +From 247e562659eac17374dc6e75156db21336a69f43 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 585df40e95bb0..531e0ea87202e 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -5145,7 +5145,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 { +@@ -5153,14 +5153,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 f726eb8449c5e..083f94e43fba0 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; + } + +@@ -1850,21 +1850,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.15/series b/queue-5.15/series index a2ceaa2acf9..f7b4ddbe215 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -244,3 +244,62 @@ s390-vdso-use-standard-stack-frame-layout.patch s390-ipl-fix-incorrect-initialization-of-len-fields-.patch s390-ipl-fix-incorrect-initialization-of-nvme-dump-b.patch s390-boot-remove-alt_stfle_fac_list-from-decompresso.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-dsi-print-dual-dsi-adjusted-pclk-instead-of-.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 +fs-ntfs3-use-64-bit-variable-to-avoid-32-bit-overflo.patch +fs-ntfs3-use-variable-length-array-instead-of-fixed-.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 +input-cyapa-add-missing-input-core-locking-to-suspen.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-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 +asoc-mediatek-mt8192-fix-register-configuration-for-.patch +regulator-bd71828-don-t-overwrite-runtime-voltages.patch +x86-kconfig-select-arch_want_frame_pointers-again-wh.patch +net-always-descend-into-dsa-folder-with-config_net_d.patch +ipv6-sr-fix-missing-sk_buff-release-in-seg6_input_co.patch +nfc-nci-fix-uninit-value-in-nci_rx_work.patch +asoc-tas2552-add-tx-path-for-capturing-audio-out-dat.patch +nfsv4-fixup-smatch-warning-for-ambiguous-return.patch +sunrpc-fix-nfsacl-rpc-retry-on-soft-mount.patch +rpcrdma-fix-handling-for-rdma_cm_event_device_remova.patch +af_unix-update-unix_sk-sk-oob_skb-under-sk_receive_q.patch +ipv6-sr-fix-memleak-in-seg6_hmac_init_algo.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-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 +ice-interpret-.set_channels-input-differently.patch diff --git a/queue-5.15/sunrpc-fix-nfsacl-rpc-retry-on-soft-mount.patch b/queue-5.15/sunrpc-fix-nfsacl-rpc-retry-on-soft-mount.patch new file mode 100644 index 00000000000..629b32ae5ff --- /dev/null +++ b/queue-5.15/sunrpc-fix-nfsacl-rpc-retry-on-soft-mount.patch @@ -0,0 +1,55 @@ +From cc1d2da77fc80a00fdf6c0d661c630b91225953f 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 59fd6dedbbed2..f73d4593625cd 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -982,6 +982,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.15/tcp-fix-shift-out-of-bounds-in-dctcp_update_alpha.patch b/queue-5.15/tcp-fix-shift-out-of-bounds-in-dctcp_update_alpha.patch new file mode 100644 index 00000000000..aa325b9a36f --- /dev/null +++ b/queue-5.15/tcp-fix-shift-out-of-bounds-in-dctcp_update_alpha.patch @@ -0,0 +1,125 @@ +From 892e7c9e11f1cdc046078a66c268301ba4277956 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 43bcefbaefbb1..d6db7c25649f9 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.15/tcp-remove-64-kbyte-limit-for-initial-tp-rcv_wnd-val.patch b/queue-5.15/tcp-remove-64-kbyte-limit-for-initial-tp-rcv_wnd-val.patch new file mode 100644 index 00000000000..f5b3611d202 --- /dev/null +++ b/queue-5.15/tcp-remove-64-kbyte-limit-for-initial-tp-rcv_wnd-val.patch @@ -0,0 +1,76 @@ +From 12c59477dac82528294ef140ba1ce9bfd3e39a36 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 0fb84e57a2d49..dc35dbbbb5b33 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.15/tls-fix-missing-memory-barrier-in-tls_init.patch b/queue-5.15/tls-fix-missing-memory-barrier-in-tls_init.patch new file mode 100644 index 00000000000..b78ad901949 --- /dev/null +++ b/queue-5.15/tls-fix-missing-memory-barrier-in-tls_init.patch @@ -0,0 +1,73 @@ +From e7f2cee08c9c8f4b707f8b7de4961f4ab1cece26 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 79ea1ab34570f..4a3bf8528da7c 100644 +--- a/net/tls/tls_main.c ++++ b/net/tls/tls_main.c +@@ -636,9 +636,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.15/um-add-winch-to-winch_handlers-before-registering-wi.patch b/queue-5.15/um-add-winch-to-winch_handlers-before-registering-wi.patch new file mode 100644 index 00000000000..e0d1a81017b --- /dev/null +++ b/queue-5.15/um-add-winch-to-winch_handlers-before-registering-wi.patch @@ -0,0 +1,68 @@ +From 04f8aea837c39843dea19abcf4cc4c66ad17f3bf 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 02b0befd67632..95ad6b190d1d1 100644 +--- a/arch/um/drivers/line.c ++++ b/arch/um/drivers/line.c +@@ -673,24 +673,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.15/um-fix-return-value-in-ubd_init.patch b/queue-5.15/um-fix-return-value-in-ubd_init.patch new file mode 100644 index 00000000000..a8ba555dede --- /dev/null +++ b/queue-5.15/um-fix-return-value-in-ubd_init.patch @@ -0,0 +1,46 @@ +From 18d9e4d5c8dcba9cb64dfd18a75080a3f4e502cd 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 fefd343412c79..b3a4cc5a2091f 100644 +--- a/arch/um/drivers/ubd_kern.c ++++ b/arch/um/drivers/ubd_kern.c +@@ -1097,7 +1097,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 *), +@@ -1108,7 +1108,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.15/um-fix-the-wmissing-prototypes-warning-for-__switch_.patch b/queue-5.15/um-fix-the-wmissing-prototypes-warning-for-__switch_.patch new file mode 100644 index 00000000000..663985a91ec --- /dev/null +++ b/queue-5.15/um-fix-the-wmissing-prototypes-warning-for-__switch_.patch @@ -0,0 +1,48 @@ +From f1e77ff1072e43ef5c8da316302990b30ab3e03c 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.15/um-vector-fix-bpfflash-parameter-evaluation.patch b/queue-5.15/um-vector-fix-bpfflash-parameter-evaluation.patch new file mode 100644 index 00000000000..051129c8924 --- /dev/null +++ b/queue-5.15/um-vector-fix-bpfflash-parameter-evaluation.patch @@ -0,0 +1,37 @@ +From 142af4f21a32276690a6c3e5afec039e11e410a4 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 45a4bcd27a39b..310fb14a85f77 100644 +--- a/arch/um/drivers/vector_kern.c ++++ b/arch/um/drivers/vector_kern.c +@@ -141,7 +141,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.15/virtio-delete-vq-in-vp_find_vqs_msix-when-request_ir.patch b/queue-5.15/virtio-delete-vq-in-vp_find_vqs_msix-when-request_ir.patch new file mode 100644 index 00000000000..b45afef18fe --- /dev/null +++ b/queue-5.15/virtio-delete-vq-in-vp_find_vqs_msix-when-request_ir.patch @@ -0,0 +1,94 @@ +From 4e041f76efabf22427181e6a4ed91a0f49335f78 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.15/x86-kconfig-select-arch_want_frame_pointers-again-wh.patch b/queue-5.15/x86-kconfig-select-arch_want_frame_pointers-again-wh.patch new file mode 100644 index 00000000000..7bfdcac008f --- /dev/null +++ b/queue-5.15/x86-kconfig-select-arch_want_frame_pointers-again-wh.patch @@ -0,0 +1,63 @@ +From 02f4377c0515137d5582602421a388e122b5f9f6 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 d4d6db4dde220..5d72d52fbc1b1 100644 +--- a/arch/x86/Kconfig.debug ++++ b/arch/x86/Kconfig.debug +@@ -249,6 +249,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 +@@ -272,7 +273,3 @@ config UNWINDER_GUESS + overhead. + + endchoice +- +-config FRAME_POINTER +- depends on !UNWINDER_ORC && !UNWINDER_GUESS +- bool +-- +2.43.0 +