]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Mon, 3 Jun 2024 11:42:15 +0000 (07:42 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 3 Jun 2024 11:42:15 +0000 (07:42 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
54 files changed:
queue-5.10/arm64-asm-bug-add-.align-2-to-the-end-of-__bug_entry.patch [new file with mode: 0644]
queue-5.10/asoc-tas2552-add-tx-path-for-capturing-audio-out-dat.patch [new file with mode: 0644]
queue-5.10/drm-bridge-tc358775-fix-support-for-jeida-18-and-jei.patch [new file with mode: 0644]
queue-5.10/drm-msm-dpu-always-flush-the-slave-intf-on-the-ctl.patch [new file with mode: 0644]
queue-5.10/input-ims-pcu-fix-printf-string-overflow.patch [new file with mode: 0644]
queue-5.10/input-ioc3kbd-add-device-table.patch [new file with mode: 0644]
queue-5.10/input-ioc3kbd-convert-to-platform-remove-callback-re.patch [new file with mode: 0644]
queue-5.10/input-pm8xxx-vibrator-correct-vib_max_levels-calcula.patch [new file with mode: 0644]
queue-5.10/ipv6-sr-fix-memleak-in-seg6_hmac_init_algo.patch [new file with mode: 0644]
queue-5.10/media-cec-abort-if-the-current-transmit-was-canceled.patch [new file with mode: 0644]
queue-5.10/media-cec-adap.c-drop-activate_cnt-use-state-info-in.patch [new file with mode: 0644]
queue-5.10/media-cec-call-enable_adap-on-s_log_addrs.patch [new file with mode: 0644]
queue-5.10/media-cec-cec-adap-always-cancel-work-in-cec_transmi.patch [new file with mode: 0644]
queue-5.10/media-cec-cec-api-add-locking-in-cec_release.patch [new file with mode: 0644]
queue-5.10/media-cec-core-avoid-confusing-transmit-timed-out-me.patch [new file with mode: 0644]
queue-5.10/media-cec-core-avoid-recursive-cec_claim_log_addrs.patch [new file with mode: 0644]
queue-5.10/media-cec-correctly-pass-on-reply-results.patch [new file with mode: 0644]
queue-5.10/media-cec-fix-a-deadlock-situation.patch [new file with mode: 0644]
queue-5.10/media-cec-use-call_op-and-check-for-unregistered.patch [new file with mode: 0644]
queue-5.10/media-core-headers-fix-kernel-doc-warnings.patch [new file with mode: 0644]
queue-5.10/media-flexcop-usb-clean-up-endpoint-sanity-checks.patch [new file with mode: 0644]
queue-5.10/media-flexcop-usb-fix-sanity-check-of-bnumendpoints.patch [new file with mode: 0644]
queue-5.10/media-stk1160-fix-bounds-checking-in-stk1160_copy_vi.patch [new file with mode: 0644]
queue-5.10/mmc-sdhci_am654-add-itapdlysel-in-sdhci_j721e_4bit_s.patch [new file with mode: 0644]
queue-5.10/mmc-sdhci_am654-add-otap-itap-delay-enable.patch [new file with mode: 0644]
queue-5.10/mmc-sdhci_am654-add-tuning-algorithm-for-delay-chain.patch [new file with mode: 0644]
queue-5.10/mmc-sdhci_am654-drop-lookup-for-deprecated-ti-otap-d.patch [new file with mode: 0644]
queue-5.10/mmc-sdhci_am654-fix-itapdly-for-hs400-timing.patch [new file with mode: 0644]
queue-5.10/mmc-sdhci_am654-write-itapdly-for-ddr52-timing.patch [new file with mode: 0644]
queue-5.10/net-fec-avoid-lock-evasion-when-reading-pps_enable.patch [new file with mode: 0644]
queue-5.10/nfc-nci-fix-handling-of-zero-length-payload-packets-.patch [new file with mode: 0644]
queue-5.10/nfc-nci-fix-kcov-check-in-nci_rx_work.patch [new file with mode: 0644]
queue-5.10/nfc-nci-fix-uninit-value-in-nci_rx_work.patch [new file with mode: 0644]
queue-5.10/null_blk-fix-the-warning-modpost-missing-module_desc.patch [new file with mode: 0644]
queue-5.10/openvswitch-set-the-skbuff-pkt_type-for-proper-pmtud.patch [new file with mode: 0644]
queue-5.10/params-lift-param_set_uint_minmax-to-common-code.patch [new file with mode: 0644]
queue-5.10/powerpc-pseries-add-failure-related-checks-for-h_get.patch [new file with mode: 0644]
queue-5.10/regulator-bd71828-don-t-overwrite-runtime-voltages.patch [new file with mode: 0644]
queue-5.10/riscv-cleanup-stacktrace.patch [new file with mode: 0644]
queue-5.10/riscv-stacktrace-fixed-walk_stackframe.patch [new file with mode: 0644]
queue-5.10/riscv-stacktrace-make-walk_stackframe-cross-pt_regs-.patch [new file with mode: 0644]
queue-5.10/rpcrdma-fix-handling-for-rdma_cm_event_device_remova.patch [new file with mode: 0644]
queue-5.10/scsi-qla2xxx-replace-all-non-returning-strlcpy-with-.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/sunrpc-fix-nfsacl-rpc-retry-on-soft-mount.patch [new file with mode: 0644]
queue-5.10/tcp-fix-shift-out-of-bounds-in-dctcp_update_alpha.patch [new file with mode: 0644]
queue-5.10/tcp-remove-64-kbyte-limit-for-initial-tp-rcv_wnd-val.patch [new file with mode: 0644]
queue-5.10/tls-fix-missing-memory-barrier-in-tls_init.patch [new file with mode: 0644]
queue-5.10/um-add-winch-to-winch_handlers-before-registering-wi.patch [new file with mode: 0644]
queue-5.10/um-fix-return-value-in-ubd_init.patch [new file with mode: 0644]
queue-5.10/um-fix-the-wmissing-prototypes-warning-for-__switch_.patch [new file with mode: 0644]
queue-5.10/um-vector-fix-bpfflash-parameter-evaluation.patch [new file with mode: 0644]
queue-5.10/virtio-delete-vq-in-vp_find_vqs_msix-when-request_ir.patch [new file with mode: 0644]
queue-5.10/x86-kconfig-select-arch_want_frame_pointers-again-wh.patch [new file with mode: 0644]

diff --git a/queue-5.10/arm64-asm-bug-add-.align-2-to-the-end-of-__bug_entry.patch b/queue-5.10/arm64-asm-bug-add-.align-2-to-the-end-of-__bug_entry.patch
new file mode 100644 (file)
index 0000000..726afbe
--- /dev/null
@@ -0,0 +1,160 @@
+From 404078ce2d7362c0bd8d373e77dc26521fd61850 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <xiaojiangfeng@huawei.com>
+
+[ 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 <xieyuanbin1@huawei.com>
+Signed-off-by: Jiangfeng Xiao <xiaojiangfeng@huawei.com>
+Reviewed-by: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/1716212077-43826-1-git-send-email-xiaojiangfeng@huawei.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/asm-bug.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/include/asm/asm-bug.h b/arch/arm64/include/asm/asm-bug.h
+index 03f52f84a4f3f..bc2dcc8a00009 100644
+--- a/arch/arm64/include/asm/asm-bug.h
++++ b/arch/arm64/include/asm/asm-bug.h
+@@ -28,6 +28,7 @@
+       14470:  .long 14471f - 14470b;                  \
+ _BUGVERBOSE_LOCATION(__FILE__, __LINE__)              \
+               .short flags;                           \
++              .align 2;                               \
+               .popsection;                            \
+       14471:
+ #else
+-- 
+2.43.0
+
diff --git a/queue-5.10/asoc-tas2552-add-tx-path-for-capturing-audio-out-dat.patch b/queue-5.10/asoc-tas2552-add-tx-path-for-capturing-audio-out-dat.patch
new file mode 100644 (file)
index 0000000..3fa2285
--- /dev/null
@@ -0,0 +1,76 @@
+From bbe54b0fd3b9234217cca86f0fd6e3c7e4d51bee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 18 May 2024 11:35:15 +0800
+Subject: ASoC: tas2552: Add TX path for capturing AUDIO-OUT data
+
+From: Shenghao Ding <shenghao-ding@ti.com>
+
+[ 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 <shenghao-ding@ti.com>
+Link: https://msgid.link/r/20240518033515.866-1-shenghao-ding@ti.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/tas2552.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c
+index bd00c35116cd5..f045876c12f17 100644
+--- a/sound/soc/codecs/tas2552.c
++++ b/sound/soc/codecs/tas2552.c
+@@ -2,7 +2,8 @@
+ /*
+  * tas2552.c - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier
+  *
+- * Copyright (C) 2014 Texas Instruments Incorporated -  https://www.ti.com
++ * Copyright (C) 2014 - 2024 Texas Instruments Incorporated -
++ *    https://www.ti.com
+  *
+  * Author: Dan Murphy <dmurphy@ti.com>
+  */
+@@ -119,12 +120,14 @@ static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] =
+                        &tas2552_input_mux_control),
+       SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0),
++      SND_SOC_DAPM_AIF_OUT("ASI OUT", "DAC Capture", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0),
+       SND_SOC_DAPM_POST("Post Event", tas2552_post_event),
+-      SND_SOC_DAPM_OUTPUT("OUT")
++      SND_SOC_DAPM_OUTPUT("OUT"),
++      SND_SOC_DAPM_INPUT("DMIC")
+ };
+ static const struct snd_soc_dapm_route tas2552_audio_map[] = {
+@@ -134,6 +137,7 @@ static const struct snd_soc_dapm_route tas2552_audio_map[] = {
+       {"ClassD", NULL, "Input selection"},
+       {"OUT", NULL, "ClassD"},
+       {"ClassD", NULL, "PLL"},
++      {"ASI OUT", NULL, "DMIC"}
+ };
+ #ifdef CONFIG_PM
+@@ -538,6 +542,13 @@ static struct snd_soc_dai_driver tas2552_dai[] = {
+                       .rates = SNDRV_PCM_RATE_8000_192000,
+                       .formats = TAS2552_FORMATS,
+               },
++              .capture = {
++                      .stream_name = "Capture",
++                      .channels_min = 2,
++                      .channels_max = 2,
++                      .rates = SNDRV_PCM_RATE_8000_192000,
++                      .formats = TAS2552_FORMATS,
++              },
+               .ops = &tas2552_speaker_dai_ops,
+       },
+ };
+-- 
+2.43.0
+
diff --git a/queue-5.10/drm-bridge-tc358775-fix-support-for-jeida-18-and-jei.patch b/queue-5.10/drm-bridge-tc358775-fix-support-for-jeida-18-and-jei.patch
new file mode 100644 (file)
index 0000000..873e6b3
--- /dev/null
@@ -0,0 +1,75 @@
+From 9cd6f6edf5de485cbcac1b8834025e371b501ddd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 25 Feb 2024 08:19:33 +0200
+Subject: drm/bridge: tc358775: fix support for jeida-18 and jeida-24
+
+From: Michael Walle <mwalle@kernel.org>
+
+[ 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 <mwalle@kernel.org>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Reviewed-by: Robert Foss <rfoss@kernel.org>
+Signed-off-by: Robert Foss <rfoss@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240225062008.33191-5-tony@atomide.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/tc358775.c | 21 +++++++++------------
+ 1 file changed, 9 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c
+index 55697fa4d7c8b..2e299cfe4e487 100644
+--- a/drivers/gpu/drm/bridge/tc358775.c
++++ b/drivers/gpu/drm/bridge/tc358775.c
+@@ -453,10 +453,6 @@ static void tc_bridge_enable(struct drm_bridge *bridge)
+       dev_dbg(tc->dev, "bus_formats %04x bpc %d\n",
+               connector->display_info.bus_formats[0],
+               tc->bpc);
+-      /*
+-       * Default hardware register settings of tc358775 configured
+-       * with MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA jeida-24 format
+-       */
+       if (connector->display_info.bus_formats[0] ==
+               MEDIA_BUS_FMT_RGB888_1X7X4_SPWG) {
+               /* VESA-24 */
+@@ -467,14 +463,15 @@ static void tc_bridge_enable(struct drm_bridge *bridge)
+               d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_B6, LVI_B7, LVI_B1, LVI_B2));
+               d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0));
+               d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R6));
+-      } else { /*  MEDIA_BUS_FMT_RGB666_1X7X3_SPWG - JEIDA-18 */
+-              d2l_write(tc->i2c, LV_MX0003, LV_MX(LVI_R0, LVI_R1, LVI_R2, LVI_R3));
+-              d2l_write(tc->i2c, LV_MX0407, LV_MX(LVI_R4, LVI_L0, LVI_R5, LVI_G0));
+-              d2l_write(tc->i2c, LV_MX0811, LV_MX(LVI_G1, LVI_G2, LVI_L0, LVI_L0));
+-              d2l_write(tc->i2c, LV_MX1215, LV_MX(LVI_G3, LVI_G4, LVI_G5, LVI_B0));
+-              d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_L0, LVI_L0, LVI_B1, LVI_B2));
+-              d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0));
+-              d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_L0));
++      } else {
++              /* JEIDA-18 and JEIDA-24 */
++              d2l_write(tc->i2c, LV_MX0003, LV_MX(LVI_R2, LVI_R3, LVI_R4, LVI_R5));
++              d2l_write(tc->i2c, LV_MX0407, LV_MX(LVI_R6, LVI_R1, LVI_R7, LVI_G2));
++              d2l_write(tc->i2c, LV_MX0811, LV_MX(LVI_G3, LVI_G4, LVI_G0, LVI_G1));
++              d2l_write(tc->i2c, LV_MX1215, LV_MX(LVI_G5, LVI_G6, LVI_G7, LVI_B2));
++              d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_B0, LVI_B1, LVI_B3, LVI_B4));
++              d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B5, LVI_B6, LVI_B7, LVI_L0));
++              d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R0));
+       }
+       d2l_write(tc->i2c, VFUEN, VFUEN_EN);
+-- 
+2.43.0
+
diff --git a/queue-5.10/drm-msm-dpu-always-flush-the-slave-intf-on-the-ctl.patch b/queue-5.10/drm-msm-dpu-always-flush-the-slave-intf-on-the-ctl.patch
new file mode 100644 (file)
index 0000000..6771cb9
--- /dev/null
@@ -0,0 +1,49 @@
+From 484315cfc06fcc24748058cb9e64e13dacca55b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Apr 2024 01:57:43 +0200
+Subject: drm/msm/dpu: Always flush the slave INTF on the CTL
+
+From: Marijn Suijten <marijn.suijten@somainline.org>
+
+[ 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 <marijn.suijten@somainline.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+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 <dmitry.baryshkov@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+index 8493d68ad8417..e1a97c10c0e41 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+@@ -448,9 +448,6 @@ static void dpu_encoder_phys_cmd_enable_helper(
+       _dpu_encoder_phys_cmd_pingpong_config(phys_enc);
+-      if (!dpu_encoder_phys_cmd_is_master(phys_enc))
+-              return;
+-
+       ctl = phys_enc->hw_ctl;
+       ctl->ops.get_bitmask_intf(ctl, &flush_mask, phys_enc->intf_idx);
+       ctl->ops.update_pending_flush(ctl, flush_mask);
+-- 
+2.43.0
+
diff --git a/queue-5.10/input-ims-pcu-fix-printf-string-overflow.patch b/queue-5.10/input-ims-pcu-fix-printf-string-overflow.patch
new file mode 100644 (file)
index 0000000..ccac0a4
--- /dev/null
@@ -0,0 +1,43 @@
+From b8d7248fe94c6d3877562939cfd8d34dbbe7df7d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Mar 2024 13:28:56 -0700
+Subject: Input: ims-pcu - fix printf string overflow
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ 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 <arnd@arndb.de>
+Link: https://lore.kernel.org/r/20240326223825.4084412-7-arnd@kernel.org
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/input/misc/ims-pcu.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
+index 08b9b5cdb943e..e5cb20e7f57b1 100644
+--- a/drivers/input/misc/ims-pcu.c
++++ b/drivers/input/misc/ims-pcu.c
+@@ -42,8 +42,8 @@ struct ims_pcu_backlight {
+ #define IMS_PCU_PART_NUMBER_LEN               15
+ #define IMS_PCU_SERIAL_NUMBER_LEN     8
+ #define IMS_PCU_DOM_LEN                       8
+-#define IMS_PCU_FW_VERSION_LEN                (9 + 1)
+-#define IMS_PCU_BL_VERSION_LEN                (9 + 1)
++#define IMS_PCU_FW_VERSION_LEN                16
++#define IMS_PCU_BL_VERSION_LEN                16
+ #define IMS_PCU_BL_RESET_REASON_LEN   (2 + 1)
+ #define IMS_PCU_PCU_B_DEVICE_ID               5
+-- 
+2.43.0
+
diff --git a/queue-5.10/input-ioc3kbd-add-device-table.patch b/queue-5.10/input-ioc3kbd-add-device-table.patch
new file mode 100644 (file)
index 0000000..b1e0c1b
--- /dev/null
@@ -0,0 +1,45 @@
+From 7b6590bf50b9c927294a3c9db230e1b23bca24fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Mar 2024 12:46:14 -0700
+Subject: Input: ioc3kbd - add device table
+
+From: Karel Balej <balejk@matfyz.cz>
+
+[ 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 <balejk@matfyz.cz>
+Link: https://lore.kernel.org/r/20240313115832.8052-1-balejk@matfyz.cz
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/input/serio/ioc3kbd.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/input/serio/ioc3kbd.c b/drivers/input/serio/ioc3kbd.c
+index 50552dc7b4f5e..676b0bda3d720 100644
+--- a/drivers/input/serio/ioc3kbd.c
++++ b/drivers/input/serio/ioc3kbd.c
+@@ -200,9 +200,16 @@ static void ioc3kbd_remove(struct platform_device *pdev)
+       serio_unregister_port(d->aux);
+ }
++static const struct platform_device_id ioc3kbd_id_table[] = {
++      { "ioc3-kbd", },
++      { }
++};
++MODULE_DEVICE_TABLE(platform, ioc3kbd_id_table);
++
+ static struct platform_driver ioc3kbd_driver = {
+       .probe          = ioc3kbd_probe,
+       .remove_new     = ioc3kbd_remove,
++      .id_table       = ioc3kbd_id_table,
+       .driver = {
+               .name = "ioc3-kbd",
+       },
+-- 
+2.43.0
+
diff --git a/queue-5.10/input-ioc3kbd-convert-to-platform-remove-callback-re.patch b/queue-5.10/input-ioc3kbd-convert-to-platform-remove-callback-re.patch
new file mode 100644 (file)
index 0000000..00453cb
--- /dev/null
@@ -0,0 +1,64 @@
+From 6bad48478a7e6a17c2c12aade16c12b9ef385553 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <u.kleine-koenig@pengutronix.de>
+
+[ 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 <u.kleine-koenig@pengutronix.de>
+Link: https://lore.kernel.org/r/20230920125829.1478827-37-u.kleine-koenig@pengutronix.de
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Stable-dep-of: d40e9edcf3eb ("Input: ioc3kbd - add device table")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/input/serio/ioc3kbd.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/input/serio/ioc3kbd.c b/drivers/input/serio/ioc3kbd.c
+index d51bfe912db5b..50552dc7b4f5e 100644
+--- a/drivers/input/serio/ioc3kbd.c
++++ b/drivers/input/serio/ioc3kbd.c
+@@ -190,7 +190,7 @@ static int ioc3kbd_probe(struct platform_device *pdev)
+       return 0;
+ }
+-static int ioc3kbd_remove(struct platform_device *pdev)
++static void ioc3kbd_remove(struct platform_device *pdev)
+ {
+       struct ioc3kbd_data *d = platform_get_drvdata(pdev);
+@@ -198,13 +198,11 @@ static int ioc3kbd_remove(struct platform_device *pdev)
+       serio_unregister_port(d->kbd);
+       serio_unregister_port(d->aux);
+-
+-      return 0;
+ }
+ static struct platform_driver ioc3kbd_driver = {
+       .probe          = ioc3kbd_probe,
+-      .remove         = ioc3kbd_remove,
++      .remove_new     = ioc3kbd_remove,
+       .driver = {
+               .name = "ioc3-kbd",
+       },
+-- 
+2.43.0
+
diff --git a/queue-5.10/input-pm8xxx-vibrator-correct-vib_max_levels-calcula.patch b/queue-5.10/input-pm8xxx-vibrator-correct-vib_max_levels-calcula.patch
new file mode 100644 (file)
index 0000000..311c373
--- /dev/null
@@ -0,0 +1,55 @@
+From af471761bef7bfe67e92a22197a0bde7704ca000 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Apr 2024 16:03:40 -0700
+Subject: Input: pm8xxx-vibrator - correct VIB_MAX_LEVELS calculation
+
+From: Fenglin Wu <quic_fenglinw@quicinc.com>
+
+[ 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 <quic_fenglinw@quicinc.com>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20240412-pm8xxx-vibrator-new-design-v10-1-0ec0ad133866@quicinc.com
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/input/misc/pm8xxx-vibrator.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c
+index 53ad25eaf1a28..8bfe5c7b1244c 100644
+--- a/drivers/input/misc/pm8xxx-vibrator.c
++++ b/drivers/input/misc/pm8xxx-vibrator.c
+@@ -14,7 +14,8 @@
+ #define VIB_MAX_LEVEL_mV      (3100)
+ #define VIB_MIN_LEVEL_mV      (1200)
+-#define VIB_MAX_LEVELS                (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV)
++#define VIB_PER_STEP_mV               (100)
++#define VIB_MAX_LEVELS                (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV + VIB_PER_STEP_mV)
+ #define MAX_FF_SPEED          0xff
+@@ -118,10 +119,10 @@ static void pm8xxx_work_handler(struct work_struct *work)
+               vib->active = true;
+               vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) +
+                                               VIB_MIN_LEVEL_mV;
+-              vib->level /= 100;
++              vib->level /= VIB_PER_STEP_mV;
+       } else {
+               vib->active = false;
+-              vib->level = VIB_MIN_LEVEL_mV / 100;
++              vib->level = VIB_MIN_LEVEL_mV / VIB_PER_STEP_mV;
+       }
+       pm8xxx_vib_set(vib, vib->active);
+-- 
+2.43.0
+
diff --git a/queue-5.10/ipv6-sr-fix-memleak-in-seg6_hmac_init_algo.patch b/queue-5.10/ipv6-sr-fix-memleak-in-seg6_hmac_init_algo.patch
new file mode 100644 (file)
index 0000000..672eeee
--- /dev/null
@@ -0,0 +1,125 @@
+From 2b375a4627fddb53dbc9c9cb8df51e3b1a9c726b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 May 2024 08:54:35 +0800
+Subject: ipv6: sr: fix memleak in seg6_hmac_init_algo
+
+From: Hangbin Liu <liuhangbin@gmail.com>
+
+[ 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 <sd@queasysnail.net>
+Closes: https://lore.kernel.org/netdev/Zj3bh-gE7eT6V6aH@hog/
+Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
+Link: https://lore.kernel.org/r/20240517005435.2600277-1-liuhangbin@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/seg6_hmac.c | 42 ++++++++++++++++++++++++++++--------------
+ 1 file changed, 28 insertions(+), 14 deletions(-)
+
+diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c
+index 552bce1fdfb94..2e2b94ae63552 100644
+--- a/net/ipv6/seg6_hmac.c
++++ b/net/ipv6/seg6_hmac.c
+@@ -355,6 +355,7 @@ static int seg6_hmac_init_algo(void)
+       struct crypto_shash *tfm;
+       struct shash_desc *shash;
+       int i, alg_count, cpu;
++      int ret = -ENOMEM;
+       alg_count = ARRAY_SIZE(hmac_algos);
+@@ -365,12 +366,14 @@ static int seg6_hmac_init_algo(void)
+               algo = &hmac_algos[i];
+               algo->tfms = alloc_percpu(struct crypto_shash *);
+               if (!algo->tfms)
+-                      return -ENOMEM;
++                      goto error_out;
+               for_each_possible_cpu(cpu) {
+                       tfm = crypto_alloc_shash(algo->name, 0, 0);
+-                      if (IS_ERR(tfm))
+-                              return PTR_ERR(tfm);
++                      if (IS_ERR(tfm)) {
++                              ret = PTR_ERR(tfm);
++                              goto error_out;
++                      }
+                       p_tfm = per_cpu_ptr(algo->tfms, cpu);
+                       *p_tfm = tfm;
+               }
+@@ -382,18 +385,22 @@ static int seg6_hmac_init_algo(void)
+               algo->shashs = alloc_percpu(struct shash_desc *);
+               if (!algo->shashs)
+-                      return -ENOMEM;
++                      goto error_out;
+               for_each_possible_cpu(cpu) {
+                       shash = kzalloc_node(shsize, GFP_KERNEL,
+                                            cpu_to_node(cpu));
+                       if (!shash)
+-                              return -ENOMEM;
++                              goto error_out;
+                       *per_cpu_ptr(algo->shashs, cpu) = shash;
+               }
+       }
+       return 0;
++
++error_out:
++      seg6_hmac_exit();
++      return ret;
+ }
+ int __init seg6_hmac_init(void)
+@@ -413,22 +420,29 @@ int __net_init seg6_hmac_net_init(struct net *net)
+ void seg6_hmac_exit(void)
+ {
+       struct seg6_hmac_algo *algo = NULL;
++      struct crypto_shash *tfm;
++      struct shash_desc *shash;
+       int i, alg_count, cpu;
+       alg_count = ARRAY_SIZE(hmac_algos);
+       for (i = 0; i < alg_count; i++) {
+               algo = &hmac_algos[i];
+-              for_each_possible_cpu(cpu) {
+-                      struct crypto_shash *tfm;
+-                      struct shash_desc *shash;
+-                      shash = *per_cpu_ptr(algo->shashs, cpu);
+-                      kfree(shash);
+-                      tfm = *per_cpu_ptr(algo->tfms, cpu);
+-                      crypto_free_shash(tfm);
++              if (algo->shashs) {
++                      for_each_possible_cpu(cpu) {
++                              shash = *per_cpu_ptr(algo->shashs, cpu);
++                              kfree(shash);
++                      }
++                      free_percpu(algo->shashs);
++              }
++
++              if (algo->tfms) {
++                      for_each_possible_cpu(cpu) {
++                              tfm = *per_cpu_ptr(algo->tfms, cpu);
++                              crypto_free_shash(tfm);
++                      }
++                      free_percpu(algo->tfms);
+               }
+-              free_percpu(algo->tfms);
+-              free_percpu(algo->shashs);
+       }
+ }
+ EXPORT_SYMBOL(seg6_hmac_exit);
+-- 
+2.43.0
+
diff --git a/queue-5.10/media-cec-abort-if-the-current-transmit-was-canceled.patch b/queue-5.10/media-cec-abort-if-the-current-transmit-was-canceled.patch
new file mode 100644 (file)
index 0000000..819edf6
--- /dev/null
@@ -0,0 +1,125 @@
+From 18441ea31cb04328ab04aac122c1f4f95abd0e71 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 3 Mar 2022 14:01:44 +0000
+Subject: media: cec: abort if the current transmit was canceled
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ 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 <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
+Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/cec/core/cec-adap.c | 14 +++++++++++---
+ include/media/cec.h               |  6 ++++++
+ 2 files changed, 17 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
+index 6415a80c9040e..fd4af157f4ce7 100644
+--- a/drivers/media/cec/core/cec-adap.c
++++ b/drivers/media/cec/core/cec-adap.c
+@@ -421,7 +421,7 @@ static void cec_flush(struct cec_adapter *adap)
+               cec_data_cancel(data, CEC_TX_STATUS_ABORTED);
+       }
+       if (adap->transmitting)
+-              cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED);
++              adap->transmit_in_progress_aborted = true;
+       /* Cancel the pending timeout work. */
+       list_for_each_entry_safe(data, n, &adap->wait_queue, list) {
+@@ -572,6 +572,7 @@ int cec_thread_func(void *_adap)
+               if (data->attempts == 0)
+                       data->attempts = attempts;
++              adap->transmit_in_progress_aborted = false;
+               /* Tell the adapter to transmit, cancel on error */
+               if (adap->ops->adap_transmit(adap, data->attempts,
+                                            signal_free_time, &data->msg))
+@@ -599,6 +600,8 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status,
+       struct cec_msg *msg;
+       unsigned int attempts_made = arb_lost_cnt + nack_cnt +
+                                    low_drive_cnt + error_cnt;
++      bool done = status & (CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_OK);
++      bool aborted = adap->transmit_in_progress_aborted;
+       dprintk(2, "%s: status 0x%02x\n", __func__, status);
+       if (attempts_made < 1)
+@@ -619,6 +622,7 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status,
+               goto wake_thread;
+       }
+       adap->transmit_in_progress = false;
++      adap->transmit_in_progress_aborted = false;
+       msg = &data->msg;
+@@ -639,8 +643,7 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status,
+        * the hardware didn't signal that it retried itself (by setting
+        * CEC_TX_STATUS_MAX_RETRIES), then we will retry ourselves.
+        */
+-      if (data->attempts > attempts_made &&
+-          !(status & (CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_OK))) {
++      if (!aborted && data->attempts > attempts_made && !done) {
+               /* Retry this message */
+               data->attempts -= attempts_made;
+               if (msg->timeout)
+@@ -655,6 +658,8 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status,
+               goto wake_thread;
+       }
++      if (aborted && !done)
++              status |= CEC_TX_STATUS_ABORTED;
+       data->attempts = 0;
+       /* Always set CEC_TX_STATUS_MAX_RETRIES on error */
+@@ -1576,6 +1581,9 @@ static void cec_activate_cnt_dec(struct cec_adapter *adap)
+       WARN_ON(adap->ops->adap_enable(adap, false));
+       adap->last_initiator = 0xff;
+       adap->transmit_in_progress = false;
++      adap->transmit_in_progress_aborted = false;
++      if (adap->transmitting)
++              cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED);
+       mutex_unlock(&adap->devnode.lock);
+ }
+diff --git a/include/media/cec.h b/include/media/cec.h
+index 97c5f5bfcbd00..31d704f367074 100644
+--- a/include/media/cec.h
++++ b/include/media/cec.h
+@@ -163,6 +163,11 @@ struct cec_adap_ops {
+  * @wait_queue:               queue of transmits waiting for a reply
+  * @transmitting:     CEC messages currently being transmitted
+  * @transmit_in_progress: true if a transmit is in progress
++ * @transmit_in_progress_aborted: true if a transmit is in progress is to be
++ *                    aborted. This happens if the logical address is
++ *                    invalidated while the transmit is ongoing. In that
++ *                    case the transmit will finish, but will not retransmit
++ *                    and be marked as ABORTED.
+  * @kthread_config:   kthread used to configure a CEC adapter
+  * @config_completion:        used to signal completion of the config kthread
+  * @kthread:          main CEC processing thread
+@@ -218,6 +223,7 @@ struct cec_adapter {
+       struct list_head wait_queue;
+       struct cec_data *transmitting;
+       bool transmit_in_progress;
++      bool transmit_in_progress_aborted;
+       struct task_struct *kthread_config;
+       struct completion config_completion;
+-- 
+2.43.0
+
diff --git a/queue-5.10/media-cec-adap.c-drop-activate_cnt-use-state-info-in.patch b/queue-5.10/media-cec-adap.c-drop-activate_cnt-use-state-info-in.patch
new file mode 100644 (file)
index 0000000..9f89a59
--- /dev/null
@@ -0,0 +1,314 @@
+From 26052739d14571572a27d4790b5b18ceeeb45b31 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 May 2022 10:53:05 +0200
+Subject: media: cec-adap.c: drop activate_cnt, use state info instead
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ 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 <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
+Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/cec/core/cec-adap.c | 152 ++++++++++++------------------
+ include/media/cec.h               |   4 +-
+ 2 files changed, 61 insertions(+), 95 deletions(-)
+
+diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
+index 07ff4b0c8461e..920c108b84aaf 100644
+--- a/drivers/media/cec/core/cec-adap.c
++++ b/drivers/media/cec/core/cec-adap.c
+@@ -1548,47 +1548,59 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
+ }
+ /*
+- * Helper functions to enable/disable the CEC adapter.
++ * Helper function to enable/disable the CEC adapter.
+  *
+- * These functions are called with adap->lock held.
++ * This function is called with adap->lock held.
+  */
+-static int cec_activate_cnt_inc(struct cec_adapter *adap)
++static int cec_adap_enable(struct cec_adapter *adap)
+ {
+-      int ret;
++      bool enable;
++      int ret = 0;
++
++      enable = adap->monitor_all_cnt || adap->monitor_pin_cnt ||
++               adap->log_addrs.num_log_addrs;
++      if (adap->needs_hpd)
++              enable = enable && adap->phys_addr != CEC_PHYS_ADDR_INVALID;
+-      if (adap->activate_cnt++)
++      if (enable == adap->is_enabled)
+               return 0;
+       /* serialize adap_enable */
+       mutex_lock(&adap->devnode.lock);
+-      adap->last_initiator = 0xff;
+-      adap->transmit_in_progress = false;
+-      ret = call_op(adap, adap_enable, true);
+-      if (ret)
+-              adap->activate_cnt--;
++      if (enable) {
++              adap->last_initiator = 0xff;
++              adap->transmit_in_progress = false;
++              ret = adap->ops->adap_enable(adap, true);
++              if (!ret) {
++                      /*
++                       * Enable monitor-all/pin modes if needed. We warn, but
++                       * continue if this fails as this is not a critical error.
++                       */
++                      if (adap->monitor_all_cnt)
++                              WARN_ON(call_op(adap, adap_monitor_all_enable, true));
++                      if (adap->monitor_pin_cnt)
++                              WARN_ON(call_op(adap, adap_monitor_pin_enable, true));
++              }
++      } else {
++              /* Disable monitor-all/pin modes if needed (needs_hpd == 1) */
++              if (adap->monitor_all_cnt)
++                      WARN_ON(call_op(adap, adap_monitor_all_enable, false));
++              if (adap->monitor_pin_cnt)
++                      WARN_ON(call_op(adap, adap_monitor_pin_enable, false));
++              WARN_ON(adap->ops->adap_enable(adap, false));
++              adap->last_initiator = 0xff;
++              adap->transmit_in_progress = false;
++              adap->transmit_in_progress_aborted = false;
++              if (adap->transmitting)
++                      cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED, 0);
++      }
++      if (!ret)
++              adap->is_enabled = enable;
++      wake_up_interruptible(&adap->kthread_waitq);
+       mutex_unlock(&adap->devnode.lock);
+       return ret;
+ }
+-static void cec_activate_cnt_dec(struct cec_adapter *adap)
+-{
+-      if (WARN_ON(!adap->activate_cnt))
+-              return;
+-
+-      if (--adap->activate_cnt)
+-              return;
+-
+-      /* serialize adap_enable */
+-      mutex_lock(&adap->devnode.lock);
+-      WARN_ON(call_op(adap, adap_enable, false));
+-      adap->last_initiator = 0xff;
+-      adap->transmit_in_progress = false;
+-      adap->transmit_in_progress_aborted = false;
+-      if (adap->transmitting)
+-              cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED, 0);
+-      mutex_unlock(&adap->devnode.lock);
+-}
+-
+ /* Set a new physical address and send an event notifying userspace of this.
+  *
+  * This function is called with adap->lock held.
+@@ -1609,33 +1621,16 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
+               adap->phys_addr = CEC_PHYS_ADDR_INVALID;
+               cec_post_state_event(adap);
+               cec_adap_unconfigure(adap);
+-              if (becomes_invalid && adap->needs_hpd) {
+-                      /* Disable monitor-all/pin modes if needed */
+-                      if (adap->monitor_all_cnt)
+-                              WARN_ON(call_op(adap, adap_monitor_all_enable, false));
+-                      if (adap->monitor_pin_cnt)
+-                              WARN_ON(call_op(adap, adap_monitor_pin_enable, false));
+-                      cec_activate_cnt_dec(adap);
+-                      wake_up_interruptible(&adap->kthread_waitq);
+-              }
+-              if (becomes_invalid)
++              if (becomes_invalid) {
++                      cec_adap_enable(adap);
+                       return;
+-      }
+-
+-      if (is_invalid && adap->needs_hpd) {
+-              if (cec_activate_cnt_inc(adap))
+-                      return;
+-              /*
+-               * Re-enable monitor-all/pin modes if needed. We warn, but
+-               * continue if this fails as this is not a critical error.
+-               */
+-              if (adap->monitor_all_cnt)
+-                      WARN_ON(call_op(adap, adap_monitor_all_enable, true));
+-              if (adap->monitor_pin_cnt)
+-                      WARN_ON(call_op(adap, adap_monitor_pin_enable, true));
++              }
+       }
+       adap->phys_addr = phys_addr;
++      if (is_invalid)
++              cec_adap_enable(adap);
++
+       cec_post_state_event(adap);
+       if (adap->log_addrs.num_log_addrs)
+               cec_claim_log_addrs(adap, block);
+@@ -1692,6 +1687,7 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
+                     struct cec_log_addrs *log_addrs, bool block)
+ {
+       u16 type_mask = 0;
++      int err;
+       int i;
+       if (adap->devnode.unregistered)
+@@ -1707,8 +1703,7 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
+               adap->log_addrs.osd_name[0] = '\0';
+               adap->log_addrs.vendor_id = CEC_VENDOR_ID_NONE;
+               adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0;
+-              if (!adap->needs_hpd)
+-                      cec_activate_cnt_dec(adap);
++              cec_adap_enable(adap);
+               return 0;
+       }
+@@ -1842,17 +1837,12 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
+                      sizeof(log_addrs->features[i]));
+       }
+-      if (!adap->needs_hpd && !adap->is_configuring && !adap->is_configured) {
+-              int ret = cec_activate_cnt_inc(adap);
+-
+-              if (ret)
+-                      return ret;
+-      }
+       log_addrs->log_addr_mask = adap->log_addrs.log_addr_mask;
+       adap->log_addrs = *log_addrs;
+-      if (adap->phys_addr != CEC_PHYS_ADDR_INVALID)
++      err = cec_adap_enable(adap);
++      if (!err && adap->phys_addr != CEC_PHYS_ADDR_INVALID)
+               cec_claim_log_addrs(adap, block);
+-      return 0;
++      return err;
+ }
+ int cec_s_log_addrs(struct cec_adapter *adap,
+@@ -2155,20 +2145,9 @@ int cec_monitor_all_cnt_inc(struct cec_adapter *adap)
+       if (adap->monitor_all_cnt++)
+               return 0;
+-      if (!adap->needs_hpd) {
+-              ret = cec_activate_cnt_inc(adap);
+-              if (ret) {
+-                      adap->monitor_all_cnt--;
+-                      return ret;
+-              }
+-      }
+-
+-      ret = call_op(adap, adap_monitor_all_enable, true);
+-      if (ret) {
++      ret = cec_adap_enable(adap);
++      if (ret)
+               adap->monitor_all_cnt--;
+-              if (!adap->needs_hpd)
+-                      cec_activate_cnt_dec(adap);
+-      }
+       return ret;
+ }
+@@ -2179,8 +2158,7 @@ void cec_monitor_all_cnt_dec(struct cec_adapter *adap)
+       if (--adap->monitor_all_cnt)
+               return;
+       WARN_ON(call_op(adap, adap_monitor_all_enable, false));
+-      if (!adap->needs_hpd)
+-              cec_activate_cnt_dec(adap);
++      cec_adap_enable(adap);
+ }
+ /*
+@@ -2195,20 +2173,9 @@ int cec_monitor_pin_cnt_inc(struct cec_adapter *adap)
+       if (adap->monitor_pin_cnt++)
+               return 0;
+-      if (!adap->needs_hpd) {
+-              ret = cec_activate_cnt_inc(adap);
+-              if (ret) {
+-                      adap->monitor_pin_cnt--;
+-                      return ret;
+-              }
+-      }
+-
+-      ret = call_op(adap, adap_monitor_pin_enable, true);
+-      if (ret) {
++      ret = cec_adap_enable(adap);
++      if (ret)
+               adap->monitor_pin_cnt--;
+-              if (!adap->needs_hpd)
+-                      cec_activate_cnt_dec(adap);
+-      }
+       return ret;
+ }
+@@ -2219,8 +2186,7 @@ void cec_monitor_pin_cnt_dec(struct cec_adapter *adap)
+       if (--adap->monitor_pin_cnt)
+               return;
+       WARN_ON(call_op(adap, adap_monitor_pin_enable, false));
+-      if (!adap->needs_hpd)
+-              cec_activate_cnt_dec(adap);
++      cec_adap_enable(adap);
+ }
+ #ifdef CONFIG_DEBUG_FS
+@@ -2234,7 +2200,7 @@ int cec_adap_status(struct seq_file *file, void *priv)
+       struct cec_data *data;
+       mutex_lock(&adap->lock);
+-      seq_printf(file, "activation count: %u\n", adap->activate_cnt);
++      seq_printf(file, "enabled: %d\n", adap->is_enabled);
+       seq_printf(file, "configured: %d\n", adap->is_configured);
+       seq_printf(file, "configuring: %d\n", adap->is_configuring);
+       seq_printf(file, "phys_addr: %x.%x.%x.%x\n",
+diff --git a/include/media/cec.h b/include/media/cec.h
+index 31d704f367074..df3e8738d512b 100644
+--- a/include/media/cec.h
++++ b/include/media/cec.h
+@@ -180,6 +180,7 @@ struct cec_adap_ops {
+  * @needs_hpd:                if true, then the HDMI HotPlug Detect pin must be high
+  *    in order to transmit or receive CEC messages. This is usually a HW
+  *    limitation.
++ * @is_enabled:               the CEC adapter is enabled
+  * @is_configuring:   the CEC adapter is configuring (i.e. claiming LAs)
+  * @is_configured:    the CEC adapter is configured (i.e. has claimed LAs)
+  * @cec_pin_is_high:  if true then the CEC pin is high. Only used with the
+@@ -190,7 +191,6 @@ struct cec_adap_ops {
+  *    Drivers that need this can set this field to true after the
+  *    cec_allocate_adapter() call.
+  * @last_initiator:   the initiator of the last transmitted message.
+- * @activate_cnt:     number of times that CEC is activated
+  * @monitor_all_cnt:  number of filehandles monitoring all msgs
+  * @monitor_pin_cnt:  number of filehandles monitoring pin changes
+  * @follower_cnt:     number of filehandles in follower mode
+@@ -238,12 +238,12 @@ struct cec_adapter {
+       u16 phys_addr;
+       bool needs_hpd;
++      bool is_enabled;
+       bool is_configuring;
+       bool is_configured;
+       bool cec_pin_is_high;
+       bool adap_controls_phys_addr;
+       u8 last_initiator;
+-      u32 activate_cnt;
+       u32 monitor_all_cnt;
+       u32 monitor_pin_cnt;
+       u32 follower_cnt;
+-- 
+2.43.0
+
diff --git a/queue-5.10/media-cec-call-enable_adap-on-s_log_addrs.patch b/queue-5.10/media-cec-call-enable_adap-on-s_log_addrs.patch
new file mode 100644 (file)
index 0000000..2128b57
--- /dev/null
@@ -0,0 +1,389 @@
+From dc0a182c46a4e04faf3d33c5d81942f592b089b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 3 Mar 2022 13:55:08 +0000
+Subject: media: cec: call enable_adap on s_log_addrs
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ 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 <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
+Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/cec/core/cec-adap.c | 174 ++++++++++++++++++++++--------
+ drivers/media/cec/core/cec-api.c  |  18 +---
+ include/media/cec.h               |   2 +
+ 3 files changed, 130 insertions(+), 64 deletions(-)
+
+diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
+index d2a6fd8b65014..6415a80c9040e 100644
+--- a/drivers/media/cec/core/cec-adap.c
++++ b/drivers/media/cec/core/cec-adap.c
+@@ -1532,6 +1532,7 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
+                                          "ceccfg-%s", adap->name);
+       if (IS_ERR(adap->kthread_config)) {
+               adap->kthread_config = NULL;
++              adap->is_configuring = false;
+       } else if (block) {
+               mutex_unlock(&adap->lock);
+               wait_for_completion(&adap->config_completion);
+@@ -1539,59 +1540,90 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
+       }
+ }
++/*
++ * Helper functions to enable/disable the CEC adapter.
++ *
++ * These functions are called with adap->lock held.
++ */
++static int cec_activate_cnt_inc(struct cec_adapter *adap)
++{
++      int ret;
++
++      if (adap->activate_cnt++)
++              return 0;
++
++      /* serialize adap_enable */
++      mutex_lock(&adap->devnode.lock);
++      adap->last_initiator = 0xff;
++      adap->transmit_in_progress = false;
++      ret = adap->ops->adap_enable(adap, true);
++      if (ret)
++              adap->activate_cnt--;
++      mutex_unlock(&adap->devnode.lock);
++      return ret;
++}
++
++static void cec_activate_cnt_dec(struct cec_adapter *adap)
++{
++      if (WARN_ON(!adap->activate_cnt))
++              return;
++
++      if (--adap->activate_cnt)
++              return;
++
++      /* serialize adap_enable */
++      mutex_lock(&adap->devnode.lock);
++      WARN_ON(adap->ops->adap_enable(adap, false));
++      adap->last_initiator = 0xff;
++      adap->transmit_in_progress = false;
++      mutex_unlock(&adap->devnode.lock);
++}
++
+ /* Set a new physical address and send an event notifying userspace of this.
+  *
+  * This function is called with adap->lock held.
+  */
+ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
+ {
++      bool becomes_invalid = phys_addr == CEC_PHYS_ADDR_INVALID;
++      bool is_invalid = adap->phys_addr == CEC_PHYS_ADDR_INVALID;
++
+       if (phys_addr == adap->phys_addr)
+               return;
+-      if (phys_addr != CEC_PHYS_ADDR_INVALID && adap->devnode.unregistered)
++      if (!becomes_invalid && adap->devnode.unregistered)
+               return;
+       dprintk(1, "new physical address %x.%x.%x.%x\n",
+               cec_phys_addr_exp(phys_addr));
+-      if (phys_addr == CEC_PHYS_ADDR_INVALID ||
+-          adap->phys_addr != CEC_PHYS_ADDR_INVALID) {
++      if (becomes_invalid || !is_invalid) {
+               adap->phys_addr = CEC_PHYS_ADDR_INVALID;
+               cec_post_state_event(adap);
+               cec_adap_unconfigure(adap);
+-              /* Disabling monitor all mode should always succeed */
+-              if (adap->monitor_all_cnt)
+-                      WARN_ON(call_op(adap, adap_monitor_all_enable, false));
+-              /* serialize adap_enable */
+-              mutex_lock(&adap->devnode.lock);
+-              if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) {
+-                      WARN_ON(adap->ops->adap_enable(adap, false));
+-                      adap->transmit_in_progress = false;
++              if (becomes_invalid && adap->needs_hpd) {
++                      /* Disable monitor-all/pin modes if needed */
++                      if (adap->monitor_all_cnt)
++                              WARN_ON(call_op(adap, adap_monitor_all_enable, false));
++                      if (adap->monitor_pin_cnt)
++                              WARN_ON(call_op(adap, adap_monitor_pin_enable, false));
++                      cec_activate_cnt_dec(adap);
+                       wake_up_interruptible(&adap->kthread_waitq);
+               }
+-              mutex_unlock(&adap->devnode.lock);
+-              if (phys_addr == CEC_PHYS_ADDR_INVALID)
++              if (becomes_invalid)
+                       return;
+       }
+-      /* serialize adap_enable */
+-      mutex_lock(&adap->devnode.lock);
+-      adap->last_initiator = 0xff;
+-      adap->transmit_in_progress = false;
+-
+-      if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) {
+-              if (adap->ops->adap_enable(adap, true)) {
+-                      mutex_unlock(&adap->devnode.lock);
++      if (is_invalid && adap->needs_hpd) {
++              if (cec_activate_cnt_inc(adap))
+                       return;
+-              }
+-      }
+-
+-      if (adap->monitor_all_cnt &&
+-          call_op(adap, adap_monitor_all_enable, true)) {
+-              if (adap->needs_hpd || list_empty(&adap->devnode.fhs))
+-                      WARN_ON(adap->ops->adap_enable(adap, false));
+-              mutex_unlock(&adap->devnode.lock);
+-              return;
++              /*
++               * Re-enable monitor-all/pin modes if needed. We warn, but
++               * continue if this fails as this is not a critical error.
++               */
++              if (adap->monitor_all_cnt)
++                      WARN_ON(call_op(adap, adap_monitor_all_enable, true));
++              if (adap->monitor_pin_cnt)
++                      WARN_ON(call_op(adap, adap_monitor_pin_enable, true));
+       }
+-      mutex_unlock(&adap->devnode.lock);
+       adap->phys_addr = phys_addr;
+       cec_post_state_event(adap);
+@@ -1656,6 +1688,8 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
+               return -ENODEV;
+       if (!log_addrs || log_addrs->num_log_addrs == 0) {
++              if (!adap->is_configuring && !adap->is_configured)
++                      return 0;
+               cec_adap_unconfigure(adap);
+               adap->log_addrs.num_log_addrs = 0;
+               for (i = 0; i < CEC_MAX_LOG_ADDRS; i++)
+@@ -1663,6 +1697,8 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
+               adap->log_addrs.osd_name[0] = '\0';
+               adap->log_addrs.vendor_id = CEC_VENDOR_ID_NONE;
+               adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0;
++              if (!adap->needs_hpd)
++                      cec_activate_cnt_dec(adap);
+               return 0;
+       }
+@@ -1796,6 +1832,12 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
+                      sizeof(log_addrs->features[i]));
+       }
++      if (!adap->needs_hpd && !adap->is_configuring && !adap->is_configured) {
++              int ret = cec_activate_cnt_inc(adap);
++
++              if (ret)
++                      return ret;
++      }
+       log_addrs->log_addr_mask = adap->log_addrs.log_addr_mask;
+       adap->log_addrs = *log_addrs;
+       if (adap->phys_addr != CEC_PHYS_ADDR_INVALID)
+@@ -2099,20 +2141,37 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
+  */
+ int cec_monitor_all_cnt_inc(struct cec_adapter *adap)
+ {
+-      int ret = 0;
++      int ret;
+-      if (adap->monitor_all_cnt == 0)
+-              ret = call_op(adap, adap_monitor_all_enable, 1);
+-      if (ret == 0)
+-              adap->monitor_all_cnt++;
++      if (adap->monitor_all_cnt++)
++              return 0;
++
++      if (!adap->needs_hpd) {
++              ret = cec_activate_cnt_inc(adap);
++              if (ret) {
++                      adap->monitor_all_cnt--;
++                      return ret;
++              }
++      }
++
++      ret = call_op(adap, adap_monitor_all_enable, true);
++      if (ret) {
++              adap->monitor_all_cnt--;
++              if (!adap->needs_hpd)
++                      cec_activate_cnt_dec(adap);
++      }
+       return ret;
+ }
+ void cec_monitor_all_cnt_dec(struct cec_adapter *adap)
+ {
+-      adap->monitor_all_cnt--;
+-      if (adap->monitor_all_cnt == 0)
+-              WARN_ON(call_op(adap, adap_monitor_all_enable, 0));
++      if (WARN_ON(!adap->monitor_all_cnt))
++              return;
++      if (--adap->monitor_all_cnt)
++              return;
++      WARN_ON(call_op(adap, adap_monitor_all_enable, false));
++      if (!adap->needs_hpd)
++              cec_activate_cnt_dec(adap);
+ }
+ /*
+@@ -2122,20 +2181,37 @@ void cec_monitor_all_cnt_dec(struct cec_adapter *adap)
+  */
+ int cec_monitor_pin_cnt_inc(struct cec_adapter *adap)
+ {
+-      int ret = 0;
++      int ret;
+-      if (adap->monitor_pin_cnt == 0)
+-              ret = call_op(adap, adap_monitor_pin_enable, 1);
+-      if (ret == 0)
+-              adap->monitor_pin_cnt++;
++      if (adap->monitor_pin_cnt++)
++              return 0;
++
++      if (!adap->needs_hpd) {
++              ret = cec_activate_cnt_inc(adap);
++              if (ret) {
++                      adap->monitor_pin_cnt--;
++                      return ret;
++              }
++      }
++
++      ret = call_op(adap, adap_monitor_pin_enable, true);
++      if (ret) {
++              adap->monitor_pin_cnt--;
++              if (!adap->needs_hpd)
++                      cec_activate_cnt_dec(adap);
++      }
+       return ret;
+ }
+ void cec_monitor_pin_cnt_dec(struct cec_adapter *adap)
+ {
+-      adap->monitor_pin_cnt--;
+-      if (adap->monitor_pin_cnt == 0)
+-              WARN_ON(call_op(adap, adap_monitor_pin_enable, 0));
++      if (WARN_ON(!adap->monitor_pin_cnt))
++              return;
++      if (--adap->monitor_pin_cnt)
++              return;
++      WARN_ON(call_op(adap, adap_monitor_pin_enable, false));
++      if (!adap->needs_hpd)
++              cec_activate_cnt_dec(adap);
+ }
+ #ifdef CONFIG_DEBUG_FS
+@@ -2149,6 +2225,7 @@ int cec_adap_status(struct seq_file *file, void *priv)
+       struct cec_data *data;
+       mutex_lock(&adap->lock);
++      seq_printf(file, "activation count: %u\n", adap->activate_cnt);
+       seq_printf(file, "configured: %d\n", adap->is_configured);
+       seq_printf(file, "configuring: %d\n", adap->is_configuring);
+       seq_printf(file, "phys_addr: %x.%x.%x.%x\n",
+@@ -2163,6 +2240,9 @@ int cec_adap_status(struct seq_file *file, void *priv)
+       if (adap->monitor_all_cnt)
+               seq_printf(file, "file handles in Monitor All mode: %u\n",
+                          adap->monitor_all_cnt);
++      if (adap->monitor_pin_cnt)
++              seq_printf(file, "file handles in Monitor Pin mode: %u\n",
++                         adap->monitor_pin_cnt);
+       if (adap->tx_timeouts) {
+               seq_printf(file, "transmit timeouts: %u\n",
+                          adap->tx_timeouts);
+diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c
+index 899017a0e514e..0be4e822211e7 100644
+--- a/drivers/media/cec/core/cec-api.c
++++ b/drivers/media/cec/core/cec-api.c
+@@ -586,18 +586,6 @@ static int cec_open(struct inode *inode, struct file *filp)
+               return err;
+       }
+-      /* serialize adap_enable */
+-      mutex_lock(&devnode->lock);
+-      if (list_empty(&devnode->fhs) &&
+-          !adap->needs_hpd &&
+-          adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
+-              err = adap->ops->adap_enable(adap, true);
+-              if (err) {
+-                      mutex_unlock(&devnode->lock);
+-                      kfree(fh);
+-                      return err;
+-              }
+-      }
+       filp->private_data = fh;
+       /* Queue up initial state events */
+@@ -625,6 +613,7 @@ static int cec_open(struct inode *inode, struct file *filp)
+       }
+ #endif
++      mutex_lock(&devnode->lock);
+       mutex_lock(&devnode->lock_fhs);
+       list_add(&fh->list, &devnode->fhs);
+       mutex_unlock(&devnode->lock_fhs);
+@@ -656,15 +645,10 @@ static int cec_release(struct inode *inode, struct file *filp)
+               cec_monitor_all_cnt_dec(adap);
+       mutex_unlock(&adap->lock);
+-      /* serialize adap_enable */
+       mutex_lock(&devnode->lock);
+       mutex_lock(&devnode->lock_fhs);
+       list_del(&fh->list);
+       mutex_unlock(&devnode->lock_fhs);
+-      if (cec_is_registered(adap) && list_empty(&devnode->fhs) &&
+-          !adap->needs_hpd && adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
+-              WARN_ON(adap->ops->adap_enable(adap, false));
+-      }
+       mutex_unlock(&devnode->lock);
+       /* Unhook pending transmits from this filehandle. */
+diff --git a/include/media/cec.h b/include/media/cec.h
+index 77346f757036d..97c5f5bfcbd00 100644
+--- a/include/media/cec.h
++++ b/include/media/cec.h
+@@ -185,6 +185,7 @@ struct cec_adap_ops {
+  *    Drivers that need this can set this field to true after the
+  *    cec_allocate_adapter() call.
+  * @last_initiator:   the initiator of the last transmitted message.
++ * @activate_cnt:     number of times that CEC is activated
+  * @monitor_all_cnt:  number of filehandles monitoring all msgs
+  * @monitor_pin_cnt:  number of filehandles monitoring pin changes
+  * @follower_cnt:     number of filehandles in follower mode
+@@ -236,6 +237,7 @@ struct cec_adapter {
+       bool cec_pin_is_high;
+       bool adap_controls_phys_addr;
+       u8 last_initiator;
++      u32 activate_cnt;
+       u32 monitor_all_cnt;
+       u32 monitor_pin_cnt;
+       u32 follower_cnt;
+-- 
+2.43.0
+
diff --git a/queue-5.10/media-cec-cec-adap-always-cancel-work-in-cec_transmi.patch b/queue-5.10/media-cec-cec-adap-always-cancel-work-in-cec_transmi.patch
new file mode 100644 (file)
index 0000000..b591fc0
--- /dev/null
@@ -0,0 +1,39 @@
+From 5c8c58fb9e3cbef99983feb93853b326586ef163 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <hverkuil-cisco@xs4all.nl>
+
+[ 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 <hverkuil-cisco@xs4all.nl>
+Reported-by: Yang, Chenyuan <cy54@illinois.edu>
+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 <mchehab@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/cec/core/cec-adap.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
+index 2f7ab5df1c584..78027f0310acd 100644
+--- a/drivers/media/cec/core/cec-adap.c
++++ b/drivers/media/cec/core/cec-adap.c
+@@ -913,8 +913,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
+        */
+       mutex_unlock(&adap->lock);
+       wait_for_completion_killable(&data->c);
+-      if (!data->completed)
+-              cancel_delayed_work_sync(&data->work);
++      cancel_delayed_work_sync(&data->work);
+       mutex_lock(&adap->lock);
+       /* Cancel the transmit if it was interrupted */
+-- 
+2.43.0
+
diff --git a/queue-5.10/media-cec-cec-api-add-locking-in-cec_release.patch b/queue-5.10/media-cec-cec-api-add-locking-in-cec_release.patch
new file mode 100644 (file)
index 0000000..e91ff70
--- /dev/null
@@ -0,0 +1,46 @@
+From bfb378aba7791a3c77529ad53f8026c234bcfe56 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Feb 2024 12:25:55 +0000
+Subject: media: cec: cec-api: add locking in cec_release()
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ 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 <hverkuil-cisco@xs4all.nl>
+Reported-by: Yang, Chenyuan <cy54@illinois.edu>
+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 <mchehab@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/cec/core/cec-api.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c
+index f922a2196b2b7..893641ebc644b 100644
+--- a/drivers/media/cec/core/cec-api.c
++++ b/drivers/media/cec/core/cec-api.c
+@@ -672,6 +672,8 @@ static int cec_release(struct inode *inode, struct file *filp)
+               list_del(&data->xfer_list);
+       }
+       mutex_unlock(&adap->lock);
++
++      mutex_lock(&fh->lock);
+       while (!list_empty(&fh->msgs)) {
+               struct cec_msg_entry *entry =
+                       list_first_entry(&fh->msgs, struct cec_msg_entry, list);
+@@ -689,6 +691,7 @@ static int cec_release(struct inode *inode, struct file *filp)
+                       kfree(entry);
+               }
+       }
++      mutex_unlock(&fh->lock);
+       kfree(fh);
+       cec_put_device(devnode);
+-- 
+2.43.0
+
diff --git a/queue-5.10/media-cec-core-avoid-confusing-transmit-timed-out-me.patch b/queue-5.10/media-cec-core-avoid-confusing-transmit-timed-out-me.patch
new file mode 100644 (file)
index 0000000..19a742f
--- /dev/null
@@ -0,0 +1,73 @@
+From 70a0b1de0a165e52a7aab50cf24e21c55c50373a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Apr 2024 11:13:47 +0100
+Subject: media: cec: core: avoid confusing "transmit timed out" message
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ 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 <hverkuil-cisco@xs4all.nl>
+Reported-by: Yang, Chenyuan <cy54@illinois.edu>
+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 <mchehab@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/cec/core/cec-adap.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
+index 42d66ae27b19f..a5853c82d5e4f 100644
+--- a/drivers/media/cec/core/cec-adap.c
++++ b/drivers/media/cec/core/cec-adap.c
+@@ -502,6 +502,15 @@ int cec_thread_func(void *_adap)
+                       goto unlock;
+               }
++              if (adap->transmit_in_progress &&
++                  adap->transmit_in_progress_aborted) {
++                      if (adap->transmitting)
++                              cec_data_cancel(adap->transmitting,
++                                              CEC_TX_STATUS_ABORTED, 0);
++                      adap->transmit_in_progress = false;
++                      adap->transmit_in_progress_aborted = false;
++                      goto unlock;
++              }
+               if (adap->transmit_in_progress && timeout) {
+                       /*
+                        * If we timeout, then log that. Normally this does
+@@ -755,6 +764,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
+ {
+       struct cec_data *data;
+       bool is_raw = msg_is_raw(msg);
++      int err;
+       if (adap->devnode.unregistered)
+               return -ENODEV;
+@@ -917,10 +927,13 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
+        * Release the lock and wait, retake the lock afterwards.
+        */
+       mutex_unlock(&adap->lock);
+-      wait_for_completion_killable(&data->c);
++      err = wait_for_completion_killable(&data->c);
+       cancel_delayed_work_sync(&data->work);
+       mutex_lock(&adap->lock);
++      if (err)
++              adap->transmit_in_progress_aborted = true;
++
+       /* Cancel the transmit if it was interrupted */
+       if (!data->completed) {
+               if (data->msg.tx_status & CEC_TX_STATUS_OK)
+-- 
+2.43.0
+
diff --git a/queue-5.10/media-cec-core-avoid-recursive-cec_claim_log_addrs.patch b/queue-5.10/media-cec-core-avoid-recursive-cec_claim_log_addrs.patch
new file mode 100644 (file)
index 0000000..b631e2e
--- /dev/null
@@ -0,0 +1,81 @@
+From 3e2892b57b2d3703b7848e418943c0ccfa8e6d57 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Feb 2024 16:17:33 +0000
+Subject: media: cec: core: avoid recursive cec_claim_log_addrs
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ 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 <hverkuil-cisco@xs4all.nl>
+Reported-by: Yang, Chenyuan <cy54@illinois.edu>
+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 <mchehab@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/cec/core/cec-adap.c | 6 +++++-
+ drivers/media/cec/core/cec-api.c  | 2 +-
+ include/media/cec.h               | 1 +
+ 3 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
+index 920c108b84aaf..42d66ae27b19f 100644
+--- a/drivers/media/cec/core/cec-adap.c
++++ b/drivers/media/cec/core/cec-adap.c
+@@ -1528,9 +1528,12 @@ static int cec_config_thread_func(void *arg)
+  */
+ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
+ {
+-      if (WARN_ON(adap->is_configuring || adap->is_configured))
++      if (WARN_ON(adap->is_claiming_log_addrs ||
++                  adap->is_configuring || adap->is_configured))
+               return;
++      adap->is_claiming_log_addrs = true;
++
+       init_completion(&adap->config_completion);
+       /* Ready to kick off the thread */
+@@ -1545,6 +1548,7 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
+               wait_for_completion(&adap->config_completion);
+               mutex_lock(&adap->lock);
+       }
++      adap->is_claiming_log_addrs = false;
+ }
+ /*
+diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c
+index feaf100a44c2d..8bdf58abdf965 100644
+--- a/drivers/media/cec/core/cec-api.c
++++ b/drivers/media/cec/core/cec-api.c
+@@ -178,7 +178,7 @@ static long cec_adap_s_log_addrs(struct cec_adapter *adap, struct cec_fh *fh,
+                          CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU |
+                          CEC_LOG_ADDRS_FL_CDC_ONLY;
+       mutex_lock(&adap->lock);
+-      if (!adap->is_configuring &&
++      if (!adap->is_claiming_log_addrs && !adap->is_configuring &&
+           (!log_addrs.num_log_addrs || !adap->is_configured) &&
+           !cec_is_busy(adap, fh)) {
+               err = __cec_s_log_addrs(adap, &log_addrs, block);
+diff --git a/include/media/cec.h b/include/media/cec.h
+index df3e8738d512b..23202bf439b47 100644
+--- a/include/media/cec.h
++++ b/include/media/cec.h
+@@ -239,6 +239,7 @@ struct cec_adapter {
+       u16 phys_addr;
+       bool needs_hpd;
+       bool is_enabled;
++      bool is_claiming_log_addrs;
+       bool is_configuring;
+       bool is_configured;
+       bool cec_pin_is_high;
+-- 
+2.43.0
+
diff --git a/queue-5.10/media-cec-correctly-pass-on-reply-results.patch b/queue-5.10/media-cec-correctly-pass-on-reply-results.patch
new file mode 100644 (file)
index 0000000..637a0f6
--- /dev/null
@@ -0,0 +1,166 @@
+From bbc91d41136df8053b26495e984568b0158f68f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 13 Nov 2021 11:02:36 +0000
+Subject: media: cec: correctly pass on reply results
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ 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 <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
+Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/cec/core/cec-adap.c | 48 +++++++++++++++++++------------
+ 1 file changed, 30 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
+index fd4af157f4ce7..41f4def8a31ca 100644
+--- a/drivers/media/cec/core/cec-adap.c
++++ b/drivers/media/cec/core/cec-adap.c
+@@ -366,38 +366,48 @@ static void cec_data_completed(struct cec_data *data)
+ /*
+  * A pending CEC transmit needs to be cancelled, either because the CEC
+  * adapter is disabled or the transmit takes an impossibly long time to
+- * finish.
++ * finish, or the reply timed out.
+  *
+  * This function is called with adap->lock held.
+  */
+-static void cec_data_cancel(struct cec_data *data, u8 tx_status)
++static void cec_data_cancel(struct cec_data *data, u8 tx_status, u8 rx_status)
+ {
++      struct cec_adapter *adap = data->adap;
++
+       /*
+        * It's either the current transmit, or it is a pending
+        * transmit. Take the appropriate action to clear it.
+        */
+-      if (data->adap->transmitting == data) {
+-              data->adap->transmitting = NULL;
++      if (adap->transmitting == data) {
++              adap->transmitting = NULL;
+       } else {
+               list_del_init(&data->list);
+               if (!(data->msg.tx_status & CEC_TX_STATUS_OK))
+-                      if (!WARN_ON(!data->adap->transmit_queue_sz))
+-                              data->adap->transmit_queue_sz--;
++                      if (!WARN_ON(!adap->transmit_queue_sz))
++                              adap->transmit_queue_sz--;
+       }
+       if (data->msg.tx_status & CEC_TX_STATUS_OK) {
+               data->msg.rx_ts = ktime_get_ns();
+-              data->msg.rx_status = CEC_RX_STATUS_ABORTED;
++              data->msg.rx_status = rx_status;
++              if (!data->blocking)
++                      data->msg.tx_status = 0;
+       } else {
+               data->msg.tx_ts = ktime_get_ns();
+               data->msg.tx_status |= tx_status |
+                                      CEC_TX_STATUS_MAX_RETRIES;
+               data->msg.tx_error_cnt++;
+               data->attempts = 0;
++              if (!data->blocking)
++                      data->msg.rx_status = 0;
+       }
+       /* Queue transmitted message for monitoring purposes */
+-      cec_queue_msg_monitor(data->adap, &data->msg, 1);
++      cec_queue_msg_monitor(adap, &data->msg, 1);
++
++      if (!data->blocking && data->msg.sequence && adap->ops->received)
++              /* Allow drivers to process the message first */
++              adap->ops->received(adap, &data->msg);
+       cec_data_completed(data);
+ }
+@@ -418,7 +428,7 @@ static void cec_flush(struct cec_adapter *adap)
+       while (!list_empty(&adap->transmit_queue)) {
+               data = list_first_entry(&adap->transmit_queue,
+                                       struct cec_data, list);
+-              cec_data_cancel(data, CEC_TX_STATUS_ABORTED);
++              cec_data_cancel(data, CEC_TX_STATUS_ABORTED, 0);
+       }
+       if (adap->transmitting)
+               adap->transmit_in_progress_aborted = true;
+@@ -426,7 +436,7 @@ static void cec_flush(struct cec_adapter *adap)
+       /* Cancel the pending timeout work. */
+       list_for_each_entry_safe(data, n, &adap->wait_queue, list) {
+               if (cancel_delayed_work(&data->work))
+-                      cec_data_cancel(data, CEC_TX_STATUS_OK);
++                      cec_data_cancel(data, CEC_TX_STATUS_OK, CEC_RX_STATUS_ABORTED);
+               /*
+                * If cancel_delayed_work returned false, then
+                * the cec_wait_timeout function is running,
+@@ -516,7 +526,7 @@ int cec_thread_func(void *_adap)
+                                       adap->transmitting->msg.msg);
+                               /* Just give up on this. */
+                               cec_data_cancel(adap->transmitting,
+-                                              CEC_TX_STATUS_TIMEOUT);
++                                              CEC_TX_STATUS_TIMEOUT, 0);
+                       } else {
+                               pr_warn("cec-%s: transmit timed out\n", adap->name);
+                       }
+@@ -576,7 +586,7 @@ int cec_thread_func(void *_adap)
+               /* Tell the adapter to transmit, cancel on error */
+               if (adap->ops->adap_transmit(adap, data->attempts,
+                                            signal_free_time, &data->msg))
+-                      cec_data_cancel(data, CEC_TX_STATUS_ABORTED);
++                      cec_data_cancel(data, CEC_TX_STATUS_ABORTED, 0);
+               else
+                       adap->transmit_in_progress = true;
+@@ -738,9 +748,7 @@ static void cec_wait_timeout(struct work_struct *work)
+       /* Mark the message as timed out */
+       list_del_init(&data->list);
+-      data->msg.rx_ts = ktime_get_ns();
+-      data->msg.rx_status = CEC_RX_STATUS_TIMEOUT;
+-      cec_data_completed(data);
++      cec_data_cancel(data, CEC_TX_STATUS_OK, CEC_RX_STATUS_TIMEOUT);
+ unlock:
+       mutex_unlock(&adap->lock);
+ }
+@@ -923,8 +931,12 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
+       mutex_lock(&adap->lock);
+       /* Cancel the transmit if it was interrupted */
+-      if (!data->completed)
+-              cec_data_cancel(data, CEC_TX_STATUS_ABORTED);
++      if (!data->completed) {
++              if (data->msg.tx_status & CEC_TX_STATUS_OK)
++                      cec_data_cancel(data, CEC_TX_STATUS_OK, CEC_RX_STATUS_ABORTED);
++              else
++                      cec_data_cancel(data, CEC_TX_STATUS_ABORTED, 0);
++      }
+       /* The transmit completed (possibly with an error) */
+       *msg = data->msg;
+@@ -1583,7 +1595,7 @@ static void cec_activate_cnt_dec(struct cec_adapter *adap)
+       adap->transmit_in_progress = false;
+       adap->transmit_in_progress_aborted = false;
+       if (adap->transmitting)
+-              cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED);
++              cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED, 0);
+       mutex_unlock(&adap->devnode.lock);
+ }
+-- 
+2.43.0
+
diff --git a/queue-5.10/media-cec-fix-a-deadlock-situation.patch b/queue-5.10/media-cec-fix-a-deadlock-situation.patch
new file mode 100644 (file)
index 0000000..48c3076
--- /dev/null
@@ -0,0 +1,271 @@
+From afc180e1cb4b1241d198a3175a13b10cf307dcba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 1 Dec 2021 13:41:26 +0100
+Subject: media: cec: fix a deadlock situation
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ Upstream commit a9e6107616bb8108aa4fc22584a05e69761a91f7 ]
+
+The cec_devnode struct has a lock meant to serialize access
+to the fields of this struct. This lock is taken during
+device node (un)registration and when opening or releasing a
+filehandle to the device node. When the last open filehandle
+is closed the cec adapter might be disabled by calling the
+adap_enable driver callback with the devnode.lock held.
+
+However, if during that callback a message or event arrives
+then the driver will call one of the cec_queue_event()
+variants in cec-adap.c, and those will take the same devnode.lock
+to walk the open filehandle list.
+
+This obviously causes a deadlock.
+
+This is quite easy to reproduce with the cec-gpio driver since that
+uses the cec-pin framework which generated lots of events and uses
+a kernel thread for the processing, so when adap_enable is called
+the thread is still running and can generate events.
+
+But I suspect that it might also happen with other drivers if an
+interrupt arrives signaling e.g. a received message before adap_enable
+had a chance to disable the interrupts.
+
+This patch adds a new mutex to serialize access to the fhs list.
+When adap_enable() is called the devnode.lock mutex is held, but
+not devnode.lock_fhs. The event functions in cec-adap.c will now
+use devnode.lock_fhs instead of devnode.lock, ensuring that it is
+safe to call those functions from the adap_enable callback.
+
+This specific issue only happens if the last open filehandle is closed
+and the physical address is invalid. This is not something that
+happens during normal operation, but it does happen when monitoring
+CEC traffic (e.g. cec-ctl --monitor) with an unconfigured CEC adapter.
+
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Cc: <stable@vger.kernel.org>  # for v5.13 and up
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/cec/core/cec-adap.c | 38 +++++++++++++++++--------------
+ drivers/media/cec/core/cec-api.c  |  6 +++++
+ drivers/media/cec/core/cec-core.c |  3 +++
+ include/media/cec.h               | 11 +++++++--
+ 4 files changed, 39 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
+index 78027f0310acd..d2a6fd8b65014 100644
+--- a/drivers/media/cec/core/cec-adap.c
++++ b/drivers/media/cec/core/cec-adap.c
+@@ -161,10 +161,10 @@ static void cec_queue_event(struct cec_adapter *adap,
+       u64 ts = ktime_get_ns();
+       struct cec_fh *fh;
+-      mutex_lock(&adap->devnode.lock);
++      mutex_lock(&adap->devnode.lock_fhs);
+       list_for_each_entry(fh, &adap->devnode.fhs, list)
+               cec_queue_event_fh(fh, ev, ts);
+-      mutex_unlock(&adap->devnode.lock);
++      mutex_unlock(&adap->devnode.lock_fhs);
+ }
+ /* Notify userspace that the CEC pin changed state at the given time. */
+@@ -178,11 +178,12 @@ void cec_queue_pin_cec_event(struct cec_adapter *adap, bool is_high,
+       };
+       struct cec_fh *fh;
+-      mutex_lock(&adap->devnode.lock);
+-      list_for_each_entry(fh, &adap->devnode.fhs, list)
++      mutex_lock(&adap->devnode.lock_fhs);
++      list_for_each_entry(fh, &adap->devnode.fhs, list) {
+               if (fh->mode_follower == CEC_MODE_MONITOR_PIN)
+                       cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
+-      mutex_unlock(&adap->devnode.lock);
++      }
++      mutex_unlock(&adap->devnode.lock_fhs);
+ }
+ EXPORT_SYMBOL_GPL(cec_queue_pin_cec_event);
+@@ -195,10 +196,10 @@ void cec_queue_pin_hpd_event(struct cec_adapter *adap, bool is_high, ktime_t ts)
+       };
+       struct cec_fh *fh;
+-      mutex_lock(&adap->devnode.lock);
++      mutex_lock(&adap->devnode.lock_fhs);
+       list_for_each_entry(fh, &adap->devnode.fhs, list)
+               cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
+-      mutex_unlock(&adap->devnode.lock);
++      mutex_unlock(&adap->devnode.lock_fhs);
+ }
+ EXPORT_SYMBOL_GPL(cec_queue_pin_hpd_event);
+@@ -211,10 +212,10 @@ void cec_queue_pin_5v_event(struct cec_adapter *adap, bool is_high, ktime_t ts)
+       };
+       struct cec_fh *fh;
+-      mutex_lock(&adap->devnode.lock);
++      mutex_lock(&adap->devnode.lock_fhs);
+       list_for_each_entry(fh, &adap->devnode.fhs, list)
+               cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
+-      mutex_unlock(&adap->devnode.lock);
++      mutex_unlock(&adap->devnode.lock_fhs);
+ }
+ EXPORT_SYMBOL_GPL(cec_queue_pin_5v_event);
+@@ -286,12 +287,12 @@ static void cec_queue_msg_monitor(struct cec_adapter *adap,
+       u32 monitor_mode = valid_la ? CEC_MODE_MONITOR :
+                                     CEC_MODE_MONITOR_ALL;
+-      mutex_lock(&adap->devnode.lock);
++      mutex_lock(&adap->devnode.lock_fhs);
+       list_for_each_entry(fh, &adap->devnode.fhs, list) {
+               if (fh->mode_follower >= monitor_mode)
+                       cec_queue_msg_fh(fh, msg);
+       }
+-      mutex_unlock(&adap->devnode.lock);
++      mutex_unlock(&adap->devnode.lock_fhs);
+ }
+ /*
+@@ -302,12 +303,12 @@ static void cec_queue_msg_followers(struct cec_adapter *adap,
+ {
+       struct cec_fh *fh;
+-      mutex_lock(&adap->devnode.lock);
++      mutex_lock(&adap->devnode.lock_fhs);
+       list_for_each_entry(fh, &adap->devnode.fhs, list) {
+               if (fh->mode_follower == CEC_MODE_FOLLOWER)
+                       cec_queue_msg_fh(fh, msg);
+       }
+-      mutex_unlock(&adap->devnode.lock);
++      mutex_unlock(&adap->devnode.lock_fhs);
+ }
+ /* Notify userspace of an adapter state change. */
+@@ -1559,6 +1560,7 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
+               /* Disabling monitor all mode should always succeed */
+               if (adap->monitor_all_cnt)
+                       WARN_ON(call_op(adap, adap_monitor_all_enable, false));
++              /* serialize adap_enable */
+               mutex_lock(&adap->devnode.lock);
+               if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) {
+                       WARN_ON(adap->ops->adap_enable(adap, false));
+@@ -1570,14 +1572,16 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
+                       return;
+       }
++      /* serialize adap_enable */
+       mutex_lock(&adap->devnode.lock);
+       adap->last_initiator = 0xff;
+       adap->transmit_in_progress = false;
+-      if ((adap->needs_hpd || list_empty(&adap->devnode.fhs)) &&
+-          adap->ops->adap_enable(adap, true)) {
+-              mutex_unlock(&adap->devnode.lock);
+-              return;
++      if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) {
++              if (adap->ops->adap_enable(adap, true)) {
++                      mutex_unlock(&adap->devnode.lock);
++                      return;
++              }
+       }
+       if (adap->monitor_all_cnt &&
+diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c
+index 893641ebc644b..899017a0e514e 100644
+--- a/drivers/media/cec/core/cec-api.c
++++ b/drivers/media/cec/core/cec-api.c
+@@ -586,6 +586,7 @@ static int cec_open(struct inode *inode, struct file *filp)
+               return err;
+       }
++      /* serialize adap_enable */
+       mutex_lock(&devnode->lock);
+       if (list_empty(&devnode->fhs) &&
+           !adap->needs_hpd &&
+@@ -624,7 +625,9 @@ static int cec_open(struct inode *inode, struct file *filp)
+       }
+ #endif
++      mutex_lock(&devnode->lock_fhs);
+       list_add(&fh->list, &devnode->fhs);
++      mutex_unlock(&devnode->lock_fhs);
+       mutex_unlock(&devnode->lock);
+       return 0;
+@@ -653,8 +656,11 @@ static int cec_release(struct inode *inode, struct file *filp)
+               cec_monitor_all_cnt_dec(adap);
+       mutex_unlock(&adap->lock);
++      /* serialize adap_enable */
+       mutex_lock(&devnode->lock);
++      mutex_lock(&devnode->lock_fhs);
+       list_del(&fh->list);
++      mutex_unlock(&devnode->lock_fhs);
+       if (cec_is_registered(adap) && list_empty(&devnode->fhs) &&
+           !adap->needs_hpd && adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
+               WARN_ON(adap->ops->adap_enable(adap, false));
+diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c
+index ece236291f358..61139b0a08699 100644
+--- a/drivers/media/cec/core/cec-core.c
++++ b/drivers/media/cec/core/cec-core.c
+@@ -167,8 +167,10 @@ static void cec_devnode_unregister(struct cec_adapter *adap)
+               return;
+       }
++      mutex_lock(&devnode->lock_fhs);
+       list_for_each_entry(fh, &devnode->fhs, list)
+               wake_up_interruptible(&fh->wait);
++      mutex_unlock(&devnode->lock_fhs);
+       devnode->registered = false;
+       devnode->unregistered = true;
+@@ -272,6 +274,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
+       /* adap->devnode initialization */
+       INIT_LIST_HEAD(&adap->devnode.fhs);
++      mutex_init(&adap->devnode.lock_fhs);
+       mutex_init(&adap->devnode.lock);
+       adap->kthread = kthread_run(cec_thread_func, adap, "cec-%s", name);
+diff --git a/include/media/cec.h b/include/media/cec.h
+index 208c9613c07eb..77346f757036d 100644
+--- a/include/media/cec.h
++++ b/include/media/cec.h
+@@ -26,13 +26,17 @@
+  * @dev:      cec device
+  * @cdev:     cec character device
+  * @minor:    device node minor number
++ * @lock:     lock to serialize open/release and registration
+  * @registered:       the device was correctly registered
+  * @unregistered: the device was unregistered
++ * @lock_fhs: lock to control access to @fhs
+  * @fhs:      the list of open filehandles (cec_fh)
+- * @lock:     lock to control access to this structure
+  *
+  * This structure represents a cec-related device node.
+  *
++ * To add or remove filehandles from @fhs the @lock must be taken first,
++ * followed by @lock_fhs. It is safe to access @fhs if either lock is held.
++ *
+  * The @parent is a physical device. It must be set by core or device drivers
+  * before registering the node.
+  */
+@@ -43,10 +47,13 @@ struct cec_devnode {
+       /* device info */
+       int minor;
++      /* serialize open/release and registration */
++      struct mutex lock;
+       bool registered;
+       bool unregistered;
++      /* protect access to fhs */
++      struct mutex lock_fhs;
+       struct list_head fhs;
+-      struct mutex lock;
+ };
+ struct cec_adapter;
+-- 
+2.43.0
+
diff --git a/queue-5.10/media-cec-use-call_op-and-check-for-unregistered.patch b/queue-5.10/media-cec-use-call_op-and-check-for-unregistered.patch
new file mode 100644 (file)
index 0000000..ddd854c
--- /dev/null
@@ -0,0 +1,312 @@
+From e6cc59c37dbe766dae9af5c58a023beffdbea040 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Mar 2022 08:51:20 +0000
+Subject: media: cec: use call_op and check for !unregistered
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ 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 <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
+Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/cec/core/cec-adap.c     | 37 ++++++++++-----------------
+ drivers/media/cec/core/cec-api.c      |  6 +++--
+ drivers/media/cec/core/cec-core.c     |  4 +--
+ drivers/media/cec/core/cec-pin-priv.h | 11 ++++++++
+ drivers/media/cec/core/cec-pin.c      | 23 ++++++++---------
+ drivers/media/cec/core/cec-priv.h     | 10 ++++++++
+ 6 files changed, 51 insertions(+), 40 deletions(-)
+
+diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
+index 41f4def8a31ca..07ff4b0c8461e 100644
+--- a/drivers/media/cec/core/cec-adap.c
++++ b/drivers/media/cec/core/cec-adap.c
+@@ -39,15 +39,6 @@ static void cec_fill_msg_report_features(struct cec_adapter *adap,
+  */
+ #define CEC_XFER_TIMEOUT_MS (5 * 400 + 100)
+-#define call_op(adap, op, arg...) \
+-      (adap->ops->op ? adap->ops->op(adap, ## arg) : 0)
+-
+-#define call_void_op(adap, op, arg...)                        \
+-      do {                                            \
+-              if (adap->ops->op)                      \
+-                      adap->ops->op(adap, ## arg);    \
+-      } while (0)
+-
+ static int cec_log_addr2idx(const struct cec_adapter *adap, u8 log_addr)
+ {
+       int i;
+@@ -405,9 +396,9 @@ static void cec_data_cancel(struct cec_data *data, u8 tx_status, u8 rx_status)
+       /* Queue transmitted message for monitoring purposes */
+       cec_queue_msg_monitor(adap, &data->msg, 1);
+-      if (!data->blocking && data->msg.sequence && adap->ops->received)
++      if (!data->blocking && data->msg.sequence)
+               /* Allow drivers to process the message first */
+-              adap->ops->received(adap, &data->msg);
++              call_op(adap, received, &data->msg);
+       cec_data_completed(data);
+ }
+@@ -584,8 +575,8 @@ int cec_thread_func(void *_adap)
+               adap->transmit_in_progress_aborted = false;
+               /* Tell the adapter to transmit, cancel on error */
+-              if (adap->ops->adap_transmit(adap, data->attempts,
+-                                           signal_free_time, &data->msg))
++              if (call_op(adap, adap_transmit, data->attempts,
++                          signal_free_time, &data->msg))
+                       cec_data_cancel(data, CEC_TX_STATUS_ABORTED, 0);
+               else
+                       adap->transmit_in_progress = true;
+@@ -1311,7 +1302,7 @@ static int cec_config_log_addr(struct cec_adapter *adap,
+        * Message not acknowledged, so this logical
+        * address is free to use.
+        */
+-      err = adap->ops->adap_log_addr(adap, log_addr);
++      err = call_op(adap, adap_log_addr, log_addr);
+       if (err)
+               return err;
+@@ -1328,9 +1319,8 @@ static int cec_config_log_addr(struct cec_adapter *adap,
+  */
+ static void cec_adap_unconfigure(struct cec_adapter *adap)
+ {
+-      if (!adap->needs_hpd ||
+-          adap->phys_addr != CEC_PHYS_ADDR_INVALID)
+-              WARN_ON(adap->ops->adap_log_addr(adap, CEC_LOG_ADDR_INVALID));
++      if (!adap->needs_hpd || adap->phys_addr != CEC_PHYS_ADDR_INVALID)
++              WARN_ON(call_op(adap, adap_log_addr, CEC_LOG_ADDR_INVALID));
+       adap->log_addrs.log_addr_mask = 0;
+       adap->is_configured = false;
+       cec_flush(adap);
+@@ -1573,7 +1563,7 @@ static int cec_activate_cnt_inc(struct cec_adapter *adap)
+       mutex_lock(&adap->devnode.lock);
+       adap->last_initiator = 0xff;
+       adap->transmit_in_progress = false;
+-      ret = adap->ops->adap_enable(adap, true);
++      ret = call_op(adap, adap_enable, true);
+       if (ret)
+               adap->activate_cnt--;
+       mutex_unlock(&adap->devnode.lock);
+@@ -1590,7 +1580,7 @@ static void cec_activate_cnt_dec(struct cec_adapter *adap)
+       /* serialize adap_enable */
+       mutex_lock(&adap->devnode.lock);
+-      WARN_ON(adap->ops->adap_enable(adap, false));
++      WARN_ON(call_op(adap, adap_enable, false));
+       adap->last_initiator = 0xff;
+       adap->transmit_in_progress = false;
+       adap->transmit_in_progress_aborted = false;
+@@ -1964,11 +1954,10 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
+           msg->msg[1] != CEC_MSG_CDC_MESSAGE)
+               return 0;
+-      if (adap->ops->received) {
+-              /* Allow drivers to process the message first */
+-              if (adap->ops->received(adap, msg) != -ENOMSG)
+-                      return 0;
+-      }
++      /* Allow drivers to process the message first */
++      if (adap->ops->received && !adap->devnode.unregistered &&
++          adap->ops->received(adap, msg) != -ENOMSG)
++              return 0;
+       /*
+        * REPORT_PHYSICAL_ADDR, CEC_MSG_USER_CONTROL_PRESSED and
+diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c
+index 0be4e822211e7..feaf100a44c2d 100644
+--- a/drivers/media/cec/core/cec-api.c
++++ b/drivers/media/cec/core/cec-api.c
+@@ -595,7 +595,8 @@ static int cec_open(struct inode *inode, struct file *filp)
+               adap->conn_info.type != CEC_CONNECTOR_TYPE_NO_CONNECTOR;
+       cec_queue_event_fh(fh, &ev, 0);
+ #ifdef CONFIG_CEC_PIN
+-      if (adap->pin && adap->pin->ops->read_hpd) {
++      if (adap->pin && adap->pin->ops->read_hpd &&
++          !adap->devnode.unregistered) {
+               err = adap->pin->ops->read_hpd(adap);
+               if (err >= 0) {
+                       ev.event = err ? CEC_EVENT_PIN_HPD_HIGH :
+@@ -603,7 +604,8 @@ static int cec_open(struct inode *inode, struct file *filp)
+                       cec_queue_event_fh(fh, &ev, 0);
+               }
+       }
+-      if (adap->pin && adap->pin->ops->read_5v) {
++      if (adap->pin && adap->pin->ops->read_5v &&
++          !adap->devnode.unregistered) {
+               err = adap->pin->ops->read_5v(adap);
+               if (err >= 0) {
+                       ev.event = err ? CEC_EVENT_PIN_5V_HIGH :
+diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c
+index 61139b0a08699..0a3345e1a0f3a 100644
+--- a/drivers/media/cec/core/cec-core.c
++++ b/drivers/media/cec/core/cec-core.c
+@@ -204,7 +204,7 @@ static ssize_t cec_error_inj_write(struct file *file,
+               line = strsep(&p, "\n");
+               if (!*line || *line == '#')
+                       continue;
+-              if (!adap->ops->error_inj_parse_line(adap, line)) {
++              if (!call_op(adap, error_inj_parse_line, line)) {
+                       kfree(buf);
+                       return -EINVAL;
+               }
+@@ -217,7 +217,7 @@ static int cec_error_inj_show(struct seq_file *sf, void *unused)
+ {
+       struct cec_adapter *adap = sf->private;
+-      return adap->ops->error_inj_show(adap, sf);
++      return call_op(adap, error_inj_show, sf);
+ }
+ static int cec_error_inj_open(struct inode *inode, struct file *file)
+diff --git a/drivers/media/cec/core/cec-pin-priv.h b/drivers/media/cec/core/cec-pin-priv.h
+index f423db8855d9e..5577c62e4131f 100644
+--- a/drivers/media/cec/core/cec-pin-priv.h
++++ b/drivers/media/cec/core/cec-pin-priv.h
+@@ -12,6 +12,17 @@
+ #include <linux/atomic.h>
+ #include <media/cec-pin.h>
++#define call_pin_op(pin, op, arg...)                                  \
++      ((pin && pin->ops->op && !pin->adap->devnode.unregistered) ?    \
++       pin->ops->op(pin->adap, ## arg) : 0)
++
++#define call_void_pin_op(pin, op, arg...)                             \
++      do {                                                            \
++              if (pin && pin->ops->op &&                              \
++                  !pin->adap->devnode.unregistered)                   \
++                      pin->ops->op(pin->adap, ## arg);                \
++      } while (0)
++
+ enum cec_pin_state {
+       /* CEC is off */
+       CEC_ST_OFF,
+diff --git a/drivers/media/cec/core/cec-pin.c b/drivers/media/cec/core/cec-pin.c
+index f8452a1f9fc6c..447fdada20e98 100644
+--- a/drivers/media/cec/core/cec-pin.c
++++ b/drivers/media/cec/core/cec-pin.c
+@@ -135,7 +135,7 @@ static void cec_pin_update(struct cec_pin *pin, bool v, bool force)
+ static bool cec_pin_read(struct cec_pin *pin)
+ {
+-      bool v = pin->ops->read(pin->adap);
++      bool v = call_pin_op(pin, read);
+       cec_pin_update(pin, v, false);
+       return v;
+@@ -143,13 +143,13 @@ static bool cec_pin_read(struct cec_pin *pin)
+ static void cec_pin_low(struct cec_pin *pin)
+ {
+-      pin->ops->low(pin->adap);
++      call_void_pin_op(pin, low);
+       cec_pin_update(pin, false, false);
+ }
+ static bool cec_pin_high(struct cec_pin *pin)
+ {
+-      pin->ops->high(pin->adap);
++      call_void_pin_op(pin, high);
+       return cec_pin_read(pin);
+ }
+@@ -1086,7 +1086,7 @@ static int cec_pin_thread_func(void *_adap)
+                                   CEC_PIN_IRQ_UNCHANGED)) {
+               case CEC_PIN_IRQ_DISABLE:
+                       if (irq_enabled) {
+-                              pin->ops->disable_irq(adap);
++                              call_void_pin_op(pin, disable_irq);
+                               irq_enabled = false;
+                       }
+                       cec_pin_high(pin);
+@@ -1097,7 +1097,7 @@ static int cec_pin_thread_func(void *_adap)
+               case CEC_PIN_IRQ_ENABLE:
+                       if (irq_enabled)
+                               break;
+-                      pin->enable_irq_failed = !pin->ops->enable_irq(adap);
++                      pin->enable_irq_failed = !call_pin_op(pin, enable_irq);
+                       if (pin->enable_irq_failed) {
+                               cec_pin_to_idle(pin);
+                               hrtimer_start(&pin->timer, ns_to_ktime(0),
+@@ -1112,8 +1112,8 @@ static int cec_pin_thread_func(void *_adap)
+               if (kthread_should_stop())
+                       break;
+       }
+-      if (pin->ops->disable_irq && irq_enabled)
+-              pin->ops->disable_irq(adap);
++      if (irq_enabled)
++              call_void_pin_op(pin, disable_irq);
+       hrtimer_cancel(&pin->timer);
+       cec_pin_read(pin);
+       cec_pin_to_idle(pin);
+@@ -1208,7 +1208,7 @@ static void cec_pin_adap_status(struct cec_adapter *adap,
+       seq_printf(file, "state: %s\n", states[pin->state].name);
+       seq_printf(file, "tx_bit: %d\n", pin->tx_bit);
+       seq_printf(file, "rx_bit: %d\n", pin->rx_bit);
+-      seq_printf(file, "cec pin: %d\n", pin->ops->read(adap));
++      seq_printf(file, "cec pin: %d\n", call_pin_op(pin, read));
+       seq_printf(file, "cec pin events dropped: %u\n",
+                  pin->work_pin_events_dropped_cnt);
+       seq_printf(file, "irq failed: %d\n", pin->enable_irq_failed);
+@@ -1261,8 +1261,7 @@ static void cec_pin_adap_status(struct cec_adapter *adap,
+       pin->rx_data_bit_too_long_cnt = 0;
+       pin->rx_low_drive_cnt = 0;
+       pin->tx_low_drive_cnt = 0;
+-      if (pin->ops->status)
+-              pin->ops->status(adap, file);
++      call_void_pin_op(pin, status, file);
+ }
+ static int cec_pin_adap_monitor_all_enable(struct cec_adapter *adap,
+@@ -1278,7 +1277,7 @@ static void cec_pin_adap_free(struct cec_adapter *adap)
+ {
+       struct cec_pin *pin = adap->pin;
+-      if (pin->ops->free)
++      if (pin && pin->ops->free)
+               pin->ops->free(adap);
+       adap->pin = NULL;
+       kfree(pin);
+@@ -1288,7 +1287,7 @@ static int cec_pin_received(struct cec_adapter *adap, struct cec_msg *msg)
+ {
+       struct cec_pin *pin = adap->pin;
+-      if (pin->ops->received)
++      if (pin->ops->received && !adap->devnode.unregistered)
+               return pin->ops->received(adap, msg);
+       return -ENOMSG;
+ }
+diff --git a/drivers/media/cec/core/cec-priv.h b/drivers/media/cec/core/cec-priv.h
+index 9bbd05053d420..b78df931aa74b 100644
+--- a/drivers/media/cec/core/cec-priv.h
++++ b/drivers/media/cec/core/cec-priv.h
+@@ -17,6 +17,16 @@
+                       pr_info("cec-%s: " fmt, adap->name, ## arg);    \
+       } while (0)
++#define call_op(adap, op, arg...)                                     \
++      ((adap->ops->op && !adap->devnode.unregistered) ?               \
++       adap->ops->op(adap, ## arg) : 0)
++
++#define call_void_op(adap, op, arg...)                                        \
++      do {                                                            \
++              if (adap->ops->op && !adap->devnode.unregistered)       \
++                      adap->ops->op(adap, ## arg);                    \
++      } while (0)
++
+ /* devnode to cec_adapter */
+ #define to_cec_adapter(node) container_of(node, struct cec_adapter, devnode)
+-- 
+2.43.0
+
diff --git a/queue-5.10/media-core-headers-fix-kernel-doc-warnings.patch b/queue-5.10/media-core-headers-fix-kernel-doc-warnings.patch
new file mode 100644 (file)
index 0000000..ee9ffdc
--- /dev/null
@@ -0,0 +1,276 @@
+From 0456bc48703200f8aa568c29abe1db0fe0be679c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Mar 2021 12:48:20 +0100
+Subject: media: core headers: fix kernel-doc warnings
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ Upstream commit f12b81e47f48940a6ec82ff308a7d97cd2307442 ]
+
+This patch fixes the following kernel-doc warnings:
+
+include/uapi/linux/videodev2.h:996: warning: Function parameter or member 'm' not described in 'v4l2_plane'
+include/uapi/linux/videodev2.h:996: warning: Function parameter or member 'reserved' not described in 'v4l2_plane'
+include/uapi/linux/videodev2.h:1057: warning: Function parameter or member 'm' not described in 'v4l2_buffer'
+include/uapi/linux/videodev2.h:1057: warning: Function parameter or member 'reserved2' not described in 'v4l2_buffer'
+include/uapi/linux/videodev2.h:1057: warning: Function parameter or member 'reserved' not described in 'v4l2_buffer'
+include/uapi/linux/videodev2.h:1068: warning: Function parameter or member 'tv' not described in 'v4l2_timeval_to_ns'
+include/uapi/linux/videodev2.h:1068: warning: Excess function parameter 'ts' description in 'v4l2_timeval_to_ns'
+include/uapi/linux/videodev2.h:1138: warning: Function parameter or member 'reserved' not described in 'v4l2_exportbuffer'
+include/uapi/linux/videodev2.h:2237: warning: Function parameter or member 'reserved' not described in 'v4l2_plane_pix_format'
+include/uapi/linux/videodev2.h:2270: warning: Function parameter or member 'hsv_enc' not described in 'v4l2_pix_format_mplane'
+include/uapi/linux/videodev2.h:2270: warning: Function parameter or member 'reserved' not described in 'v4l2_pix_format_mplane'
+include/uapi/linux/videodev2.h:2281: warning: Function parameter or member 'reserved' not described in 'v4l2_sdr_format'
+include/uapi/linux/videodev2.h:2315: warning: Function parameter or member 'fmt' not described in 'v4l2_format'
+
+include/uapi/linux/v4l2-subdev.h:53: warning: Function parameter or member 'reserved' not described in 'v4l2_subdev_format'
+include/uapi/linux/v4l2-subdev.h:66: warning: Function parameter or member 'reserved' not described in 'v4l2_subdev_crop'
+include/uapi/linux/v4l2-subdev.h:89: warning: Function parameter or member 'reserved' not described in 'v4l2_subdev_mbus_code_enum'
+include/uapi/linux/v4l2-subdev.h:108: warning: Function parameter or member 'min_width' not described in 'v4l2_subdev_frame_size_enum'
+include/uapi/linux/v4l2-subdev.h:108: warning: Function parameter or member 'max_width' not described in 'v4l2_subdev_frame_size_enum'
+include/uapi/linux/v4l2-subdev.h:108: warning: Function parameter or member 'min_height' not described in 'v4l2_subdev_frame_size_enum'
+include/uapi/linux/v4l2-subdev.h:108: warning: Function parameter or member 'max_height' not described in 'v4l2_subdev_frame_size_enum'
+include/uapi/linux/v4l2-subdev.h:108: warning: Function parameter or member 'reserved' not described in 'v4l2_subdev_frame_size_enum'
+include/uapi/linux/v4l2-subdev.h:119: warning: Function parameter or member 'reserved' not described in 'v4l2_subdev_frame_interval'
+include/uapi/linux/v4l2-subdev.h:140: warning: Function parameter or member 'reserved' not described in 'v4l2_subdev_frame_interval_enum'
+
+include/uapi/linux/cec.h:406: warning: Function parameter or member 'raw' not described in 'cec_connector_info'
+include/uapi/linux/cec.h:470: warning: Function parameter or member 'flags' not described in 'cec_event'
+
+include/media/v4l2-h264.h:82: warning: Function parameter or member 'reflist' not described in 'v4l2_h264_build_p_ref_list'
+include/media/v4l2-h264.h:82: warning: expecting prototype for v4l2_h264_build_b_ref_lists(). Prototype was for v4l2_h264_build_p_ref_list()
+instead
+
+include/media/cec.h:50: warning: Function parameter or member 'lock' not described in 'cec_devnode'
+
+include/media/v4l2-jpeg.h:122: warning: Function parameter or member 'num_dht' not described in 'v4l2_jpeg_header'
+include/media/v4l2-jpeg.h:122: warning: Function parameter or member 'num_dqt' not described in 'v4l2_jpeg_header'
+
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/media/cec.h              |  2 +-
+ include/media/v4l2-h264.h        |  6 +++---
+ include/media/v4l2-jpeg.h        |  2 ++
+ include/uapi/linux/cec.h         |  3 ++-
+ include/uapi/linux/v4l2-subdev.h | 12 +++++++++++-
+ include/uapi/linux/videodev2.h   | 15 ++++++++++++++-
+ 6 files changed, 33 insertions(+), 7 deletions(-)
+
+diff --git a/include/media/cec.h b/include/media/cec.h
+index cd35ae6b7560f..208c9613c07eb 100644
+--- a/include/media/cec.h
++++ b/include/media/cec.h
+@@ -28,8 +28,8 @@
+  * @minor:    device node minor number
+  * @registered:       the device was correctly registered
+  * @unregistered: the device was unregistered
+- * @fhs_lock: lock to control access to the filehandle list
+  * @fhs:      the list of open filehandles (cec_fh)
++ * @lock:     lock to control access to this structure
+  *
+  * This structure represents a cec-related device node.
+  *
+diff --git a/include/media/v4l2-h264.h b/include/media/v4l2-h264.h
+index f08ba181263d1..1cc89d2e693a3 100644
+--- a/include/media/v4l2-h264.h
++++ b/include/media/v4l2-h264.h
+@@ -66,11 +66,11 @@ v4l2_h264_build_b_ref_lists(const struct v4l2_h264_reflist_builder *builder,
+                           u8 *b0_reflist, u8 *b1_reflist);
+ /**
+- * v4l2_h264_build_b_ref_lists() - Build the P reference list
++ * v4l2_h264_build_p_ref_list() - Build the P reference list
+  *
+  * @builder: reference list builder context
+- * @p_reflist: 16-bytes array used to store the P reference list. Each entry
+- *           is an index in the DPB
++ * @reflist: 16-bytes array used to store the P reference list. Each entry
++ *         is an index in the DPB
+  *
+  * This functions builds the P reference lists. This procedure is describe in
+  * section '8.2.4 Decoding process for reference picture lists construction'
+diff --git a/include/media/v4l2-jpeg.h b/include/media/v4l2-jpeg.h
+index ddba2a56c3214..3a3344a976782 100644
+--- a/include/media/v4l2-jpeg.h
++++ b/include/media/v4l2-jpeg.h
+@@ -91,7 +91,9 @@ struct v4l2_jpeg_scan_header {
+  * struct v4l2_jpeg_header - parsed JPEG header
+  * @sof: pointer to frame header and size
+  * @sos: pointer to scan header and size
++ * @num_dht: number of entries in @dht
+  * @dht: pointers to huffman tables and sizes
++ * @num_dqt: number of entries in @dqt
+  * @dqt: pointers to quantization tables and sizes
+  * @frame: parsed frame header
+  * @scan: pointer to parsed scan header, optional
+diff --git a/include/uapi/linux/cec.h b/include/uapi/linux/cec.h
+index 7d1a06c524696..dc8879d179fdf 100644
+--- a/include/uapi/linux/cec.h
++++ b/include/uapi/linux/cec.h
+@@ -396,6 +396,7 @@ struct cec_drm_connector_info {
+  * associated with the CEC adapter.
+  * @type: connector type (if any)
+  * @drm: drm connector info
++ * @raw: array to pad the union
+  */
+ struct cec_connector_info {
+       __u32 type;
+@@ -453,7 +454,7 @@ struct cec_event_lost_msgs {
+  * struct cec_event - CEC event structure
+  * @ts: the timestamp of when the event was sent.
+  * @event: the event.
+- * array.
++ * @flags: event flags.
+  * @state_change: the event payload for CEC_EVENT_STATE_CHANGE.
+  * @lost_msgs: the event payload for CEC_EVENT_LOST_MSGS.
+  * @raw: array to pad the union.
+diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
+index a38454d9e0f54..658106f5b5dc9 100644
+--- a/include/uapi/linux/v4l2-subdev.h
++++ b/include/uapi/linux/v4l2-subdev.h
+@@ -44,6 +44,7 @@ enum v4l2_subdev_format_whence {
+  * @which: format type (from enum v4l2_subdev_format_whence)
+  * @pad: pad number, as reported by the media API
+  * @format: media bus format (format code and frame size)
++ * @reserved: drivers and applications must zero this array
+  */
+ struct v4l2_subdev_format {
+       __u32 which;
+@@ -57,6 +58,7 @@ struct v4l2_subdev_format {
+  * @which: format type (from enum v4l2_subdev_format_whence)
+  * @pad: pad number, as reported by the media API
+  * @rect: pad crop rectangle boundaries
++ * @reserved: drivers and applications must zero this array
+  */
+ struct v4l2_subdev_crop {
+       __u32 which;
+@@ -78,6 +80,7 @@ struct v4l2_subdev_crop {
+  * @code: format code (MEDIA_BUS_FMT_ definitions)
+  * @which: format type (from enum v4l2_subdev_format_whence)
+  * @flags: flags set by the driver, (V4L2_SUBDEV_MBUS_CODE_*)
++ * @reserved: drivers and applications must zero this array
+  */
+ struct v4l2_subdev_mbus_code_enum {
+       __u32 pad;
+@@ -90,10 +93,15 @@ struct v4l2_subdev_mbus_code_enum {
+ /**
+  * struct v4l2_subdev_frame_size_enum - Media bus format enumeration
+- * @pad: pad number, as reported by the media API
+  * @index: format index during enumeration
++ * @pad: pad number, as reported by the media API
+  * @code: format code (MEDIA_BUS_FMT_ definitions)
++ * @min_width: minimum frame width, in pixels
++ * @max_width: maximum frame width, in pixels
++ * @min_height: minimum frame height, in pixels
++ * @max_height: maximum frame height, in pixels
+  * @which: format type (from enum v4l2_subdev_format_whence)
++ * @reserved: drivers and applications must zero this array
+  */
+ struct v4l2_subdev_frame_size_enum {
+       __u32 index;
+@@ -111,6 +119,7 @@ struct v4l2_subdev_frame_size_enum {
+  * struct v4l2_subdev_frame_interval - Pad-level frame rate
+  * @pad: pad number, as reported by the media API
+  * @interval: frame interval in seconds
++ * @reserved: drivers and applications must zero this array
+  */
+ struct v4l2_subdev_frame_interval {
+       __u32 pad;
+@@ -127,6 +136,7 @@ struct v4l2_subdev_frame_interval {
+  * @height: frame height in pixels
+  * @interval: frame interval in seconds
+  * @which: format type (from enum v4l2_subdev_format_whence)
++ * @reserved: drivers and applications must zero this array
+  */
+ struct v4l2_subdev_frame_interval_enum {
+       __u32 index;
+diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
+index 55b8c4b824797..1bbd81f031fe0 100644
+--- a/include/uapi/linux/videodev2.h
++++ b/include/uapi/linux/videodev2.h
+@@ -976,8 +976,10 @@ struct v4l2_requestbuffers {
+  *                    pointing to this plane
+  * @fd:                       when memory is V4L2_MEMORY_DMABUF, a userspace file
+  *                    descriptor associated with this plane
++ * @m:                        union of @mem_offset, @userptr and @fd
+  * @data_offset:      offset in the plane to the start of data; usually 0,
+  *                    unless there is a header in front of the data
++ * @reserved:         drivers and applications must zero this array
+  *
+  * Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer
+  * with two planes can have one plane for Y, and another for interleaved CbCr
+@@ -1019,10 +1021,14 @@ struct v4l2_plane {
+  *            a userspace file descriptor associated with this buffer
+  * @planes:   for multiplanar buffers; userspace pointer to the array of plane
+  *            info structs for this buffer
++ * @m:                union of @offset, @userptr, @planes and @fd
+  * @length:   size in bytes of the buffer (NOT its payload) for single-plane
+  *            buffers (when type != *_MPLANE); number of elements in the
+  *            planes array for multi-plane buffers
++ * @reserved2:        drivers and applications must zero this field
+  * @request_fd: fd of the request that this buffer should use
++ * @reserved: for backwards compatibility with applications that do not know
++ *            about @request_fd
+  *
+  * Contains data exchanged by application and driver using one of the Streaming
+  * I/O methods.
+@@ -1060,7 +1066,7 @@ struct v4l2_buffer {
+ #ifndef __KERNEL__
+ /**
+  * v4l2_timeval_to_ns - Convert timeval to nanoseconds
+- * @ts:               pointer to the timeval variable to be converted
++ * @tv:               pointer to the timeval variable to be converted
+  *
+  * Returns the scalar nanosecond representation of the timeval
+  * parameter.
+@@ -1121,6 +1127,7 @@ static inline __u64 v4l2_timeval_to_ns(const struct timeval *tv)
+  * @flags:    flags for newly created file, currently only O_CLOEXEC is
+  *            supported, refer to manual of open syscall for more details
+  * @fd:               file descriptor associated with DMABUF (set by driver)
++ * @reserved: drivers and applications must zero this array
+  *
+  * Contains data used for exporting a video buffer as DMABUF file descriptor.
+  * The buffer is identified by a 'cookie' returned by VIDIOC_QUERYBUF
+@@ -2215,6 +2222,7 @@ struct v4l2_mpeg_vbi_fmt_ivtv {
+  *                    this plane will be used
+  * @bytesperline:     distance in bytes between the leftmost pixels in two
+  *                    adjacent lines
++ * @reserved:         drivers and applications must zero this array
+  */
+ struct v4l2_plane_pix_format {
+       __u32           sizeimage;
+@@ -2233,8 +2241,10 @@ struct v4l2_plane_pix_format {
+  * @num_planes:               number of planes for this format
+  * @flags:            format flags (V4L2_PIX_FMT_FLAG_*)
+  * @ycbcr_enc:                enum v4l2_ycbcr_encoding, Y'CbCr encoding
++ * @hsv_enc:          enum v4l2_hsv_encoding, HSV encoding
+  * @quantization:     enum v4l2_quantization, colorspace quantization
+  * @xfer_func:                enum v4l2_xfer_func, colorspace transfer function
++ * @reserved:         drivers and applications must zero this array
+  */
+ struct v4l2_pix_format_mplane {
+       __u32                           width;
+@@ -2259,6 +2269,7 @@ struct v4l2_pix_format_mplane {
+  * struct v4l2_sdr_format - SDR format definition
+  * @pixelformat:      little endian four character code (fourcc)
+  * @buffersize:               maximum size in bytes required for data
++ * @reserved:         drivers and applications must zero this array
+  */
+ struct v4l2_sdr_format {
+       __u32                           pixelformat;
+@@ -2285,6 +2296,8 @@ struct v4l2_meta_format {
+  * @vbi:      raw VBI capture or output parameters
+  * @sliced:   sliced VBI capture or output parameters
+  * @raw_data: placeholder for future extensions and custom formats
++ * @fmt:      union of @pix, @pix_mp, @win, @vbi, @sliced, @sdr, @meta
++ *            and @raw_data
+  */
+ struct v4l2_format {
+       __u32    type;
+-- 
+2.43.0
+
diff --git a/queue-5.10/media-flexcop-usb-clean-up-endpoint-sanity-checks.patch b/queue-5.10/media-flexcop-usb-clean-up-endpoint-sanity-checks.patch
new file mode 100644 (file)
index 0000000..1c01a67
--- /dev/null
@@ -0,0 +1,56 @@
+From f80dd34278ac0342fc7fcb42e6954e582cf6ff6b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Aug 2022 17:14:54 +0200
+Subject: media: flexcop-usb: clean up endpoint sanity checks
+
+From: Johan Hovold <johan@kernel.org>
+
+[ 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 <johan@kernel.org>
+Link: https://lore.kernel.org/r/20220822151456.27178-2-johan@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: f62dc8f6bf82 ("media: flexcop-usb: fix sanity check of bNumEndpoints")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/b2c2/flexcop-usb.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c
+index 2299d5cca8ffb..6d199b32e3170 100644
+--- a/drivers/media/usb/b2c2/flexcop-usb.c
++++ b/drivers/media/usb/b2c2/flexcop-usb.c
+@@ -502,17 +502,21 @@ static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
+ static int flexcop_usb_init(struct flexcop_usb *fc_usb)
+ {
+-      /* use the alternate setting with the larges buffer */
+-      int ret = usb_set_interface(fc_usb->udev, 0, 1);
++      struct usb_host_interface *alt;
++      int ret;
++      /* use the alternate setting with the largest buffer */
++      ret = usb_set_interface(fc_usb->udev, 0, 1);
+       if (ret) {
+               err("set interface failed.");
+               return ret;
+       }
+-      if (fc_usb->uintf->cur_altsetting->desc.bNumEndpoints < 1)
++      alt = fc_usb->uintf->cur_altsetting;
++
++      if (alt->desc.bNumEndpoints < 1)
+               return -ENODEV;
+-      if (!usb_endpoint_is_isoc_in(&fc_usb->uintf->cur_altsetting->endpoint[0].desc))
++      if (!usb_endpoint_is_isoc_in(&alt->endpoint[0].desc))
+               return -ENODEV;
+       switch (fc_usb->udev->speed) {
+-- 
+2.43.0
+
diff --git a/queue-5.10/media-flexcop-usb-fix-sanity-check-of-bnumendpoints.patch b/queue-5.10/media-flexcop-usb-fix-sanity-check-of-bnumendpoints.patch
new file mode 100644 (file)
index 0000000..3eefafb
--- /dev/null
@@ -0,0 +1,40 @@
+From c9782023df6440cd048dc761cb431a95597f6a5f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 2 Jun 2022 06:50:24 +0100
+Subject: media: flexcop-usb: fix sanity check of bNumEndpoints
+
+From: Dongliang Mu <mudongliangabcd@gmail.com>
+
+[ 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 <mudongliangabcd@gmail.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/b2c2/flexcop-usb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c
+index 6d199b32e3170..6ded5a6181aa2 100644
+--- a/drivers/media/usb/b2c2/flexcop-usb.c
++++ b/drivers/media/usb/b2c2/flexcop-usb.c
+@@ -514,7 +514,7 @@ static int flexcop_usb_init(struct flexcop_usb *fc_usb)
+       alt = fc_usb->uintf->cur_altsetting;
+-      if (alt->desc.bNumEndpoints < 1)
++      if (alt->desc.bNumEndpoints < 2)
+               return -ENODEV;
+       if (!usb_endpoint_is_isoc_in(&alt->endpoint[0].desc))
+               return -ENODEV;
+-- 
+2.43.0
+
diff --git a/queue-5.10/media-stk1160-fix-bounds-checking-in-stk1160_copy_vi.patch b/queue-5.10/media-stk1160-fix-bounds-checking-in-stk1160_copy_vi.patch
new file mode 100644 (file)
index 0000000..ce4fbda
--- /dev/null
@@ -0,0 +1,84 @@
+From 95f4f3ed09e3cea74d69f42c0b9fc6e1e6cdc943 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Apr 2024 12:32:44 +0300
+Subject: media: stk1160: fix bounds checking in stk1160_copy_video()
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+[ 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 <dan.carpenter@linaro.org>
+Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/stk1160/stk1160-video.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c
+index 4cf540d1b2501..2a5a90311e0cc 100644
+--- a/drivers/media/usb/stk1160/stk1160-video.c
++++ b/drivers/media/usb/stk1160/stk1160-video.c
+@@ -99,7 +99,7 @@ void stk1160_buffer_done(struct stk1160 *dev)
+ static inline
+ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len)
+ {
+-      int linesdone, lineoff, lencopy;
++      int linesdone, lineoff, lencopy, offset;
+       int bytesperline = dev->width * 2;
+       struct stk1160_buffer *buf = dev->isoc_ctl.buf;
+       u8 *dst = buf->mem;
+@@ -139,8 +139,13 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len)
+        * Check if we have enough space left in the buffer.
+        * In that case, we force loop exit after copy.
+        */
+-      if (lencopy > buf->bytesused - buf->length) {
+-              lencopy = buf->bytesused - buf->length;
++      offset = dst - (u8 *)buf->mem;
++      if (offset > buf->length) {
++              dev_warn_ratelimited(dev->dev, "out of bounds offset\n");
++              return;
++      }
++      if (lencopy > buf->length - offset) {
++              lencopy = buf->length - offset;
+               remain = lencopy;
+       }
+@@ -182,8 +187,13 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len)
+                * Check if we have enough space left in the buffer.
+                * In that case, we force loop exit after copy.
+                */
+-              if (lencopy > buf->bytesused - buf->length) {
+-                      lencopy = buf->bytesused - buf->length;
++              offset = dst - (u8 *)buf->mem;
++              if (offset > buf->length) {
++                      dev_warn_ratelimited(dev->dev, "offset out of bounds\n");
++                      return;
++              }
++              if (lencopy > buf->length - offset) {
++                      lencopy = buf->length - offset;
+                       remain = lencopy;
+               }
+-- 
+2.43.0
+
diff --git a/queue-5.10/mmc-sdhci_am654-add-itapdlysel-in-sdhci_j721e_4bit_s.patch b/queue-5.10/mmc-sdhci_am654-add-itapdlysel-in-sdhci_j721e_4bit_s.patch
new file mode 100644 (file)
index 0000000..5bfe4d1
--- /dev/null
@@ -0,0 +1,60 @@
+From 0d60332ca2ce3cacbe640836314d6cf75afa073c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Mar 2024 17:38:36 -0500
+Subject: mmc: sdhci_am654: Add ITAPDLYSEL in sdhci_j721e_4bit_set_clock
+
+From: Judith Mendez <jm@ti.com>
+
+[ 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 <jm@ti.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Link: https://lore.kernel.org/r/20240320223837.959900-7-jm@ti.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/sdhci_am654.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
+index 1968381b93100..879ead07f8022 100644
+--- a/drivers/mmc/host/sdhci_am654.c
++++ b/drivers/mmc/host/sdhci_am654.c
+@@ -319,6 +319,7 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host,
+       unsigned char timing = host->mmc->ios.timing;
+       u32 otap_del_sel;
+       u32 itap_del_ena;
++      u32 itap_del_sel;
+       u32 mask, val;
+       /* Setup DLL Output TAP delay */
+@@ -328,13 +329,18 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host,
+       val = (0x1 << OTAPDLYENA_SHIFT) |
+             (otap_del_sel << OTAPDLYSEL_SHIFT);
++      /* Setup Input TAP delay */
+       itap_del_ena = sdhci_am654->itap_del_ena[timing];
++      itap_del_sel = sdhci_am654->itap_del_sel[timing];
+-      mask |= ITAPDLYENA_MASK;
+-      val |= (itap_del_ena << ITAPDLYENA_SHIFT);
++      mask |= ITAPDLYENA_MASK | ITAPDLYSEL_MASK;
++      val |= (itap_del_ena << ITAPDLYENA_SHIFT) |
++             (itap_del_sel << ITAPDLYSEL_SHIFT);
++      regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK,
++                         1 << ITAPCHGWIN_SHIFT);
+       regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val);
+-
++      regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0);
+       regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK,
+                          sdhci_am654->clkbuf_sel);
+-- 
+2.43.0
+
diff --git a/queue-5.10/mmc-sdhci_am654-add-otap-itap-delay-enable.patch b/queue-5.10/mmc-sdhci_am654-add-otap-itap-delay-enable.patch
new file mode 100644 (file)
index 0000000..6f4d1eb
--- /dev/null
@@ -0,0 +1,168 @@
+From 8f3e71db5da96340560134bad1fdaff9d099ac7b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Mar 2024 17:38:33 -0500
+Subject: mmc: sdhci_am654: Add OTAP/ITAP delay enable
+
+From: Judith Mendez <jm@ti.com>
+
+[ 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 <jm@ti.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Link: https://lore.kernel.org/r/20240320223837.959900-4-jm@ti.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/sdhci_am654.c | 40 ++++++++++++++++++++++------------
+ 1 file changed, 26 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
+index 847cd4e434721..1968381b93100 100644
+--- a/drivers/mmc/host/sdhci_am654.c
++++ b/drivers/mmc/host/sdhci_am654.c
+@@ -142,6 +142,7 @@ struct sdhci_am654_data {
+       struct regmap *base;
+       int otap_del_sel[ARRAY_SIZE(td)];
+       int itap_del_sel[ARRAY_SIZE(td)];
++      u32 itap_del_ena[ARRAY_SIZE(td)];
+       int clkbuf_sel;
+       int trm_icp;
+       int drv_strength;
+@@ -238,11 +239,13 @@ static void sdhci_am654_setup_dll(struct sdhci_host *host, unsigned int clock)
+ }
+ static void sdhci_am654_write_itapdly(struct sdhci_am654_data *sdhci_am654,
+-                                    u32 itapdly)
++                                    u32 itapdly, u32 enable)
+ {
+       /* Set ITAPCHGWIN before writing to ITAPDLY */
+       regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK,
+                          1 << ITAPCHGWIN_SHIFT);
++      regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYENA_MASK,
++                         enable << ITAPDLYENA_SHIFT);
+       regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYSEL_MASK,
+                          itapdly << ITAPDLYSEL_SHIFT);
+       regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0);
+@@ -259,8 +262,8 @@ static void sdhci_am654_setup_delay_chain(struct sdhci_am654_data *sdhci_am654,
+       mask = SELDLYTXCLK_MASK | SELDLYRXCLK_MASK;
+       regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask, val);
+-      sdhci_am654_write_itapdly(sdhci_am654,
+-                                sdhci_am654->itap_del_sel[timing]);
++      sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing],
++                                sdhci_am654->itap_del_ena[timing]);
+ }
+ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
+@@ -269,7 +272,6 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
+       struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);
+       unsigned char timing = host->mmc->ios.timing;
+       u32 otap_del_sel;
+-      u32 otap_del_ena;
+       u32 mask, val;
+       regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0);
+@@ -278,10 +280,9 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
+       /* Setup DLL Output TAP delay */
+       otap_del_sel = sdhci_am654->otap_del_sel[timing];
+-      otap_del_ena = (timing > MMC_TIMING_UHS_SDR25) ? 1 : 0;
+       mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
+-      val = (otap_del_ena << OTAPDLYENA_SHIFT) |
++      val = (0x1 << OTAPDLYENA_SHIFT) |
+             (otap_del_sel << OTAPDLYSEL_SHIFT);
+       /* Write to STRBSEL for HS400 speed mode */
+@@ -299,7 +300,8 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
+       if (timing > MMC_TIMING_UHS_SDR25 && clock >= CLOCK_TOO_SLOW_HZ) {
+               sdhci_am654_setup_dll(host, clock);
+               sdhci_am654->dll_enable = true;
+-              sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing]);
++              sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing],
++                                        sdhci_am654->itap_del_ena[timing]);
+       } else {
+               sdhci_am654_setup_delay_chain(sdhci_am654, timing);
+               sdhci_am654->dll_enable = false;
+@@ -316,6 +318,7 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host,
+       struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);
+       unsigned char timing = host->mmc->ios.timing;
+       u32 otap_del_sel;
++      u32 itap_del_ena;
+       u32 mask, val;
+       /* Setup DLL Output TAP delay */
+@@ -324,6 +327,12 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host,
+       mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
+       val = (0x1 << OTAPDLYENA_SHIFT) |
+             (otap_del_sel << OTAPDLYSEL_SHIFT);
++
++      itap_del_ena = sdhci_am654->itap_del_ena[timing];
++
++      mask |= ITAPDLYENA_MASK;
++      val |= (itap_del_ena << ITAPDLYENA_SHIFT);
++
+       regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val);
+       regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK,
+@@ -477,6 +486,7 @@ static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host,
+ {
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);
++      unsigned char timing = host->mmc->ios.timing;
+       struct window fail_window[ITAPDLY_LENGTH];
+       u8 curr_pass, itap;
+       u8 fail_index = 0;
+@@ -485,11 +495,10 @@ static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host,
+       memset(fail_window, 0, sizeof(fail_window));
+       /* Enable ITAPDLY */
+-      regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYENA_MASK,
+-                         1 << ITAPDLYENA_SHIFT);
++      sdhci_am654->itap_del_ena[timing] = 0x1;
+       for (itap = 0; itap < ITAPDLY_LENGTH; itap++) {
+-              sdhci_am654_write_itapdly(sdhci_am654, itap);
++              sdhci_am654_write_itapdly(sdhci_am654, itap, sdhci_am654->itap_del_ena[timing]);
+               curr_pass = !mmc_send_tuning(host->mmc, opcode, NULL);
+@@ -513,7 +522,7 @@ static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host,
+       itap = sdhci_am654_calculate_itap(host, fail_window, fail_index,
+                                         sdhci_am654->dll_enable);
+-      sdhci_am654_write_itapdly(sdhci_am654, itap);
++      sdhci_am654_write_itapdly(sdhci_am654, itap, sdhci_am654->itap_del_ena[timing]);
+       return 0;
+ }
+@@ -665,9 +674,12 @@ static int sdhci_am654_get_otap_delay(struct sdhci_host *host,
+                               host->mmc->caps2 &= ~td[i].capability;
+               }
+-              if (td[i].itap_binding)
+-                      device_property_read_u32(dev, td[i].itap_binding,
+-                                               &sdhci_am654->itap_del_sel[i]);
++              if (td[i].itap_binding) {
++                      ret = device_property_read_u32(dev, td[i].itap_binding,
++                                                     &sdhci_am654->itap_del_sel[i]);
++                      if (!ret)
++                              sdhci_am654->itap_del_ena[i] = 0x1;
++              }
+       }
+       return 0;
+-- 
+2.43.0
+
diff --git a/queue-5.10/mmc-sdhci_am654-add-tuning-algorithm-for-delay-chain.patch b/queue-5.10/mmc-sdhci_am654-add-tuning-algorithm-for-delay-chain.patch
new file mode 100644 (file)
index 0000000..9bcc498
--- /dev/null
@@ -0,0 +1,195 @@
+From 80b0af2faa31963d326cd9f96954ac370f3e1701 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Mar 2024 17:38:31 -0500
+Subject: mmc: sdhci_am654: Add tuning algorithm for delay chain
+
+From: Judith Mendez <jm@ti.com>
+
+[ 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 <jm@ti.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Link: https://lore.kernel.org/r/20240320223837.959900-2-jm@ti.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/sdhci_am654.c | 112 +++++++++++++++++++++++++++------
+ 1 file changed, 92 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
+index eb52e0c5a0202..2e302c2b0ac12 100644
+--- a/drivers/mmc/host/sdhci_am654.c
++++ b/drivers/mmc/host/sdhci_am654.c
+@@ -149,10 +149,17 @@ struct sdhci_am654_data {
+       int strb_sel;
+       u32 flags;
+       u32 quirks;
++      bool dll_enable;
+ #define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0)
+ };
++struct window {
++      u8 start;
++      u8 end;
++      u8 length;
++};
++
+ struct sdhci_am654_driver_data {
+       const struct sdhci_pltfm_data *pdata;
+       u32 flags;
+@@ -294,10 +301,13 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
+       regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val);
+-      if (timing > MMC_TIMING_UHS_SDR25 && clock >= CLOCK_TOO_SLOW_HZ)
++      if (timing > MMC_TIMING_UHS_SDR25 && clock >= CLOCK_TOO_SLOW_HZ) {
+               sdhci_am654_setup_dll(host, clock);
+-      else
++              sdhci_am654->dll_enable = true;
++      } else {
+               sdhci_am654_setup_delay_chain(sdhci_am654, timing);
++              sdhci_am654->dll_enable = false;
++      }
+       regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK,
+                          sdhci_am654->clkbuf_sel);
+@@ -415,39 +425,101 @@ static u32 sdhci_am654_cqhci_irq(struct sdhci_host *host, u32 intmask)
+       return 0;
+ }
+-#define ITAP_MAX      32
++#define ITAPDLY_LENGTH 32
++#define ITAPDLY_LAST_INDEX (ITAPDLY_LENGTH - 1)
++
++static u32 sdhci_am654_calculate_itap(struct sdhci_host *host, struct window
++                        *fail_window, u8 num_fails, bool circular_buffer)
++{
++      u8 itap = 0, start_fail = 0, end_fail = 0, pass_length = 0;
++      u8 first_fail_start = 0, last_fail_end = 0;
++      struct device *dev = mmc_dev(host->mmc);
++      struct window pass_window = {0, 0, 0};
++      int prev_fail_end = -1;
++      u8 i;
++
++      if (!num_fails)
++              return ITAPDLY_LAST_INDEX >> 1;
++
++      if (fail_window->length == ITAPDLY_LENGTH) {
++              dev_err(dev, "No passing ITAPDLY, return 0\n");
++              return 0;
++      }
++
++      first_fail_start = fail_window->start;
++      last_fail_end = fail_window[num_fails - 1].end;
++
++      for (i = 0; i < num_fails; i++) {
++              start_fail = fail_window[i].start;
++              end_fail = fail_window[i].end;
++              pass_length = start_fail - (prev_fail_end + 1);
++
++              if (pass_length > pass_window.length) {
++                      pass_window.start = prev_fail_end + 1;
++                      pass_window.length = pass_length;
++              }
++              prev_fail_end = end_fail;
++      }
++
++      if (!circular_buffer)
++              pass_length = ITAPDLY_LAST_INDEX - last_fail_end;
++      else
++              pass_length = ITAPDLY_LAST_INDEX - last_fail_end + first_fail_start;
++
++      if (pass_length > pass_window.length) {
++              pass_window.start = last_fail_end + 1;
++              pass_window.length = pass_length;
++      }
++
++      if (!circular_buffer)
++              itap = pass_window.start + (pass_window.length >> 1);
++      else
++              itap = (pass_window.start + (pass_window.length >> 1)) % ITAPDLY_LENGTH;
++
++      return (itap > ITAPDLY_LAST_INDEX) ? ITAPDLY_LAST_INDEX >> 1 : itap;
++}
++
+ static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host,
+                                              u32 opcode)
+ {
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);
+-      int cur_val, prev_val = 1, fail_len = 0, pass_window = 0, pass_len;
+-      u32 itap;
++      struct window fail_window[ITAPDLY_LENGTH];
++      u8 curr_pass, itap;
++      u8 fail_index = 0;
++      u8 prev_pass = 1;
++
++      memset(fail_window, 0, sizeof(fail_window));
+       /* Enable ITAPDLY */
+       regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYENA_MASK,
+                          1 << ITAPDLYENA_SHIFT);
+-      for (itap = 0; itap < ITAP_MAX; itap++) {
++      for (itap = 0; itap < ITAPDLY_LENGTH; itap++) {
+               sdhci_am654_write_itapdly(sdhci_am654, itap);
+-              cur_val = !mmc_send_tuning(host->mmc, opcode, NULL);
+-              if (cur_val && !prev_val)
+-                      pass_window = itap;
++              curr_pass = !mmc_send_tuning(host->mmc, opcode, NULL);
+-              if (!cur_val)
+-                      fail_len++;
++              if (!curr_pass && prev_pass)
++                      fail_window[fail_index].start = itap;
+-              prev_val = cur_val;
++              if (!curr_pass) {
++                      fail_window[fail_index].end = itap;
++                      fail_window[fail_index].length++;
++              }
++
++              if (curr_pass && !prev_pass)
++                      fail_index++;
++
++              prev_pass = curr_pass;
+       }
+-      /*
+-       * Having determined the length of the failing window and start of
+-       * the passing window calculate the length of the passing window and
+-       * set the final value halfway through it considering the range as a
+-       * circular buffer
+-       */
+-      pass_len = ITAP_MAX - fail_len;
+-      itap = (pass_window + (pass_len >> 1)) % ITAP_MAX;
++
++      if (fail_window[fail_index].length != 0)
++              fail_index++;
++
++      itap = sdhci_am654_calculate_itap(host, fail_window, fail_index,
++                                        sdhci_am654->dll_enable);
++
+       sdhci_am654_write_itapdly(sdhci_am654, itap);
+       return 0;
+-- 
+2.43.0
+
diff --git a/queue-5.10/mmc-sdhci_am654-drop-lookup-for-deprecated-ti-otap-d.patch b/queue-5.10/mmc-sdhci_am654-drop-lookup-for-deprecated-ti-otap-d.patch
new file mode 100644 (file)
index 0000000..b9bd7bf
--- /dev/null
@@ -0,0 +1,102 @@
+From 0e1ca613331404a45dc7229eb8044cdfe7471f63 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Nov 2023 11:32:14 +0530
+Subject: mmc: sdhci_am654: Drop lookup for deprecated ti,otap-del-sel
+
+From: Vignesh Raghavendra <vigneshr@ti.com>
+
+[ 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 <vigneshr@ti.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Link: https://lore.kernel.org/r/20231122060215.2074799-1-vigneshr@ti.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Stable-dep-of: 387c1bf7dce0 ("mmc: sdhci_am654: Add OTAP/ITAP delay enable")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/sdhci_am654.c | 37 ++++++----------------------------
+ 1 file changed, 6 insertions(+), 31 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
+index 13bff543f7c06..847cd4e434721 100644
+--- a/drivers/mmc/host/sdhci_am654.c
++++ b/drivers/mmc/host/sdhci_am654.c
+@@ -140,7 +140,6 @@ static const struct timing_data td[] = {
+ struct sdhci_am654_data {
+       struct regmap *base;
+-      bool legacy_otapdly;
+       int otap_del_sel[ARRAY_SIZE(td)];
+       int itap_del_sel[ARRAY_SIZE(td)];
+       int clkbuf_sel;
+@@ -278,11 +277,7 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
+       sdhci_set_clock(host, clock);
+       /* Setup DLL Output TAP delay */
+-      if (sdhci_am654->legacy_otapdly)
+-              otap_del_sel = sdhci_am654->otap_del_sel[0];
+-      else
+-              otap_del_sel = sdhci_am654->otap_del_sel[timing];
+-
++      otap_del_sel = sdhci_am654->otap_del_sel[timing];
+       otap_del_ena = (timing > MMC_TIMING_UHS_SDR25) ? 1 : 0;
+       mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
+@@ -324,10 +319,7 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host,
+       u32 mask, val;
+       /* Setup DLL Output TAP delay */
+-      if (sdhci_am654->legacy_otapdly)
+-              otap_del_sel = sdhci_am654->otap_del_sel[0];
+-      else
+-              otap_del_sel = sdhci_am654->otap_del_sel[timing];
++      otap_del_sel = sdhci_am654->otap_del_sel[timing];
+       mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
+       val = (0x1 << OTAPDLYENA_SHIFT) |
+@@ -652,32 +644,15 @@ static int sdhci_am654_get_otap_delay(struct sdhci_host *host,
+       int i;
+       int ret;
+-      ret = device_property_read_u32(dev, td[MMC_TIMING_LEGACY].otap_binding,
+-                               &sdhci_am654->otap_del_sel[MMC_TIMING_LEGACY]);
+-      if (ret) {
+-              /*
+-               * ti,otap-del-sel-legacy is mandatory, look for old binding
+-               * if not found.
+-               */
+-              ret = device_property_read_u32(dev, "ti,otap-del-sel",
+-                                             &sdhci_am654->otap_del_sel[0]);
+-              if (ret) {
+-                      dev_err(dev, "Couldn't find otap-del-sel\n");
+-
+-                      return ret;
+-              }
+-
+-              dev_info(dev, "Using legacy binding ti,otap-del-sel\n");
+-              sdhci_am654->legacy_otapdly = true;
+-
+-              return 0;
+-      }
+-
+       for (i = MMC_TIMING_LEGACY; i <= MMC_TIMING_MMC_HS400; i++) {
+               ret = device_property_read_u32(dev, td[i].otap_binding,
+                                              &sdhci_am654->otap_del_sel[i]);
+               if (ret) {
++                      if (i == MMC_TIMING_LEGACY) {
++                              dev_err(dev, "Couldn't find mandatory ti,otap-del-sel-legacy\n");
++                              return ret;
++                      }
+                       dev_dbg(dev, "Couldn't find %s\n",
+                               td[i].otap_binding);
+                       /*
+-- 
+2.43.0
+
diff --git a/queue-5.10/mmc-sdhci_am654-fix-itapdly-for-hs400-timing.patch b/queue-5.10/mmc-sdhci_am654-fix-itapdly-for-hs400-timing.patch
new file mode 100644 (file)
index 0000000..91c9516
--- /dev/null
@@ -0,0 +1,59 @@
+From b8633da72511f88b5e6c6e9662c397cc025ddd62 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Mar 2024 17:38:37 -0500
+Subject: mmc: sdhci_am654: Fix ITAPDLY for HS400 timing
+
+From: Judith Mendez <jm@ti.com>
+
+[ 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 <jm@ti.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Link: https://lore.kernel.org/r/20240320223837.959900-8-jm@ti.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/sdhci_am654.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
+index 879ead07f8022..9d74ee989cb72 100644
+--- a/drivers/mmc/host/sdhci_am654.c
++++ b/drivers/mmc/host/sdhci_am654.c
+@@ -300,6 +300,12 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
+       if (timing > MMC_TIMING_UHS_SDR25 && clock >= CLOCK_TOO_SLOW_HZ) {
+               sdhci_am654_setup_dll(host, clock);
+               sdhci_am654->dll_enable = true;
++
++              if (timing == MMC_TIMING_MMC_HS400) {
++                      sdhci_am654->itap_del_ena[timing] = 0x1;
++                      sdhci_am654->itap_del_sel[timing] = sdhci_am654->itap_del_sel[timing - 1];
++              }
++
+               sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing],
+                                         sdhci_am654->itap_del_ena[timing]);
+       } else {
+@@ -530,6 +536,9 @@ static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host,
+       sdhci_am654_write_itapdly(sdhci_am654, itap, sdhci_am654->itap_del_ena[timing]);
++      /* Save ITAPDLY */
++      sdhci_am654->itap_del_sel[timing] = itap;
++
+       return 0;
+ }
+-- 
+2.43.0
+
diff --git a/queue-5.10/mmc-sdhci_am654-write-itapdly-for-ddr52-timing.patch b/queue-5.10/mmc-sdhci_am654-write-itapdly-for-ddr52-timing.patch
new file mode 100644 (file)
index 0000000..a58dfec
--- /dev/null
@@ -0,0 +1,39 @@
+From c57330ac305c53ba0f09a1e6b9b38322cdfb4d94 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Mar 2024 17:38:32 -0500
+Subject: mmc: sdhci_am654: Write ITAPDLY for DDR52 timing
+
+From: Judith Mendez <jm@ti.com>
+
+[ 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 <jm@ti.com>
+Reviewed-by: Andrew Davis <afd@ti.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Link: https://lore.kernel.org/r/20240320223837.959900-3-jm@ti.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/sdhci_am654.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
+index 2e302c2b0ac12..13bff543f7c06 100644
+--- a/drivers/mmc/host/sdhci_am654.c
++++ b/drivers/mmc/host/sdhci_am654.c
+@@ -304,6 +304,7 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
+       if (timing > MMC_TIMING_UHS_SDR25 && clock >= CLOCK_TOO_SLOW_HZ) {
+               sdhci_am654_setup_dll(host, clock);
+               sdhci_am654->dll_enable = true;
++              sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing]);
+       } else {
+               sdhci_am654_setup_delay_chain(sdhci_am654, timing);
+               sdhci_am654->dll_enable = false;
+-- 
+2.43.0
+
diff --git a/queue-5.10/net-fec-avoid-lock-evasion-when-reading-pps_enable.patch b/queue-5.10/net-fec-avoid-lock-evasion-when-reading-pps_enable.patch
new file mode 100644 (file)
index 0000000..05847ec
--- /dev/null
@@ -0,0 +1,62 @@
+From a79ad2e7f60efada05719ec31752d55f47e0c640 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 May 2024 10:38:00 +0800
+Subject: net: fec: avoid lock evasion when reading pps_enable
+
+From: Wei Fang <wei.fang@nxp.com>
+
+[ 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 <wei.fang@nxp.com>
+Link: https://lore.kernel.org/r/20240521023800.17102-1-wei.fang@nxp.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fec_ptp.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
+index c5ae673005908..780fbb3e1ed06 100644
+--- a/drivers/net/ethernet/freescale/fec_ptp.c
++++ b/drivers/net/ethernet/freescale/fec_ptp.c
+@@ -103,14 +103,13 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
+       u64 ns;
+       val = 0;
+-      if (fep->pps_enable == enable)
+-              return 0;
+-
+-      fep->pps_channel = DEFAULT_PPS_CHANNEL;
+-      fep->reload_period = PPS_OUPUT_RELOAD_PERIOD;
+-
+       spin_lock_irqsave(&fep->tmreg_lock, flags);
++      if (fep->pps_enable == enable) {
++              spin_unlock_irqrestore(&fep->tmreg_lock, flags);
++              return 0;
++      }
++
+       if (enable) {
+               /* clear capture or output compare interrupt status if have.
+                */
+@@ -441,6 +440,9 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,
+       int ret = 0;
+       if (rq->type == PTP_CLK_REQ_PPS) {
++              fep->pps_channel = DEFAULT_PPS_CHANNEL;
++              fep->reload_period = PPS_OUPUT_RELOAD_PERIOD;
++
+               ret = fec_ptp_enable_pps(fep, on);
+               return ret;
+-- 
+2.43.0
+
diff --git a/queue-5.10/nfc-nci-fix-handling-of-zero-length-payload-packets-.patch b/queue-5.10/nfc-nci-fix-handling-of-zero-length-payload-packets-.patch
new file mode 100644 (file)
index 0000000..5a3bd76
--- /dev/null
@@ -0,0 +1,42 @@
+From c91fbcc7d49e4813f3d4fd148f9fbc728c970d62 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <ryasuoka@redhat.com>
+
+[ 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 <ryasuoka@redhat.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20240521153444.535399-1-ryasuoka@redhat.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/nci/core.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
+index ada7f32d03e48..a7e6b8b272505 100644
+--- a/net/nfc/nci/core.c
++++ b/net/nfc/nci/core.c
+@@ -1517,8 +1517,7 @@ static void nci_rx_work(struct work_struct *work)
+               if (!nci_valid_size(skb)) {
+                       kfree_skb(skb);
+-                      kcov_remote_stop();
+-                      break;
++                      continue;
+               }
+               /* Process frame */
+-- 
+2.43.0
+
diff --git a/queue-5.10/nfc-nci-fix-kcov-check-in-nci_rx_work.patch b/queue-5.10/nfc-nci-fix-kcov-check-in-nci_rx_work.patch
new file mode 100644 (file)
index 0000000..91af6d0
--- /dev/null
@@ -0,0 +1,45 @@
+From 404a205cc5df2ce4f4e56166badc3c3e3c681be6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 5 May 2024 19:36:49 +0900
+Subject: nfc: nci: Fix kcov check in nci_rx_work()
+
+From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+
+[ 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 <syzbot+0438378d6f157baae1a2@syzkaller.appspotmail.com>
+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 <andreyknvl@gmail.com>
+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/6d10f829-5a0c-405a-b39a-d7266f3a1a0b@I-love.SAKURA.ne.jp
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 6671e352497c ("nfc: nci: Fix handling of zero-length payload packets in nci_rx_work()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/nci/core.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
+index 7b3f3d6285004..ada7f32d03e48 100644
+--- a/net/nfc/nci/core.c
++++ b/net/nfc/nci/core.c
+@@ -1517,6 +1517,7 @@ static void nci_rx_work(struct work_struct *work)
+               if (!nci_valid_size(skb)) {
+                       kfree_skb(skb);
++                      kcov_remote_stop();
+                       break;
+               }
+-- 
+2.43.0
+
diff --git a/queue-5.10/nfc-nci-fix-uninit-value-in-nci_rx_work.patch b/queue-5.10/nfc-nci-fix-uninit-value-in-nci_rx_work.patch
new file mode 100644 (file)
index 0000000..cd2340a
--- /dev/null
@@ -0,0 +1,63 @@
+From 3d13ce5fe4463b901a223e04f6ac6514e76676b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 19 May 2024 18:43:03 +0900
+Subject: nfc: nci: Fix uninit-value in nci_rx_work
+
+From: Ryosuke Yasuoka <ryasuoka@redhat.com>
+
+[ 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 <ryasuoka@redhat.com>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/nci/core.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
+index d8002065baaef..7b3f3d6285004 100644
+--- a/net/nfc/nci/core.c
++++ b/net/nfc/nci/core.c
+@@ -1452,6 +1452,19 @@ int nci_core_ntf_packet(struct nci_dev *ndev, __u16 opcode,
+                                ndev->ops->n_core_ops);
+ }
++static bool nci_valid_size(struct sk_buff *skb)
++{
++      BUILD_BUG_ON(NCI_CTRL_HDR_SIZE != NCI_DATA_HDR_SIZE);
++      unsigned int hdr_size = NCI_CTRL_HDR_SIZE;
++
++      if (skb->len < hdr_size ||
++          !nci_plen(skb->data) ||
++          skb->len < hdr_size + nci_plen(skb->data)) {
++              return false;
++      }
++      return true;
++}
++
+ /* ---- NCI TX Data worker thread ---- */
+ static void nci_tx_work(struct work_struct *work)
+@@ -1502,7 +1515,7 @@ static void nci_rx_work(struct work_struct *work)
+               nfc_send_to_raw_sock(ndev->nfc_dev, skb,
+                                    RAW_PAYLOAD_NCI, NFC_DIRECTION_RX);
+-              if (!nci_plen(skb->data)) {
++              if (!nci_valid_size(skb)) {
+                       kfree_skb(skb);
+                       break;
+               }
+-- 
+2.43.0
+
diff --git a/queue-5.10/null_blk-fix-the-warning-modpost-missing-module_desc.patch b/queue-5.10/null_blk-fix-the-warning-modpost-missing-module_desc.patch
new file mode 100644 (file)
index 0000000..972af3c
--- /dev/null
@@ -0,0 +1,34 @@
+From 284bfde64da056e205e085bda608e515291a0445 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 May 2024 09:55:38 +0200
+Subject: null_blk: Fix the WARNING: modpost: missing MODULE_DESCRIPTION()
+
+From: Zhu Yanjun <yanjun.zhu@linux.dev>
+
+[ Upstream commit 9e6727f824edcdb8fdd3e6e8a0862eb49546e1cd ]
+
+No functional changes intended.
+
+Fixes: f2298c0403b0 ("null_blk: multi queue aware block test driver")
+Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
+Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
+Link: https://lore.kernel.org/r/20240506075538.6064-1-yanjun.zhu@linux.dev
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/block/null_blk/main.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
+index ee1c3f476a3a0..862a9420df526 100644
+--- a/drivers/block/null_blk/main.c
++++ b/drivers/block/null_blk/main.c
+@@ -2040,4 +2040,5 @@ module_init(null_init);
+ module_exit(null_exit);
+ MODULE_AUTHOR("Jens Axboe <axboe@kernel.dk>");
++MODULE_DESCRIPTION("multi queue aware block test driver");
+ MODULE_LICENSE("GPL");
+-- 
+2.43.0
+
diff --git a/queue-5.10/openvswitch-set-the-skbuff-pkt_type-for-proper-pmtud.patch b/queue-5.10/openvswitch-set-the-skbuff-pkt_type-for-proper-pmtud.patch
new file mode 100644 (file)
index 0000000..62381ed
--- /dev/null
@@ -0,0 +1,101 @@
+From 62d52fb0fd2896218550c72f39dcc177ab07dfa2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 May 2024 16:09:41 -0400
+Subject: openvswitch: Set the skbuff pkt_type for proper pmtud support.
+
+From: Aaron Conole <aconole@redhat.com>
+
+[ 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 <jcaamano@redhat.com>
+Reported-at: https://issues.redhat.com/browse/FDP-164
+Fixes: 58264848a5a7 ("openvswitch: Add vxlan tunneling support.")
+Signed-off-by: Aaron Conole <aconole@redhat.com>
+Acked-by: Eelco Chaudron <echaudro@redhat.com>
+Link: https://lore.kernel.org/r/20240516200941.16152-1-aconole@redhat.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/openvswitch/actions.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
+index 80fee9d118eec..4095456f413df 100644
+--- a/net/openvswitch/actions.c
++++ b/net/openvswitch/actions.c
+@@ -923,6 +923,12 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
+                               pskb_trim(skb, ovs_mac_header_len(key));
+               }
++              /* Need to set the pkt_type to involve the routing layer.  The
++               * packet movement through the OVS datapath doesn't generally
++               * use routing, but this is needed for tunnel cases.
++               */
++              skb->pkt_type = PACKET_OUTGOING;
++
+               if (likely(!mru ||
+                          (skb->len <= mru + vport->dev->hard_header_len))) {
+                       ovs_vport_send(vport, skb, ovs_key_mac_proto(key));
+-- 
+2.43.0
+
diff --git a/queue-5.10/params-lift-param_set_uint_minmax-to-common-code.patch b/queue-5.10/params-lift-param_set_uint_minmax-to-common-code.patch
new file mode 100644 (file)
index 0000000..f3d58c1
--- /dev/null
@@ -0,0 +1,99 @@
+From 7ab9191f9b7519de7489afbd0da823ec1d4e687f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Jun 2021 14:19:33 -0700
+Subject: params: lift param_set_uint_minmax to common code
+
+From: Sagi Grimberg <sagi@grimberg.me>
+
+[ Upstream commit 2a14c9ae15a38148484a128b84bff7e9ffd90d68 ]
+
+It is a useful helper hence move it to common code so others can enjoy
+it.
+
+Suggested-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
+Reviewed-by: Hannes Reinecke <hare@suse.com>
+Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Stable-dep-of: 3ebc46ca8675 ("tcp: Fix shift-out-of-bounds in dctcp_update_alpha().")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/moduleparam.h |  2 ++
+ kernel/params.c             | 18 ++++++++++++++++++
+ net/sunrpc/xprtsock.c       | 18 ------------------
+ 3 files changed, 20 insertions(+), 18 deletions(-)
+
+diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
+index 6388eb9734a51..f25a1c4843903 100644
+--- a/include/linux/moduleparam.h
++++ b/include/linux/moduleparam.h
+@@ -431,6 +431,8 @@ extern int param_get_int(char *buffer, const struct kernel_param *kp);
+ extern const struct kernel_param_ops param_ops_uint;
+ extern int param_set_uint(const char *val, const struct kernel_param *kp);
+ extern int param_get_uint(char *buffer, const struct kernel_param *kp);
++int param_set_uint_minmax(const char *val, const struct kernel_param *kp,
++              unsigned int min, unsigned int max);
+ #define param_check_uint(name, p) __param_check(name, p, unsigned int)
+ extern const struct kernel_param_ops param_ops_long;
+diff --git a/kernel/params.c b/kernel/params.c
+index 164d79330849a..eb00abef7076a 100644
+--- a/kernel/params.c
++++ b/kernel/params.c
+@@ -243,6 +243,24 @@ STANDARD_PARAM_DEF(ulong, unsigned long,          "%lu",          kstrtoul);
+ STANDARD_PARAM_DEF(ullong,    unsigned long long,     "%llu",         kstrtoull);
+ STANDARD_PARAM_DEF(hexint,    unsigned int,           "%#08x",        kstrtouint);
++int param_set_uint_minmax(const char *val, const struct kernel_param *kp,
++              unsigned int min, unsigned int max)
++{
++      unsigned int num;
++      int ret;
++
++      if (!val)
++              return -EINVAL;
++      ret = kstrtouint(val, 0, &num);
++      if (ret)
++              return ret;
++      if (num < min || num > max)
++              return -EINVAL;
++      *((unsigned int *)kp->arg) = num;
++      return 0;
++}
++EXPORT_SYMBOL_GPL(param_set_uint_minmax);
++
+ int param_set_charp(const char *val, const struct kernel_param *kp)
+ {
+       if (strlen(val) > 1024) {
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index ae5b5380f0f03..0666f981618a2 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -3166,24 +3166,6 @@ void cleanup_socket_xprt(void)
+       xprt_unregister_transport(&xs_bc_tcp_transport);
+ }
+-static int param_set_uint_minmax(const char *val,
+-              const struct kernel_param *kp,
+-              unsigned int min, unsigned int max)
+-{
+-      unsigned int num;
+-      int ret;
+-
+-      if (!val)
+-              return -EINVAL;
+-      ret = kstrtouint(val, 0, &num);
+-      if (ret)
+-              return ret;
+-      if (num < min || num > max)
+-              return -EINVAL;
+-      *((unsigned int *)kp->arg) = num;
+-      return 0;
+-}
+-
+ static int param_set_portnr(const char *val, const struct kernel_param *kp)
+ {
+       return param_set_uint_minmax(val, kp,
+-- 
+2.43.0
+
diff --git a/queue-5.10/powerpc-pseries-add-failure-related-checks-for-h_get.patch b/queue-5.10/powerpc-pseries-add-failure-related-checks-for-h_get.patch
new file mode 100644 (file)
index 0000000..12f2532
--- /dev/null
@@ -0,0 +1,86 @@
+From f276ed018331b56de7121edab2f5398c082ab693 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <sshegde@linux.ibm.com>
+
+[ 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 <sshegde@linux.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/20240412092047.455483-3-sshegde@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/include/asm/hvcall.h        | 2 +-
+ arch/powerpc/platforms/pseries/lpar.c    | 6 +++---
+ arch/powerpc/platforms/pseries/lparcfg.c | 6 +++---
+ 3 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
+index 00c8cda1c9c31..1a60188f74ad8 100644
+--- a/arch/powerpc/include/asm/hvcall.h
++++ b/arch/powerpc/include/asm/hvcall.h
+@@ -494,7 +494,7 @@ struct hvcall_mpp_data {
+       unsigned long backing_mem;
+ };
+-int h_get_mpp(struct hvcall_mpp_data *);
++long h_get_mpp(struct hvcall_mpp_data *mpp_data);
+ struct hvcall_mpp_x_data {
+       unsigned long coalesced_bytes;
+diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
+index 4a3425fb19398..aed67f1a1bc56 100644
+--- a/arch/powerpc/platforms/pseries/lpar.c
++++ b/arch/powerpc/platforms/pseries/lpar.c
+@@ -1883,10 +1883,10 @@ void __trace_hcall_exit(long opcode, long retval, unsigned long *retbuf)
+  * h_get_mpp
+  * H_GET_MPP hcall returns info in 7 parms
+  */
+-int h_get_mpp(struct hvcall_mpp_data *mpp_data)
++long h_get_mpp(struct hvcall_mpp_data *mpp_data)
+ {
+-      int rc;
+-      unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
++      unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
++      long rc;
+       rc = plpar_hcall9(H_GET_MPP, retbuf);
+diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c
+index a7d4e25ae82a1..e0c5fc9ab242e 100644
+--- a/arch/powerpc/platforms/pseries/lparcfg.c
++++ b/arch/powerpc/platforms/pseries/lparcfg.c
+@@ -112,8 +112,8 @@ struct hvcall_ppp_data {
+  */
+ static unsigned int h_get_ppp(struct hvcall_ppp_data *ppp_data)
+ {
+-      unsigned long rc;
+-      unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
++      unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
++      long rc;
+       rc = plpar_hcall9(H_GET_PPP, retbuf);
+@@ -192,7 +192,7 @@ static void parse_ppp_data(struct seq_file *m)
+       struct hvcall_ppp_data ppp_data;
+       struct device_node *root;
+       const __be32 *perf_level;
+-      int rc;
++      long rc;
+       rc = h_get_ppp(&ppp_data);
+       if (rc)
+-- 
+2.43.0
+
diff --git a/queue-5.10/regulator-bd71828-don-t-overwrite-runtime-voltages.patch b/queue-5.10/regulator-bd71828-don-t-overwrite-runtime-voltages.patch
new file mode 100644 (file)
index 0000000..d3a800d
--- /dev/null
@@ -0,0 +1,186 @@
+From 5652070e0948609dba092b3896fde386462ba449 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 May 2024 11:54:41 +0300
+Subject: regulator: bd71828: Don't overwrite runtime voltages
+
+From: Matti Vaittinen <mazziesaccount@gmail.com>
+
+[ 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 <mazziesaccount@gmail.com>
+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 <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/regulator/bd71828-regulator.c | 58 +--------------------------
+ 1 file changed, 2 insertions(+), 56 deletions(-)
+
+diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c
+index 85c0b90009639..fc08f6f61655e 100644
+--- a/drivers/regulator/bd71828-regulator.c
++++ b/drivers/regulator/bd71828-regulator.c
+@@ -234,14 +234,11 @@ static const struct bd71828_regulator_data bd71828_rdata[] = {
+                       .suspend_reg = BD71828_REG_BUCK1_SUSP_VOLT,
+                       .suspend_mask = BD71828_MASK_BUCK1267_VOLT,
+                       .suspend_on_mask = BD71828_MASK_SUSP_EN,
+-                      .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+                       /*
+                        * LPSR voltage is same as SUSPEND voltage. Allow
+-                       * setting it so that regulator can be set enabled at
+-                       * LPSR state
++                       * only enabling/disabling regulator for LPSR state
+                        */
+-                      .lpsr_reg = BD71828_REG_BUCK1_SUSP_VOLT,
+-                      .lpsr_mask = BD71828_MASK_BUCK1267_VOLT,
++                      .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+               },
+               .reg_inits = buck1_inits,
+               .reg_init_amnt = ARRAY_SIZE(buck1_inits),
+@@ -312,13 +309,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = {
+                                    ROHM_DVS_LEVEL_SUSPEND |
+                                    ROHM_DVS_LEVEL_LPSR,
+                       .run_reg = BD71828_REG_BUCK3_VOLT,
+-                      .idle_reg = BD71828_REG_BUCK3_VOLT,
+-                      .suspend_reg = BD71828_REG_BUCK3_VOLT,
+-                      .lpsr_reg = BD71828_REG_BUCK3_VOLT,
+                       .run_mask = BD71828_MASK_BUCK3_VOLT,
+-                      .idle_mask = BD71828_MASK_BUCK3_VOLT,
+-                      .suspend_mask = BD71828_MASK_BUCK3_VOLT,
+-                      .lpsr_mask = BD71828_MASK_BUCK3_VOLT,
+                       .idle_on_mask = BD71828_MASK_IDLE_EN,
+                       .suspend_on_mask = BD71828_MASK_SUSP_EN,
+                       .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+@@ -353,13 +344,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = {
+                                    ROHM_DVS_LEVEL_SUSPEND |
+                                    ROHM_DVS_LEVEL_LPSR,
+                       .run_reg = BD71828_REG_BUCK4_VOLT,
+-                      .idle_reg = BD71828_REG_BUCK4_VOLT,
+-                      .suspend_reg = BD71828_REG_BUCK4_VOLT,
+-                      .lpsr_reg = BD71828_REG_BUCK4_VOLT,
+                       .run_mask = BD71828_MASK_BUCK4_VOLT,
+-                      .idle_mask = BD71828_MASK_BUCK4_VOLT,
+-                      .suspend_mask = BD71828_MASK_BUCK4_VOLT,
+-                      .lpsr_mask = BD71828_MASK_BUCK4_VOLT,
+                       .idle_on_mask = BD71828_MASK_IDLE_EN,
+                       .suspend_on_mask = BD71828_MASK_SUSP_EN,
+                       .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+@@ -394,13 +379,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = {
+                                    ROHM_DVS_LEVEL_SUSPEND |
+                                    ROHM_DVS_LEVEL_LPSR,
+                       .run_reg = BD71828_REG_BUCK5_VOLT,
+-                      .idle_reg = BD71828_REG_BUCK5_VOLT,
+-                      .suspend_reg = BD71828_REG_BUCK5_VOLT,
+-                      .lpsr_reg = BD71828_REG_BUCK5_VOLT,
+                       .run_mask = BD71828_MASK_BUCK5_VOLT,
+-                      .idle_mask = BD71828_MASK_BUCK5_VOLT,
+-                      .suspend_mask = BD71828_MASK_BUCK5_VOLT,
+-                      .lpsr_mask = BD71828_MASK_BUCK5_VOLT,
+                       .idle_on_mask = BD71828_MASK_IDLE_EN,
+                       .suspend_on_mask = BD71828_MASK_SUSP_EN,
+                       .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+@@ -509,13 +488,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = {
+                                    ROHM_DVS_LEVEL_SUSPEND |
+                                    ROHM_DVS_LEVEL_LPSR,
+                       .run_reg = BD71828_REG_LDO1_VOLT,
+-                      .idle_reg = BD71828_REG_LDO1_VOLT,
+-                      .suspend_reg = BD71828_REG_LDO1_VOLT,
+-                      .lpsr_reg = BD71828_REG_LDO1_VOLT,
+                       .run_mask = BD71828_MASK_LDO_VOLT,
+-                      .idle_mask = BD71828_MASK_LDO_VOLT,
+-                      .suspend_mask = BD71828_MASK_LDO_VOLT,
+-                      .lpsr_mask = BD71828_MASK_LDO_VOLT,
+                       .idle_on_mask = BD71828_MASK_IDLE_EN,
+                       .suspend_on_mask = BD71828_MASK_SUSP_EN,
+                       .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+@@ -549,13 +522,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = {
+                                    ROHM_DVS_LEVEL_SUSPEND |
+                                    ROHM_DVS_LEVEL_LPSR,
+                       .run_reg = BD71828_REG_LDO2_VOLT,
+-                      .idle_reg = BD71828_REG_LDO2_VOLT,
+-                      .suspend_reg = BD71828_REG_LDO2_VOLT,
+-                      .lpsr_reg = BD71828_REG_LDO2_VOLT,
+                       .run_mask = BD71828_MASK_LDO_VOLT,
+-                      .idle_mask = BD71828_MASK_LDO_VOLT,
+-                      .suspend_mask = BD71828_MASK_LDO_VOLT,
+-                      .lpsr_mask = BD71828_MASK_LDO_VOLT,
+                       .idle_on_mask = BD71828_MASK_IDLE_EN,
+                       .suspend_on_mask = BD71828_MASK_SUSP_EN,
+                       .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+@@ -589,13 +556,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = {
+                                    ROHM_DVS_LEVEL_SUSPEND |
+                                    ROHM_DVS_LEVEL_LPSR,
+                       .run_reg = BD71828_REG_LDO3_VOLT,
+-                      .idle_reg = BD71828_REG_LDO3_VOLT,
+-                      .suspend_reg = BD71828_REG_LDO3_VOLT,
+-                      .lpsr_reg = BD71828_REG_LDO3_VOLT,
+                       .run_mask = BD71828_MASK_LDO_VOLT,
+-                      .idle_mask = BD71828_MASK_LDO_VOLT,
+-                      .suspend_mask = BD71828_MASK_LDO_VOLT,
+-                      .lpsr_mask = BD71828_MASK_LDO_VOLT,
+                       .idle_on_mask = BD71828_MASK_IDLE_EN,
+                       .suspend_on_mask = BD71828_MASK_SUSP_EN,
+                       .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+@@ -630,13 +591,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = {
+                                    ROHM_DVS_LEVEL_SUSPEND |
+                                    ROHM_DVS_LEVEL_LPSR,
+                       .run_reg = BD71828_REG_LDO4_VOLT,
+-                      .idle_reg = BD71828_REG_LDO4_VOLT,
+-                      .suspend_reg = BD71828_REG_LDO4_VOLT,
+-                      .lpsr_reg = BD71828_REG_LDO4_VOLT,
+                       .run_mask = BD71828_MASK_LDO_VOLT,
+-                      .idle_mask = BD71828_MASK_LDO_VOLT,
+-                      .suspend_mask = BD71828_MASK_LDO_VOLT,
+-                      .lpsr_mask = BD71828_MASK_LDO_VOLT,
+                       .idle_on_mask = BD71828_MASK_IDLE_EN,
+                       .suspend_on_mask = BD71828_MASK_SUSP_EN,
+                       .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+@@ -671,13 +626,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = {
+                                    ROHM_DVS_LEVEL_SUSPEND |
+                                    ROHM_DVS_LEVEL_LPSR,
+                       .run_reg = BD71828_REG_LDO5_VOLT,
+-                      .idle_reg = BD71828_REG_LDO5_VOLT,
+-                      .suspend_reg = BD71828_REG_LDO5_VOLT,
+-                      .lpsr_reg = BD71828_REG_LDO5_VOLT,
+                       .run_mask = BD71828_MASK_LDO_VOLT,
+-                      .idle_mask = BD71828_MASK_LDO_VOLT,
+-                      .suspend_mask = BD71828_MASK_LDO_VOLT,
+-                      .lpsr_mask = BD71828_MASK_LDO_VOLT,
+                       .idle_on_mask = BD71828_MASK_IDLE_EN,
+                       .suspend_on_mask = BD71828_MASK_SUSP_EN,
+                       .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+@@ -736,9 +685,6 @@ static const struct bd71828_regulator_data bd71828_rdata[] = {
+                       .suspend_reg = BD71828_REG_LDO7_VOLT,
+                       .lpsr_reg = BD71828_REG_LDO7_VOLT,
+                       .run_mask = BD71828_MASK_LDO_VOLT,
+-                      .idle_mask = BD71828_MASK_LDO_VOLT,
+-                      .suspend_mask = BD71828_MASK_LDO_VOLT,
+-                      .lpsr_mask = BD71828_MASK_LDO_VOLT,
+                       .idle_on_mask = BD71828_MASK_IDLE_EN,
+                       .suspend_on_mask = BD71828_MASK_SUSP_EN,
+                       .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+-- 
+2.43.0
+
diff --git a/queue-5.10/riscv-cleanup-stacktrace.patch b/queue-5.10/riscv-cleanup-stacktrace.patch
new file mode 100644 (file)
index 0000000..2778dfa
--- /dev/null
@@ -0,0 +1,123 @@
+From 937215a95b66766cc984c02d2a9f70d160523364 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Nov 2020 14:42:21 +0800
+Subject: riscv: Cleanup stacktrace
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kefeng Wang <wangkefeng.wang@huawei.com>
+
+[ Upstream commit 99c168fccbfedbc10ce1cb2dcb9eb790c478d833 ]
+
+1. add asm/stacktrace.h for walk_stackframe and struct stackframe
+2. remove unnecessary blank lines in stacktrace.c
+3. fix warning "no previous prototype for â€˜fill_callchain’"
+
+Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
+Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
+Stable-dep-of: a2a4d4a6a0bf ("riscv: stacktrace: fixed walk_stackframe()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/include/asm/stacktrace.h | 17 +++++++++++++++++
+ arch/riscv/kernel/perf_callchain.c  | 10 ++--------
+ arch/riscv/kernel/stacktrace.c      |  9 ++-------
+ 3 files changed, 21 insertions(+), 15 deletions(-)
+ create mode 100644 arch/riscv/include/asm/stacktrace.h
+
+diff --git a/arch/riscv/include/asm/stacktrace.h b/arch/riscv/include/asm/stacktrace.h
+new file mode 100644
+index 0000000000000..f09c1e31bde9c
+--- /dev/null
++++ b/arch/riscv/include/asm/stacktrace.h
+@@ -0,0 +1,17 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++#ifndef _ASM_RISCV_STACKTRACE_H
++#define _ASM_RISCV_STACKTRACE_H
++
++#include <linux/sched.h>
++#include <asm/ptrace.h>
++
++struct stackframe {
++      unsigned long fp;
++      unsigned long ra;
++};
++
++extern void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
++                                  bool (*fn)(unsigned long, void *), void *arg);
++
++#endif /* _ASM_RISCV_STACKTRACE_H */
+diff --git a/arch/riscv/kernel/perf_callchain.c b/arch/riscv/kernel/perf_callchain.c
+index fb02811df7143..8b4bd418b3434 100644
+--- a/arch/riscv/kernel/perf_callchain.c
++++ b/arch/riscv/kernel/perf_callchain.c
+@@ -4,11 +4,7 @@
+ #include <linux/perf_event.h>
+ #include <linux/uaccess.h>
+-/* Kernel callchain */
+-struct stackframe {
+-      unsigned long fp;
+-      unsigned long ra;
+-};
++#include <asm/stacktrace.h>
+ /*
+  * Get the return address for a single stackframe and return a pointer to the
+@@ -75,13 +71,11 @@ void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
+               fp = user_backtrace(entry, fp, 0);
+ }
+-bool fill_callchain(unsigned long pc, void *entry)
++static bool fill_callchain(unsigned long pc, void *entry)
+ {
+       return perf_callchain_store(entry, pc) == 0;
+ }
+-void notrace walk_stackframe(struct task_struct *task,
+-      struct pt_regs *regs, bool (*fn)(unsigned long, void *), void *arg);
+ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
+                          struct pt_regs *regs)
+ {
+diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c
+index 9c34735c1e771..cd14309fff0d9 100644
+--- a/arch/riscv/kernel/stacktrace.c
++++ b/arch/riscv/kernel/stacktrace.c
+@@ -12,15 +12,12 @@
+ #include <linux/stacktrace.h>
+ #include <linux/ftrace.h>
++#include <asm/stacktrace.h>
++
+ register unsigned long sp_in_global __asm__("sp");
+ #ifdef CONFIG_FRAME_POINTER
+-struct stackframe {
+-      unsigned long fp;
+-      unsigned long ra;
+-};
+-
+ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
+                            bool (*fn)(unsigned long, void *), void *arg)
+ {
+@@ -102,7 +99,6 @@ void notrace walk_stackframe(struct task_struct *task,
+ #endif /* CONFIG_FRAME_POINTER */
+-
+ static bool print_trace_address(unsigned long pc, void *arg)
+ {
+       const char *loglvl = arg;
+@@ -136,7 +132,6 @@ unsigned long get_wchan(struct task_struct *task)
+       return pc;
+ }
+-
+ #ifdef CONFIG_STACKTRACE
+ static bool __save_trace(unsigned long pc, void *arg, bool nosched)
+-- 
+2.43.0
+
diff --git a/queue-5.10/riscv-stacktrace-fixed-walk_stackframe.patch b/queue-5.10/riscv-stacktrace-fixed-walk_stackframe.patch
new file mode 100644 (file)
index 0000000..73a2278
--- /dev/null
@@ -0,0 +1,132 @@
+From 4e43cdd51db17bdafaf21fca0c3b534358c1b481 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 May 2024 22:13:13 +0300
+Subject: riscv: stacktrace: fixed walk_stackframe()
+
+From: Matthew Bystrin <dev.mbstr@gmail.com>
+
+[ 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:
+
+[<ffffffff804853c2>] regmap_mmio_read32le+0xe/0x1c
+---[ end trace 0000000000000000 ]---
+
+Registers dump:
+    ra     0xffffffff80485758 <regmap_mmio_read+36>
+    sp     0xffffffc80200b9a0
+    fp     0xffffffc80200b9b0
+    pc     0xffffffff804853ba <regmap_mmio_read32le+6>
+
+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:
+
+[<ffffffff804853c2>] regmap_mmio_read32le+0xe/0x1c
+[<ffffffff80485758>] regmap_mmio_read+0x24/0x52
+[<ffffffff8047c526>] _regmap_bus_reg_read+0x1a/0x22
+[<ffffffff8047fe9a>] _regmap_read+0x5c/0xea
+[<ffffffff80480376>] _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 <dev.mbstr@gmail.com>
+Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
+Link: https://lore.kernel.org/r/20240521191727.62012-1-dev.mbstr@gmail.com
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/kernel/stacktrace.c | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c
+index ff877ee3fb942..c38b20caad7cc 100644
+--- a/arch/riscv/kernel/stacktrace.c
++++ b/arch/riscv/kernel/stacktrace.c
+@@ -20,6 +20,16 @@ register unsigned long sp_in_global __asm__("sp");
+ extern asmlinkage void ret_from_exception(void);
++static inline int fp_is_valid(unsigned long fp, unsigned long sp)
++{
++      unsigned long low, high;
++
++      low = sp + sizeof(struct stackframe);
++      high = ALIGN(sp, THREAD_SIZE);
++
++      return !(fp < low || fp > high || fp & 0x07);
++}
++
+ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
+                            bool (*fn)(unsigned long, void *), void *arg)
+ {
+@@ -42,21 +52,19 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
+       }
+       for (;;) {
+-              unsigned long low, high;
+               struct stackframe *frame;
+               if (unlikely(!__kernel_text_address(pc) || fn(pc, arg)))
+                       break;
+-              /* Validate frame pointer */
+-              low = sp + sizeof(struct stackframe);
+-              high = ALIGN(sp, THREAD_SIZE);
+-              if (unlikely(fp < low || fp > high || fp & 0x7))
++              if (unlikely(!fp_is_valid(fp, sp)))
+                       break;
++
+               /* Unwind stack frame */
+               frame = (struct stackframe *)fp - 1;
+               sp = fp;
+-              if (regs && (regs->epc == pc) && (frame->fp & 0x7)) {
++              if (regs && (regs->epc == pc) && fp_is_valid(frame->ra, sp)) {
++                      /* We hit function where ra is not saved on the stack */
+                       fp = frame->ra;
+                       pc = regs->ra;
+               } else {
+-- 
+2.43.0
+
diff --git a/queue-5.10/riscv-stacktrace-make-walk_stackframe-cross-pt_regs-.patch b/queue-5.10/riscv-stacktrace-make-walk_stackframe-cross-pt_regs-.patch
new file mode 100644 (file)
index 0000000..a2caa33
--- /dev/null
@@ -0,0 +1,126 @@
+From 0e9e6af8571bcc141fed0f560a07a33c19abf1ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Nov 2022 01:49:37 -0500
+Subject: riscv: stacktrace: Make walk_stackframe cross pt_regs frame
+
+From: Guo Ren <guoren@linux.alibaba.com>
+
+[ 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:
+  [<ffffffe0002038c8>] walk_stackframe+0x0/0xee
+  [<ffffffe000aecf48>] show_stack+0x32/0x4a
+  [<ffffffe000af1618>] dump_stack_lvl+0x72/0x8e
+  [<ffffffe000af1648>] dump_stack+0x14/0x1c
+  [<ffffffe000239ad2>] ___might_sleep+0x12e/0x138
+  [<ffffffe000239aec>] __might_sleep+0x10/0x18
+  [<ffffffe000afe3fe>] down_read+0x22/0xa4
+  [<ffffffe000207588>] do_page_fault+0xb0/0x2fe
+  [<ffffffe000201b80>] 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:
+  [<ffffffe0002038c8>] walk_stackframe+0x0/0xee
+  [<ffffffe000aecf48>] show_stack+0x32/0x4a
+  [<ffffffe000af1618>] dump_stack_lvl+0x72/0x8e
+  [<ffffffe000af1648>] dump_stack+0x14/0x1c
+  [<ffffffe000239ad2>] ___might_sleep+0x12e/0x138
+  [<ffffffe000239aec>] __might_sleep+0x10/0x18
+  [<ffffffe000afe3fe>] down_read+0x22/0xa4
+  [<ffffffe000207588>] do_page_fault+0xb0/0x2fe
+  [<ffffffe000201b80>] ret_from_exception+0x0/0xc
+  [<ffffffe000613c06>] riscv_intc_irq+0x1a/0x72
+  [<ffffffe000201b80>] ret_from_exception+0x0/0xc
+  [<ffffffe00033f44a>] vma_link+0x54/0x160
+  [<ffffffe000341d7a>] mmap_region+0x2cc/0x4d0
+  [<ffffffe000342256>] do_mmap+0x2d8/0x3ac
+  [<ffffffe000326318>] vm_mmap_pgoff+0x70/0xb8
+  [<ffffffe00032638a>] vm_mmap+0x2a/0x36
+  [<ffffffe0003cfdde>] elf_map+0x72/0x84
+  [<ffffffe0003d05f8>] load_elf_binary+0x69a/0xec8
+  [<ffffffe000376240>] bprm_execve+0x246/0x53a
+  [<ffffffe00037786c>] kernel_execve+0xe8/0x124
+  [<ffffffe000aecdf2>] run_init_process+0xfa/0x10c
+  [<ffffffe000aece16>] try_to_run_init_process+0x12/0x3c
+  [<ffffffe000afa920>] kernel_init+0xb4/0xf8
+  [<ffffffe000201b80>] 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 <guoren@linux.alibaba.com>
+Signed-off-by: Guo Ren <guoren@kernel.org>
+Link: https://lore.kernel.org/r/20221109064937.3643993-3-guoren@kernel.org
+[Palmer: use SYM_CODE_*]
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Stable-dep-of: a2a4d4a6a0bf ("riscv: stacktrace: fixed walk_stackframe()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/kernel/entry.S      | 3 ++-
+ arch/riscv/kernel/stacktrace.c | 9 +++++++++
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
+index 5214c578a6023..88bd7e5f74cee 100644
+--- a/arch/riscv/kernel/entry.S
++++ b/arch/riscv/kernel/entry.S
+@@ -218,7 +218,7 @@ ret_from_syscall_rejected:
+       andi t0, t0, _TIF_SYSCALL_WORK
+       bnez t0, handle_syscall_trace_exit
+-ret_from_exception:
++SYM_CODE_START_NOALIGN(ret_from_exception)
+       REG_L s0, PT_STATUS(sp)
+       csrc CSR_STATUS, SR_IE
+ #ifdef CONFIG_TRACE_IRQFLAGS
+@@ -232,6 +232,7 @@ ret_from_exception:
+       andi s0, s0, SR_SPP
+ #endif
+       bnez s0, resume_kernel
++SYM_CODE_END(ret_from_exception)
+ resume_userspace:
+       /* Interrupts must be disabled here so flags are checked atomically */
+diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c
+index cd14309fff0d9..ff877ee3fb942 100644
+--- a/arch/riscv/kernel/stacktrace.c
++++ b/arch/riscv/kernel/stacktrace.c
+@@ -18,6 +18,8 @@ register unsigned long sp_in_global __asm__("sp");
+ #ifdef CONFIG_FRAME_POINTER
++extern asmlinkage void ret_from_exception(void);
++
+ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
+                            bool (*fn)(unsigned long, void *), void *arg)
+ {
+@@ -61,6 +63,13 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
+                       fp = frame->fp;
+                       pc = ftrace_graph_ret_addr(current, NULL, frame->ra,
+                                                  &frame->ra);
++                      if (pc == (unsigned long)ret_from_exception) {
++                              if (unlikely(!__kernel_text_address(pc) || !fn(arg, pc)))
++                                      break;
++
++                              pc = ((struct pt_regs *)sp)->epc;
++                              fp = ((struct pt_regs *)sp)->s0;
++                      }
+               }
+       }
+-- 
+2.43.0
+
diff --git a/queue-5.10/rpcrdma-fix-handling-for-rdma_cm_event_device_remova.patch b/queue-5.10/rpcrdma-fix-handling-for-rdma_cm_event_device_remova.patch
new file mode 100644 (file)
index 0000000..37008bf
--- /dev/null
@@ -0,0 +1,51 @@
+From 95dc804381b56efa7f0143fdfe00ac485977767f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 May 2024 12:37:59 +0300
+Subject: rpcrdma: fix handling for RDMA_CM_EVENT_DEVICE_REMOVAL
+
+From: Dan Aloni <dan.aloni@vastdata.com>
+
+[ 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 <sagi.grimberg@vastdata.com>
+Signed-off-by: Dan Aloni <dan.aloni@vastdata.com>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sunrpc/xprtrdma/verbs.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
+index d015576f3081a..9e9df38b29f74 100644
+--- a/net/sunrpc/xprtrdma/verbs.c
++++ b/net/sunrpc/xprtrdma/verbs.c
+@@ -268,7 +268,11 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
+       case RDMA_CM_EVENT_DEVICE_REMOVAL:
+               pr_info("rpcrdma: removing device %s for %pISpc\n",
+                       ep->re_id->device->name, sap);
+-              fallthrough;
++              switch (xchg(&ep->re_connect_status, -ENODEV)) {
++              case 0: goto wake_connect_worker;
++              case 1: goto disconnected;
++              }
++              return 0;
+       case RDMA_CM_EVENT_ADDR_CHANGE:
+               ep->re_connect_status = -ENODEV;
+               goto disconnected;
+-- 
+2.43.0
+
diff --git a/queue-5.10/scsi-qla2xxx-replace-all-non-returning-strlcpy-with-.patch b/queue-5.10/scsi-qla2xxx-replace-all-non-returning-strlcpy-with-.patch
new file mode 100644 (file)
index 0000000..7941f8f
--- /dev/null
@@ -0,0 +1,117 @@
+From 8c6f67b2d81ddea811a0c761ad5ed4bb6fb7108d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 May 2023 02:54:04 +0000
+Subject: scsi: qla2xxx: Replace all non-returning strlcpy() with strscpy()
+
+From: Azeem Shaikh <azeemshaikh38@gmail.com>
+
+[ 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 <azeemshaikh38@gmail.com>
+Link: https://lore.kernel.org/r/20230516025404.2843867-1-azeemshaikh38@gmail.com
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Stable-dep-of: c3408c4ae041 ("scsi: qla2xxx: Avoid possible run-time warning with long model_num")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_init.c |  8 ++++----
+ drivers/scsi/qla2xxx/qla_mr.c   | 20 ++++++++++----------
+ 2 files changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
+index 3d56f971cdc4d..8d54f60998029 100644
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -4644,7 +4644,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
+               if (use_tbl &&
+                   ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
+                   index < QLA_MODEL_NAMES)
+-                      strlcpy(ha->model_desc,
++                      strscpy(ha->model_desc,
+                           qla2x00_model_name[index * 2 + 1],
+                           sizeof(ha->model_desc));
+       } else {
+@@ -4652,14 +4652,14 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
+               if (use_tbl &&
+                   ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
+                   index < QLA_MODEL_NAMES) {
+-                      strlcpy(ha->model_number,
++                      strscpy(ha->model_number,
+                               qla2x00_model_name[index * 2],
+                               sizeof(ha->model_number));
+-                      strlcpy(ha->model_desc,
++                      strscpy(ha->model_desc,
+                           qla2x00_model_name[index * 2 + 1],
+                           sizeof(ha->model_desc));
+               } else {
+-                      strlcpy(ha->model_number, def,
++                      strscpy(ha->model_number, def,
+                               sizeof(ha->model_number));
+               }
+       }
+diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
+index 7178646ee0f06..cc8994a7c9942 100644
+--- a/drivers/scsi/qla2xxx/qla_mr.c
++++ b/drivers/scsi/qla2xxx/qla_mr.c
+@@ -691,7 +691,7 @@ qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len)
+       struct qla_hw_data *ha = vha->hw;
+       if (pci_is_pcie(ha->pdev))
+-              strlcpy(str, "PCIe iSA", str_len);
++              strscpy(str, "PCIe iSA", str_len);
+       return str;
+ }
+@@ -1849,21 +1849,21 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
+                       phost_info = &preg_hsi->hsi;
+                       memset(preg_hsi, 0, sizeof(struct register_host_info));
+                       phost_info->os_type = OS_TYPE_LINUX;
+-                      strlcpy(phost_info->sysname, p_sysid->sysname,
++                      strscpy(phost_info->sysname, p_sysid->sysname,
+                               sizeof(phost_info->sysname));
+-                      strlcpy(phost_info->nodename, p_sysid->nodename,
++                      strscpy(phost_info->nodename, p_sysid->nodename,
+                               sizeof(phost_info->nodename));
+                       if (!strcmp(phost_info->nodename, "(none)"))
+                               ha->mr.host_info_resend = true;
+-                      strlcpy(phost_info->release, p_sysid->release,
++                      strscpy(phost_info->release, p_sysid->release,
+                               sizeof(phost_info->release));
+-                      strlcpy(phost_info->version, p_sysid->version,
++                      strscpy(phost_info->version, p_sysid->version,
+                               sizeof(phost_info->version));
+-                      strlcpy(phost_info->machine, p_sysid->machine,
++                      strscpy(phost_info->machine, p_sysid->machine,
+                               sizeof(phost_info->machine));
+-                      strlcpy(phost_info->domainname, p_sysid->domainname,
++                      strscpy(phost_info->domainname, p_sysid->domainname,
+                               sizeof(phost_info->domainname));
+-                      strlcpy(phost_info->hostdriver, QLA2XXX_VERSION,
++                      strscpy(phost_info->hostdriver, QLA2XXX_VERSION,
+                               sizeof(phost_info->hostdriver));
+                       preg_hsi->utc = (uint64_t)ktime_get_real_seconds();
+                       ql_dbg(ql_dbg_init, vha, 0x0149,
+@@ -1909,9 +1909,9 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
+       if (fx_type == FXDISC_GET_CONFIG_INFO) {
+               struct config_info_data *pinfo =
+                   (struct config_info_data *) fdisc->u.fxiocb.rsp_addr;
+-              strlcpy(vha->hw->model_number, pinfo->model_num,
++              strscpy(vha->hw->model_number, pinfo->model_num,
+                       ARRAY_SIZE(vha->hw->model_number));
+-              strlcpy(vha->hw->model_desc, pinfo->model_description,
++              strscpy(vha->hw->model_desc, pinfo->model_description,
+                       ARRAY_SIZE(vha->hw->model_desc));
+               memcpy(&vha->hw->mr.symbolic_name, pinfo->symbolic_name,
+                   sizeof(vha->hw->mr.symbolic_name));
+-- 
+2.43.0
+
index 83c08a3962af27bf571910394475861943ff22b3..25bc2a16e5be99adb21060ba1a0f585e74ecdc2c 100644 (file)
@@ -191,3 +191,56 @@ libsubcmd-fix-parse-options-memory-leak.patch
 perf-stat-don-t-display-metric-header-for-non-leader.patch
 s390-ipl-fix-incorrect-initialization-of-len-fields-.patch
 s390-ipl-fix-incorrect-initialization-of-nvme-dump-b.patch
+input-ims-pcu-fix-printf-string-overflow.patch
+input-ioc3kbd-convert-to-platform-remove-callback-re.patch
+input-ioc3kbd-add-device-table.patch
+mmc-sdhci_am654-add-tuning-algorithm-for-delay-chain.patch
+mmc-sdhci_am654-write-itapdly-for-ddr52-timing.patch
+mmc-sdhci_am654-drop-lookup-for-deprecated-ti-otap-d.patch
+mmc-sdhci_am654-add-otap-itap-delay-enable.patch
+mmc-sdhci_am654-add-itapdlysel-in-sdhci_j721e_4bit_s.patch
+mmc-sdhci_am654-fix-itapdly-for-hs400-timing.patch
+input-pm8xxx-vibrator-correct-vib_max_levels-calcula.patch
+drm-msm-dpu-always-flush-the-slave-intf-on-the-ctl.patch
+um-fix-return-value-in-ubd_init.patch
+um-add-winch-to-winch_handlers-before-registering-wi.patch
+um-vector-fix-bpfflash-parameter-evaluation.patch
+drm-bridge-tc358775-fix-support-for-jeida-18-and-jei.patch
+media-stk1160-fix-bounds-checking-in-stk1160_copy_vi.patch
+scsi-qla2xxx-replace-all-non-returning-strlcpy-with-.patch
+media-flexcop-usb-clean-up-endpoint-sanity-checks.patch
+media-flexcop-usb-fix-sanity-check-of-bnumendpoints.patch
+powerpc-pseries-add-failure-related-checks-for-h_get.patch
+um-fix-the-wmissing-prototypes-warning-for-__switch_.patch
+media-cec-cec-adap-always-cancel-work-in-cec_transmi.patch
+media-cec-cec-api-add-locking-in-cec_release.patch
+media-core-headers-fix-kernel-doc-warnings.patch
+media-cec-fix-a-deadlock-situation.patch
+media-cec-call-enable_adap-on-s_log_addrs.patch
+media-cec-abort-if-the-current-transmit-was-canceled.patch
+media-cec-correctly-pass-on-reply-results.patch
+media-cec-use-call_op-and-check-for-unregistered.patch
+media-cec-adap.c-drop-activate_cnt-use-state-info-in.patch
+media-cec-core-avoid-recursive-cec_claim_log_addrs.patch
+media-cec-core-avoid-confusing-transmit-timed-out-me.patch
+null_blk-fix-the-warning-modpost-missing-module_desc.patch
+regulator-bd71828-don-t-overwrite-runtime-voltages.patch
+x86-kconfig-select-arch_want_frame_pointers-again-wh.patch
+nfc-nci-fix-uninit-value-in-nci_rx_work.patch
+asoc-tas2552-add-tx-path-for-capturing-audio-out-dat.patch
+sunrpc-fix-nfsacl-rpc-retry-on-soft-mount.patch
+rpcrdma-fix-handling-for-rdma_cm_event_device_remova.patch
+ipv6-sr-fix-memleak-in-seg6_hmac_init_algo.patch
+params-lift-param_set_uint_minmax-to-common-code.patch
+tcp-fix-shift-out-of-bounds-in-dctcp_update_alpha.patch
+openvswitch-set-the-skbuff-pkt_type-for-proper-pmtud.patch
+arm64-asm-bug-add-.align-2-to-the-end-of-__bug_entry.patch
+virtio-delete-vq-in-vp_find_vqs_msix-when-request_ir.patch
+riscv-cleanup-stacktrace.patch
+riscv-stacktrace-make-walk_stackframe-cross-pt_regs-.patch
+riscv-stacktrace-fixed-walk_stackframe.patch
+net-fec-avoid-lock-evasion-when-reading-pps_enable.patch
+tls-fix-missing-memory-barrier-in-tls_init.patch
+tcp-remove-64-kbyte-limit-for-initial-tp-rcv_wnd-val.patch
+nfc-nci-fix-kcov-check-in-nci_rx_work.patch
+nfc-nci-fix-handling-of-zero-length-payload-packets-.patch
diff --git a/queue-5.10/sunrpc-fix-nfsacl-rpc-retry-on-soft-mount.patch b/queue-5.10/sunrpc-fix-nfsacl-rpc-retry-on-soft-mount.patch
new file mode 100644 (file)
index 0000000..58980e0
--- /dev/null
@@ -0,0 +1,55 @@
+From ad6f7359741d3f4d86cb22ad0aac851b5e733867 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Apr 2024 13:49:38 +0300
+Subject: sunrpc: fix NFSACL RPC retry on soft mount
+
+From: Dan Aloni <dan.aloni@vastdata.com>
+
+[ 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 <chuck.lever@oracle.com>
+Cc: Benjamin Coddington <bcodding@redhat.com>
+Link: https://lore.kernel.org/all/20231105154857.ryakhmgaptq3hb6b@gmail.com/T/
+Fixes: 1b63a75180c6 ('SUNRPC: Refactor rpc_clone_client()')
+Signed-off-by: Dan Aloni <dan.aloni@vastdata.com>
+Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sunrpc/clnt.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index a5ce9b937c42e..196a3b11d1509 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -970,6 +970,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
+               .authflavor     = old->cl_auth->au_flavor,
+               .cred           = old->cl_cred,
+               .stats          = old->cl_stats,
++              .timeout        = old->cl_timeout,
+       };
+       struct rpc_clnt *clnt;
+       int err;
+-- 
+2.43.0
+
diff --git a/queue-5.10/tcp-fix-shift-out-of-bounds-in-dctcp_update_alpha.patch b/queue-5.10/tcp-fix-shift-out-of-bounds-in-dctcp_update_alpha.patch
new file mode 100644 (file)
index 0000000..3f6ed85
--- /dev/null
@@ -0,0 +1,125 @@
+From 895110ca036e6968f01ed57201c3e138d73770d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 May 2024 18:16:26 +0900
+Subject: tcp: Fix shift-out-of-bounds in dctcp_update_alpha().
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ 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:
+ <TASK>
+ __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
+ </TASK>
+
+Reported-by: syzkaller <syzkaller@googlegroups.com>
+Reported-by: Yue Sun <samsun1006219@gmail.com>
+Reported-by: xingwei lee <xrivendell7@gmail.com>
+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 <kuniyu@amazon.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://lore.kernel.org/r/20240517091626.32772-1-kuniyu@amazon.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_dctcp.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/net/ipv4/tcp_dctcp.c b/net/ipv4/tcp_dctcp.c
+index 79f705450c162..be2c97e907ae2 100644
+--- a/net/ipv4/tcp_dctcp.c
++++ b/net/ipv4/tcp_dctcp.c
+@@ -55,7 +55,18 @@ struct dctcp {
+ };
+ static unsigned int dctcp_shift_g __read_mostly = 4; /* g = 1/2^4 */
+-module_param(dctcp_shift_g, uint, 0644);
++
++static int dctcp_shift_g_set(const char *val, const struct kernel_param *kp)
++{
++      return param_set_uint_minmax(val, kp, 0, 10);
++}
++
++static const struct kernel_param_ops dctcp_shift_g_ops = {
++      .set = dctcp_shift_g_set,
++      .get = param_get_uint,
++};
++
++module_param_cb(dctcp_shift_g, &dctcp_shift_g_ops, &dctcp_shift_g, 0644);
+ MODULE_PARM_DESC(dctcp_shift_g, "parameter g for updating dctcp_alpha");
+ static unsigned int dctcp_alpha_on_init __read_mostly = DCTCP_MAX_ALPHA;
+-- 
+2.43.0
+
diff --git a/queue-5.10/tcp-remove-64-kbyte-limit-for-initial-tp-rcv_wnd-val.patch b/queue-5.10/tcp-remove-64-kbyte-limit-for-initial-tp-rcv_wnd-val.patch
new file mode 100644 (file)
index 0000000..2ba4fad
--- /dev/null
@@ -0,0 +1,76 @@
+From d95db3294f123d366133d54b7f3c12a5ee0ac717 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 May 2024 21:42:20 +0800
+Subject: tcp: remove 64 KByte limit for initial tp->rcv_wnd value
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ 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 <kernelxing@tencent.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Acked-by: Neal Cardwell <ncardwell@google.com>
+Link: https://lore.kernel.org/r/20240521134220.12510-1-kerneljasonxing@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_output.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
+index 68f1633c477ae..efc57fa04f860 100644
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -229,7 +229,7 @@ void tcp_select_initial_window(const struct sock *sk, int __space, __u32 mss,
+       if (sock_net(sk)->ipv4.sysctl_tcp_workaround_signed_windows)
+               (*rcv_wnd) = min(space, MAX_TCP_WINDOW);
+       else
+-              (*rcv_wnd) = min_t(u32, space, U16_MAX);
++              (*rcv_wnd) = space;
+       if (init_rcv_wnd)
+               *rcv_wnd = min(*rcv_wnd, init_rcv_wnd * mss);
+-- 
+2.43.0
+
diff --git a/queue-5.10/tls-fix-missing-memory-barrier-in-tls_init.patch b/queue-5.10/tls-fix-missing-memory-barrier-in-tls_init.patch
new file mode 100644 (file)
index 0000000..72addb3
--- /dev/null
@@ -0,0 +1,73 @@
+From e86ada08dec2f044b34a6ed3fc8a6addd32dc58d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 May 2024 19:34:38 +0900
+Subject: tls: fix missing memory barrier in tls_init
+
+From: Dae R. Jeong <threeearcat@gmail.com>
+
+[ 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 <woni9911@gmail.com>
+Signed-off-by: Dae R. Jeong <threeearcat@gmail.com>
+Link: https://lore.kernel.org/netdev/ZU4OJG56g2V9z_H7@dragonet/T/
+Link: https://lore.kernel.org/r/Zkx4vjSFp0mfpjQ2@libra05
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tls/tls_main.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
+index 2bbacd9b97e56..ebf856cf821da 100644
+--- a/net/tls/tls_main.c
++++ b/net/tls/tls_main.c
+@@ -633,9 +633,17 @@ struct tls_context *tls_ctx_create(struct sock *sk)
+               return NULL;
+       mutex_init(&ctx->tx_lock);
+-      rcu_assign_pointer(icsk->icsk_ulp_data, ctx);
+       ctx->sk_proto = READ_ONCE(sk->sk_prot);
+       ctx->sk = sk;
++      /* Release semantic of rcu_assign_pointer() ensures that
++       * ctx->sk_proto is visible before changing sk->sk_prot in
++       * update_sk_prot(), and prevents reading uninitialized value in
++       * tls_{getsockopt, setsockopt}. Note that we do not need a
++       * read barrier in tls_{getsockopt,setsockopt} as there is an
++       * address dependency between sk->sk_proto->{getsockopt,setsockopt}
++       * and ctx->sk_proto.
++       */
++      rcu_assign_pointer(icsk->icsk_ulp_data, ctx);
+       return ctx;
+ }
+-- 
+2.43.0
+
diff --git a/queue-5.10/um-add-winch-to-winch_handlers-before-registering-wi.patch b/queue-5.10/um-add-winch-to-winch_handlers-before-registering-wi.patch
new file mode 100644 (file)
index 0000000..9dea238
--- /dev/null
@@ -0,0 +1,68 @@
+From 907c883f23a76e1023c80ba1da0791e3a55446b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Mar 2024 11:49:26 +0100
+Subject: um: Add winch to winch_handlers before registering winch IRQ
+
+From: Roberto Sassu <roberto.sassu@huawei.com>
+
+[ 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 <roberto.sassu@huawei.com>
+Reviewed-by: Johannes Berg <johannes@sipsolutions.net>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/um/drivers/line.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
+index 14ad9f495fe69..37e96ba0f5fb1 100644
+--- a/arch/um/drivers/line.c
++++ b/arch/um/drivers/line.c
+@@ -668,24 +668,26 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_port *port,
+               goto cleanup;
+       }
+-      *winch = ((struct winch) { .list        = LIST_HEAD_INIT(winch->list),
+-                                 .fd          = fd,
++      *winch = ((struct winch) { .fd          = fd,
+                                  .tty_fd      = tty_fd,
+                                  .pid         = pid,
+                                  .port        = port,
+                                  .stack       = stack });
++      spin_lock(&winch_handler_lock);
++      list_add(&winch->list, &winch_handlers);
++      spin_unlock(&winch_handler_lock);
++
+       if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
+                          IRQF_SHARED, "winch", winch) < 0) {
+               printk(KERN_ERR "register_winch_irq - failed to register "
+                      "IRQ\n");
++              spin_lock(&winch_handler_lock);
++              list_del(&winch->list);
++              spin_unlock(&winch_handler_lock);
+               goto out_free;
+       }
+-      spin_lock(&winch_handler_lock);
+-      list_add(&winch->list, &winch_handlers);
+-      spin_unlock(&winch_handler_lock);
+-
+       return;
+  out_free:
+-- 
+2.43.0
+
diff --git a/queue-5.10/um-fix-return-value-in-ubd_init.patch b/queue-5.10/um-fix-return-value-in-ubd_init.patch
new file mode 100644 (file)
index 0000000..35638ad
--- /dev/null
@@ -0,0 +1,46 @@
+From f230d80ed04e39fb2614035c54fb29f49b1f0abe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Mar 2024 17:12:59 +0800
+Subject: um: Fix return value in ubd_init()
+
+From: Duoming Zhou <duoming@zju.edu.cn>
+
+[ 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 <duoming@zju.edu.cn>
+Reviewed-by: Johannes Berg <johannes@sipsolutions.net>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/um/drivers/ubd_kern.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
+index b12c1b0d3e1d0..de28ce711687e 100644
+--- a/arch/um/drivers/ubd_kern.c
++++ b/arch/um/drivers/ubd_kern.c
+@@ -1158,7 +1158,7 @@ static int __init ubd_init(void)
+       if (irq_req_buffer == NULL) {
+               printk(KERN_ERR "Failed to initialize ubd buffering\n");
+-              return -1;
++              return -ENOMEM;
+       }
+       io_req_buffer = kmalloc_array(UBD_REQ_BUFFER_SIZE,
+                                     sizeof(struct io_thread_req *),
+@@ -1169,7 +1169,7 @@ static int __init ubd_init(void)
+       if (io_req_buffer == NULL) {
+               printk(KERN_ERR "Failed to initialize ubd buffering\n");
+-              return -1;
++              return -ENOMEM;
+       }
+       platform_driver_register(&ubd_driver);
+       mutex_lock(&ubd_lock);
+-- 
+2.43.0
+
diff --git a/queue-5.10/um-fix-the-wmissing-prototypes-warning-for-__switch_.patch b/queue-5.10/um-fix-the-wmissing-prototypes-warning-for-__switch_.patch
new file mode 100644 (file)
index 0000000..87f14d5
--- /dev/null
@@ -0,0 +1,48 @@
+From aa3e776a2fb6c8efc6d33c500174af5ffdcf9f10 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Apr 2024 20:58:53 +0800
+Subject: um: Fix the -Wmissing-prototypes warning for __switch_mm
+
+From: Tiwei Bie <tiwei.btw@antgroup.com>
+
+[ 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 <tiwei.btw@antgroup.com>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/um/include/asm/mmu.h           | 2 --
+ arch/um/include/shared/skas/mm_id.h | 2 ++
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/um/include/asm/mmu.h b/arch/um/include/asm/mmu.h
+index 5b072aba5b658..a7cb380c0b5c0 100644
+--- a/arch/um/include/asm/mmu.h
++++ b/arch/um/include/asm/mmu.h
+@@ -15,8 +15,6 @@ typedef struct mm_context {
+       struct page *stub_pages[2];
+ } mm_context_t;
+-extern void __switch_mm(struct mm_id * mm_idp);
+-
+ /* Avoid tangled inclusion with asm/ldt.h */
+ extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm);
+ extern void free_ldt(struct mm_context *mm);
+diff --git a/arch/um/include/shared/skas/mm_id.h b/arch/um/include/shared/skas/mm_id.h
+index e82e203f5f419..92dbf727e3842 100644
+--- a/arch/um/include/shared/skas/mm_id.h
++++ b/arch/um/include/shared/skas/mm_id.h
+@@ -15,4 +15,6 @@ struct mm_id {
+       int kill;
+ };
++void __switch_mm(struct mm_id *mm_idp);
++
+ #endif
+-- 
+2.43.0
+
diff --git a/queue-5.10/um-vector-fix-bpfflash-parameter-evaluation.patch b/queue-5.10/um-vector-fix-bpfflash-parameter-evaluation.patch
new file mode 100644 (file)
index 0000000..7552e65
--- /dev/null
@@ -0,0 +1,37 @@
+From 31e2f795ed5c4c47bd111de03c230300df9d8a09 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Mar 2024 10:06:36 +0100
+Subject: um: vector: fix bpfflash parameter evaluation
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ 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 <johannes.berg@intel.com>
+Reviewed-by: Tiwei Bie <tiwei.btw@antgroup.com>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/um/drivers/vector_kern.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
+index fc662f7cc2afb..c10432ef2d410 100644
+--- a/arch/um/drivers/vector_kern.c
++++ b/arch/um/drivers/vector_kern.c
+@@ -142,7 +142,7 @@ static bool get_bpf_flash(struct arglist *def)
+       if (allow != NULL) {
+               if (kstrtoul(allow, 10, &result) == 0)
+-                      return (allow > 0);
++                      return result > 0;
+       }
+       return false;
+ }
+-- 
+2.43.0
+
diff --git a/queue-5.10/virtio-delete-vq-in-vp_find_vqs_msix-when-request_ir.patch b/queue-5.10/virtio-delete-vq-in-vp_find_vqs_msix-when-request_ir.patch
new file mode 100644 (file)
index 0000000..95fb2cf
--- /dev/null
@@ -0,0 +1,94 @@
+From f0f91983a177a533df6d0ecf34a67fb106fbc4f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <jiri@nvidia.com>
+
+[ 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]  <TASK>
+[    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]  </TASK>
+
+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 <jiri@nvidia.com>
+Message-Id: <20240426150845.3999481-1-jiri@resnulli.us>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/virtio/virtio_pci_common.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
+index 1e890ef176873..a6f375417fd54 100644
+--- a/drivers/virtio/virtio_pci_common.c
++++ b/drivers/virtio/virtio_pci_common.c
+@@ -339,8 +339,10 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
+                                 vring_interrupt, 0,
+                                 vp_dev->msix_names[msix_vec],
+                                 vqs[i]);
+-              if (err)
++              if (err) {
++                      vp_del_vq(vqs[i]);
+                       goto error_find;
++              }
+       }
+       return 0;
+-- 
+2.43.0
+
diff --git a/queue-5.10/x86-kconfig-select-arch_want_frame_pointers-again-wh.patch b/queue-5.10/x86-kconfig-select-arch_want_frame_pointers-again-wh.patch
new file mode 100644 (file)
index 0000000..73532db
--- /dev/null
@@ -0,0 +1,63 @@
+From ac56f3fafa4176b1b80ebad2124b4fb36db712d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <masahiroy@kernel.org>
+
+[ 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 <masahiroy@kernel.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Acked-by: Josh Poimboeuf <jpoimboe@kernel.org>
+Link: https://lore.kernel.org/r/20240204122003.53795-1-masahiroy@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/Kconfig.debug | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
+index 27b5e2bc6a016..e6546aa448de1 100644
+--- a/arch/x86/Kconfig.debug
++++ b/arch/x86/Kconfig.debug
+@@ -258,6 +258,7 @@ config UNWINDER_ORC
+ config UNWINDER_FRAME_POINTER
+       bool "Frame pointer unwinder"
++      select ARCH_WANT_FRAME_POINTERS
+       select FRAME_POINTER
+       help
+         This option enables the frame pointer unwinder for unwinding kernel
+@@ -281,7 +282,3 @@ config UNWINDER_GUESS
+         overhead.
+ endchoice
+-
+-config FRAME_POINTER
+-      depends on !UNWINDER_ORC && !UNWINDER_GUESS
+-      bool
+-- 
+2.43.0
+