--- /dev/null
+From 7aadfbdd7e9bab174931e450fbcd96a83d6194e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Feb 2025 21:07:28 +0000
+Subject: ALSA: hda/cirrus: Correct the full scale volume set logic
+
+From: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
+
+[ Upstream commit 08b613b9e2ba431db3bd15cb68ca72472a50ef5c ]
+
+This patch corrects the full-scale volume setting logic. On certain
+platforms, the full-scale volume bit is required. The current logic
+mistakenly sets this bit and incorrectly clears reserved bit 0, causing
+the headphone output to be muted.
+
+Fixes: 342b6b610ae2 ("ALSA: hda/cs8409: Fix Full Scale Volume setting for all variants")
+Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
+Link: https://patch.msgid.link/20250214210736.30814-1-vitalyr@opensource.cirrus.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/patch_cs8409-tables.c | 6 +++---
+ sound/pci/hda/patch_cs8409.c | 20 +++++++++++---------
+ sound/pci/hda/patch_cs8409.h | 5 +++--
+ 3 files changed, 17 insertions(+), 14 deletions(-)
+
+diff --git a/sound/pci/hda/patch_cs8409-tables.c b/sound/pci/hda/patch_cs8409-tables.c
+index b288874e401e5..b2e1856ab8918 100644
+--- a/sound/pci/hda/patch_cs8409-tables.c
++++ b/sound/pci/hda/patch_cs8409-tables.c
+@@ -121,7 +121,7 @@ static const struct cs8409_i2c_param cs42l42_init_reg_seq[] = {
+ { CS42L42_MIXER_CHA_VOL, 0x3F },
+ { CS42L42_MIXER_CHB_VOL, 0x3F },
+ { CS42L42_MIXER_ADC_VOL, 0x3f },
+- { CS42L42_HP_CTL, 0x03 },
++ { CS42L42_HP_CTL, 0x0D },
+ { CS42L42_MIC_DET_CTL1, 0xB6 },
+ { CS42L42_TIPSENSE_CTL, 0xC2 },
+ { CS42L42_HS_CLAMP_DISABLE, 0x01 },
+@@ -315,7 +315,7 @@ static const struct cs8409_i2c_param dolphin_c0_init_reg_seq[] = {
+ { CS42L42_ASP_TX_SZ_EN, 0x01 },
+ { CS42L42_PWR_CTL1, 0x0A },
+ { CS42L42_PWR_CTL2, 0x84 },
+- { CS42L42_HP_CTL, 0x03 },
++ { CS42L42_HP_CTL, 0x0D },
+ { CS42L42_MIXER_CHA_VOL, 0x3F },
+ { CS42L42_MIXER_CHB_VOL, 0x3F },
+ { CS42L42_MIXER_ADC_VOL, 0x3f },
+@@ -371,7 +371,7 @@ static const struct cs8409_i2c_param dolphin_c1_init_reg_seq[] = {
+ { CS42L42_ASP_TX_SZ_EN, 0x00 },
+ { CS42L42_PWR_CTL1, 0x0E },
+ { CS42L42_PWR_CTL2, 0x84 },
+- { CS42L42_HP_CTL, 0x01 },
++ { CS42L42_HP_CTL, 0x0D },
+ { CS42L42_MIXER_CHA_VOL, 0x3F },
+ { CS42L42_MIXER_CHB_VOL, 0x3F },
+ { CS42L42_MIXER_ADC_VOL, 0x3f },
+diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c
+index 892223d9e64ab..b003ac1990ba8 100644
+--- a/sound/pci/hda/patch_cs8409.c
++++ b/sound/pci/hda/patch_cs8409.c
+@@ -876,7 +876,7 @@ static void cs42l42_resume(struct sub_codec *cs42l42)
+ { CS42L42_DET_INT_STATUS2, 0x00 },
+ { CS42L42_TSRS_PLUG_STATUS, 0x00 },
+ };
+- int fsv_old, fsv_new;
++ unsigned int fsv;
+
+ /* Bring CS42L42 out of Reset */
+ spec->gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
+@@ -893,13 +893,15 @@ static void cs42l42_resume(struct sub_codec *cs42l42)
+ /* Clear interrupts, by reading interrupt status registers */
+ cs8409_i2c_bulk_read(cs42l42, irq_regs, ARRAY_SIZE(irq_regs));
+
+- fsv_old = cs8409_i2c_read(cs42l42, CS42L42_HP_CTL);
+- if (cs42l42->full_scale_vol == CS42L42_FULL_SCALE_VOL_0DB)
+- fsv_new = fsv_old & ~CS42L42_FULL_SCALE_VOL_MASK;
+- else
+- fsv_new = fsv_old & CS42L42_FULL_SCALE_VOL_MASK;
+- if (fsv_new != fsv_old)
+- cs8409_i2c_write(cs42l42, CS42L42_HP_CTL, fsv_new);
++ fsv = cs8409_i2c_read(cs42l42, CS42L42_HP_CTL);
++ if (cs42l42->full_scale_vol) {
++ // Set the full scale volume bit
++ fsv |= CS42L42_FULL_SCALE_VOL_MASK;
++ cs8409_i2c_write(cs42l42, CS42L42_HP_CTL, fsv);
++ }
++ // Unmute analog channels A and B
++ fsv = (fsv & ~CS42L42_ANA_MUTE_AB);
++ cs8409_i2c_write(cs42l42, CS42L42_HP_CTL, fsv);
+
+ /* we have to explicitly allow unsol event handling even during the
+ * resume phase so that the jack event is processed properly
+@@ -921,7 +923,7 @@ static void cs42l42_suspend(struct sub_codec *cs42l42)
+ { CS42L42_MIXER_CHA_VOL, 0x3F },
+ { CS42L42_MIXER_ADC_VOL, 0x3F },
+ { CS42L42_MIXER_CHB_VOL, 0x3F },
+- { CS42L42_HP_CTL, 0x0F },
++ { CS42L42_HP_CTL, 0x0D },
+ { CS42L42_ASP_RX_DAI0_EN, 0x00 },
+ { CS42L42_ASP_CLK_CFG, 0x00 },
+ { CS42L42_PWR_CTL1, 0xFE },
+diff --git a/sound/pci/hda/patch_cs8409.h b/sound/pci/hda/patch_cs8409.h
+index 937e9387abdc7..bca81d49f201a 100644
+--- a/sound/pci/hda/patch_cs8409.h
++++ b/sound/pci/hda/patch_cs8409.h
+@@ -230,9 +230,10 @@ enum cs8409_coefficient_index_registers {
+ #define CS42L42_PDN_TIMEOUT_US (250000)
+ #define CS42L42_PDN_SLEEP_US (2000)
+ #define CS42L42_INIT_TIMEOUT_MS (45)
++#define CS42L42_ANA_MUTE_AB (0x0C)
+ #define CS42L42_FULL_SCALE_VOL_MASK (2)
+-#define CS42L42_FULL_SCALE_VOL_0DB (1)
+-#define CS42L42_FULL_SCALE_VOL_MINUS6DB (0)
++#define CS42L42_FULL_SCALE_VOL_0DB (0)
++#define CS42L42_FULL_SCALE_VOL_MINUS6DB (1)
+
+ /* Dell BULLSEYE / WARLOCK / CYBORG Specific Definitions */
+
+--
+2.39.5
+
--- /dev/null
+From 9e0b3c6b00c770bca3101127758341c6f27e78e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 14:40:46 +0800
+Subject: ALSA: hda/realtek: Fixup ALC225 depop procedure
+
+From: Kailang Yang <kailang@realtek.com>
+
+[ Upstream commit 174448badb4409491bfba2e6b46f7aa078741c5e ]
+
+Headset MIC will no function when power_save=0.
+
+Fixes: 1fd50509fe14 ("ALSA: hda/realtek: Update ALC225 depop procedure")
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=219743
+Signed-off-by: Kailang Yang <kailang@realtek.com>
+Link: https://lore.kernel.org/0474a095ab0044d0939ec4bf4362423d@realtek.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/patch_realtek.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 183c8a587acfe..96725b6599ec9 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -3776,6 +3776,7 @@ static void alc225_init(struct hda_codec *codec)
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+
+ msleep(75);
++ alc_update_coef_idx(codec, 0x4a, 3 << 10, 0);
+ alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */
+ }
+ }
+--
+2.39.5
+
--- /dev/null
+From 86e8a9d2fac06415d7d2f68a728f562f11979915 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Oct 2024 15:56:28 +0800
+Subject: arm64: dts: mediatek: mt8183: Disable DSI display output by default
+
+From: Chen-Yu Tsai <wenst@chromium.org>
+
+[ Upstream commit 26f6e91fa29a58fdc76b47f94f8f6027944a490c ]
+
+Most SoC dtsi files have the display output interfaces disabled by
+default, and only enabled on boards that utilize them. The MT8183
+has it backwards: the display outputs are left enabled by default,
+and only disabled at the board level.
+
+Reverse the situation for the DSI output so that it follows the
+normal scheme. For ease of backporting the DPI output is handled
+in a separate patch.
+
+Fixes: 88ec840270e6 ("arm64: dts: mt8183: Add dsi node")
+Fixes: 19b6403f1e2a ("arm64: dts: mt8183: add mt8183 pumpkin board")
+Cc: stable@vger.kernel.org
+Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
+Reviewed-by: Fei Shao <fshao@chromium.org>
+Link: https://lore.kernel.org/r/20241025075630.3917458-2-wenst@chromium.org
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/mediatek/mt8183.dtsi | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+index 2147e152683bf..fe4632744f6e5 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+@@ -1753,6 +1753,7 @@
+ resets = <&mmsys MT8183_MMSYS_SW0_RST_B_DISP_DSI0>;
+ phys = <&mipi_tx0>;
+ phy-names = "dphy";
++ status = "disabled";
+ };
+
+ mutex: mutex@14016000 {
+--
+2.39.5
+
--- /dev/null
+From 43dbbdb3f00a095dac7b83284f491f235425bab9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Dec 2024 15:53:54 +0100
+Subject: arm64: dts: qcom: sm8450: Fix CDSP memory length
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 3751fe2cba2a9fba2204ef62102bc4bb027cec7b ]
+
+The address space in CDSP PAS (Peripheral Authentication Service)
+remoteproc node should point to the QDSP PUB address space
+(QDSP6...SS_PUB) which has a length of 0x10000. Value of 0x1400000 was
+copied from older DTS, but it does not look accurate at all.
+
+This should have no functional impact on Linux users, because PAS loader
+does not use this address space at all.
+
+Fixes: 1172729576fb ("arm64: dts: qcom: sm8450: Add remoteproc enablers and instances")
+Cc: stable@vger.kernel.org
+Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20241213-dts-qcom-cdsp-mpss-base-address-v3-5-2e0036fccd8d@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sm8450.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi
+index 9151ed3b0a62f..9420857871b1e 100644
+--- a/arch/arm64/boot/dts/qcom/sm8450.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi
+@@ -2159,7 +2159,7 @@
+
+ remoteproc_cdsp: remoteproc@32300000 {
+ compatible = "qcom,sm8450-cdsp-pas";
+- reg = <0 0x32300000 0 0x1400000>;
++ reg = <0 0x32300000 0 0x10000>;
+
+ interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
+--
+2.39.5
+
--- /dev/null
+From c087fbc0f80952812b3149763025f1ab31bbbb3f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Nov 2022 11:50:46 +0100
+Subject: arm64: dts: qcom: trim addresses to 8 digits
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 22dbcfd6f4a9f7d4391f0aa66d3f46addea4bee9 ]
+
+Hex numbers in addresses and sizes should be rather eight digits, not
+nine. Drop leading zeros. No functional change (same DTB).
+
+Suggested-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Link: https://lore.kernel.org/r/20221115105046.95254-1-krzysztof.kozlowski@linaro.org
+Stable-dep-of: 3751fe2cba2a ("arm64: dts: qcom: sm8450: Fix CDSP memory length")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sm8350.dtsi | 2 +-
+ arch/arm64/boot/dts/qcom/sm8450.dtsi | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi
+index 956237489bc46..5a4972afc9776 100644
+--- a/arch/arm64/boot/dts/qcom/sm8350.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi
+@@ -2226,7 +2226,7 @@
+
+ cdsp: remoteproc@98900000 {
+ compatible = "qcom,sm8350-cdsp-pas";
+- reg = <0 0x098900000 0 0x1400000>;
++ reg = <0 0x98900000 0 0x1400000>;
+
+ interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
+ <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
+diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi
+index 3f79aea644460..9151ed3b0a62f 100644
+--- a/arch/arm64/boot/dts/qcom/sm8450.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi
+@@ -2093,7 +2093,7 @@
+
+ remoteproc_adsp: remoteproc@30000000 {
+ compatible = "qcom,sm8450-adsp-pas";
+- reg = <0 0x030000000 0 0x100>;
++ reg = <0 0x30000000 0 0x100>;
+
+ interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
+@@ -2159,7 +2159,7 @@
+
+ remoteproc_cdsp: remoteproc@32300000 {
+ compatible = "qcom,sm8450-cdsp-pas";
+- reg = <0 0x032300000 0 0x1400000>;
++ reg = <0 0x32300000 0 0x1400000>;
+
+ interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
+--
+2.39.5
+
--- /dev/null
+From a37662e1838c83e280210fde4d9405dd3d079348 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 05:49:31 -0800
+Subject: arp: switch to dev_getbyhwaddr() in arp_req_set_public()
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit 4eae0ee0f1e6256d0b0b9dd6e72f1d9cf8f72e08 ]
+
+The arp_req_set_public() function is called with the rtnl lock held,
+which provides enough synchronization protection. This makes the RCU
+variant of dev_getbyhwaddr() unnecessary. Switch to using the simpler
+dev_getbyhwaddr() function since we already have the required rtnl
+locking.
+
+This change helps maintain consistency in the networking code by using
+the appropriate helper function for the existing locking context.
+Since we're not holding the RCU read lock in arp_req_set_public()
+existing code could trigger false positive locking warnings.
+
+Fixes: 941666c2e3e0 ("net: RCU conversion of dev_getbyhwaddr() and arp_ioctl()")
+Suggested-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Link: https://patch.msgid.link/20250218-arm_fix_selftest-v5-2-d3d6892db9e1@debian.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/arp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
+index 8f9b5568f1dc1..50e2b4939d8e9 100644
+--- a/net/ipv4/arp.c
++++ b/net/ipv4/arp.c
+@@ -1030,7 +1030,7 @@ static int arp_req_set_public(struct net *net, struct arpreq *r,
+ if (mask && mask != htonl(0xFFFFFFFF))
+ return -EINVAL;
+ if (!dev && (r->arp_flags & ATF_COM)) {
+- dev = dev_getbyhwaddr_rcu(net, r->arp_ha.sa_family,
++ dev = dev_getbyhwaddr(net, r->arp_ha.sa_family,
+ r->arp_ha.sa_data);
+ if (!dev)
+ return -ENODEV;
+--
+2.39.5
+
--- /dev/null
+From b1dd67102066217ad50d2249bf8b64e3d6561fdf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Jan 2025 12:28:46 +0300
+Subject: ASoC: renesas: rz-ssi: Add a check for negative sample_space
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+[ Upstream commit 82a0a3e6f8c02b3236b55e784a083fa4ee07c321 ]
+
+My static checker rule complains about this code. The concern is that
+if "sample_space" is negative then the "sample_space >= runtime->channels"
+condition will not work as intended because it will be type promoted to a
+high unsigned int value.
+
+strm->fifo_sample_size is SSI_FIFO_DEPTH (32). The SSIFSR_TDC_MASK is
+0x3f. Without any further context it does seem like a reasonable warning
+and it can't hurt to add a check for negatives.
+
+Cc: stable@vger.kernel.org
+Fixes: 03e786bd4341 ("ASoC: sh: Add RZ/G2L SSIF-2 driver")
+Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://patch.msgid.link/e07c3dc5-d885-4b04-a742-71f42243f4fd@stanley.mountain
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/sh/rz-ssi.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
+index 468050467bb39..12e063c29a2ab 100644
+--- a/sound/soc/sh/rz-ssi.c
++++ b/sound/soc/sh/rz-ssi.c
+@@ -483,6 +483,8 @@ static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
+ sample_space = strm->fifo_sample_size;
+ ssifsr = rz_ssi_reg_readl(ssi, SSIFSR);
+ sample_space -= (ssifsr >> SSIFSR_TDC_SHIFT) & SSIFSR_TDC_MASK;
++ if (sample_space < 0)
++ return -EINVAL;
+
+ /* Only add full frames at a time */
+ while (frames_left && (sample_space >= runtime->channels)) {
+--
+2.39.5
+
--- /dev/null
+From cc5dbf4cd246c558ad009389f10cad22e58a8f81 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 16:13:10 +0000
+Subject: ASoC: rockchip: i2s-tdm: fix shift config for SND_SOC_DAIFMT_DSP_[AB]
+
+From: John Keeping <jkeeping@inmusicbrands.com>
+
+[ Upstream commit 6b24e67b4056ba83b1e95e005b7e50fdb1cc6cf4 ]
+
+Commit 2f45a4e289779 ("ASoC: rockchip: i2s_tdm: Fixup config for
+SND_SOC_DAIFMT_DSP_A/B") applied a partial change to fix the
+configuration for DSP A and DSP B formats.
+
+The shift control also needs updating to set the correct offset for
+frame data compared to LRCK. Set the correct values.
+
+Fixes: 081068fd64140 ("ASoC: rockchip: add support for i2s-tdm controller")
+Signed-off-by: John Keeping <jkeeping@inmusicbrands.com>
+Link: https://patch.msgid.link/20250204161311.2117240-1-jkeeping@inmusicbrands.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/rockchip/rockchip_i2s_tdm.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c
+index d20438cf8fc4a..ff743ba0a9441 100644
+--- a/sound/soc/rockchip/rockchip_i2s_tdm.c
++++ b/sound/soc/rockchip/rockchip_i2s_tdm.c
+@@ -453,11 +453,11 @@ static int rockchip_i2s_tdm_set_fmt(struct snd_soc_dai *cpu_dai,
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ val = I2S_TXCR_TFS_TDM_PCM;
+- tdm_val = TDM_SHIFT_CTRL(0);
++ tdm_val = TDM_SHIFT_CTRL(2);
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ val = I2S_TXCR_TFS_TDM_PCM;
+- tdm_val = TDM_SHIFT_CTRL(2);
++ tdm_val = TDM_SHIFT_CTRL(4);
+ break;
+ default:
+ ret = -EINVAL;
+--
+2.39.5
+
--- /dev/null
+From 1b61f5da948536472cbd54f0140b267f40fcf632 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 22:43:23 +0800
+Subject: Bluetooth: qca: Fix poor RF performance for WCN6855
+
+From: Zijun Hu <quic_zijuhu@quicinc.com>
+
+[ Upstream commit a2fad248947d702ed3dcb52b8377c1a3ae201e44 ]
+
+For WCN6855, board ID specific NVM needs to be downloaded once board ID
+is available, but the default NVM is always downloaded currently.
+
+The wrong NVM causes poor RF performance, and effects user experience
+for several types of laptop with WCN6855 on the market.
+
+Fix by downloading board ID specific NVM if board ID is available.
+
+Fixes: 095327fede00 ("Bluetooth: hci_qca: Add support for QTI Bluetooth chip wcn6855")
+Cc: stable@vger.kernel.org # 6.4
+Signed-off-by: Zijun Hu <quic_zijuhu@quicinc.com>
+Tested-by: Johan Hovold <johan+linaro@kernel.org>
+Reviewed-by: Johan Hovold <johan+linaro@kernel.org>
+Tested-by: Steev Klimaszewski <steev@kali.org> #Thinkpad X13s
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btqca.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
+index 484a860785fde..892e2540f008a 100644
+--- a/drivers/bluetooth/btqca.c
++++ b/drivers/bluetooth/btqca.c
+@@ -927,8 +927,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
+ "qca/msnv%02x.bin", rom_ver);
+ break;
+ case QCA_WCN6855:
+- snprintf(config.fwname, sizeof(config.fwname),
+- "qca/hpnv%02x.bin", rom_ver);
++ qca_read_fw_board_id(hdev, &boardid);
++ qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname),
++ "hpnv", soc_type, ver, rom_ver, boardid);
+ break;
+ case QCA_WCN7850:
+ qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname),
+--
+2.39.5
+
--- /dev/null
+From 547f15a754b68f3d42d7811c45263d3766d7303b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Apr 2024 15:49:34 +0800
+Subject: Bluetooth: qca: Support downloading board id specific NVM for WCN7850
+
+From: Zijun Hu <quic_zijuhu@quicinc.com>
+
+[ Upstream commit e41137d8bd1a8e8bab8dcbfe3ec056418db3df18 ]
+
+Download board id specific NVM instead of default for WCN7850 if board id
+is available.
+
+Signed-off-by: Zijun Hu <quic_zijuhu@quicinc.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: a2fad248947d ("Bluetooth: qca: Fix poor RF performance for WCN6855")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btqca.c | 18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
+index 35fb26cbf2294..513ff87a7a049 100644
+--- a/drivers/bluetooth/btqca.c
++++ b/drivers/bluetooth/btqca.c
+@@ -739,6 +739,19 @@ static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size,
+ snprintf(fwname, max_size, "qca/hpnv%02x%s.%x", rom_ver, variant, bid);
+ }
+
++static inline void qca_get_nvm_name_generic(struct qca_fw_config *cfg,
++ const char *stem, u8 rom_ver, u16 bid)
++{
++ if (bid == 0x0)
++ snprintf(cfg->fwname, sizeof(cfg->fwname), "qca/%snv%02x.bin", stem, rom_ver);
++ else if (bid & 0xff00)
++ snprintf(cfg->fwname, sizeof(cfg->fwname),
++ "qca/%snv%02x.b%x", stem, rom_ver, bid);
++ else
++ snprintf(cfg->fwname, sizeof(cfg->fwname),
++ "qca/%snv%02x.b%02x", stem, rom_ver, bid);
++}
++
+ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
+ enum qca_btsoc_type soc_type, struct qca_btsoc_version ver,
+ const char *firmware_name)
+@@ -819,7 +832,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
+ /* Give the controller some time to get ready to receive the NVM */
+ msleep(10);
+
+- if (soc_type == QCA_QCA2066)
++ if (soc_type == QCA_QCA2066 || soc_type == QCA_WCN7850)
+ qca_read_fw_board_id(hdev, &boardid);
+
+ /* Download NVM configuration */
+@@ -861,8 +874,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
+ "qca/hpnv%02x.bin", rom_ver);
+ break;
+ case QCA_WCN7850:
+- snprintf(config.fwname, sizeof(config.fwname),
+- "qca/hmtnv%02x.bin", rom_ver);
++ qca_get_nvm_name_generic(&config, "hmt", rom_ver, boardid);
+ break;
+
+ default:
+--
+2.39.5
+
--- /dev/null
+From 8e952b7c4bf1d5a6efd43c16e4ba190b183f0998 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jan 2025 17:26:49 +0800
+Subject: Bluetooth: qca: Update firmware-name to support board specific nvm
+
+From: Cheng Jiang <quic_chejiang@quicinc.com>
+
+[ Upstream commit a4c5a468c6329bde7dfd46bacff2cbf5f8a8152e ]
+
+Different connectivity boards may be attached to the same platform. For
+example, QCA6698-based boards can support either a two-antenna or
+three-antenna solution, both of which work on the sa8775p-ride platform.
+Due to differences in connectivity boards and variations in RF
+performance from different foundries, different NVM configurations are
+used based on the board ID.
+
+Therefore, in the firmware-name property, if the NVM file has an
+extension, the NVM file will be used. Otherwise, the system will first
+try the .bNN (board ID) file, and if that fails, it will fall back to
+the .bin file.
+
+Possible configurations:
+firmware-name = "QCA6698/hpnv21";
+firmware-name = "QCA6698/hpnv21.bin";
+
+Signed-off-by: Cheng Jiang <quic_chejiang@quicinc.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: a2fad248947d ("Bluetooth: qca: Fix poor RF performance for WCN6855")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btqca.c | 113 ++++++++++++++++++++++++++++----------
+ 1 file changed, 85 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
+index 513ff87a7a049..484a860785fde 100644
+--- a/drivers/bluetooth/btqca.c
++++ b/drivers/bluetooth/btqca.c
+@@ -289,6 +289,39 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
+ }
+ EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);
+
++static bool qca_filename_has_extension(const char *filename)
++{
++ const char *suffix = strrchr(filename, '.');
++
++ /* File extensions require a dot, but not as the first or last character */
++ if (!suffix || suffix == filename || *(suffix + 1) == '\0')
++ return 0;
++
++ /* Avoid matching directories with names that look like files with extensions */
++ return !strchr(suffix, '/');
++}
++
++static bool qca_get_alt_nvm_file(char *filename, size_t max_size)
++{
++ char fwname[64];
++ const char *suffix;
++
++ /* nvm file name has an extension, replace with .bin */
++ if (qca_filename_has_extension(filename)) {
++ suffix = strrchr(filename, '.');
++ strscpy(fwname, filename, suffix - filename + 1);
++ snprintf(fwname + (suffix - filename),
++ sizeof(fwname) - (suffix - filename), ".bin");
++ /* If nvm file is already the default one, return false to skip the retry. */
++ if (strcmp(fwname, filename) == 0)
++ return false;
++
++ snprintf(filename, max_size, "%s", fwname);
++ return true;
++ }
++ return false;
++}
++
+ static int qca_tlv_check_data(struct hci_dev *hdev,
+ struct qca_fw_config *config,
+ u8 *fw_data, size_t fw_size,
+@@ -586,6 +619,19 @@ static int qca_download_firmware(struct hci_dev *hdev,
+ config->fwname, ret);
+ return ret;
+ }
++ }
++ /* If the board-specific file is missing, try loading the default
++ * one, unless that was attempted already.
++ */
++ else if (config->type == TLV_TYPE_NVM &&
++ qca_get_alt_nvm_file(config->fwname, sizeof(config->fwname))) {
++ bt_dev_info(hdev, "QCA Downloading %s", config->fwname);
++ ret = request_firmware(&fw, config->fwname, &hdev->dev);
++ if (ret) {
++ bt_dev_err(hdev, "QCA Failed to request file: %s (%d)",
++ config->fwname, ret);
++ return ret;
++ }
+ } else {
+ bt_dev_err(hdev, "QCA Failed to request file: %s (%d)",
+ config->fwname, ret);
+@@ -722,34 +768,38 @@ static int qca_check_bdaddr(struct hci_dev *hdev, const struct qca_fw_config *co
+ return 0;
+ }
+
+-static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size,
++static void qca_get_nvm_name_by_board(char *fwname, size_t max_size,
++ const char *stem, enum qca_btsoc_type soc_type,
+ struct qca_btsoc_version ver, u8 rom_ver, u16 bid)
+ {
+ const char *variant;
++ const char *prefix;
+
+- /* hsp gf chip */
+- if ((le32_to_cpu(ver.soc_id) & QCA_HSP_GF_SOC_MASK) == QCA_HSP_GF_SOC_ID)
+- variant = "g";
+- else
+- variant = "";
++ /* Set the default value to variant and prefix */
++ variant = "";
++ prefix = "b";
+
+- if (bid == 0x0)
+- snprintf(fwname, max_size, "qca/hpnv%02x%s.bin", rom_ver, variant);
+- else
+- snprintf(fwname, max_size, "qca/hpnv%02x%s.%x", rom_ver, variant, bid);
+-}
++ if (soc_type == QCA_QCA2066)
++ prefix = "";
+
+-static inline void qca_get_nvm_name_generic(struct qca_fw_config *cfg,
+- const char *stem, u8 rom_ver, u16 bid)
+-{
+- if (bid == 0x0)
+- snprintf(cfg->fwname, sizeof(cfg->fwname), "qca/%snv%02x.bin", stem, rom_ver);
+- else if (bid & 0xff00)
+- snprintf(cfg->fwname, sizeof(cfg->fwname),
+- "qca/%snv%02x.b%x", stem, rom_ver, bid);
+- else
+- snprintf(cfg->fwname, sizeof(cfg->fwname),
+- "qca/%snv%02x.b%02x", stem, rom_ver, bid);
++ if (soc_type == QCA_WCN6855 || soc_type == QCA_QCA2066) {
++ /* If the chip is manufactured by GlobalFoundries */
++ if ((le32_to_cpu(ver.soc_id) & QCA_HSP_GF_SOC_MASK) == QCA_HSP_GF_SOC_ID)
++ variant = "g";
++ }
++
++ if (rom_ver != 0) {
++ if (bid == 0x0 || bid == 0xffff)
++ snprintf(fwname, max_size, "qca/%s%02x%s.bin", stem, rom_ver, variant);
++ else
++ snprintf(fwname, max_size, "qca/%s%02x%s.%s%02x", stem, rom_ver,
++ variant, prefix, bid);
++ } else {
++ if (bid == 0x0 || bid == 0xffff)
++ snprintf(fwname, max_size, "qca/%s%s.bin", stem, variant);
++ else
++ snprintf(fwname, max_size, "qca/%s%s.%s%02x", stem, variant, prefix, bid);
++ }
+ }
+
+ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
+@@ -838,8 +888,14 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
+ /* Download NVM configuration */
+ config.type = TLV_TYPE_NVM;
+ if (firmware_name) {
+- snprintf(config.fwname, sizeof(config.fwname),
+- "qca/%s", firmware_name);
++ /* The firmware name has an extension, use it directly */
++ if (qca_filename_has_extension(firmware_name)) {
++ snprintf(config.fwname, sizeof(config.fwname), "qca/%s", firmware_name);
++ } else {
++ qca_read_fw_board_id(hdev, &boardid);
++ qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname),
++ firmware_name, soc_type, ver, 0, boardid);
++ }
+ } else {
+ switch (soc_type) {
+ case QCA_WCN3990:
+@@ -858,8 +914,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
+ "qca/apnv%02x.bin", rom_ver);
+ break;
+ case QCA_QCA2066:
+- qca_generate_hsp_nvm_name(config.fwname,
+- sizeof(config.fwname), ver, rom_ver, boardid);
++ qca_get_nvm_name_by_board(config.fwname,
++ sizeof(config.fwname), "hpnv", soc_type, ver,
++ rom_ver, boardid);
+ break;
+ case QCA_QCA6390:
+ snprintf(config.fwname, sizeof(config.fwname),
+@@ -874,9 +931,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
+ "qca/hpnv%02x.bin", rom_ver);
+ break;
+ case QCA_WCN7850:
+- qca_get_nvm_name_generic(&config, "hmt", rom_ver, boardid);
++ qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname),
++ "hmtnv", soc_type, ver, rom_ver, boardid);
+ break;
+-
+ default:
+ snprintf(config.fwname, sizeof(config.fwname),
+ "qca/nvm_%08x.bin", soc_ver);
+--
+2.39.5
+
--- /dev/null
+From daefbdcee8c6991293455bb64805436083ebb243 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Jan 2023 10:20:37 +0100
+Subject: clk: mediatek: clk-mtk: Add dummy clock ops
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+[ Upstream commit b8eb1081d267708ba976525a1fe2162901b34f3a ]
+
+In order to migrate some (few) old clock drivers to the common
+mtk_clk_simple_probe() function, add dummy clock ops to be able
+to insert a dummy clock with ID 0 at the beginning of the list.
+
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Miles Chen <miles.chen@mediatek.com>
+Reviewed-by: Chen-Yu Tsai <wenst@chromium.org>
+Tested-by: Miles Chen <miles.chen@mediatek.com>
+Link: https://lore.kernel.org/r/20230120092053.182923-8-angelogioacchino.delregno@collabora.com
+Tested-by: Mingming Su <mingming.su@mediatek.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Stable-dep-of: 7c8746126a4e ("clk: mediatek: mt2701-vdec: fix conversion to mtk_clk_simple_probe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/mediatek/clk-mtk.c | 16 ++++++++++++++++
+ drivers/clk/mediatek/clk-mtk.h | 19 +++++++++++++++++++
+ 2 files changed, 35 insertions(+)
+
+diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
+index 9dbfc11d5c591..7b1ad73309b1a 100644
+--- a/drivers/clk/mediatek/clk-mtk.c
++++ b/drivers/clk/mediatek/clk-mtk.c
+@@ -21,6 +21,22 @@
+ #include "clk-gate.h"
+ #include "clk-mux.h"
+
++const struct mtk_gate_regs cg_regs_dummy = { 0, 0, 0 };
++EXPORT_SYMBOL_GPL(cg_regs_dummy);
++
++static int mtk_clk_dummy_enable(struct clk_hw *hw)
++{
++ return 0;
++}
++
++static void mtk_clk_dummy_disable(struct clk_hw *hw) { }
++
++const struct clk_ops mtk_clk_dummy_ops = {
++ .enable = mtk_clk_dummy_enable,
++ .disable = mtk_clk_dummy_disable,
++};
++EXPORT_SYMBOL_GPL(mtk_clk_dummy_ops);
++
+ static void mtk_init_clk_data(struct clk_hw_onecell_data *clk_data,
+ unsigned int clk_num)
+ {
+diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
+index 65c24ab6c9470..04f371730ee30 100644
+--- a/drivers/clk/mediatek/clk-mtk.h
++++ b/drivers/clk/mediatek/clk-mtk.h
+@@ -22,6 +22,25 @@
+
+ struct platform_device;
+
++/*
++ * We need the clock IDs to start from zero but to maintain devicetree
++ * backwards compatibility we can't change bindings to start from zero.
++ * Only a few platforms are affected, so we solve issues given by the
++ * commonized MTK clocks probe function(s) by adding a dummy clock at
++ * the beginning where needed.
++ */
++#define CLK_DUMMY 0
++
++extern const struct clk_ops mtk_clk_dummy_ops;
++extern const struct mtk_gate_regs cg_regs_dummy;
++
++#define GATE_DUMMY(_id, _name) { \
++ .id = _id, \
++ .name = _name, \
++ .regs = &cg_regs_dummy, \
++ .ops = &mtk_clk_dummy_ops, \
++ }
++
+ struct mtk_fixed_clk {
+ int id;
+ const char *name;
+--
+2.39.5
+
--- /dev/null
+From 0d1e18fb174011aaaaaeee44eef78e6b43014f09 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 15 Dec 2024 22:14:24 +0000
+Subject: clk: mediatek: mt2701-bdp: add missing dummy clk
+
+From: Daniel Golle <daniel@makrotopia.org>
+
+[ Upstream commit fd291adc5e9a4ee6cd91e57f148f3b427f80647b ]
+
+Add dummy clk for index 0 which was missed during the conversion to
+mtk_clk_simple_probe().
+
+Fixes: 973d1607d936 ("clk: mediatek: mt2701: use mtk_clk_simple_probe to simplify driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://lore.kernel.org/r/b8526c882a50f2b158df0eccb4a165956fd8fa13.1734300668.git.daniel@makrotopia.org
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/mediatek/clk-mt2701-bdp.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/clk/mediatek/clk-mt2701-bdp.c b/drivers/clk/mediatek/clk-mt2701-bdp.c
+index b0f0572079452..d2647ea58ae28 100644
+--- a/drivers/clk/mediatek/clk-mt2701-bdp.c
++++ b/drivers/clk/mediatek/clk-mt2701-bdp.c
+@@ -31,6 +31,7 @@ static const struct mtk_gate_regs bdp1_cg_regs = {
+ GATE_MTK(_id, _name, _parent, &bdp1_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv)
+
+ static const struct mtk_gate bdp_clks[] = {
++ GATE_DUMMY(CLK_DUMMY, "bdp_dummy"),
+ GATE_BDP0(CLK_BDP_BRG_BA, "brg_baclk", "mm_sel", 0),
+ GATE_BDP0(CLK_BDP_BRG_DRAM, "brg_dram", "mm_sel", 1),
+ GATE_BDP0(CLK_BDP_LARB_DRAM, "larb_dram", "mm_sel", 2),
+--
+2.39.5
+
--- /dev/null
+From 154a15763a2ccadb6d27fdfc94baf5fce961d528 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 15 Dec 2024 22:14:48 +0000
+Subject: clk: mediatek: mt2701-img: add missing dummy clk
+
+From: Daniel Golle <daniel@makrotopia.org>
+
+[ Upstream commit 366640868ccb4a7991aebe8442b01340fab218e2 ]
+
+Add dummy clk for index 0 which was missed during the conversion to
+mtk_clk_simple_probe().
+
+Fixes: 973d1607d936 ("clk: mediatek: mt2701: use mtk_clk_simple_probe to simplify driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://lore.kernel.org/r/d677486a5c563fe5c47aa995841adc2aaa183b8a.1734300668.git.daniel@makrotopia.org
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/mediatek/clk-mt2701-img.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/clk/mediatek/clk-mt2701-img.c b/drivers/clk/mediatek/clk-mt2701-img.c
+index eb172473f0755..569b6d3607dd6 100644
+--- a/drivers/clk/mediatek/clk-mt2701-img.c
++++ b/drivers/clk/mediatek/clk-mt2701-img.c
+@@ -22,6 +22,7 @@ static const struct mtk_gate_regs img_cg_regs = {
+ GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+ static const struct mtk_gate img_clks[] = {
++ GATE_DUMMY(CLK_DUMMY, "img_dummy"),
+ GATE_IMG(CLK_IMG_SMI_COMM, "img_smi_comm", "mm_sel", 0),
+ GATE_IMG(CLK_IMG_RESZ, "img_resz", "mm_sel", 1),
+ GATE_IMG(CLK_IMG_JPGDEC_SMI, "img_jpgdec_smi", "mm_sel", 5),
+--
+2.39.5
+
--- /dev/null
+From e3bc22d58df4ae25990159d3f13475d6177aaeac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 15 Dec 2024 22:13:49 +0000
+Subject: clk: mediatek: mt2701-vdec: fix conversion to mtk_clk_simple_probe
+
+From: Daniel Golle <daniel@makrotopia.org>
+
+[ Upstream commit 7c8746126a4e256fcf1af9174ee7d92cc3f3bc31 ]
+
+Commit 973d1607d936 ("clk: mediatek: mt2701: use mtk_clk_simple_probe to
+simplify driver") broke DT bindings as the highest index was reduced by
+1 because the id count starts from 1 and not from 0.
+
+Fix this, like for other drivers which had the same issue, by adding a
+dummy clk at index 0.
+
+Fixes: 973d1607d936 ("clk: mediatek: mt2701: use mtk_clk_simple_probe to simplify driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://lore.kernel.org/r/b126a5577f3667ef19b1b5feea5e70174084fb03.1734300668.git.daniel@makrotopia.org
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/mediatek/clk-mt2701-vdec.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/clk/mediatek/clk-mt2701-vdec.c b/drivers/clk/mediatek/clk-mt2701-vdec.c
+index 0f07c5d731df6..fdd2645c167f4 100644
+--- a/drivers/clk/mediatek/clk-mt2701-vdec.c
++++ b/drivers/clk/mediatek/clk-mt2701-vdec.c
+@@ -31,6 +31,7 @@ static const struct mtk_gate_regs vdec1_cg_regs = {
+ GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv)
+
+ static const struct mtk_gate vdec_clks[] = {
++ GATE_DUMMY(CLK_DUMMY, "vdec_dummy"),
+ GATE_VDEC0(CLK_VDEC_CKGEN, "vdec_cken", "vdec_sel", 0),
+ GATE_VDEC1(CLK_VDEC_LARB, "vdec_larb_cken", "mm_sel", 0),
+ };
+--
+2.39.5
+
--- /dev/null
+From 6d69f99e80267c379ce8725058eea6479313f7e7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 20:32:07 -0800
+Subject: flow_dissector: Fix handling of mixed port and port-range keys
+
+From: Cong Wang <xiyou.wangcong@gmail.com>
+
+[ Upstream commit 3e5796862c692ea608d96f0a1437f9290f44953a ]
+
+This patch fixes a bug in TC flower filter where rules combining a
+specific destination port with a source port range weren't working
+correctly.
+
+The specific case was when users tried to configure rules like:
+
+tc filter add dev ens38 ingress protocol ip flower ip_proto udp \
+dst_port 5000 src_port 2000-3000 action drop
+
+The root cause was in the flow dissector code. While both
+FLOW_DISSECTOR_KEY_PORTS and FLOW_DISSECTOR_KEY_PORTS_RANGE flags
+were being set correctly in the classifier, the __skb_flow_dissect_ports()
+function was only populating one of them: whichever came first in
+the enum check. This meant that when the code needed both a specific
+port and a port range, one of them would be left as 0, causing the
+filter to not match packets as expected.
+
+Fix it by removing the either/or logic and instead checking and
+populating both key types independently when they're in use.
+
+Fixes: 8ffb055beae5 ("cls_flower: Fix the behavior using port ranges with hw-offload")
+Reported-by: Qiang Zhang <dtzq01@gmail.com>
+Closes: https://lore.kernel.org/netdev/CAPx+-5uvFxkhkz4=j_Xuwkezjn9U6kzKTD5jz4tZ9msSJ0fOJA@mail.gmail.com/
+Cc: Yoshiki Komachi <komachi.yoshiki@gmail.com>
+Cc: Jamal Hadi Salim <jhs@mojatatu.com>
+Cc: Jiri Pirko <jiri@resnulli.us>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20250218043210.732959-2-xiyou.wangcong@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/flow_dissector.c | 31 +++++++++++++++++++------------
+ 1 file changed, 19 insertions(+), 12 deletions(-)
+
+diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
+index de17f13232381..41ad5c1cccf64 100644
+--- a/net/core/flow_dissector.c
++++ b/net/core/flow_dissector.c
+@@ -751,23 +751,30 @@ __skb_flow_dissect_ports(const struct sk_buff *skb,
+ void *target_container, const void *data,
+ int nhoff, u8 ip_proto, int hlen)
+ {
+- enum flow_dissector_key_id dissector_ports = FLOW_DISSECTOR_KEY_MAX;
+- struct flow_dissector_key_ports *key_ports;
++ struct flow_dissector_key_ports_range *key_ports_range = NULL;
++ struct flow_dissector_key_ports *key_ports = NULL;
++ __be32 ports;
+
+ if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_PORTS))
+- dissector_ports = FLOW_DISSECTOR_KEY_PORTS;
+- else if (dissector_uses_key(flow_dissector,
+- FLOW_DISSECTOR_KEY_PORTS_RANGE))
+- dissector_ports = FLOW_DISSECTOR_KEY_PORTS_RANGE;
++ key_ports = skb_flow_dissector_target(flow_dissector,
++ FLOW_DISSECTOR_KEY_PORTS,
++ target_container);
+
+- if (dissector_ports == FLOW_DISSECTOR_KEY_MAX)
++ if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_PORTS_RANGE))
++ key_ports_range = skb_flow_dissector_target(flow_dissector,
++ FLOW_DISSECTOR_KEY_PORTS_RANGE,
++ target_container);
++
++ if (!key_ports && !key_ports_range)
+ return;
+
+- key_ports = skb_flow_dissector_target(flow_dissector,
+- dissector_ports,
+- target_container);
+- key_ports->ports = __skb_flow_get_ports(skb, nhoff, ip_proto,
+- data, hlen);
++ ports = __skb_flow_get_ports(skb, nhoff, ip_proto, data, hlen);
++
++ if (key_ports)
++ key_ports->ports = ports;
++
++ if (key_ports_range)
++ key_ports_range->tp.ports = ports;
+ }
+
+ static void
+--
+2.39.5
+
--- /dev/null
+From 7d5f07e6a754a8ad5f5b00e3f1a94692c2fbcdfe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 20:32:09 -0800
+Subject: flow_dissector: Fix port range key handling in BPF conversion
+
+From: Cong Wang <xiyou.wangcong@gmail.com>
+
+[ Upstream commit 69ab34f705fbfabcace64b5d53bb7a4450fac875 ]
+
+Fix how port range keys are handled in __skb_flow_bpf_to_target() by:
+- Separating PORTS and PORTS_RANGE key handling
+- Using correct key_ports_range structure for range keys
+- Properly initializing both key types independently
+
+This ensures port range information is correctly stored in its dedicated
+structure rather than incorrectly using the regular ports key structure.
+
+Fixes: 59fb9b62fb6c ("flow_dissector: Fix to use new variables for port ranges in bpf hook")
+Reported-by: Qiang Zhang <dtzq01@gmail.com>
+Closes: https://lore.kernel.org/netdev/CAPx+-5uvFxkhkz4=j_Xuwkezjn9U6kzKTD5jz4tZ9msSJ0fOJA@mail.gmail.com/
+Cc: Yoshiki Komachi <komachi.yoshiki@gmail.com>
+Cc: Jamal Hadi Salim <jhs@mojatatu.com>
+Cc: Jiri Pirko <jiri@resnulli.us>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Link: https://patch.msgid.link/20250218043210.732959-4-xiyou.wangcong@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/flow_dissector.c | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
+index 41ad5c1cccf64..5f50e182acd57 100644
+--- a/net/core/flow_dissector.c
++++ b/net/core/flow_dissector.c
+@@ -829,6 +829,7 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys,
+ struct flow_dissector *flow_dissector,
+ void *target_container)
+ {
++ struct flow_dissector_key_ports_range *key_ports_range = NULL;
+ struct flow_dissector_key_ports *key_ports = NULL;
+ struct flow_dissector_key_control *key_control;
+ struct flow_dissector_key_basic *key_basic;
+@@ -873,20 +874,21 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys,
+ key_control->addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
+ }
+
+- if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_PORTS))
++ if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_PORTS)) {
+ key_ports = skb_flow_dissector_target(flow_dissector,
+ FLOW_DISSECTOR_KEY_PORTS,
+ target_container);
+- else if (dissector_uses_key(flow_dissector,
+- FLOW_DISSECTOR_KEY_PORTS_RANGE))
+- key_ports = skb_flow_dissector_target(flow_dissector,
+- FLOW_DISSECTOR_KEY_PORTS_RANGE,
+- target_container);
+-
+- if (key_ports) {
+ key_ports->src = flow_keys->sport;
+ key_ports->dst = flow_keys->dport;
+ }
++ if (dissector_uses_key(flow_dissector,
++ FLOW_DISSECTOR_KEY_PORTS_RANGE)) {
++ key_ports_range = skb_flow_dissector_target(flow_dissector,
++ FLOW_DISSECTOR_KEY_PORTS_RANGE,
++ target_container);
++ key_ports_range->tp.src = flow_keys->sport;
++ key_ports_range->tp.dst = flow_keys->dport;
++ }
+
+ if (dissector_uses_key(flow_dissector,
+ FLOW_DISSECTOR_KEY_FLOW_LABEL)) {
+--
+2.39.5
+
--- /dev/null
+From 2de96290858fa91bd9ecdd0bc599b2e2ad3184f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 13:33:54 +0900
+Subject: geneve: Fix use-after-free in geneve_find_dev().
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit 9593172d93b9f91c362baec4643003dc29802929 ]
+
+syzkaller reported a use-after-free in geneve_find_dev() [0]
+without repro.
+
+geneve_configure() links struct geneve_dev.next to
+net_generic(net, geneve_net_id)->geneve_list.
+
+The net here could differ from dev_net(dev) if IFLA_NET_NS_PID,
+IFLA_NET_NS_FD, or IFLA_TARGET_NETNSID is set.
+
+When dev_net(dev) is dismantled, geneve_exit_batch_rtnl() finally
+calls unregister_netdevice_queue() for each dev in the netns,
+and later the dev is freed.
+
+However, its geneve_dev.next is still linked to the backend UDP
+socket netns.
+
+Then, use-after-free will occur when another geneve dev is created
+in the netns.
+
+Let's call geneve_dellink() instead in geneve_destroy_tunnels().
+
+[0]:
+BUG: KASAN: slab-use-after-free in geneve_find_dev drivers/net/geneve.c:1295 [inline]
+BUG: KASAN: slab-use-after-free in geneve_configure+0x234/0x858 drivers/net/geneve.c:1343
+Read of size 2 at addr ffff000054d6ee24 by task syz.1.4029/13441
+
+CPU: 1 UID: 0 PID: 13441 Comm: syz.1.4029 Not tainted 6.13.0-g0ad9617c78ac #24 dc35ca22c79fb82e8e7bc5c9c9adafea898b1e3d
+Hardware name: linux,dummy-virt (DT)
+Call trace:
+ show_stack+0x38/0x50 arch/arm64/kernel/stacktrace.c:466 (C)
+ __dump_stack lib/dump_stack.c:94 [inline]
+ dump_stack_lvl+0xbc/0x108 lib/dump_stack.c:120
+ print_address_description mm/kasan/report.c:378 [inline]
+ print_report+0x16c/0x6f0 mm/kasan/report.c:489
+ kasan_report+0xc0/0x120 mm/kasan/report.c:602
+ __asan_report_load2_noabort+0x20/0x30 mm/kasan/report_generic.c:379
+ geneve_find_dev drivers/net/geneve.c:1295 [inline]
+ geneve_configure+0x234/0x858 drivers/net/geneve.c:1343
+ geneve_newlink+0xb8/0x128 drivers/net/geneve.c:1634
+ rtnl_newlink_create+0x23c/0x868 net/core/rtnetlink.c:3795
+ __rtnl_newlink net/core/rtnetlink.c:3906 [inline]
+ rtnl_newlink+0x1054/0x1630 net/core/rtnetlink.c:4021
+ rtnetlink_rcv_msg+0x61c/0x918 net/core/rtnetlink.c:6911
+ netlink_rcv_skb+0x1dc/0x398 net/netlink/af_netlink.c:2543
+ rtnetlink_rcv+0x34/0x50 net/core/rtnetlink.c:6938
+ netlink_unicast_kernel net/netlink/af_netlink.c:1322 [inline]
+ netlink_unicast+0x618/0x838 net/netlink/af_netlink.c:1348
+ netlink_sendmsg+0x5fc/0x8b0 net/netlink/af_netlink.c:1892
+ sock_sendmsg_nosec net/socket.c:713 [inline]
+ __sock_sendmsg net/socket.c:728 [inline]
+ ____sys_sendmsg+0x410/0x6f8 net/socket.c:2568
+ ___sys_sendmsg+0x178/0x1d8 net/socket.c:2622
+ __sys_sendmsg net/socket.c:2654 [inline]
+ __do_sys_sendmsg net/socket.c:2659 [inline]
+ __se_sys_sendmsg net/socket.c:2657 [inline]
+ __arm64_sys_sendmsg+0x12c/0x1c8 net/socket.c:2657
+ __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
+ invoke_syscall+0x90/0x278 arch/arm64/kernel/syscall.c:49
+ el0_svc_common+0x13c/0x250 arch/arm64/kernel/syscall.c:132
+ do_el0_svc+0x54/0x70 arch/arm64/kernel/syscall.c:151
+ el0_svc+0x4c/0xa8 arch/arm64/kernel/entry-common.c:744
+ el0t_64_sync_handler+0x78/0x108 arch/arm64/kernel/entry-common.c:762
+ el0t_64_sync+0x198/0x1a0 arch/arm64/kernel/entry.S:600
+
+Allocated by task 13247:
+ kasan_save_stack mm/kasan/common.c:47 [inline]
+ kasan_save_track+0x30/0x68 mm/kasan/common.c:68
+ kasan_save_alloc_info+0x44/0x58 mm/kasan/generic.c:568
+ poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
+ __kasan_kmalloc+0x84/0xa0 mm/kasan/common.c:394
+ kasan_kmalloc include/linux/kasan.h:260 [inline]
+ __do_kmalloc_node mm/slub.c:4298 [inline]
+ __kmalloc_node_noprof+0x2a0/0x560 mm/slub.c:4304
+ __kvmalloc_node_noprof+0x9c/0x230 mm/util.c:645
+ alloc_netdev_mqs+0xb8/0x11a0 net/core/dev.c:11470
+ rtnl_create_link+0x2b8/0xb50 net/core/rtnetlink.c:3604
+ rtnl_newlink_create+0x19c/0x868 net/core/rtnetlink.c:3780
+ __rtnl_newlink net/core/rtnetlink.c:3906 [inline]
+ rtnl_newlink+0x1054/0x1630 net/core/rtnetlink.c:4021
+ rtnetlink_rcv_msg+0x61c/0x918 net/core/rtnetlink.c:6911
+ netlink_rcv_skb+0x1dc/0x398 net/netlink/af_netlink.c:2543
+ rtnetlink_rcv+0x34/0x50 net/core/rtnetlink.c:6938
+ netlink_unicast_kernel net/netlink/af_netlink.c:1322 [inline]
+ netlink_unicast+0x618/0x838 net/netlink/af_netlink.c:1348
+ netlink_sendmsg+0x5fc/0x8b0 net/netlink/af_netlink.c:1892
+ sock_sendmsg_nosec net/socket.c:713 [inline]
+ __sock_sendmsg net/socket.c:728 [inline]
+ ____sys_sendmsg+0x410/0x6f8 net/socket.c:2568
+ ___sys_sendmsg+0x178/0x1d8 net/socket.c:2622
+ __sys_sendmsg net/socket.c:2654 [inline]
+ __do_sys_sendmsg net/socket.c:2659 [inline]
+ __se_sys_sendmsg net/socket.c:2657 [inline]
+ __arm64_sys_sendmsg+0x12c/0x1c8 net/socket.c:2657
+ __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
+ invoke_syscall+0x90/0x278 arch/arm64/kernel/syscall.c:49
+ el0_svc_common+0x13c/0x250 arch/arm64/kernel/syscall.c:132
+ do_el0_svc+0x54/0x70 arch/arm64/kernel/syscall.c:151
+ el0_svc+0x4c/0xa8 arch/arm64/kernel/entry-common.c:744
+ el0t_64_sync_handler+0x78/0x108 arch/arm64/kernel/entry-common.c:762
+ el0t_64_sync+0x198/0x1a0 arch/arm64/kernel/entry.S:600
+
+Freed by task 45:
+ kasan_save_stack mm/kasan/common.c:47 [inline]
+ kasan_save_track+0x30/0x68 mm/kasan/common.c:68
+ kasan_save_free_info+0x58/0x70 mm/kasan/generic.c:582
+ poison_slab_object mm/kasan/common.c:247 [inline]
+ __kasan_slab_free+0x48/0x68 mm/kasan/common.c:264
+ kasan_slab_free include/linux/kasan.h:233 [inline]
+ slab_free_hook mm/slub.c:2353 [inline]
+ slab_free mm/slub.c:4613 [inline]
+ kfree+0x140/0x420 mm/slub.c:4761
+ kvfree+0x4c/0x68 mm/util.c:688
+ netdev_release+0x94/0xc8 net/core/net-sysfs.c:2065
+ device_release+0x98/0x1c0
+ kobject_cleanup lib/kobject.c:689 [inline]
+ kobject_release lib/kobject.c:720 [inline]
+ kref_put include/linux/kref.h:65 [inline]
+ kobject_put+0x2b0/0x438 lib/kobject.c:737
+ netdev_run_todo+0xe5c/0xfc8 net/core/dev.c:11185
+ rtnl_unlock+0x20/0x38 net/core/rtnetlink.c:151
+ cleanup_net+0x4fc/0x8c0 net/core/net_namespace.c:648
+ process_one_work+0x700/0x1398 kernel/workqueue.c:3236
+ process_scheduled_works kernel/workqueue.c:3317 [inline]
+ worker_thread+0x8c4/0xe10 kernel/workqueue.c:3398
+ kthread+0x4bc/0x608 kernel/kthread.c:464
+ ret_from_fork+0x10/0x20 arch/arm64/kernel/entry.S:862
+
+The buggy address belongs to the object at ffff000054d6e000
+ which belongs to the cache kmalloc-cg-4k of size 4096
+The buggy address is located 3620 bytes inside of
+ freed 4096-byte region [ffff000054d6e000, ffff000054d6f000)
+
+The buggy address belongs to the physical page:
+page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x94d68
+head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
+memcg:ffff000016276181
+flags: 0x3fffe0000000040(head|node=0|zone=0|lastcpupid=0x1ffff)
+page_type: f5(slab)
+raw: 03fffe0000000040 ffff0000c000f500 dead000000000122 0000000000000000
+raw: 0000000000000000 0000000000040004 00000001f5000000 ffff000016276181
+head: 03fffe0000000040 ffff0000c000f500 dead000000000122 0000000000000000
+head: 0000000000000000 0000000000040004 00000001f5000000 ffff000016276181
+head: 03fffe0000000003 fffffdffc1535a01 ffffffffffffffff 0000000000000000
+head: 0000000000000008 0000000000000000 00000000ffffffff 0000000000000000
+page dumped because: kasan: bad access detected
+
+Memory state around the buggy address:
+ ffff000054d6ed00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+ ffff000054d6ed80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+>ffff000054d6ee00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+ ^
+ ffff000054d6ee80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+ ffff000054d6ef00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+
+Fixes: 2d07dc79fe04 ("geneve: add initial netdev driver for GENEVE tunnels")
+Reported-by: syzkaller <syzkaller@googlegroups.com>
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Link: https://patch.msgid.link/20250213043354.91368-1-kuniyu@amazon.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/geneve.c | 11 +++--------
+ 1 file changed, 3 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
+index 27b570678c9fc..15b85eb3daa19 100644
+--- a/drivers/net/geneve.c
++++ b/drivers/net/geneve.c
+@@ -1970,16 +1970,11 @@ static void geneve_destroy_tunnels(struct net *net, struct list_head *head)
+ /* gather any geneve devices that were moved into this ns */
+ for_each_netdev_safe(net, dev, aux)
+ if (dev->rtnl_link_ops == &geneve_link_ops)
+- unregister_netdevice_queue(dev, head);
++ geneve_dellink(dev, head);
+
+ /* now gather any other geneve devices that were created in this ns */
+- list_for_each_entry_safe(geneve, next, &gn->geneve_list, next) {
+- /* If geneve->dev is in the same netns, it was already added
+- * to the list by the previous loop.
+- */
+- if (!net_eq(dev_net(geneve->dev), net))
+- unregister_netdevice_queue(geneve->dev, head);
+- }
++ list_for_each_entry_safe(geneve, next, &gn->geneve_list, next)
++ geneve_dellink(geneve->dev, head);
+ }
+
+ static void __net_exit geneve_exit_batch_net(struct list_head *net_list)
+--
+2.39.5
+
--- /dev/null
+From a3a048b54825ebdc3b0eb08467bb7311d6ee0f39 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 12:37:05 -0800
+Subject: geneve: Suppress list corruption splat in geneve_destroy_tunnels().
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit 62fab6eef61f245dc8797e3a6a5b890ef40e8628 ]
+
+As explained in the previous patch, iterating for_each_netdev() and
+gn->geneve_list during ->exit_batch_rtnl() could trigger ->dellink()
+twice for the same device.
+
+If CONFIG_DEBUG_LIST is enabled, we will see a list_del() corruption
+splat in the 2nd call of geneve_dellink().
+
+Let's remove for_each_netdev() in geneve_destroy_tunnels() and delegate
+that part to default_device_exit_batch().
+
+Fixes: 9593172d93b9 ("geneve: Fix use-after-free in geneve_find_dev().")
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Link: https://patch.msgid.link/20250217203705.40342-3-kuniyu@amazon.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/geneve.c | 7 -------
+ 1 file changed, 7 deletions(-)
+
+diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
+index 15b85eb3daa19..3dd5c69b05cb7 100644
+--- a/drivers/net/geneve.c
++++ b/drivers/net/geneve.c
+@@ -1965,14 +1965,7 @@ static void geneve_destroy_tunnels(struct net *net, struct list_head *head)
+ {
+ struct geneve_net *gn = net_generic(net, geneve_net_id);
+ struct geneve_dev *geneve, *next;
+- struct net_device *dev, *aux;
+
+- /* gather any geneve devices that were moved into this ns */
+- for_each_netdev_safe(net, dev, aux)
+- if (dev->rtnl_link_ops == &geneve_link_ops)
+- geneve_dellink(dev, head);
+-
+- /* now gather any other geneve devices that were created in this ns */
+ list_for_each_entry_safe(geneve, next, &gn->geneve_list, next)
+ geneve_dellink(geneve->dev, head);
+ }
+--
+2.39.5
+
--- /dev/null
+From 9081e0afc51bffa3e8b6d882a3dc43e31f46694a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 12:37:04 -0800
+Subject: gtp: Suppress list corruption splat in gtp_net_exit_batch_rtnl().
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit 4ccacf86491d33d2486b62d4d44864d7101b299d ]
+
+Brad Spengler reported the list_del() corruption splat in
+gtp_net_exit_batch_rtnl(). [0]
+
+Commit eb28fd76c0a0 ("gtp: Destroy device along with udp socket's netns
+dismantle.") added the for_each_netdev() loop in gtp_net_exit_batch_rtnl()
+to destroy devices in each netns as done in geneve and ip tunnels.
+
+However, this could trigger ->dellink() twice for the same device during
+->exit_batch_rtnl().
+
+Say we have two netns A & B and gtp device B that resides in netns B but
+whose UDP socket is in netns A.
+
+ 1. cleanup_net() processes netns A and then B.
+
+ 2. gtp_net_exit_batch_rtnl() finds the device B while iterating
+ netns A's gn->gtp_dev_list and calls ->dellink().
+
+ [ device B is not yet unlinked from netns B
+ as unregister_netdevice_many() has not been called. ]
+
+ 3. gtp_net_exit_batch_rtnl() finds the device B while iterating
+ netns B's for_each_netdev() and calls ->dellink().
+
+gtp_dellink() cleans up the device's hash table, unlinks the dev from
+gn->gtp_dev_list, and calls unregister_netdevice_queue().
+
+Basically, calling gtp_dellink() multiple times is fine unless
+CONFIG_DEBUG_LIST is enabled.
+
+Let's remove for_each_netdev() in gtp_net_exit_batch_rtnl() and
+delegate the destruction to default_device_exit_batch() as done
+in bareudp.
+
+[0]:
+list_del corruption, ffff8880aaa62c00->next (autoslab_size_M_dev_P_net_core_dev_11127_8_1328_8_S_4096_A_64_n_139+0xc00/0x1000 [slab object]) is LIST_POISON1 (ffffffffffffff02) (prev is 0xffffffffffffff04)
+kernel BUG at lib/list_debug.c:58!
+Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN
+CPU: 1 UID: 0 PID: 1804 Comm: kworker/u8:7 Tainted: G T 6.12.13-grsec-full-20250211091339 #1
+Tainted: [T]=RANDSTRUCT
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
+Workqueue: netns cleanup_net
+RIP: 0010:[<ffffffff84947381>] __list_del_entry_valid_or_report+0x141/0x200 lib/list_debug.c:58
+Code: c2 76 91 31 c0 e8 9f b1 f7 fc 0f 0b 4d 89 f0 48 c7 c1 02 ff ff ff 48 89 ea 48 89 ee 48 c7 c7 e0 c2 76 91 31 c0 e8 7f b1 f7 fc <0f> 0b 4d 89 e8 48 c7 c1 04 ff ff ff 48 89 ea 48 89 ee 48 c7 c7 60
+RSP: 0018:fffffe8040b4fbd0 EFLAGS: 00010283
+RAX: 00000000000000cc RBX: dffffc0000000000 RCX: ffffffff818c4054
+RDX: ffffffff84947381 RSI: ffffffff818d1512 RDI: 0000000000000000
+RBP: ffff8880aaa62c00 R08: 0000000000000001 R09: fffffbd008169f32
+R10: fffffe8040b4f997 R11: 0000000000000001 R12: a1988d84f24943e4
+R13: ffffffffffffff02 R14: ffffffffffffff04 R15: ffff8880aaa62c08
+RBX: kasan shadow of 0x0
+RCX: __wake_up_klogd.part.0+0x74/0xe0 kernel/printk/printk.c:4554
+RDX: __list_del_entry_valid_or_report+0x141/0x200 lib/list_debug.c:58
+RSI: vprintk+0x72/0x100 kernel/printk/printk_safe.c:71
+RBP: autoslab_size_M_dev_P_net_core_dev_11127_8_1328_8_S_4096_A_64_n_139+0xc00/0x1000 [slab object]
+RSP: process kstack fffffe8040b4fbd0+0x7bd0/0x8000 [kworker/u8:7+netns 1804 ]
+R09: kasan shadow of process kstack fffffe8040b4f990+0x7990/0x8000 [kworker/u8:7+netns 1804 ]
+R10: process kstack fffffe8040b4f997+0x7997/0x8000 [kworker/u8:7+netns 1804 ]
+R15: autoslab_size_M_dev_P_net_core_dev_11127_8_1328_8_S_4096_A_64_n_139+0xc08/0x1000 [slab object]
+FS: 0000000000000000(0000) GS:ffff888116000000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 0000748f5372c000 CR3: 0000000015408000 CR4: 00000000003406f0 shadow CR4: 00000000003406f0
+Stack:
+ 0000000000000000 ffffffff8a0c35e7 ffffffff8a0c3603 ffff8880aaa62c00
+ ffff8880aaa62c00 0000000000000004 ffff88811145311c 0000000000000005
+ 0000000000000001 ffff8880aaa62000 fffffe8040b4fd40 ffffffff8a0c360d
+Call Trace:
+ <TASK>
+ [<ffffffff8a0c360d>] __list_del_entry_valid include/linux/list.h:131 [inline] fffffe8040b4fc28
+ [<ffffffff8a0c360d>] __list_del_entry include/linux/list.h:248 [inline] fffffe8040b4fc28
+ [<ffffffff8a0c360d>] list_del include/linux/list.h:262 [inline] fffffe8040b4fc28
+ [<ffffffff8a0c360d>] gtp_dellink+0x16d/0x360 drivers/net/gtp.c:1557 fffffe8040b4fc28
+ [<ffffffff8a0d0404>] gtp_net_exit_batch_rtnl+0x124/0x2c0 drivers/net/gtp.c:2495 fffffe8040b4fc88
+ [<ffffffff8e705b24>] cleanup_net+0x5a4/0xbe0 net/core/net_namespace.c:635 fffffe8040b4fcd0
+ [<ffffffff81754c97>] process_one_work+0xbd7/0x2160 kernel/workqueue.c:3326 fffffe8040b4fd88
+ [<ffffffff81757195>] process_scheduled_works kernel/workqueue.c:3407 [inline] fffffe8040b4fec0
+ [<ffffffff81757195>] worker_thread+0x6b5/0xfa0 kernel/workqueue.c:3488 fffffe8040b4fec0
+ [<ffffffff817782a0>] kthread+0x360/0x4c0 kernel/kthread.c:397 fffffe8040b4ff78
+ [<ffffffff814d8594>] ret_from_fork+0x74/0xe0 arch/x86/kernel/process.c:172 fffffe8040b4ffb8
+ [<ffffffff8110f509>] ret_from_fork_asm+0x29/0xc0 arch/x86/entry/entry_64.S:399 fffffe8040b4ffe8
+ </TASK>
+Modules linked in:
+
+Fixes: eb28fd76c0a0 ("gtp: Destroy device along with udp socket's netns dismantle.")
+Reported-by: Brad Spengler <spender@grsecurity.net>
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Link: https://patch.msgid.link/20250217203705.40342-2-kuniyu@amazon.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/gtp.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
+index 0de3dcd07cb7e..797886f10868a 100644
+--- a/drivers/net/gtp.c
++++ b/drivers/net/gtp.c
+@@ -1894,11 +1894,6 @@ static void __net_exit gtp_net_exit_batch_rtnl(struct list_head *net_list,
+ list_for_each_entry(net, net_list, exit_list) {
+ struct gtp_net *gn = net_generic(net, gtp_net_id);
+ struct gtp_dev *gtp, *gtp_next;
+- struct net_device *dev;
+-
+- for_each_netdev(net, dev)
+- if (dev->rtnl_link_ops == >p_link_ops)
+- gtp_dellink(dev, dev_to_kill);
+
+ list_for_each_entry_safe(gtp, gtp_next, &gn->gtp_dev_list, list)
+ gtp_dellink(gtp->dev, dev_to_kill);
+--
+2.39.5
+
--- /dev/null
+From 4126b45648d76f8631f58f83208638ba8498e6cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Oct 2024 11:35:31 -0500
+Subject: ibmvnic: Add stat for tx direct vs tx batched
+
+From: Nick Child <nnac123@linux.ibm.com>
+
+[ Upstream commit 2ee73c54a615b74d2e7ee6f20844fd3ba63fc485 ]
+
+Allow tracking of packets sent with send_subcrq direct vs
+indirect. `ethtool -S <dev>` will now provide a counter
+of the number of uses of each xmit method. This metric will
+be useful in performance debugging.
+
+Signed-off-by: Nick Child <nnac123@linux.ibm.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20241001163531.1803152-1-nnac123@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: bdf5d13aa05e ("ibmvnic: Don't reference skb after sending to VIOS")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 23 ++++++++++++++++-------
+ drivers/net/ethernet/ibm/ibmvnic.h | 3 ++-
+ 2 files changed, 18 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 0b06fcd2d0f40..b83877cafaf7f 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -2136,7 +2136,7 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter,
+ tx_buff = &tx_pool->tx_buff[index];
+ adapter->netdev->stats.tx_packets--;
+ adapter->netdev->stats.tx_bytes -= tx_buff->skb->len;
+- adapter->tx_stats_buffers[queue_num].packets--;
++ adapter->tx_stats_buffers[queue_num].batched_packets--;
+ adapter->tx_stats_buffers[queue_num].bytes -=
+ tx_buff->skb->len;
+ dev_kfree_skb_any(tx_buff->skb);
+@@ -2228,7 +2228,8 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ unsigned int tx_map_failed = 0;
+ union sub_crq indir_arr[16];
+ unsigned int tx_dropped = 0;
+- unsigned int tx_packets = 0;
++ unsigned int tx_dpackets = 0;
++ unsigned int tx_bpackets = 0;
+ unsigned int tx_bytes = 0;
+ dma_addr_t data_dma_addr;
+ struct netdev_queue *txq;
+@@ -2387,6 +2388,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ if (lpar_rc != H_SUCCESS)
+ goto tx_err;
+
++ tx_dpackets++;
+ goto early_exit;
+ }
+
+@@ -2415,6 +2417,8 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ goto tx_err;
+ }
+
++ tx_bpackets++;
++
+ early_exit:
+ if (atomic_add_return(num_entries, &tx_scrq->used)
+ >= adapter->req_tx_entries_per_subcrq) {
+@@ -2422,7 +2426,6 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ netif_stop_subqueue(netdev, queue_num);
+ }
+
+- tx_packets++;
+ tx_bytes += skb->len;
+ txq_trans_cond_update(txq);
+ ret = NETDEV_TX_OK;
+@@ -2452,10 +2455,11 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ rcu_read_unlock();
+ netdev->stats.tx_dropped += tx_dropped;
+ netdev->stats.tx_bytes += tx_bytes;
+- netdev->stats.tx_packets += tx_packets;
++ netdev->stats.tx_packets += tx_bpackets + tx_dpackets;
+ adapter->tx_send_failed += tx_send_failed;
+ adapter->tx_map_failed += tx_map_failed;
+- adapter->tx_stats_buffers[queue_num].packets += tx_packets;
++ adapter->tx_stats_buffers[queue_num].batched_packets += tx_bpackets;
++ adapter->tx_stats_buffers[queue_num].direct_packets += tx_dpackets;
+ adapter->tx_stats_buffers[queue_num].bytes += tx_bytes;
+ adapter->tx_stats_buffers[queue_num].dropped_packets += tx_dropped;
+
+@@ -3621,7 +3625,10 @@ static void ibmvnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+ memcpy(data, ibmvnic_stats[i].name, ETH_GSTRING_LEN);
+
+ for (i = 0; i < adapter->req_tx_queues; i++) {
+- snprintf(data, ETH_GSTRING_LEN, "tx%d_packets", i);
++ snprintf(data, ETH_GSTRING_LEN, "tx%d_batched_packets", i);
++ data += ETH_GSTRING_LEN;
++
++ snprintf(data, ETH_GSTRING_LEN, "tx%d_direct_packets", i);
+ data += ETH_GSTRING_LEN;
+
+ snprintf(data, ETH_GSTRING_LEN, "tx%d_bytes", i);
+@@ -3686,7 +3693,9 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,
+ (adapter, ibmvnic_stats[i].offset));
+
+ for (j = 0; j < adapter->req_tx_queues; j++) {
+- data[i] = adapter->tx_stats_buffers[j].packets;
++ data[i] = adapter->tx_stats_buffers[j].batched_packets;
++ i++;
++ data[i] = adapter->tx_stats_buffers[j].direct_packets;
+ i++;
+ data[i] = adapter->tx_stats_buffers[j].bytes;
+ i++;
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h
+index e5c6ff3d0c472..f923cdab03f57 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.h
++++ b/drivers/net/ethernet/ibm/ibmvnic.h
+@@ -213,7 +213,8 @@ struct ibmvnic_statistics {
+
+ #define NUM_TX_STATS 3
+ struct ibmvnic_tx_queue_stats {
+- u64 packets;
++ u64 batched_packets;
++ u64 direct_packets;
+ u64 bytes;
+ u64 dropped_packets;
+ };
+--
+2.39.5
+
--- /dev/null
+From 37393be80ca15331f90ea48a5e2783f96abd1a60 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Feb 2025 09:52:33 -0600
+Subject: ibmvnic: Don't reference skb after sending to VIOS
+
+From: Nick Child <nnac123@linux.ibm.com>
+
+[ Upstream commit bdf5d13aa05ec314d4385b31ac974d6c7e0997c9 ]
+
+Previously, after successfully flushing the xmit buffer to VIOS,
+the tx_bytes stat was incremented by the length of the skb.
+
+It is invalid to access the skb memory after sending the buffer to
+the VIOS because, at any point after sending, the VIOS can trigger
+an interrupt to free this memory. A race between reading skb->len
+and freeing the skb is possible (especially during LPM) and will
+result in use-after-free:
+ ==================================================================
+ BUG: KASAN: slab-use-after-free in ibmvnic_xmit+0x75c/0x1808 [ibmvnic]
+ Read of size 4 at addr c00000024eb48a70 by task hxecom/14495
+ <...>
+ Call Trace:
+ [c000000118f66cf0] [c0000000018cba6c] dump_stack_lvl+0x84/0xe8 (unreliable)
+ [c000000118f66d20] [c0000000006f0080] print_report+0x1a8/0x7f0
+ [c000000118f66df0] [c0000000006f08f0] kasan_report+0x128/0x1f8
+ [c000000118f66f00] [c0000000006f2868] __asan_load4+0xac/0xe0
+ [c000000118f66f20] [c0080000046eac84] ibmvnic_xmit+0x75c/0x1808 [ibmvnic]
+ [c000000118f67340] [c0000000014be168] dev_hard_start_xmit+0x150/0x358
+ <...>
+ Freed by task 0:
+ kasan_save_stack+0x34/0x68
+ kasan_save_track+0x2c/0x50
+ kasan_save_free_info+0x64/0x108
+ __kasan_mempool_poison_object+0x148/0x2d4
+ napi_skb_cache_put+0x5c/0x194
+ net_tx_action+0x154/0x5b8
+ handle_softirqs+0x20c/0x60c
+ do_softirq_own_stack+0x6c/0x88
+ <...>
+ The buggy address belongs to the object at c00000024eb48a00 which
+ belongs to the cache skbuff_head_cache of size 224
+==================================================================
+
+Fixes: 032c5e82847a ("Driver for IBM System i/p VNIC protocol")
+Signed-off-by: Nick Child <nnac123@linux.ibm.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20250214155233.235559-1-nnac123@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index b83877cafaf7f..44991cae94045 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -2234,6 +2234,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ dma_addr_t data_dma_addr;
+ struct netdev_queue *txq;
+ unsigned long lpar_rc;
++ unsigned int skblen;
+ union sub_crq tx_crq;
+ unsigned int offset;
+ int num_entries = 1;
+@@ -2336,6 +2337,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ tx_buff->skb = skb;
+ tx_buff->index = bufidx;
+ tx_buff->pool_index = queue_num;
++ skblen = skb->len;
+
+ memset(&tx_crq, 0, sizeof(tx_crq));
+ tx_crq.v1.first = IBMVNIC_CRQ_CMD;
+@@ -2426,7 +2428,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ netif_stop_subqueue(netdev, queue_num);
+ }
+
+- tx_bytes += skb->len;
++ tx_bytes += skblen;
+ txq_trans_cond_update(txq);
+ ret = NETDEV_TX_OK;
+ goto out;
+--
+2.39.5
+
--- /dev/null
+From 0f1e4f0b66b6818dea0aaf9c850f8d2afa20d6ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 16:18:07 -0500
+Subject: ibmvnic: Introduce send sub-crq direct
+
+From: Nick Child <nnac123@linux.ibm.com>
+
+[ Upstream commit 74839f7a82689bf5a21a5447cae8e3a7b7a606d2 ]
+
+Firmware supports two hcalls to send a sub-crq request:
+H_SEND_SUB_CRQ_INDIRECT and H_SEND_SUB_CRQ. The indirect hcall allows
+for submission of batched messages while the other hcall is limited to
+only one message. This protocol is defined in PAPR section 17.2.3.3.
+
+Previously, the ibmvnic xmit function only used the indirect hcall. This
+allowed the driver to batch it's skbs. A single skb can occupy a few
+entries per hcall depending on if FW requires skb header information or
+not. The FW only needs header information if the packet is segmented.
+
+By this logic, if an skb is not GSO then it can fit in one sub-crq
+message and therefore is a candidate for H_SEND_SUB_CRQ.
+Batching skb transmission is only useful when there are more packets
+coming down the line (ie netdev_xmit_more is true).
+
+As it turns out, H_SEND_SUB_CRQ induces less latency than
+H_SEND_SUB_CRQ_INDIRECT. Therefore, use H_SEND_SUB_CRQ where
+appropriate.
+
+Small latency gains seen when doing TCP_RR_150 (request/response
+workload). Ftrace results (graph-time=1):
+ Previous:
+ ibmvnic_xmit = 29618270.83 us / 8860058.0 hits = AVG 3.34
+ ibmvnic_tx_scrq_flush = 21972231.02 us / 6553972.0 hits = AVG 3.35
+ Now:
+ ibmvnic_xmit = 22153350.96 us / 8438942.0 hits = AVG 2.63
+ ibmvnic_tx_scrq_flush = 15858922.4 us / 6244076.0 hits = AVG 2.54
+
+Signed-off-by: Nick Child <nnac123@linux.ibm.com>
+Link: https://patch.msgid.link/20240807211809.1259563-6-nnac123@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: bdf5d13aa05e ("ibmvnic: Don't reference skb after sending to VIOS")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 52 ++++++++++++++++++++++++++----
+ 1 file changed, 46 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 7fe1fefef9934..0b06fcd2d0f40 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -116,6 +116,7 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter,
+ struct ibmvnic_long_term_buff *ltb);
+ static void ibmvnic_disable_irqs(struct ibmvnic_adapter *adapter);
+ static void flush_reset_queue(struct ibmvnic_adapter *adapter);
++static void print_subcrq_error(struct device *dev, int rc, const char *func);
+
+ struct ibmvnic_stat {
+ char name[ETH_GSTRING_LEN];
+@@ -2160,8 +2161,29 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter,
+ }
+ }
+
++static int send_subcrq_direct(struct ibmvnic_adapter *adapter,
++ u64 remote_handle, u64 *entry)
++{
++ unsigned int ua = adapter->vdev->unit_address;
++ struct device *dev = &adapter->vdev->dev;
++ int rc;
++
++ /* Make sure the hypervisor sees the complete request */
++ dma_wmb();
++ rc = plpar_hcall_norets(H_SEND_SUB_CRQ, ua,
++ cpu_to_be64(remote_handle),
++ cpu_to_be64(entry[0]), cpu_to_be64(entry[1]),
++ cpu_to_be64(entry[2]), cpu_to_be64(entry[3]));
++
++ if (rc)
++ print_subcrq_error(dev, rc, __func__);
++
++ return rc;
++}
++
+ static int ibmvnic_tx_scrq_flush(struct ibmvnic_adapter *adapter,
+- struct ibmvnic_sub_crq_queue *tx_scrq)
++ struct ibmvnic_sub_crq_queue *tx_scrq,
++ bool indirect)
+ {
+ struct ibmvnic_ind_xmit_queue *ind_bufp;
+ u64 dma_addr;
+@@ -2176,7 +2198,13 @@ static int ibmvnic_tx_scrq_flush(struct ibmvnic_adapter *adapter,
+
+ if (!entries)
+ return 0;
+- rc = send_subcrq_indirect(adapter, handle, dma_addr, entries);
++
++ if (indirect)
++ rc = send_subcrq_indirect(adapter, handle, dma_addr, entries);
++ else
++ rc = send_subcrq_direct(adapter, handle,
++ (u64 *)ind_bufp->indir_arr);
++
+ if (rc)
+ ibmvnic_tx_scrq_clean_buffer(adapter, tx_scrq);
+ else
+@@ -2234,7 +2262,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ tx_dropped++;
+ tx_send_failed++;
+ ret = NETDEV_TX_OK;
+- lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq);
++ lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, true);
+ if (lpar_rc != H_SUCCESS)
+ goto tx_err;
+ goto out;
+@@ -2252,7 +2280,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ tx_send_failed++;
+ tx_dropped++;
+ ret = NETDEV_TX_OK;
+- lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq);
++ lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, true);
+ if (lpar_rc != H_SUCCESS)
+ goto tx_err;
+ goto out;
+@@ -2350,6 +2378,16 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ tx_crq.v1.flags1 |= IBMVNIC_TX_LSO;
+ tx_crq.v1.mss = cpu_to_be16(skb_shinfo(skb)->gso_size);
+ hdrs += 2;
++ } else if (!ind_bufp->index && !netdev_xmit_more()) {
++ ind_bufp->indir_arr[0] = tx_crq;
++ ind_bufp->index = 1;
++ tx_buff->num_entries = 1;
++ netdev_tx_sent_queue(txq, skb->len);
++ lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, false);
++ if (lpar_rc != H_SUCCESS)
++ goto tx_err;
++
++ goto early_exit;
+ }
+
+ if ((*hdrs >> 7) & 1)
+@@ -2359,7 +2397,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ tx_buff->num_entries = num_entries;
+ /* flush buffer if current entry can not fit */
+ if (num_entries + ind_bufp->index > IBMVNIC_MAX_IND_DESCS) {
+- lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq);
++ lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, true);
+ if (lpar_rc != H_SUCCESS)
+ goto tx_flush_err;
+ }
+@@ -2367,15 +2405,17 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ indir_arr[0] = tx_crq;
+ memcpy(&ind_bufp->indir_arr[ind_bufp->index], &indir_arr[0],
+ num_entries * sizeof(struct ibmvnic_generic_scrq));
++
+ ind_bufp->index += num_entries;
+ if (__netdev_tx_sent_queue(txq, skb->len,
+ netdev_xmit_more() &&
+ ind_bufp->index < IBMVNIC_MAX_IND_DESCS)) {
+- lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq);
++ lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, true);
+ if (lpar_rc != H_SUCCESS)
+ goto tx_err;
+ }
+
++early_exit:
+ if (atomic_add_return(num_entries, &tx_scrq->used)
+ >= adapter->req_tx_entries_per_subcrq) {
+ netdev_dbg(netdev, "Stopping queue %d\n", queue_num);
+--
+2.39.5
+
--- /dev/null
+From 6fe1eb78b481382090dd8b44609a90174898483d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Apr 2024 11:41:28 -0500
+Subject: ibmvnic: Return error code on TX scrq flush fail
+
+From: Nick Child <nnac123@linux.ibm.com>
+
+[ Upstream commit 5cb431dcf8048572e9ffc6c30cdbd8832cbe502d ]
+
+In ibmvnic_xmit() if ibmvnic_tx_scrq_flush() returns H_CLOSED then
+it will inform upper level networking functions to disable tx
+queues. H_CLOSED signals that the connection with the vnic server is
+down and a transport event is expected to recover the device.
+
+Previously, ibmvnic_tx_scrq_flush() was hard-coded to return success.
+Therefore, the queues would remain active until ibmvnic_cleanup() is
+called within do_reset().
+
+The problem is that do_reset() depends on the RTNL lock. If several
+ibmvnic devices are resetting then there can be a long wait time until
+the last device can grab the lock. During this time the tx/rx queues
+still appear active to upper level functions.
+
+FYI, we do make a call to netif_carrier_off() outside the RTNL lock but
+its calls to dev_deactivate() are also dependent on the RTNL lock.
+
+As a result, large amounts of retransmissions were observed in a short
+period of time, eventually leading to ETIMEOUT. This was specifically
+seen with HNV devices, likely because of even more RTNL dependencies.
+
+Therefore, ensure the return code of ibmvnic_tx_scrq_flush() is
+propagated to the xmit function to allow for an earlier (and lock-less)
+response to a transport event.
+
+Signed-off-by: Nick Child <nnac123@linux.ibm.com>
+Link: https://lore.kernel.org/r/20240416164128.387920-1-nnac123@linux.ibm.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: bdf5d13aa05e ("ibmvnic: Don't reference skb after sending to VIOS")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 6d17738c1c536..7fe1fefef9934 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -2181,7 +2181,7 @@ static int ibmvnic_tx_scrq_flush(struct ibmvnic_adapter *adapter,
+ ibmvnic_tx_scrq_clean_buffer(adapter, tx_scrq);
+ else
+ ind_bufp->index = 0;
+- return 0;
++ return rc;
+ }
+
+ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+@@ -2234,7 +2234,9 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ tx_dropped++;
+ tx_send_failed++;
+ ret = NETDEV_TX_OK;
+- ibmvnic_tx_scrq_flush(adapter, tx_scrq);
++ lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq);
++ if (lpar_rc != H_SUCCESS)
++ goto tx_err;
+ goto out;
+ }
+
+@@ -2249,8 +2251,10 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ dev_kfree_skb_any(skb);
+ tx_send_failed++;
+ tx_dropped++;
+- ibmvnic_tx_scrq_flush(adapter, tx_scrq);
+ ret = NETDEV_TX_OK;
++ lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq);
++ if (lpar_rc != H_SUCCESS)
++ goto tx_err;
+ goto out;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 15dee1c356175330d3f60d2cf3ab62b39be88ab7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Sep 2023 14:12:40 +0800
+Subject: md: factor out a helper from mddev_put()
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+[ Upstream commit 3d8d32873c7b6d9cec5b40c2ddb8c7c55961694f ]
+
+There are no functional changes, prepare to simplify md_seq_ops in next
+patch.
+
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20230927061241.1552837-2-yukuai1@huaweicloud.com
+Stable-dep-of: 8d28d0ddb986 ("md/md-bitmap: Synchronize bitmap_get_stats() with bitmap lifetime")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/md.c | 29 +++++++++++++++++------------
+ 1 file changed, 17 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 4b629b7a540f7..44bac1e7d47e2 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -667,23 +667,28 @@ static inline struct mddev *mddev_get(struct mddev *mddev)
+
+ static void mddev_delayed_delete(struct work_struct *ws);
+
++static void __mddev_put(struct mddev *mddev)
++{
++ if (mddev->raid_disks || !list_empty(&mddev->disks) ||
++ mddev->ctime || mddev->hold_active)
++ return;
++
++ /* Array is not configured at all, and not held active, so destroy it */
++ set_bit(MD_DELETED, &mddev->flags);
++
++ /*
++ * Call queue_work inside the spinlock so that flush_workqueue() after
++ * mddev_find will succeed in waiting for the work to be done.
++ */
++ queue_work(md_misc_wq, &mddev->del_work);
++}
++
+ void mddev_put(struct mddev *mddev)
+ {
+ if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock))
+ return;
+- if (!mddev->raid_disks && list_empty(&mddev->disks) &&
+- mddev->ctime == 0 && !mddev->hold_active) {
+- /* Array is not configured at all, and not held active,
+- * so destroy it */
+- set_bit(MD_DELETED, &mddev->flags);
+
+- /*
+- * Call queue_work inside the spinlock so that
+- * flush_workqueue() after mddev_find will succeed in waiting
+- * for the work to be done.
+- */
+- queue_work(md_misc_wq, &mddev->del_work);
+- }
++ __mddev_put(mddev);
+ spin_unlock(&all_mddevs_lock);
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 9b3c7346884615ef560dc646c4242e9345e6cebe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Aug 2024 15:44:16 +0800
+Subject: md/md-bitmap: add 'sync_size' into struct md_bitmap_stats
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+[ Upstream commit ec6bb299c7c3dd4ca1724d13d5f5fae3ee54fc65 ]
+
+To avoid dereferencing bitmap directly in md-cluster to prepare
+inventing a new bitmap.
+
+BTW, also fix following checkpatch warnings:
+
+WARNING: Deprecated use of 'kmap_atomic', prefer 'kmap_local_page' instead
+WARNING: Deprecated use of 'kunmap_atomic', prefer 'kunmap_local' instead
+
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Link: https://lore.kernel.org/r/20240826074452.1490072-7-yukuai1@huaweicloud.com
+Signed-off-by: Song Liu <song@kernel.org>
+Stable-dep-of: 8d28d0ddb986 ("md/md-bitmap: Synchronize bitmap_get_stats() with bitmap lifetime")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/md-bitmap.c | 6 ++++++
+ drivers/md/md-bitmap.h | 1 +
+ drivers/md/md-cluster.c | 34 ++++++++++++++++++++--------------
+ 3 files changed, 27 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
+index 736268447d3e1..bddf4f3d27a77 100644
+--- a/drivers/md/md-bitmap.c
++++ b/drivers/md/md-bitmap.c
+@@ -2025,10 +2025,15 @@ EXPORT_SYMBOL_GPL(md_bitmap_copy_from_slot);
+ int md_bitmap_get_stats(struct bitmap *bitmap, struct md_bitmap_stats *stats)
+ {
+ struct bitmap_counts *counts;
++ bitmap_super_t *sb;
+
+ if (!bitmap)
+ return -ENOENT;
+
++ sb = kmap_local_page(bitmap->storage.sb_page);
++ stats->sync_size = le64_to_cpu(sb->sync_size);
++ kunmap_local(sb);
++
+ counts = &bitmap->counts;
+ stats->missing_pages = counts->missing_pages;
+ stats->pages = counts->pages;
+@@ -2036,6 +2041,7 @@ int md_bitmap_get_stats(struct bitmap *bitmap, struct md_bitmap_stats *stats)
+
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(md_bitmap_get_stats);
+
+ int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks,
+ int chunksize, int init)
+diff --git a/drivers/md/md-bitmap.h b/drivers/md/md-bitmap.h
+index 00ac4c3ecf4d9..7b7a701f74be7 100644
+--- a/drivers/md/md-bitmap.h
++++ b/drivers/md/md-bitmap.h
+@@ -235,6 +235,7 @@ struct bitmap {
+
+ struct md_bitmap_stats {
+ unsigned long missing_pages;
++ unsigned long sync_size;
+ unsigned long pages;
+ struct file *file;
+ };
+diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
+index a0d3f6c397707..7484bb83171a9 100644
+--- a/drivers/md/md-cluster.c
++++ b/drivers/md/md-cluster.c
+@@ -1185,18 +1185,21 @@ static int resize_bitmaps(struct mddev *mddev, sector_t newsize, sector_t oldsiz
+ */
+ static int cluster_check_sync_size(struct mddev *mddev)
+ {
+- int i, rv;
+- bitmap_super_t *sb;
+- unsigned long my_sync_size, sync_size = 0;
+- int node_num = mddev->bitmap_info.nodes;
+ int current_slot = md_cluster_ops->slot_number(mddev);
++ int node_num = mddev->bitmap_info.nodes;
+ struct bitmap *bitmap = mddev->bitmap;
+- char str[64];
+ struct dlm_lock_resource *bm_lockres;
++ struct md_bitmap_stats stats;
++ unsigned long sync_size = 0;
++ unsigned long my_sync_size;
++ char str[64];
++ int i, rv;
+
+- sb = kmap_atomic(bitmap->storage.sb_page);
+- my_sync_size = le64_to_cpu(sb->sync_size);
+- kunmap_atomic(sb);
++ rv = md_bitmap_get_stats(bitmap, &stats);
++ if (rv)
++ return rv;
++
++ my_sync_size = stats.sync_size;
+
+ for (i = 0; i < node_num; i++) {
+ if (i == current_slot)
+@@ -1225,15 +1228,18 @@ static int cluster_check_sync_size(struct mddev *mddev)
+ md_bitmap_update_sb(bitmap);
+ lockres_free(bm_lockres);
+
+- sb = kmap_atomic(bitmap->storage.sb_page);
+- if (sync_size == 0)
+- sync_size = le64_to_cpu(sb->sync_size);
+- else if (sync_size != le64_to_cpu(sb->sync_size)) {
+- kunmap_atomic(sb);
++ rv = md_bitmap_get_stats(bitmap, &stats);
++ if (rv) {
++ md_bitmap_free(bitmap);
++ return rv;
++ }
++
++ if (sync_size == 0) {
++ sync_size = stats.sync_size;
++ } else if (sync_size != stats.sync_size) {
+ md_bitmap_free(bitmap);
+ return -1;
+ }
+- kunmap_atomic(sb);
+ md_bitmap_free(bitmap);
+ }
+
+--
+2.39.5
+
--- /dev/null
+From f14a8b6063d4662f21a6f46c9b3579f3f220ed98 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Aug 2024 15:44:12 +0800
+Subject: md/md-bitmap: replace md_bitmap_status() with a new helper
+ md_bitmap_get_stats()
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+[ Upstream commit 38f287d7e495ae00d4481702f44ff7ca79f5c9bc ]
+
+There are no functional changes, and the new helper will be used in
+multiple places in following patches to avoid dereferencing bitmap
+directly.
+
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Link: https://lore.kernel.org/r/20240826074452.1490072-3-yukuai1@huaweicloud.com
+Signed-off-by: Song Liu <song@kernel.org>
+Stable-dep-of: 8d28d0ddb986 ("md/md-bitmap: Synchronize bitmap_get_stats() with bitmap lifetime")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/md-bitmap.c | 25 ++++++-------------------
+ drivers/md/md-bitmap.h | 8 +++++++-
+ drivers/md/md.c | 29 ++++++++++++++++++++++++++++-
+ 3 files changed, 41 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
+index 9d8ac04c23462..736268447d3e1 100644
+--- a/drivers/md/md-bitmap.c
++++ b/drivers/md/md-bitmap.c
+@@ -2022,32 +2022,19 @@ int md_bitmap_copy_from_slot(struct mddev *mddev, int slot,
+ }
+ EXPORT_SYMBOL_GPL(md_bitmap_copy_from_slot);
+
+-
+-void md_bitmap_status(struct seq_file *seq, struct bitmap *bitmap)
++int md_bitmap_get_stats(struct bitmap *bitmap, struct md_bitmap_stats *stats)
+ {
+- unsigned long chunk_kb;
+ struct bitmap_counts *counts;
+
+ if (!bitmap)
+- return;
++ return -ENOENT;
+
+ counts = &bitmap->counts;
++ stats->missing_pages = counts->missing_pages;
++ stats->pages = counts->pages;
++ stats->file = bitmap->storage.file;
+
+- chunk_kb = bitmap->mddev->bitmap_info.chunksize >> 10;
+- seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], "
+- "%lu%s chunk",
+- counts->pages - counts->missing_pages,
+- counts->pages,
+- (counts->pages - counts->missing_pages)
+- << (PAGE_SHIFT - 10),
+- chunk_kb ? chunk_kb : bitmap->mddev->bitmap_info.chunksize,
+- chunk_kb ? "KB" : "B");
+- if (bitmap->storage.file) {
+- seq_printf(seq, ", file: ");
+- seq_file_path(seq, bitmap->storage.file, " \t\n");
+- }
+-
+- seq_printf(seq, "\n");
++ return 0;
+ }
+
+ int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks,
+diff --git a/drivers/md/md-bitmap.h b/drivers/md/md-bitmap.h
+index 3a4750952b3a7..00ac4c3ecf4d9 100644
+--- a/drivers/md/md-bitmap.h
++++ b/drivers/md/md-bitmap.h
+@@ -233,6 +233,12 @@ struct bitmap {
+ int cluster_slot; /* Slot offset for clustered env */
+ };
+
++struct md_bitmap_stats {
++ unsigned long missing_pages;
++ unsigned long pages;
++ struct file *file;
++};
++
+ /* the bitmap API */
+
+ /* these are used only by md/bitmap */
+@@ -243,7 +249,7 @@ void md_bitmap_destroy(struct mddev *mddev);
+
+ void md_bitmap_print_sb(struct bitmap *bitmap);
+ void md_bitmap_update_sb(struct bitmap *bitmap);
+-void md_bitmap_status(struct seq_file *seq, struct bitmap *bitmap);
++int md_bitmap_get_stats(struct bitmap *bitmap, struct md_bitmap_stats *stats);
+
+ int md_bitmap_setallbits(struct bitmap *bitmap);
+ void md_bitmap_write_all(struct bitmap *bitmap);
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 743244b06f679..887479e0d3afe 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -8280,6 +8280,33 @@ static void md_seq_stop(struct seq_file *seq, void *v)
+ spin_unlock(&all_mddevs_lock);
+ }
+
++static void md_bitmap_status(struct seq_file *seq, struct mddev *mddev)
++{
++ struct md_bitmap_stats stats;
++ unsigned long used_pages;
++ unsigned long chunk_kb;
++ int err;
++
++ err = md_bitmap_get_stats(mddev->bitmap, &stats);
++ if (err)
++ return;
++
++ chunk_kb = mddev->bitmap_info.chunksize >> 10;
++ used_pages = stats.pages - stats.missing_pages;
++
++ seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], %lu%s chunk",
++ used_pages, stats.pages, used_pages << (PAGE_SHIFT - 10),
++ chunk_kb ? chunk_kb : mddev->bitmap_info.chunksize,
++ chunk_kb ? "KB" : "B");
++
++ if (stats.file) {
++ seq_puts(seq, ", file: ");
++ seq_file_path(seq, stats.file, " \t\n");
++ }
++
++ seq_putc(seq, '\n');
++}
++
+ static int md_seq_show(struct seq_file *seq, void *v)
+ {
+ struct mddev *mddev = list_entry(v, struct mddev, all_mddevs);
+@@ -8355,7 +8382,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
+ } else
+ seq_printf(seq, "\n ");
+
+- md_bitmap_status(seq, mddev->bitmap);
++ md_bitmap_status(seq, mddev);
+
+ seq_printf(seq, "\n");
+ }
+--
+2.39.5
+
--- /dev/null
+From 40596830c2c14f53798d166d4a05adebac161053 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jan 2025 17:20:55 +0800
+Subject: md/md-bitmap: Synchronize bitmap_get_stats() with bitmap lifetime
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+[ Upstream commit 8d28d0ddb986f56920ac97ae704cc3340a699a30 ]
+
+After commit ec6bb299c7c3 ("md/md-bitmap: add 'sync_size' into struct
+md_bitmap_stats"), following panic is reported:
+
+Oops: general protection fault, probably for non-canonical address
+RIP: 0010:bitmap_get_stats+0x2b/0xa0
+Call Trace:
+ <TASK>
+ md_seq_show+0x2d2/0x5b0
+ seq_read_iter+0x2b9/0x470
+ seq_read+0x12f/0x180
+ proc_reg_read+0x57/0xb0
+ vfs_read+0xf6/0x380
+ ksys_read+0x6c/0xf0
+ do_syscall_64+0x82/0x170
+ entry_SYSCALL_64_after_hwframe+0x76/0x7e
+
+Root cause is that bitmap_get_stats() can be called at anytime if mddev
+is still there, even if bitmap is destroyed, or not fully initialized.
+Deferenceing bitmap in this case can crash the kernel. Meanwhile, the
+above commit start to deferencing bitmap->storage, make the problem
+easier to trigger.
+
+Fix the problem by protecting bitmap_get_stats() with bitmap_info.mutex.
+
+Cc: stable@vger.kernel.org # v6.12+
+Fixes: 32a7627cf3a3 ("[PATCH] md: optimised resync using Bitmap based intent logging")
+Reported-and-tested-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Closes: https://lore.kernel.org/linux-raid/ca3a91a2-50ae-4f68-b317-abd9889f3907@oracle.com/T/#m6e5086c95201135e4941fe38f9efa76daf9666c5
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Link: https://lore.kernel.org/r/20250124092055.4050195-1-yukuai1@huaweicloud.com
+Signed-off-by: Song Liu <song@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/md-bitmap.c | 5 ++++-
+ drivers/md/md.c | 5 +++++
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
+index bddf4f3d27a77..e18e21b24210d 100644
+--- a/drivers/md/md-bitmap.c
++++ b/drivers/md/md-bitmap.c
+@@ -2029,7 +2029,10 @@ int md_bitmap_get_stats(struct bitmap *bitmap, struct md_bitmap_stats *stats)
+
+ if (!bitmap)
+ return -ENOENT;
+-
++ if (bitmap->mddev->bitmap_info.external)
++ return -ENOENT;
++ if (!bitmap->storage.sb_page) /* no superblock */
++ return -EINVAL;
+ sb = kmap_local_page(bitmap->storage.sb_page);
+ stats->sync_size = le64_to_cpu(sb->sync_size);
+ kunmap_local(sb);
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 887479e0d3afe..e2a3a1e1afca0 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -8317,6 +8317,10 @@ static int md_seq_show(struct seq_file *seq, void *v)
+ return 0;
+
+ spin_unlock(&all_mddevs_lock);
++
++ /* prevent bitmap to be freed after checking */
++ mutex_lock(&mddev->bitmap_info.mutex);
++
+ spin_lock(&mddev->lock);
+ if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) {
+ seq_printf(seq, "%s : %sactive", mdname(mddev),
+@@ -8387,6 +8391,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
+ seq_printf(seq, "\n");
+ }
+ spin_unlock(&mddev->lock);
++ mutex_unlock(&mddev->bitmap_info.mutex);
+ spin_lock(&all_mddevs_lock);
+ if (atomic_dec_and_test(&mddev->active))
+ __mddev_put(mddev);
+--
+2.39.5
+
--- /dev/null
+From 82aaf4e755fd58880c1c750ff04047e25f2442e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Aug 2024 15:44:15 +0800
+Subject: md/md-cluster: fix spares warnings for __le64
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+[ Upstream commit 82697ccf7e495c1ba81e315c2886d6220ff84c2c ]
+
+drivers/md/md-cluster.c:1220:22: warning: incorrect type in assignment (different base types)
+drivers/md/md-cluster.c:1220:22: expected unsigned long my_sync_size
+drivers/md/md-cluster.c:1220:22: got restricted __le64 [usertype] sync_size
+drivers/md/md-cluster.c:1252:35: warning: incorrect type in assignment (different base types)
+drivers/md/md-cluster.c:1252:35: expected unsigned long sync_size
+drivers/md/md-cluster.c:1252:35: got restricted __le64 [usertype] sync_size
+drivers/md/md-cluster.c:1253:41: warning: restricted __le64 degrades to integer
+
+Fix the warnings by using le64_to_cpu() to convet __le64 to integer.
+
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Link: https://lore.kernel.org/r/20240826074452.1490072-6-yukuai1@huaweicloud.com
+Signed-off-by: Song Liu <song@kernel.org>
+Stable-dep-of: 8d28d0ddb986 ("md/md-bitmap: Synchronize bitmap_get_stats() with bitmap lifetime")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/md-cluster.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
+index 10e0c5381d01b..a0d3f6c397707 100644
+--- a/drivers/md/md-cluster.c
++++ b/drivers/md/md-cluster.c
+@@ -1195,7 +1195,7 @@ static int cluster_check_sync_size(struct mddev *mddev)
+ struct dlm_lock_resource *bm_lockres;
+
+ sb = kmap_atomic(bitmap->storage.sb_page);
+- my_sync_size = sb->sync_size;
++ my_sync_size = le64_to_cpu(sb->sync_size);
+ kunmap_atomic(sb);
+
+ for (i = 0; i < node_num; i++) {
+@@ -1227,8 +1227,8 @@ static int cluster_check_sync_size(struct mddev *mddev)
+
+ sb = kmap_atomic(bitmap->storage.sb_page);
+ if (sync_size == 0)
+- sync_size = sb->sync_size;
+- else if (sync_size != sb->sync_size) {
++ sync_size = le64_to_cpu(sb->sync_size);
++ else if (sync_size != le64_to_cpu(sb->sync_size)) {
+ kunmap_atomic(sb);
+ md_bitmap_free(bitmap);
+ return -1;
+--
+2.39.5
+
--- /dev/null
+From 967a2f6f9119288165ecd4de0f01a2d0ed4a887c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Sep 2023 14:12:41 +0800
+Subject: md: simplify md_seq_ops
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+[ Upstream commit cf1b6d4441fffd0ba8ae4ced6a12f578c95ca049 ]
+
+Before this patch, the implementation is hacky and hard to understand:
+
+1) md_seq_start set pos to 1;
+2) md_seq_show found pos is 1, then print Personalities;
+3) md_seq_next found pos is 1, then it update pos to the first mddev;
+4) md_seq_show found pos is not 1 or 2, show mddev;
+5) md_seq_next found pos is not 1 or 2, update pos to next mddev;
+6) loop 4-5 until the last mddev, then md_seq_next update pos to 2;
+7) md_seq_show found pos is 2, then print unused devices;
+8) md_seq_next found pos is 2, stop;
+
+This patch remove the magic value and use seq_list_start/next/stop()
+directly, and move printing "Personalities" to md_seq_start(),
+"unsed devices" to md_seq_stop():
+
+1) md_seq_start print Personalities, and then set pos to first mddev;
+2) md_seq_show show mddev;
+3) md_seq_next update pos to next mddev;
+4) loop 2-3 until the last mddev;
+5) md_seq_stop print unsed devices;
+
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20230927061241.1552837-3-yukuai1@huaweicloud.com
+Stable-dep-of: 8d28d0ddb986 ("md/md-bitmap: Synchronize bitmap_get_stats() with bitmap lifetime")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/md.c | 100 +++++++++++-------------------------------------
+ 1 file changed, 22 insertions(+), 78 deletions(-)
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 44bac1e7d47e2..743244b06f679 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -8250,105 +8250,46 @@ static int status_resync(struct seq_file *seq, struct mddev *mddev)
+ }
+
+ static void *md_seq_start(struct seq_file *seq, loff_t *pos)
++ __acquires(&all_mddevs_lock)
+ {
+- struct list_head *tmp;
+- loff_t l = *pos;
+- struct mddev *mddev;
++ struct md_personality *pers;
+
+- if (l == 0x10000) {
+- ++*pos;
+- return (void *)2;
+- }
+- if (l > 0x10000)
+- return NULL;
+- if (!l--)
+- /* header */
+- return (void*)1;
++ seq_puts(seq, "Personalities : ");
++ spin_lock(&pers_lock);
++ list_for_each_entry(pers, &pers_list, list)
++ seq_printf(seq, "[%s] ", pers->name);
++
++ spin_unlock(&pers_lock);
++ seq_puts(seq, "\n");
++ seq->poll_event = atomic_read(&md_event_count);
+
+ spin_lock(&all_mddevs_lock);
+- list_for_each(tmp,&all_mddevs)
+- if (!l--) {
+- mddev = list_entry(tmp, struct mddev, all_mddevs);
+- if (!mddev_get(mddev))
+- continue;
+- spin_unlock(&all_mddevs_lock);
+- return mddev;
+- }
+- spin_unlock(&all_mddevs_lock);
+- if (!l--)
+- return (void*)2;/* tail */
+- return NULL;
++
++ return seq_list_start(&all_mddevs, *pos);
+ }
+
+ static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+- struct list_head *tmp;
+- struct mddev *next_mddev, *mddev = v;
+- struct mddev *to_put = NULL;
+-
+- ++*pos;
+- if (v == (void*)2)
+- return NULL;
+-
+- spin_lock(&all_mddevs_lock);
+- if (v == (void*)1) {
+- tmp = all_mddevs.next;
+- } else {
+- to_put = mddev;
+- tmp = mddev->all_mddevs.next;
+- }
+-
+- for (;;) {
+- if (tmp == &all_mddevs) {
+- next_mddev = (void*)2;
+- *pos = 0x10000;
+- break;
+- }
+- next_mddev = list_entry(tmp, struct mddev, all_mddevs);
+- if (mddev_get(next_mddev))
+- break;
+- mddev = next_mddev;
+- tmp = mddev->all_mddevs.next;
+- }
+- spin_unlock(&all_mddevs_lock);
+-
+- if (to_put)
+- mddev_put(to_put);
+- return next_mddev;
+-
++ return seq_list_next(v, &all_mddevs, pos);
+ }
+
+ static void md_seq_stop(struct seq_file *seq, void *v)
++ __releases(&all_mddevs_lock)
+ {
+- struct mddev *mddev = v;
+-
+- if (mddev && v != (void*)1 && v != (void*)2)
+- mddev_put(mddev);
++ status_unused(seq);
++ spin_unlock(&all_mddevs_lock);
+ }
+
+ static int md_seq_show(struct seq_file *seq, void *v)
+ {
+- struct mddev *mddev = v;
++ struct mddev *mddev = list_entry(v, struct mddev, all_mddevs);
+ sector_t sectors;
+ struct md_rdev *rdev;
+
+- if (v == (void*)1) {
+- struct md_personality *pers;
+- seq_printf(seq, "Personalities : ");
+- spin_lock(&pers_lock);
+- list_for_each_entry(pers, &pers_list, list)
+- seq_printf(seq, "[%s] ", pers->name);
+-
+- spin_unlock(&pers_lock);
+- seq_printf(seq, "\n");
+- seq->poll_event = atomic_read(&md_event_count);
++ if (!mddev_get(mddev))
+ return 0;
+- }
+- if (v == (void*)2) {
+- status_unused(seq);
+- return 0;
+- }
+
++ spin_unlock(&all_mddevs_lock);
+ spin_lock(&mddev->lock);
+ if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) {
+ seq_printf(seq, "%s : %sactive", mdname(mddev),
+@@ -8419,6 +8360,9 @@ static int md_seq_show(struct seq_file *seq, void *v)
+ seq_printf(seq, "\n");
+ }
+ spin_unlock(&mddev->lock);
++ spin_lock(&all_mddevs_lock);
++ if (atomic_dec_and_test(&mddev->active))
++ __mddev_put(mddev);
+
+ return 0;
+ }
+--
+2.39.5
+
--- /dev/null
+From 0787fc2c3fe6a4fcf1d43a6a48718f054fc56f3f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Aug 2023 11:16:16 +0800
+Subject: md: use separate work_struct for md_start_sync()
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+[ Upstream commit ac619781967bd5663c29606246b50dbebd8b3473 ]
+
+It's a little weird to borrow 'del_work' for md_start_sync(), declare
+a new work_struct 'sync_work' for md_start_sync().
+
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Reviewed-by: Xiao Ni <xni@redhat.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20230825031622.1530464-2-yukuai1@huaweicloud.com
+Stable-dep-of: 8d28d0ddb986 ("md/md-bitmap: Synchronize bitmap_get_stats() with bitmap lifetime")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/md.c | 10 ++++++----
+ drivers/md/md.h | 5 ++++-
+ 2 files changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 297c86f5c70b5..4b629b7a540f7 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -682,13 +682,13 @@ void mddev_put(struct mddev *mddev)
+ * flush_workqueue() after mddev_find will succeed in waiting
+ * for the work to be done.
+ */
+- INIT_WORK(&mddev->del_work, mddev_delayed_delete);
+ queue_work(md_misc_wq, &mddev->del_work);
+ }
+ spin_unlock(&all_mddevs_lock);
+ }
+
+ static void md_safemode_timeout(struct timer_list *t);
++static void md_start_sync(struct work_struct *ws);
+
+ void mddev_init(struct mddev *mddev)
+ {
+@@ -710,6 +710,9 @@ void mddev_init(struct mddev *mddev)
+ mddev->resync_min = 0;
+ mddev->resync_max = MaxSector;
+ mddev->level = LEVEL_NONE;
++
++ INIT_WORK(&mddev->sync_work, md_start_sync);
++ INIT_WORK(&mddev->del_work, mddev_delayed_delete);
+ }
+ EXPORT_SYMBOL_GPL(mddev_init);
+
+@@ -9308,7 +9311,7 @@ static int remove_and_add_spares(struct mddev *mddev,
+
+ static void md_start_sync(struct work_struct *ws)
+ {
+- struct mddev *mddev = container_of(ws, struct mddev, del_work);
++ struct mddev *mddev = container_of(ws, struct mddev, sync_work);
+
+ mddev->sync_thread = md_register_thread(md_do_sync,
+ mddev,
+@@ -9516,8 +9519,7 @@ void md_check_recovery(struct mddev *mddev)
+ */
+ md_bitmap_write_all(mddev->bitmap);
+ }
+- INIT_WORK(&mddev->del_work, md_start_sync);
+- queue_work(md_misc_wq, &mddev->del_work);
++ queue_work(md_misc_wq, &mddev->sync_work);
+ goto unlock;
+ }
+ not_running:
+diff --git a/drivers/md/md.h b/drivers/md/md.h
+index 4f0b480974552..c1258c94216ac 100644
+--- a/drivers/md/md.h
++++ b/drivers/md/md.h
+@@ -452,7 +452,10 @@ struct mddev {
+ struct kernfs_node *sysfs_degraded; /*handle for 'degraded' */
+ struct kernfs_node *sysfs_level; /*handle for 'level' */
+
+- struct work_struct del_work; /* used for delayed sysfs removal */
++ /* used for delayed sysfs removal */
++ struct work_struct del_work;
++ /* used for register new sync thread */
++ struct work_struct sync_work;
+
+ /* "lock" protects:
+ * flush_bio transition from NULL to !NULL
+--
+2.39.5
+
--- /dev/null
+From ebeb53b60ac02642c4a93128ab2b87ef705d26aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Sep 2022 23:58:43 +0800
+Subject: media: Switch to use dev_err_probe() helper
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+[ Upstream commit 6cb7d1b3ff83e98e852db9739892c4643a31804b ]
+
+In the probe path, dev_err() can be replaced with dev_err_probe()
+which will check if error code is -EPROBE_DEFER.
+
+Reviewed-by: Sean Young <sean@mess.org>
+Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Stable-dep-of: a9ea1a3d88b7 ("media: uvcvideo: Fix crash during unbind if gpio unit is in use")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/cec/platform/stm32/stm32-cec.c | 9 +++----
+ drivers/media/i2c/ad5820.c | 18 +++++--------
+ drivers/media/i2c/imx274.c | 5 ++--
+ drivers/media/i2c/tc358743.c | 9 +++----
+ .../platform/mediatek/mdp/mtk_mdp_comp.c | 5 ++--
+ .../platform/samsung/exynos4-is/media-dev.c | 4 +--
+ drivers/media/platform/st/stm32/stm32-dcmi.c | 27 +++++++------------
+ drivers/media/platform/ti/omap3isp/isp.c | 3 +--
+ .../media/platform/xilinx/xilinx-csi2rxss.c | 8 +++---
+ drivers/media/rc/gpio-ir-recv.c | 10 +++----
+ drivers/media/rc/gpio-ir-tx.c | 9 +++----
+ drivers/media/rc/ir-rx51.c | 9 ++-----
+ drivers/media/usb/uvc/uvc_driver.c | 9 +++----
+ 13 files changed, 41 insertions(+), 84 deletions(-)
+
+diff --git a/drivers/media/cec/platform/stm32/stm32-cec.c b/drivers/media/cec/platform/stm32/stm32-cec.c
+index 40db7911b437b..7b2db46a57222 100644
+--- a/drivers/media/cec/platform/stm32/stm32-cec.c
++++ b/drivers/media/cec/platform/stm32/stm32-cec.c
+@@ -288,12 +288,9 @@ static int stm32_cec_probe(struct platform_device *pdev)
+ return ret;
+
+ cec->clk_cec = devm_clk_get(&pdev->dev, "cec");
+- if (IS_ERR(cec->clk_cec)) {
+- if (PTR_ERR(cec->clk_cec) != -EPROBE_DEFER)
+- dev_err(&pdev->dev, "Cannot get cec clock\n");
+-
+- return PTR_ERR(cec->clk_cec);
+- }
++ if (IS_ERR(cec->clk_cec))
++ return dev_err_probe(&pdev->dev, PTR_ERR(cec->clk_cec),
++ "Cannot get cec clock\n");
+
+ ret = clk_prepare(cec->clk_cec);
+ if (ret) {
+diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c
+index 088c29c4e2529..56d22d02a0d91 100644
+--- a/drivers/media/i2c/ad5820.c
++++ b/drivers/media/i2c/ad5820.c
+@@ -301,21 +301,15 @@ static int ad5820_probe(struct i2c_client *client,
+ return -ENOMEM;
+
+ coil->vana = devm_regulator_get(&client->dev, "VANA");
+- if (IS_ERR(coil->vana)) {
+- ret = PTR_ERR(coil->vana);
+- if (ret != -EPROBE_DEFER)
+- dev_err(&client->dev, "could not get regulator for vana\n");
+- return ret;
+- }
++ if (IS_ERR(coil->vana))
++ return dev_err_probe(&client->dev, PTR_ERR(coil->vana),
++ "could not get regulator for vana\n");
+
+ coil->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable",
+ GPIOD_OUT_LOW);
+- if (IS_ERR(coil->enable_gpio)) {
+- ret = PTR_ERR(coil->enable_gpio);
+- if (ret != -EPROBE_DEFER)
+- dev_err(&client->dev, "could not get enable gpio\n");
+- return ret;
+- }
++ if (IS_ERR(coil->enable_gpio))
++ return dev_err_probe(&client->dev, PTR_ERR(coil->enable_gpio),
++ "could not get enable gpio\n");
+
+ mutex_init(&coil->power_lock);
+
+diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c
+index a00761b1e18c2..9219f3c9594b0 100644
+--- a/drivers/media/i2c/imx274.c
++++ b/drivers/media/i2c/imx274.c
+@@ -2060,9 +2060,8 @@ static int imx274_probe(struct i2c_client *client)
+ imx274->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(imx274->reset_gpio)) {
+- if (PTR_ERR(imx274->reset_gpio) != -EPROBE_DEFER)
+- dev_err(dev, "Reset GPIO not setup in DT");
+- ret = PTR_ERR(imx274->reset_gpio);
++ ret = dev_err_probe(dev, PTR_ERR(imx274->reset_gpio),
++ "Reset GPIO not setup in DT\n");
+ goto err_me;
+ }
+
+diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c
+index 45dd91d1cd816..2c8189e04a131 100644
+--- a/drivers/media/i2c/tc358743.c
++++ b/drivers/media/i2c/tc358743.c
+@@ -1891,12 +1891,9 @@ static int tc358743_probe_of(struct tc358743_state *state)
+ int ret;
+
+ refclk = devm_clk_get(dev, "refclk");
+- if (IS_ERR(refclk)) {
+- if (PTR_ERR(refclk) != -EPROBE_DEFER)
+- dev_err(dev, "failed to get refclk: %ld\n",
+- PTR_ERR(refclk));
+- return PTR_ERR(refclk);
+- }
++ if (IS_ERR(refclk))
++ return dev_err_probe(dev, PTR_ERR(refclk),
++ "failed to get refclk\n");
+
+ ep = of_graph_get_next_endpoint(dev->of_node, NULL);
+ if (!ep) {
+diff --git a/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.c b/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.c
+index 1e3833f1c9ae2..ad5fab2d8bfae 100644
+--- a/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.c
++++ b/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.c
+@@ -52,9 +52,8 @@ int mtk_mdp_comp_init(struct device *dev, struct device_node *node,
+ for (i = 0; i < ARRAY_SIZE(comp->clk); i++) {
+ comp->clk[i] = of_clk_get(node, i);
+ if (IS_ERR(comp->clk[i])) {
+- if (PTR_ERR(comp->clk[i]) != -EPROBE_DEFER)
+- dev_err(dev, "Failed to get clock\n");
+- ret = PTR_ERR(comp->clk[i]);
++ ret = dev_err_probe(dev, PTR_ERR(comp->clk[i]),
++ "Failed to get clock\n");
+ goto put_dev;
+ }
+
+diff --git a/drivers/media/platform/samsung/exynos4-is/media-dev.c b/drivers/media/platform/samsung/exynos4-is/media-dev.c
+index 2f3071acb9c97..98a60f01129d4 100644
+--- a/drivers/media/platform/samsung/exynos4-is/media-dev.c
++++ b/drivers/media/platform/samsung/exynos4-is/media-dev.c
+@@ -1471,9 +1471,7 @@ static int fimc_md_probe(struct platform_device *pdev)
+
+ pinctrl = devm_pinctrl_get(dev);
+ if (IS_ERR(pinctrl)) {
+- ret = PTR_ERR(pinctrl);
+- if (ret != -EPROBE_DEFER)
+- dev_err(dev, "Failed to get pinctrl: %d\n", ret);
++ ret = dev_err_probe(dev, PTR_ERR(pinctrl), "Failed to get pinctrl\n");
+ goto err_clk;
+ }
+
+diff --git a/drivers/media/platform/st/stm32/stm32-dcmi.c b/drivers/media/platform/st/stm32/stm32-dcmi.c
+index 37458d4d9564b..06be28b361f1a 100644
+--- a/drivers/media/platform/st/stm32/stm32-dcmi.c
++++ b/drivers/media/platform/st/stm32/stm32-dcmi.c
+@@ -1946,12 +1946,9 @@ static int dcmi_probe(struct platform_device *pdev)
+ return -ENOMEM;
+
+ dcmi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+- if (IS_ERR(dcmi->rstc)) {
+- if (PTR_ERR(dcmi->rstc) != -EPROBE_DEFER)
+- dev_err(&pdev->dev, "Could not get reset control\n");
+-
+- return PTR_ERR(dcmi->rstc);
+- }
++ if (IS_ERR(dcmi->rstc))
++ return dev_err_probe(&pdev->dev, PTR_ERR(dcmi->rstc),
++ "Could not get reset control\n");
+
+ /* Get bus characteristics from devicetree */
+ np = of_graph_get_next_endpoint(np, NULL);
+@@ -2003,20 +2000,14 @@ static int dcmi_probe(struct platform_device *pdev)
+ }
+
+ mclk = devm_clk_get(&pdev->dev, "mclk");
+- if (IS_ERR(mclk)) {
+- if (PTR_ERR(mclk) != -EPROBE_DEFER)
+- dev_err(&pdev->dev, "Unable to get mclk\n");
+- return PTR_ERR(mclk);
+- }
++ if (IS_ERR(mclk))
++ return dev_err_probe(&pdev->dev, PTR_ERR(mclk),
++ "Unable to get mclk\n");
+
+ chan = dma_request_chan(&pdev->dev, "tx");
+- if (IS_ERR(chan)) {
+- ret = PTR_ERR(chan);
+- if (ret != -EPROBE_DEFER)
+- dev_err(&pdev->dev,
+- "Failed to request DMA channel: %d\n", ret);
+- return ret;
+- }
++ if (IS_ERR(chan))
++ return dev_err_probe(&pdev->dev, PTR_ERR(chan),
++ "Failed to request DMA channel\n");
+
+ dcmi->dma_max_burst = UINT_MAX;
+ ret = dma_get_slave_caps(chan, &caps);
+diff --git a/drivers/media/platform/ti/omap3isp/isp.c b/drivers/media/platform/ti/omap3isp/isp.c
+index 11ae479ee89c8..e7327e38482de 100644
+--- a/drivers/media/platform/ti/omap3isp/isp.c
++++ b/drivers/media/platform/ti/omap3isp/isp.c
+@@ -1884,8 +1884,7 @@ static int isp_initialize_modules(struct isp_device *isp)
+
+ ret = omap3isp_ccp2_init(isp);
+ if (ret < 0) {
+- if (ret != -EPROBE_DEFER)
+- dev_err(isp->dev, "CCP2 initialization failed\n");
++ dev_err_probe(isp->dev, ret, "CCP2 initialization failed\n");
+ goto error_ccp2;
+ }
+
+diff --git a/drivers/media/platform/xilinx/xilinx-csi2rxss.c b/drivers/media/platform/xilinx/xilinx-csi2rxss.c
+index 29b53febc2e7a..d8a23f18cfbce 100644
+--- a/drivers/media/platform/xilinx/xilinx-csi2rxss.c
++++ b/drivers/media/platform/xilinx/xilinx-csi2rxss.c
+@@ -976,11 +976,9 @@ static int xcsi2rxss_probe(struct platform_device *pdev)
+ /* Reset GPIO */
+ xcsi2rxss->rst_gpio = devm_gpiod_get_optional(dev, "video-reset",
+ GPIOD_OUT_HIGH);
+- if (IS_ERR(xcsi2rxss->rst_gpio)) {
+- if (PTR_ERR(xcsi2rxss->rst_gpio) != -EPROBE_DEFER)
+- dev_err(dev, "Video Reset GPIO not setup in DT");
+- return PTR_ERR(xcsi2rxss->rst_gpio);
+- }
++ if (IS_ERR(xcsi2rxss->rst_gpio))
++ return dev_err_probe(dev, PTR_ERR(xcsi2rxss->rst_gpio),
++ "Video Reset GPIO not setup in DT\n");
+
+ ret = xcsi2rxss_parse_of(xcsi2rxss);
+ if (ret < 0)
+diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
+index 16795e07dc103..41ef8cdba28c4 100644
+--- a/drivers/media/rc/gpio-ir-recv.c
++++ b/drivers/media/rc/gpio-ir-recv.c
+@@ -74,13 +74,9 @@ static int gpio_ir_recv_probe(struct platform_device *pdev)
+ return -ENOMEM;
+
+ gpio_dev->gpiod = devm_gpiod_get(dev, NULL, GPIOD_IN);
+- if (IS_ERR(gpio_dev->gpiod)) {
+- rc = PTR_ERR(gpio_dev->gpiod);
+- /* Just try again if this happens */
+- if (rc != -EPROBE_DEFER)
+- dev_err(dev, "error getting gpio (%d)\n", rc);
+- return rc;
+- }
++ if (IS_ERR(gpio_dev->gpiod))
++ return dev_err_probe(dev, PTR_ERR(gpio_dev->gpiod),
++ "error getting gpio\n");
+ gpio_dev->irq = gpiod_to_irq(gpio_dev->gpiod);
+ if (gpio_dev->irq < 0)
+ return gpio_dev->irq;
+diff --git a/drivers/media/rc/gpio-ir-tx.c b/drivers/media/rc/gpio-ir-tx.c
+index d3063ddb472e3..2b829c146db15 100644
+--- a/drivers/media/rc/gpio-ir-tx.c
++++ b/drivers/media/rc/gpio-ir-tx.c
+@@ -174,12 +174,9 @@ static int gpio_ir_tx_probe(struct platform_device *pdev)
+ return -ENOMEM;
+
+ gpio_ir->gpio = devm_gpiod_get(&pdev->dev, NULL, GPIOD_OUT_LOW);
+- if (IS_ERR(gpio_ir->gpio)) {
+- if (PTR_ERR(gpio_ir->gpio) != -EPROBE_DEFER)
+- dev_err(&pdev->dev, "Failed to get gpio (%ld)\n",
+- PTR_ERR(gpio_ir->gpio));
+- return PTR_ERR(gpio_ir->gpio);
+- }
++ if (IS_ERR(gpio_ir->gpio))
++ return dev_err_probe(&pdev->dev, PTR_ERR(gpio_ir->gpio),
++ "Failed to get gpio\n");
+
+ rcdev->priv = gpio_ir;
+ rcdev->driver_name = DRIVER_NAME;
+diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
+index a3b1451832603..85080c3d20535 100644
+--- a/drivers/media/rc/ir-rx51.c
++++ b/drivers/media/rc/ir-rx51.c
+@@ -231,13 +231,8 @@ static int ir_rx51_probe(struct platform_device *dev)
+ struct rc_dev *rcdev;
+
+ pwm = pwm_get(&dev->dev, NULL);
+- if (IS_ERR(pwm)) {
+- int err = PTR_ERR(pwm);
+-
+- if (err != -EPROBE_DEFER)
+- dev_err(&dev->dev, "pwm_get failed: %d\n", err);
+- return err;
+- }
++ if (IS_ERR(pwm))
++ return dev_err_probe(&dev->dev, PTR_ERR(pwm), "pwm_get failed\n");
+
+ /* Use default, in case userspace does not set the carrier */
+ ir_rx51.freq = DIV_ROUND_CLOSEST_ULL(pwm_get_period(pwm), NSEC_PER_SEC);
+diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
+index c8e72079b4278..92af9caf6b5db 100644
+--- a/drivers/media/usb/uvc/uvc_driver.c
++++ b/drivers/media/usb/uvc/uvc_driver.c
+@@ -1253,12 +1253,9 @@ static int uvc_gpio_parse(struct uvc_device *dev)
+ return PTR_ERR_OR_ZERO(gpio_privacy);
+
+ irq = gpiod_to_irq(gpio_privacy);
+- if (irq < 0) {
+- if (irq != EPROBE_DEFER)
+- dev_err(&dev->udev->dev,
+- "No IRQ for privacy GPIO (%d)\n", irq);
+- return irq;
+- }
++ if (irq < 0)
++ return dev_err_probe(&dev->udev->dev, irq,
++ "No IRQ for privacy GPIO\n");
+
+ unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1);
+ if (!unit)
+--
+2.39.5
+
--- /dev/null
+From 1ac9306f7b84eed1a962138b70fbeab4d5a775b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Nov 2024 20:36:07 +0000
+Subject: media: uvcvideo: Fix crash during unbind if gpio unit is in use
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+[ Upstream commit a9ea1a3d88b7947ce8cadb2afceee7a54872bbc5 ]
+
+We used the wrong device for the device managed functions. We used the
+usb device, when we should be using the interface device.
+
+If we unbind the driver from the usb interface, the cleanup functions
+are never called. In our case, the IRQ is never disabled.
+
+If an IRQ is triggered, it will try to access memory sections that are
+already free, causing an OOPS.
+
+We cannot use the function devm_request_threaded_irq here. The devm_*
+clean functions may be called after the main structure is released by
+uvc_delete.
+
+Luckily this bug has small impact, as it is only affected by devices
+with gpio units and the user has to unbind the device, a disconnect will
+not trigger this error.
+
+Cc: stable@vger.kernel.org
+Fixes: 2886477ff987 ("media: uvcvideo: Implement UVC_EXT_GPIO_UNIT")
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Link: https://lore.kernel.org/r/20241106-uvc-crashrmmod-v6-1-fbf9781c6e83@chromium.org
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_driver.c | 28 +++++++++++++++++++++-------
+ drivers/media/usb/uvc/uvcvideo.h | 1 +
+ 2 files changed, 22 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
+index 92af9caf6b5db..47a6cedd5578c 100644
+--- a/drivers/media/usb/uvc/uvc_driver.c
++++ b/drivers/media/usb/uvc/uvc_driver.c
+@@ -1247,14 +1247,14 @@ static int uvc_gpio_parse(struct uvc_device *dev)
+ struct gpio_desc *gpio_privacy;
+ int irq;
+
+- gpio_privacy = devm_gpiod_get_optional(&dev->udev->dev, "privacy",
++ gpio_privacy = devm_gpiod_get_optional(&dev->intf->dev, "privacy",
+ GPIOD_IN);
+ if (IS_ERR_OR_NULL(gpio_privacy))
+ return PTR_ERR_OR_ZERO(gpio_privacy);
+
+ irq = gpiod_to_irq(gpio_privacy);
+ if (irq < 0)
+- return dev_err_probe(&dev->udev->dev, irq,
++ return dev_err_probe(&dev->intf->dev, irq,
+ "No IRQ for privacy GPIO\n");
+
+ unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1);
+@@ -1280,15 +1280,27 @@ static int uvc_gpio_parse(struct uvc_device *dev)
+ static int uvc_gpio_init_irq(struct uvc_device *dev)
+ {
+ struct uvc_entity *unit = dev->gpio_unit;
++ int ret;
+
+ if (!unit || unit->gpio.irq < 0)
+ return 0;
+
+- return devm_request_threaded_irq(&dev->udev->dev, unit->gpio.irq, NULL,
+- uvc_gpio_irq,
+- IRQF_ONESHOT | IRQF_TRIGGER_FALLING |
+- IRQF_TRIGGER_RISING,
+- "uvc_privacy_gpio", dev);
++ ret = request_threaded_irq(unit->gpio.irq, NULL, uvc_gpio_irq,
++ IRQF_ONESHOT | IRQF_TRIGGER_FALLING |
++ IRQF_TRIGGER_RISING,
++ "uvc_privacy_gpio", dev);
++
++ unit->gpio.initialized = !ret;
++
++ return ret;
++}
++
++static void uvc_gpio_deinit(struct uvc_device *dev)
++{
++ if (!dev->gpio_unit || !dev->gpio_unit->gpio.initialized)
++ return;
++
++ free_irq(dev->gpio_unit->gpio.irq, dev);
+ }
+
+ /* ------------------------------------------------------------------------
+@@ -1882,6 +1894,8 @@ static void uvc_unregister_video(struct uvc_device *dev)
+ {
+ struct uvc_streaming *stream;
+
++ uvc_gpio_deinit(dev);
++
+ list_for_each_entry(stream, &dev->streams, list) {
+ /* Nothing to do here, continue. */
+ if (!video_is_registered(&stream->vdev))
+diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
+index 33e7475d4e64a..475bf185be8a8 100644
+--- a/drivers/media/usb/uvc/uvcvideo.h
++++ b/drivers/media/usb/uvc/uvcvideo.h
+@@ -227,6 +227,7 @@ struct uvc_entity {
+ u8 *bmControls;
+ struct gpio_desc *gpio_privacy;
+ int irq;
++ bool initialized;
+ } gpio;
+ };
+
+--
+2.39.5
+
--- /dev/null
+From d7832fc652cdda4835eec5241bf26025e29fdb55 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 21:20:08 +0000
+Subject: media: uvcvideo: Only save async fh if success
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+[ Upstream commit d9fecd096f67a4469536e040a8a10bbfb665918b ]
+
+Now we keep a reference to the active fh for any call to uvc_ctrl_set,
+regardless if it is an actual set or if it is a just a try or if the
+device refused the operation.
+
+We should only keep the file handle if the device actually accepted
+applying the operation.
+
+Cc: stable@vger.kernel.org
+Fixes: e5225c820c05 ("media: uvcvideo: Send a control event when a Control Change interrupt arrives")
+Suggested-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Link: https://lore.kernel.org/r/20241203-uvc-fix-async-v6-1-26c867231118@chromium.org
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_ctrl.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
+index 986e94f7164a6..6be1aff23e71c 100644
+--- a/drivers/media/usb/uvc/uvc_ctrl.c
++++ b/drivers/media/usb/uvc/uvc_ctrl.c
+@@ -1700,7 +1700,10 @@ int uvc_ctrl_begin(struct uvc_video_chain *chain)
+ }
+
+ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
+- struct uvc_entity *entity, int rollback, struct uvc_control **err_ctrl)
++ struct uvc_fh *handle,
++ struct uvc_entity *entity,
++ int rollback,
++ struct uvc_control **err_ctrl)
+ {
+ struct uvc_control *ctrl;
+ unsigned int i;
+@@ -1748,6 +1751,10 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
+ *err_ctrl = ctrl;
+ return ret;
+ }
++
++ if (!rollback && handle &&
++ ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS)
++ ctrl->handle = handle;
+ }
+
+ return 0;
+@@ -1784,8 +1791,8 @@ int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback,
+
+ /* Find the control. */
+ list_for_each_entry(entity, &chain->entities, chain) {
+- ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback,
+- &err_ctrl);
++ ret = uvc_ctrl_commit_entity(chain->dev, handle, entity,
++ rollback, &err_ctrl);
+ if (ret < 0) {
+ if (ctrls)
+ ctrls->error_idx =
+@@ -1927,9 +1934,6 @@ int uvc_ctrl_set(struct uvc_fh *handle,
+ mapping->set(mapping, value,
+ uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
+
+- if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS)
+- ctrl->handle = handle;
+-
+ ctrl->dirty = 1;
+ ctrl->modified = 1;
+ return 0;
+@@ -2258,7 +2262,7 @@ int uvc_ctrl_restore_values(struct uvc_device *dev)
+ ctrl->dirty = 1;
+ }
+
+- ret = uvc_ctrl_commit_entity(dev, entity, 0, NULL);
++ ret = uvc_ctrl_commit_entity(dev, NULL, entity, 0, NULL);
+ if (ret < 0)
+ return ret;
+ }
+--
+2.39.5
+
--- /dev/null
+From 502b207379150cad163fcf78f176bf9125ac4560 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Apr 2024 15:04:42 +0000
+Subject: media: uvcvideo: Refactor iterators
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+[ Upstream commit 64627daf0c5f7838111f52bbbd1a597cb5d6871a ]
+
+Avoid using the iterators after the list_for_each() constructs.
+This patch should be a NOP, but makes cocci, happier:
+
+drivers/media/usb/uvc/uvc_ctrl.c:1861:44-50: ERROR: invalid reference to the index variable of the iterator on line 1850
+drivers/media/usb/uvc/uvc_ctrl.c:2195:17-23: ERROR: invalid reference to the index variable of the iterator on line 2179
+
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Stable-dep-of: d9fecd096f67 ("media: uvcvideo: Only save async fh if success")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_ctrl.c | 24 +++++++++++++-----------
+ 1 file changed, 13 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
+index 1bad64f4499ae..986e94f7164a6 100644
+--- a/drivers/media/usb/uvc/uvc_ctrl.c
++++ b/drivers/media/usb/uvc/uvc_ctrl.c
+@@ -1786,16 +1786,18 @@ int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback,
+ list_for_each_entry(entity, &chain->entities, chain) {
+ ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback,
+ &err_ctrl);
+- if (ret < 0)
++ if (ret < 0) {
++ if (ctrls)
++ ctrls->error_idx =
++ uvc_ctrl_find_ctrl_idx(entity, ctrls,
++ err_ctrl);
+ goto done;
++ }
+ }
+
+ if (!rollback)
+ uvc_ctrl_send_events(handle, ctrls->controls, ctrls->count);
+ done:
+- if (ret < 0 && ctrls)
+- ctrls->error_idx = uvc_ctrl_find_ctrl_idx(entity, ctrls,
+- err_ctrl);
+ mutex_unlock(&chain->ctrl_mutex);
+ return ret;
+ }
+@@ -2100,7 +2102,7 @@ static int uvc_ctrl_init_xu_ctrl(struct uvc_device *dev,
+ int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
+ struct uvc_xu_control_query *xqry)
+ {
+- struct uvc_entity *entity;
++ struct uvc_entity *entity, *iter;
+ struct uvc_control *ctrl;
+ unsigned int i;
+ bool found;
+@@ -2110,16 +2112,16 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
+ int ret;
+
+ /* Find the extension unit. */
+- found = false;
+- list_for_each_entry(entity, &chain->entities, chain) {
+- if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT &&
+- entity->id == xqry->unit) {
+- found = true;
++ entity = NULL;
++ list_for_each_entry(iter, &chain->entities, chain) {
++ if (UVC_ENTITY_TYPE(iter) == UVC_VC_EXTENSION_UNIT &&
++ iter->id == xqry->unit) {
++ entity = iter;
+ break;
+ }
+ }
+
+- if (!found) {
++ if (!entity) {
+ uvc_dbg(chain->dev, CONTROL, "Extension unit %u not found\n",
+ xqry->unit);
+ return -ENOENT;
+--
+2.39.5
+
--- /dev/null
+From 10cf6a541188d8a8dba2827e19090a7c3e4d27b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 21:20:10 +0000
+Subject: media: uvcvideo: Remove dangling pointers
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+[ Upstream commit 221cd51efe4565501a3dbf04cc011b537dcce7fb ]
+
+When an async control is written, we copy a pointer to the file handle
+that started the operation. That pointer will be used when the device is
+done. Which could be anytime in the future.
+
+If the user closes that file descriptor, its structure will be freed,
+and there will be one dangling pointer per pending async control, that
+the driver will try to use.
+
+Clean all the dangling pointers during release().
+
+To avoid adding a performance penalty in the most common case (no async
+operation), a counter has been introduced with some logic to make sure
+that it is properly handled.
+
+Cc: stable@vger.kernel.org
+Fixes: e5225c820c05 ("media: uvcvideo: Send a control event when a Control Change interrupt arrives")
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Link: https://lore.kernel.org/r/20241203-uvc-fix-async-v6-3-26c867231118@chromium.org
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_ctrl.c | 59 ++++++++++++++++++++++++++++++--
+ drivers/media/usb/uvc/uvc_v4l2.c | 2 ++
+ drivers/media/usb/uvc/uvcvideo.h | 9 ++++-
+ 3 files changed, 67 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
+index 6be1aff23e71c..69f9f451ab400 100644
+--- a/drivers/media/usb/uvc/uvc_ctrl.c
++++ b/drivers/media/usb/uvc/uvc_ctrl.c
+@@ -1470,6 +1470,40 @@ static void uvc_ctrl_send_slave_event(struct uvc_video_chain *chain,
+ uvc_ctrl_send_event(chain, handle, ctrl, mapping, val, changes);
+ }
+
++static void uvc_ctrl_set_handle(struct uvc_fh *handle, struct uvc_control *ctrl,
++ struct uvc_fh *new_handle)
++{
++ lockdep_assert_held(&handle->chain->ctrl_mutex);
++
++ if (new_handle) {
++ if (ctrl->handle)
++ dev_warn_ratelimited(&handle->stream->dev->udev->dev,
++ "UVC non compliance: Setting an async control with a pending operation.");
++
++ if (new_handle == ctrl->handle)
++ return;
++
++ if (ctrl->handle) {
++ WARN_ON(!ctrl->handle->pending_async_ctrls);
++ if (ctrl->handle->pending_async_ctrls)
++ ctrl->handle->pending_async_ctrls--;
++ }
++
++ ctrl->handle = new_handle;
++ handle->pending_async_ctrls++;
++ return;
++ }
++
++ /* Cannot clear the handle for a control not owned by us.*/
++ if (WARN_ON(ctrl->handle != handle))
++ return;
++
++ ctrl->handle = NULL;
++ if (WARN_ON(!handle->pending_async_ctrls))
++ return;
++ handle->pending_async_ctrls--;
++}
++
+ void uvc_ctrl_status_event(struct uvc_video_chain *chain,
+ struct uvc_control *ctrl, const u8 *data)
+ {
+@@ -1480,7 +1514,8 @@ void uvc_ctrl_status_event(struct uvc_video_chain *chain,
+ mutex_lock(&chain->ctrl_mutex);
+
+ handle = ctrl->handle;
+- ctrl->handle = NULL;
++ if (handle)
++ uvc_ctrl_set_handle(handle, ctrl, NULL);
+
+ list_for_each_entry(mapping, &ctrl->info.mappings, list) {
+ s32 value = __uvc_ctrl_get_value(mapping, data);
+@@ -1754,7 +1789,7 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
+
+ if (!rollback && handle &&
+ ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS)
+- ctrl->handle = handle;
++ uvc_ctrl_set_handle(handle, ctrl, handle);
+ }
+
+ return 0;
+@@ -2666,6 +2701,26 @@ int uvc_ctrl_init_device(struct uvc_device *dev)
+ return 0;
+ }
+
++void uvc_ctrl_cleanup_fh(struct uvc_fh *handle)
++{
++ struct uvc_entity *entity;
++
++ guard(mutex)(&handle->chain->ctrl_mutex);
++
++ if (!handle->pending_async_ctrls)
++ return;
++
++ list_for_each_entry(entity, &handle->chain->dev->entities, list) {
++ for (unsigned int i = 0; i < entity->ncontrols; ++i) {
++ if (entity->controls[i].handle != handle)
++ continue;
++ uvc_ctrl_set_handle(handle, &entity->controls[i], NULL);
++ }
++ }
++
++ WARN_ON(handle->pending_async_ctrls);
++}
++
+ /*
+ * Cleanup device controls.
+ */
+diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
+index 950b42d78a107..bd4677a6e653a 100644
+--- a/drivers/media/usb/uvc/uvc_v4l2.c
++++ b/drivers/media/usb/uvc/uvc_v4l2.c
+@@ -607,6 +607,8 @@ static int uvc_v4l2_release(struct file *file)
+
+ uvc_dbg(stream->dev, CALLS, "%s\n", __func__);
+
++ uvc_ctrl_cleanup_fh(handle);
++
+ /* Only free resources if this is a privileged handle. */
+ if (uvc_has_privileges(handle))
+ uvc_queue_release(&stream->queue);
+diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
+index 475bf185be8a8..45caa8523426d 100644
+--- a/drivers/media/usb/uvc/uvcvideo.h
++++ b/drivers/media/usb/uvc/uvcvideo.h
+@@ -331,7 +331,11 @@ struct uvc_video_chain {
+ struct uvc_entity *processing; /* Processing unit */
+ struct uvc_entity *selector; /* Selector unit */
+
+- struct mutex ctrl_mutex; /* Protects ctrl.info */
++ struct mutex ctrl_mutex; /*
++ * Protects ctrl.info,
++ * ctrl.handle and
++ * uvc_fh.pending_async_ctrls
++ */
+
+ struct v4l2_prio_state prio; /* V4L2 priority state */
+ u32 caps; /* V4L2 chain-wide caps */
+@@ -585,6 +589,7 @@ struct uvc_fh {
+ struct uvc_video_chain *chain;
+ struct uvc_streaming *stream;
+ enum uvc_handle_state state;
++ unsigned int pending_async_ctrls;
+ };
+
+ struct uvc_driver {
+@@ -769,6 +774,8 @@ int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id,
+ int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
+ struct uvc_xu_control_query *xqry);
+
++void uvc_ctrl_cleanup_fh(struct uvc_fh *handle);
++
+ /* Utility functions */
+ struct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts,
+ u8 epaddr);
+--
+2.39.5
+
--- /dev/null
+From 79c490b951959dcd6070c3073fba6054b92f6d82 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Dec 2024 02:52:38 +0000
+Subject: memcg: fix soft lockup in the OOM process
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Chen Ridong <chenridong@huawei.com>
+
+[ Upstream commit ade81479c7dda1ce3eedb215c78bc615bbd04f06 ]
+
+A soft lockup issue was found in the product with about 56,000 tasks were
+in the OOM cgroup, it was traversing them when the soft lockup was
+triggered.
+
+watchdog: BUG: soft lockup - CPU#2 stuck for 23s! [VM Thread:1503066]
+CPU: 2 PID: 1503066 Comm: VM Thread Kdump: loaded Tainted: G
+Hardware name: Huawei Cloud OpenStack Nova, BIOS
+RIP: 0010:console_unlock+0x343/0x540
+RSP: 0000:ffffb751447db9a0 EFLAGS: 00000247 ORIG_RAX: ffffffffffffff13
+RAX: 0000000000000001 RBX: 0000000000000000 RCX: 00000000ffffffff
+RDX: 0000000000000000 RSI: 0000000000000004 RDI: 0000000000000247
+RBP: ffffffffafc71f90 R08: 0000000000000000 R09: 0000000000000040
+R10: 0000000000000080 R11: 0000000000000000 R12: ffffffffafc74bd0
+R13: ffffffffaf60a220 R14: 0000000000000247 R15: 0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f2fe6ad91f0 CR3: 00000004b2076003 CR4: 0000000000360ee0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ vprintk_emit+0x193/0x280
+ printk+0x52/0x6e
+ dump_task+0x114/0x130
+ mem_cgroup_scan_tasks+0x76/0x100
+ dump_header+0x1fe/0x210
+ oom_kill_process+0xd1/0x100
+ out_of_memory+0x125/0x570
+ mem_cgroup_out_of_memory+0xb5/0xd0
+ try_charge+0x720/0x770
+ mem_cgroup_try_charge+0x86/0x180
+ mem_cgroup_try_charge_delay+0x1c/0x40
+ do_anonymous_page+0xb5/0x390
+ handle_mm_fault+0xc4/0x1f0
+
+This is because thousands of processes are in the OOM cgroup, it takes a
+long time to traverse all of them. As a result, this lead to soft lockup
+in the OOM process.
+
+To fix this issue, call 'cond_resched' in the 'mem_cgroup_scan_tasks'
+function per 1000 iterations. For global OOM, call
+'touch_softlockup_watchdog' per 1000 iterations to avoid this issue.
+
+Link: https://lkml.kernel.org/r/20241224025238.3768787-1-chenridong@huaweicloud.com
+Fixes: 9cbb78bb3143 ("mm, memcg: introduce own oom handler to iterate only over its own threads")
+Signed-off-by: Chen Ridong <chenridong@huawei.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Cc: Roman Gushchin <roman.gushchin@linux.dev>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Shakeel Butt <shakeelb@google.com>
+Cc: Muchun Song <songmuchun@bytedance.com>
+Cc: Michal Koutný <mkoutny@suse.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/memcontrol.c | 7 ++++++-
+ mm/oom_kill.c | 8 +++++++-
+ 2 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/mm/memcontrol.c b/mm/memcontrol.c
+index 280bb6969c0bf..3f7cab196eb62 100644
+--- a/mm/memcontrol.c
++++ b/mm/memcontrol.c
+@@ -1242,6 +1242,7 @@ int mem_cgroup_scan_tasks(struct mem_cgroup *memcg,
+ {
+ struct mem_cgroup *iter;
+ int ret = 0;
++ int i = 0;
+
+ BUG_ON(memcg == root_mem_cgroup);
+
+@@ -1250,8 +1251,12 @@ int mem_cgroup_scan_tasks(struct mem_cgroup *memcg,
+ struct task_struct *task;
+
+ css_task_iter_start(&iter->css, CSS_TASK_ITER_PROCS, &it);
+- while (!ret && (task = css_task_iter_next(&it)))
++ while (!ret && (task = css_task_iter_next(&it))) {
++ /* Avoid potential softlockup warning */
++ if ((++i & 1023) == 0)
++ cond_resched();
+ ret = fn(task, arg);
++ }
+ css_task_iter_end(&it);
+ if (ret) {
+ mem_cgroup_iter_break(memcg, iter);
+diff --git a/mm/oom_kill.c b/mm/oom_kill.c
+index 4de30c6c5183f..f4c8ef863ea79 100644
+--- a/mm/oom_kill.c
++++ b/mm/oom_kill.c
+@@ -45,6 +45,7 @@
+ #include <linux/init.h>
+ #include <linux/mmu_notifier.h>
+ #include <linux/cred.h>
++#include <linux/nmi.h>
+
+ #include <asm/tlb.h>
+ #include "internal.h"
+@@ -430,10 +431,15 @@ static void dump_tasks(struct oom_control *oc)
+ mem_cgroup_scan_tasks(oc->memcg, dump_task, oc);
+ else {
+ struct task_struct *p;
++ int i = 0;
+
+ rcu_read_lock();
+- for_each_process(p)
++ for_each_process(p) {
++ /* Avoid potential softlockup warning */
++ if ((++i & 1023) == 0)
++ touch_softlockup_watchdog();
+ dump_task(p, oc);
++ }
+ rcu_read_unlock();
+ }
+ }
+--
+2.39.5
+
--- /dev/null
+From 4b972b64a74e26a8e2f5a17b48d9aef397beaadf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Feb 2024 17:32:49 +0000
+Subject: mm: update mark_victim tracepoints fields
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Carlos Galo <carlosgalo@google.com>
+
+[ Upstream commit 72ba14deb40a9e9668ec5e66a341ed657e5215c2 ]
+
+The current implementation of the mark_victim tracepoint provides only the
+process ID (pid) of the victim process. This limitation poses challenges
+for userspace tools requiring real-time OOM analysis and intervention.
+Although this information is available from the kernel logs, it’s not
+the appropriate format to provide OOM notifications. In Android, BPF
+programs are used with the mark_victim trace events to notify userspace of
+an OOM kill. For consistency, update the trace event to include the same
+information about the OOMed victim as the kernel logs.
+
+- UID
+ In Android each installed application has a unique UID. Including
+ the `uid` assists in correlating OOM events with specific apps.
+
+- Process Name (comm)
+ Enables identification of the affected process.
+
+- OOM Score
+ Will allow userspace to get additional insight of the relative kill
+ priority of the OOM victim. In Android, the oom_score_adj is used to
+ categorize app state (foreground, background, etc.), which aids in
+ analyzing user-perceptible impacts of OOM events [1].
+
+- Total VM, RSS Stats, and pgtables
+ Amount of memory used by the victim that will, potentially, be freed up
+ by killing it.
+
+[1] https://cs.android.com/android/platform/superproject/main/+/246dc8fc95b6d93afcba5c6d6c133307abb3ac2e:frameworks/base/services/core/java/com/android/server/am/ProcessList.java;l=188-283
+Signed-off-by: Carlos Galo <carlosgalo@google.com>
+Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: "Masami Hiramatsu (Google)" <mhiramat@kernel.org>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: ade81479c7dd ("memcg: fix soft lockup in the OOM process")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/trace/events/oom.h | 36 ++++++++++++++++++++++++++++++++----
+ mm/oom_kill.c | 6 +++++-
+ 2 files changed, 37 insertions(+), 5 deletions(-)
+
+diff --git a/include/trace/events/oom.h b/include/trace/events/oom.h
+index 26a11e4a2c361..b799f3bcba823 100644
+--- a/include/trace/events/oom.h
++++ b/include/trace/events/oom.h
+@@ -7,6 +7,8 @@
+ #include <linux/tracepoint.h>
+ #include <trace/events/mmflags.h>
+
++#define PG_COUNT_TO_KB(x) ((x) << (PAGE_SHIFT - 10))
++
+ TRACE_EVENT(oom_score_adj_update,
+
+ TP_PROTO(struct task_struct *task),
+@@ -72,19 +74,45 @@ TRACE_EVENT(reclaim_retry_zone,
+ );
+
+ TRACE_EVENT(mark_victim,
+- TP_PROTO(int pid),
++ TP_PROTO(struct task_struct *task, uid_t uid),
+
+- TP_ARGS(pid),
++ TP_ARGS(task, uid),
+
+ TP_STRUCT__entry(
+ __field(int, pid)
++ __string(comm, task->comm)
++ __field(unsigned long, total_vm)
++ __field(unsigned long, anon_rss)
++ __field(unsigned long, file_rss)
++ __field(unsigned long, shmem_rss)
++ __field(uid_t, uid)
++ __field(unsigned long, pgtables)
++ __field(short, oom_score_adj)
+ ),
+
+ TP_fast_assign(
+- __entry->pid = pid;
++ __entry->pid = task->pid;
++ __assign_str(comm, task->comm);
++ __entry->total_vm = PG_COUNT_TO_KB(task->mm->total_vm);
++ __entry->anon_rss = PG_COUNT_TO_KB(get_mm_counter(task->mm, MM_ANONPAGES));
++ __entry->file_rss = PG_COUNT_TO_KB(get_mm_counter(task->mm, MM_FILEPAGES));
++ __entry->shmem_rss = PG_COUNT_TO_KB(get_mm_counter(task->mm, MM_SHMEMPAGES));
++ __entry->uid = uid;
++ __entry->pgtables = mm_pgtables_bytes(task->mm) >> 10;
++ __entry->oom_score_adj = task->signal->oom_score_adj;
+ ),
+
+- TP_printk("pid=%d", __entry->pid)
++ TP_printk("pid=%d comm=%s total-vm=%lukB anon-rss=%lukB file-rss:%lukB shmem-rss:%lukB uid=%u pgtables=%lukB oom_score_adj=%hd",
++ __entry->pid,
++ __get_str(comm),
++ __entry->total_vm,
++ __entry->anon_rss,
++ __entry->file_rss,
++ __entry->shmem_rss,
++ __entry->uid,
++ __entry->pgtables,
++ __entry->oom_score_adj
++ )
+ );
+
+ TRACE_EVENT(wake_reaper,
+diff --git a/mm/oom_kill.c b/mm/oom_kill.c
+index 1276e49b31b0a..4de30c6c5183f 100644
+--- a/mm/oom_kill.c
++++ b/mm/oom_kill.c
+@@ -44,6 +44,7 @@
+ #include <linux/kthread.h>
+ #include <linux/init.h>
+ #include <linux/mmu_notifier.h>
++#include <linux/cred.h>
+
+ #include <asm/tlb.h>
+ #include "internal.h"
+@@ -757,6 +758,7 @@ static inline void queue_oom_reaper(struct task_struct *tsk)
+ */
+ static void mark_oom_victim(struct task_struct *tsk)
+ {
++ const struct cred *cred;
+ struct mm_struct *mm = tsk->mm;
+
+ WARN_ON(oom_killer_disabled);
+@@ -776,7 +778,9 @@ static void mark_oom_victim(struct task_struct *tsk)
+ */
+ __thaw_task(tsk);
+ atomic_inc(&oom_victims);
+- trace_mark_victim(tsk->pid);
++ cred = get_task_cred(tsk);
++ trace_mark_victim(tsk, cred->uid.val);
++ put_cred(cred);
+ }
+
+ /**
+--
+2.39.5
+
--- /dev/null
+From f665a4ef442ca6189b2817e7c3a93543e4d0018a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 05:49:30 -0800
+Subject: net: Add non-RCU dev_getbyhwaddr() helper
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit 4b5a28b38c4a0106c64416a1b2042405166b26ce ]
+
+Add dedicated helper for finding devices by hardware address when
+holding rtnl_lock, similar to existing dev_getbyhwaddr_rcu(). This prevents
+PROVE_LOCKING warnings when rtnl_lock is held but RCU read lock is not.
+
+Extract common address comparison logic into dev_addr_cmp().
+
+The context about this change could be found in the following
+discussion:
+
+Link: https://lore.kernel.org/all/20250206-scarlet-ermine-of-improvement-1fcac5@leitao/
+
+Cc: kuniyu@amazon.com
+Cc: ushankar@purestorage.com
+Suggested-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Link: https://patch.msgid.link/20250218-arm_fix_selftest-v5-1-d3d6892db9e1@debian.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 4eae0ee0f1e6 ("arp: switch to dev_getbyhwaddr() in arp_req_set_public()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/netdevice.h | 2 ++
+ net/core/dev.c | 37 ++++++++++++++++++++++++++++++++++---
+ 2 files changed, 36 insertions(+), 3 deletions(-)
+
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index d0b4920dee730..f44701b82ea80 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -3011,6 +3011,8 @@ static inline struct net_device *first_net_device_rcu(struct net *net)
+ }
+
+ int netdev_boot_setup_check(struct net_device *dev);
++struct net_device *dev_getbyhwaddr(struct net *net, unsigned short type,
++ const char *hwaddr);
+ struct net_device *dev_getbyhwaddr_rcu(struct net *net, unsigned short type,
+ const char *hwaddr);
+ struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type);
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 90559cb668039..212a909b48405 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -921,6 +921,12 @@ int netdev_get_name(struct net *net, char *name, int ifindex)
+ return ret;
+ }
+
++static bool dev_addr_cmp(struct net_device *dev, unsigned short type,
++ const char *ha)
++{
++ return dev->type == type && !memcmp(dev->dev_addr, ha, dev->addr_len);
++}
++
+ /**
+ * dev_getbyhwaddr_rcu - find a device by its hardware address
+ * @net: the applicable net namespace
+@@ -929,7 +935,7 @@ int netdev_get_name(struct net *net, char *name, int ifindex)
+ *
+ * Search for an interface by MAC address. Returns NULL if the device
+ * is not found or a pointer to the device.
+- * The caller must hold RCU or RTNL.
++ * The caller must hold RCU.
+ * The returned device has not had its ref count increased
+ * and the caller must therefore be careful about locking
+ *
+@@ -941,14 +947,39 @@ struct net_device *dev_getbyhwaddr_rcu(struct net *net, unsigned short type,
+ struct net_device *dev;
+
+ for_each_netdev_rcu(net, dev)
+- if (dev->type == type &&
+- !memcmp(dev->dev_addr, ha, dev->addr_len))
++ if (dev_addr_cmp(dev, type, ha))
+ return dev;
+
+ return NULL;
+ }
+ EXPORT_SYMBOL(dev_getbyhwaddr_rcu);
+
++/**
++ * dev_getbyhwaddr() - find a device by its hardware address
++ * @net: the applicable net namespace
++ * @type: media type of device
++ * @ha: hardware address
++ *
++ * Similar to dev_getbyhwaddr_rcu(), but the owner needs to hold
++ * rtnl_lock.
++ *
++ * Context: rtnl_lock() must be held.
++ * Return: pointer to the net_device, or NULL if not found
++ */
++struct net_device *dev_getbyhwaddr(struct net *net, unsigned short type,
++ const char *ha)
++{
++ struct net_device *dev;
++
++ ASSERT_RTNL();
++ for_each_netdev(net, dev)
++ if (dev_addr_cmp(dev, type, ha))
++ return dev;
++
++ return NULL;
++}
++EXPORT_SYMBOL(dev_getbyhwaddr);
++
+ struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type)
+ {
+ struct net_device *dev, *ret = NULL;
+--
+2.39.5
+
--- /dev/null
+From ab7bca98d22ad033dcefd43b813f67ec29248eca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 13:58:42 +0800
+Subject: net: axienet: Set mac_managed_pm
+
+From: Nick Hu <nick.hu@sifive.com>
+
+[ Upstream commit a370295367b55662a32a4be92565fe72a5aa79bb ]
+
+The external PHY will undergo a soft reset twice during the resume process
+when it wake up from suspend. The first reset occurs when the axienet
+driver calls phylink_of_phy_connect(), and the second occurs when
+mdio_bus_phy_resume() invokes phy_init_hw(). The second soft reset of the
+external PHY does not reinitialize the internal PHY, which causes issues
+with the internal PHY, resulting in the PHY link being down. To prevent
+this, setting the mac_managed_pm flag skips the mdio_bus_phy_resume()
+function.
+
+Fixes: a129b41fe0a8 ("Revert "net: phy: dp83867: perform soft reset and retain established link"")
+Signed-off-by: Nick Hu <nick.hu@sifive.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Link: https://patch.msgid.link/20250217055843.19799-1-nick.hu@sifive.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+index a957721581761..f227ed8e99345 100644
+--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+@@ -2159,6 +2159,7 @@ static int axienet_probe(struct platform_device *pdev)
+
+ lp->phylink_config.dev = &ndev->dev;
+ lp->phylink_config.type = PHYLINK_NETDEV;
++ lp->phylink_config.mac_managed_pm = true;
+ lp->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE |
+ MAC_10FD | MAC_100FD | MAC_1000FD;
+
+--
+2.39.5
+
--- /dev/null
+From bb90da1fb6698b93b93ec94847cf2e98702a4cc0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 18:07:29 +1000
+Subject: powerpc/64s/mm: Move __real_pte stubs into hash-4k.h
+
+From: Michael Ellerman <mpe@ellerman.id.au>
+
+[ Upstream commit 8ae4f16f7d7b59cca55aeca6db7c9636ffe7fbaa ]
+
+The stub versions of __real_pte() etc are only used with HPT & 4K pages,
+so move them into the hash-4k.h header.
+
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/20240821080729.872034-1-mpe@ellerman.id.au
+Stable-dep-of: 61bcc752d1b8 ("powerpc/64s: Rewrite __real_pte() and __rpte_to_hidx() as static inline")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/include/asm/book3s/64/hash-4k.h | 20 +++++++++++++++
+ arch/powerpc/include/asm/book3s/64/pgtable.h | 26 --------------------
+ 2 files changed, 20 insertions(+), 26 deletions(-)
+
+diff --git a/arch/powerpc/include/asm/book3s/64/hash-4k.h b/arch/powerpc/include/asm/book3s/64/hash-4k.h
+index b6ac4f86c87b4..5a79dd66b2ed0 100644
+--- a/arch/powerpc/include/asm/book3s/64/hash-4k.h
++++ b/arch/powerpc/include/asm/book3s/64/hash-4k.h
+@@ -89,6 +89,26 @@ static inline int hash__hugepd_ok(hugepd_t hpd)
+ }
+ #endif
+
++/*
++ * With 4K page size the real_pte machinery is all nops.
++ */
++#define __real_pte(e, p, o) ((real_pte_t){(e)})
++#define __rpte_to_pte(r) ((r).pte)
++#define __rpte_to_hidx(r,index) (pte_val(__rpte_to_pte(r)) >> H_PAGE_F_GIX_SHIFT)
++
++#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \
++ do { \
++ index = 0; \
++ shift = mmu_psize_defs[psize].shift; \
++
++#define pte_iterate_hashed_end() } while(0)
++
++/*
++ * We expect this to be called only for user addresses or kernel virtual
++ * addresses other than the linear mapping.
++ */
++#define pte_pagesize_index(mm, addr, pte) MMU_PAGE_4K
++
+ /*
+ * 4K PTE format is different from 64K PTE format. Saving the hash_slot is just
+ * a matter of returning the PTE bits that need to be modified. On 64K PTE,
+diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
+index c436d84226540..fdbe0b381f3ae 100644
+--- a/arch/powerpc/include/asm/book3s/64/pgtable.h
++++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
+@@ -318,32 +318,6 @@ extern unsigned long pci_io_base;
+
+ #ifndef __ASSEMBLY__
+
+-/*
+- * This is the default implementation of various PTE accessors, it's
+- * used in all cases except Book3S with 64K pages where we have a
+- * concept of sub-pages
+- */
+-#ifndef __real_pte
+-
+-#define __real_pte(e, p, o) ((real_pte_t){(e)})
+-#define __rpte_to_pte(r) ((r).pte)
+-#define __rpte_to_hidx(r,index) (pte_val(__rpte_to_pte(r)) >> H_PAGE_F_GIX_SHIFT)
+-
+-#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \
+- do { \
+- index = 0; \
+- shift = mmu_psize_defs[psize].shift; \
+-
+-#define pte_iterate_hashed_end() } while(0)
+-
+-/*
+- * We expect this to be called only for user addresses or kernel virtual
+- * addresses other than the linear mapping.
+- */
+-#define pte_pagesize_index(mm, addr, pte) MMU_PAGE_4K
+-
+-#endif /* __real_pte */
+-
+ static inline unsigned long pte_update(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, unsigned long clr,
+ unsigned long set, int huge)
+--
+2.39.5
+
--- /dev/null
+From 5f4f22bfb31dd713b54cb352f73974cab908cbd0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 12 Jan 2025 19:24:46 +0100
+Subject: powerpc/64s: Rewrite __real_pte() and __rpte_to_hidx() as static
+ inline
+
+From: Christophe Leroy <christophe.leroy@csgroup.eu>
+
+[ Upstream commit 61bcc752d1b81fde3cae454ff20c1d3c359df500 ]
+
+Rewrite __real_pte() and __rpte_to_hidx() as static inline in order to
+avoid following warnings/errors when building with 4k page size:
+
+ CC arch/powerpc/mm/book3s64/hash_tlb.o
+ arch/powerpc/mm/book3s64/hash_tlb.c: In function 'hpte_need_flush':
+ arch/powerpc/mm/book3s64/hash_tlb.c:49:16: error: variable 'offset' set but not used [-Werror=unused-but-set-variable]
+ 49 | int i, offset;
+ | ^~~~~~
+
+ CC arch/powerpc/mm/book3s64/hash_native.o
+ arch/powerpc/mm/book3s64/hash_native.c: In function 'native_flush_hash_range':
+ arch/powerpc/mm/book3s64/hash_native.c:782:29: error: variable 'index' set but not used [-Werror=unused-but-set-variable]
+ 782 | unsigned long hash, index, hidx, shift, slot;
+ | ^~~~~
+
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202501081741.AYFwybsq-lkp@intel.com/
+Fixes: ff31e105464d ("powerpc/mm/hash64: Store the slot information at the right offset for hugetlb")
+Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/e0d340a5b7bd478ecbf245d826e6ab2778b74e06.1736706263.git.christophe.leroy@csgroup.eu
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/include/asm/book3s/64/hash-4k.h | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/arch/powerpc/include/asm/book3s/64/hash-4k.h b/arch/powerpc/include/asm/book3s/64/hash-4k.h
+index 5a79dd66b2ed0..433d164374cb6 100644
+--- a/arch/powerpc/include/asm/book3s/64/hash-4k.h
++++ b/arch/powerpc/include/asm/book3s/64/hash-4k.h
+@@ -92,9 +92,17 @@ static inline int hash__hugepd_ok(hugepd_t hpd)
+ /*
+ * With 4K page size the real_pte machinery is all nops.
+ */
+-#define __real_pte(e, p, o) ((real_pte_t){(e)})
++static inline real_pte_t __real_pte(pte_t pte, pte_t *ptep, int offset)
++{
++ return (real_pte_t){pte};
++}
++
+ #define __rpte_to_pte(r) ((r).pte)
+-#define __rpte_to_hidx(r,index) (pte_val(__rpte_to_pte(r)) >> H_PAGE_F_GIX_SHIFT)
++
++static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index)
++{
++ return pte_val(__rpte_to_pte(rpte)) >> H_PAGE_F_GIX_SHIFT;
++}
+
+ #define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \
+ do { \
+--
+2.39.5
+
--- /dev/null
+From 62fdac92ad36dc056809c183c7d91b96967b417f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 07:46:28 +0100
+Subject: powerpc/code-patching: Fix KASAN hit by not flagging text patching
+ area as VM_ALLOC
+
+From: Christophe Leroy <christophe.leroy@csgroup.eu>
+
+[ Upstream commit d262a192d38e527faa5984629aabda2e0d1c4f54 ]
+
+Erhard reported the following KASAN hit while booting his PowerMac G4
+with a KASAN-enabled kernel 6.13-rc6:
+
+ BUG: KASAN: vmalloc-out-of-bounds in copy_to_kernel_nofault+0xd8/0x1c8
+ Write of size 8 at addr f1000000 by task chronyd/1293
+
+ CPU: 0 UID: 123 PID: 1293 Comm: chronyd Tainted: G W 6.13.0-rc6-PMacG4 #2
+ Tainted: [W]=WARN
+ Hardware name: PowerMac3,6 7455 0x80010303 PowerMac
+ Call Trace:
+ [c2437590] [c1631a84] dump_stack_lvl+0x70/0x8c (unreliable)
+ [c24375b0] [c0504998] print_report+0xdc/0x504
+ [c2437610] [c050475c] kasan_report+0xf8/0x108
+ [c2437690] [c0505a3c] kasan_check_range+0x24/0x18c
+ [c24376a0] [c03fb5e4] copy_to_kernel_nofault+0xd8/0x1c8
+ [c24376c0] [c004c014] patch_instructions+0x15c/0x16c
+ [c2437710] [c00731a8] bpf_arch_text_copy+0x60/0x7c
+ [c2437730] [c0281168] bpf_jit_binary_pack_finalize+0x50/0xac
+ [c2437750] [c0073cf4] bpf_int_jit_compile+0xb30/0xdec
+ [c2437880] [c0280394] bpf_prog_select_runtime+0x15c/0x478
+ [c24378d0] [c1263428] bpf_prepare_filter+0xbf8/0xc14
+ [c2437990] [c12677ec] bpf_prog_create_from_user+0x258/0x2b4
+ [c24379d0] [c027111c] do_seccomp+0x3dc/0x1890
+ [c2437ac0] [c001d8e0] system_call_exception+0x2dc/0x420
+ [c2437f30] [c00281ac] ret_from_syscall+0x0/0x2c
+ --- interrupt: c00 at 0x5a1274
+ NIP: 005a1274 LR: 006a3b3c CTR: 005296c8
+ REGS: c2437f40 TRAP: 0c00 Tainted: G W (6.13.0-rc6-PMacG4)
+ MSR: 0200f932 <VEC,EE,PR,FP,ME,IR,DR,RI> CR: 24004422 XER: 00000000
+
+ GPR00: 00000166 af8f3fa0 a7ee3540 00000001 00000000 013b6500 005a5858 0200f932
+ GPR08: 00000000 00001fe9 013d5fc8 005296c8 2822244c 00b2fcd8 00000000 af8f4b57
+ GPR16: 00000000 00000001 00000000 00000000 00000000 00000001 00000000 00000002
+ GPR24: 00afdbb0 00000000 00000000 00000000 006e0004 013ce060 006e7c1c 00000001
+ NIP [005a1274] 0x5a1274
+ LR [006a3b3c] 0x6a3b3c
+ --- interrupt: c00
+
+ The buggy address belongs to the virtual mapping at
+ [f1000000, f1002000) created by:
+ text_area_cpu_up+0x20/0x190
+
+ The buggy address belongs to the physical page:
+ page: refcount:1 mapcount:0 mapping:00000000 index:0x0 pfn:0x76e30
+ flags: 0x80000000(zone=2)
+ raw: 80000000 00000000 00000122 00000000 00000000 00000000 ffffffff 00000001
+ raw: 00000000
+ page dumped because: kasan: bad access detected
+
+ Memory state around the buggy address:
+ f0ffff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ f0ffff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ >f1000000: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
+ ^
+ f1000080: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
+ f1000100: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
+ ==================================================================
+
+f8 corresponds to KASAN_VMALLOC_INVALID which means the area is not
+initialised hence not supposed to be used yet.
+
+Powerpc text patching infrastructure allocates a virtual memory area
+using get_vm_area() and flags it as VM_ALLOC. But that flag is meant
+to be used for vmalloc() and vmalloc() allocated memory is not
+supposed to be used before a call to __vmalloc_node_range() which is
+never called for that area.
+
+That went undetected until commit e4137f08816b ("mm, kasan, kmsan:
+instrument copy_from/to_kernel_nofault")
+
+The area allocated by text_area_cpu_up() is not vmalloc memory, it is
+mapped directly on demand when needed by map_kernel_page(). There is
+no VM flag corresponding to such usage, so just pass no flag. That way
+the area will be unpoisonned and usable immediately.
+
+Reported-by: Erhard Furtner <erhard_f@mailbox.org>
+Closes: https://lore.kernel.org/all/20250112135832.57c92322@yea/
+Fixes: 37bc3e5fd764 ("powerpc/lib/code-patching: Use alternate map for patch_instruction()")
+Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/06621423da339b374f48c0886e3a5db18e896be8.1739342693.git.christophe.leroy@csgroup.eu
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/lib/code-patching.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
+index ad0cf3108dd09..65353cf2b0a8a 100644
+--- a/arch/powerpc/lib/code-patching.c
++++ b/arch/powerpc/lib/code-patching.c
+@@ -53,7 +53,7 @@ static int text_area_cpu_up(unsigned int cpu)
+ unsigned long addr;
+ int err;
+
+- area = get_vm_area(PAGE_SIZE, VM_ALLOC);
++ area = get_vm_area(PAGE_SIZE, 0);
+ if (!area) {
+ WARN_ONCE(1, "Failed to create text area for cpu %d\n",
+ cpu);
+--
+2.39.5
+
--- /dev/null
+From ef25792d19f0937ce0d3a0e009b283757bfca250 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jan 2025 10:44:07 -0800
+Subject: scsi: core: Do not retry I/Os during depopulation
+
+From: Igor Pylypiv <ipylypiv@google.com>
+
+[ Upstream commit 9ff7c383b8ac0c482a1da7989f703406d78445c6 ]
+
+Fail I/Os instead of retry to prevent user space processes from being
+blocked on the I/O completion for several minutes.
+
+Retrying I/Os during "depopulation in progress" or "depopulation restore in
+progress" results in a continuous retry loop until the depopulation
+completes or until the I/O retry loop is aborted due to a timeout by the
+scsi_cmd_runtime_exceeced().
+
+Depopulation is slow and can take 24+ hours to complete on 20+ TB HDDs.
+Most I/Os in the depopulation retry loop end up taking several minutes
+before returning the failure to user space.
+
+Cc: stable@vger.kernel.org # 4.18.x: 2bbeb8d scsi: core: Handle depopulation and restoration in progress
+Cc: stable@vger.kernel.org # 4.18.x
+Fixes: e37c7d9a0341 ("scsi: core: sanitize++ in progress")
+Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
+Link: https://lore.kernel.org/r/20250131184408.859579-1-ipylypiv@google.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_lib.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index b8d58120badde..72d31b2267ef4 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -782,13 +782,18 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
+ case 0x1a: /* start stop unit in progress */
+ case 0x1b: /* sanitize in progress */
+ case 0x1d: /* configuration in progress */
+- case 0x24: /* depopulation in progress */
+- case 0x25: /* depopulation restore in progress */
+ action = ACTION_DELAYED_RETRY;
+ break;
+ case 0x0a: /* ALUA state transition */
+ action = ACTION_DELAYED_REPREP;
+ break;
++ /*
++ * Depopulation might take many hours,
++ * thus it is not worthwhile to retry.
++ */
++ case 0x24: /* depopulation in progress */
++ case 0x25: /* depopulation restore in progress */
++ fallthrough;
+ default:
+ action = ACTION_FAIL;
+ break;
+--
+2.39.5
+
--- /dev/null
+From 5d52bcc9ecd40c486306c2283681c7a5527e3620 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 15 Oct 2023 01:06:50 -0400
+Subject: scsi: core: Handle depopulation and restoration in progress
+
+From: Douglas Gilbert <dgilbert@interlog.com>
+
+[ Upstream commit 2bbeb8d12404cf0603f513fc33269ef9abfbb396 ]
+
+The default handling of the NOT READY sense key is to wait for the device
+to become ready. The "wait" is assumed to be relatively short. However
+there is a sub-class of NOT READY that have the "... in progress" phrase in
+their additional sense code and these can take much longer. Following on
+from commit 505aa4b6a883 ("scsi: sd: Defer spinning up drive while SANITIZE
+is in progress") we now have element depopulation and restoration that can
+take a long time. For example, over 24 hours for a 20 TB, 7200 rpm hard
+disk to depopulate 1 of its 20 elements.
+
+Add handling of ASC/ASCQ: 0x4,0x24 (depopulation in progress)
+and ASC/ASCQ: 0x4,0x25 (depopulation restoration in progress)
+to sd.c . The scsi_lib.c has incomplete handling of these
+two messages, so complete it.
+
+Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
+Link: https://lore.kernel.org/r/20231015050650.131145-1-dgilbert@interlog.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Stable-dep-of: 9ff7c383b8ac ("scsi: core: Do not retry I/Os during depopulation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_lib.c | 1 +
+ drivers/scsi/sd.c | 4 ++++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 5c5954b78585e..b8d58120badde 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -783,6 +783,7 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
+ case 0x1b: /* sanitize in progress */
+ case 0x1d: /* configuration in progress */
+ case 0x24: /* depopulation in progress */
++ case 0x25: /* depopulation restore in progress */
+ action = ACTION_DELAYED_RETRY;
+ break;
+ case 0x0a: /* ALUA state transition */
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index b35ef52d9c632..c3006524eb039 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -2191,6 +2191,10 @@ sd_spinup_disk(struct scsi_disk *sdkp)
+ break; /* unavailable */
+ if (sshdr.asc == 4 && sshdr.ascq == 0x1b)
+ break; /* sanitize in progress */
++ if (sshdr.asc == 4 && sshdr.ascq == 0x24)
++ break; /* depopulation in progress */
++ if (sshdr.asc == 4 && sshdr.ascq == 0x25)
++ break; /* depopulation restoration in progress */
+ /*
+ * Issue command to spin up drive when not ready
+ */
+--
+2.39.5
+
arm64-mte-do-not-allow-prot_mte-on-map_hugetlb-user-mappings.patch
+md-use-separate-work_struct-for-md_start_sync.patch
+md-factor-out-a-helper-from-mddev_put.patch
+md-simplify-md_seq_ops.patch
+md-md-bitmap-replace-md_bitmap_status-with-a-new-hel.patch
+md-md-cluster-fix-spares-warnings-for-__le64.patch
+md-md-bitmap-add-sync_size-into-struct-md_bitmap_sta.patch
+md-md-bitmap-synchronize-bitmap_get_stats-with-bitma.patch
+mm-update-mark_victim-tracepoints-fields.patch
+memcg-fix-soft-lockup-in-the-oom-process.patch
+spi-atmel-quadspi-add-support-for-configuring-cs-tim.patch
+spi-atmel-quadspi-switch-to-use-modern-name.patch
+spi-atmel-quadspi-create-atmel_qspi_ops-to-support-n.patch
+spi-atmel-qspi-memory-barriers-after-memory-mapped-i.patch
+bluetooth-qca-support-downloading-board-id-specific-.patch
+bluetooth-qca-update-firmware-name-to-support-board-.patch
+bluetooth-qca-fix-poor-rf-performance-for-wcn6855.patch
+clk-mediatek-clk-mtk-add-dummy-clock-ops.patch
+clk-mediatek-mt2701-vdec-fix-conversion-to-mtk_clk_s.patch
+clk-mediatek-mt2701-bdp-add-missing-dummy-clk.patch
+clk-mediatek-mt2701-img-add-missing-dummy-clk.patch
+asoc-renesas-rz-ssi-add-a-check-for-negative-sample_.patch
+scsi-core-handle-depopulation-and-restoration-in-pro.patch
+scsi-core-do-not-retry-i-os-during-depopulation.patch
+arm64-dts-mediatek-mt8183-disable-dsi-display-output.patch
+arm64-dts-qcom-trim-addresses-to-8-digits.patch
+arm64-dts-qcom-sm8450-fix-cdsp-memory-length.patch
+tpm-use-managed-allocation-for-bios-event-log.patch
+tpm-change-to-kvalloc-in-eventlog-acpi.c.patch
+soc-mediatek-mtk-devapc-switch-to-devm_clk_get_enabl.patch
+soc-mediatek-mtk-devapc-fix-leaking-io-map-on-error-.patch
+soc-mediatek-mtk-devapc-convert-to-platform-remove-c.patch
+soc-mediatek-mtk-devapc-fix-leaking-io-map-on-driver.patch
+media-switch-to-use-dev_err_probe-helper.patch
+media-uvcvideo-fix-crash-during-unbind-if-gpio-unit-.patch
+media-uvcvideo-refactor-iterators.patch
+media-uvcvideo-only-save-async-fh-if-success.patch
+media-uvcvideo-remove-dangling-pointers.patch
+usb-gadget-core-create-sysfs-link-between-udc-and-ga.patch
+usb-gadget-core-flush-gadget-workqueue-after-device-.patch
+usb-gadget-f_midi-f_midi_complete-to-call-queue_work.patch
+asoc-rockchip-i2s-tdm-fix-shift-config-for-snd_soc_d.patch
+powerpc-64s-mm-move-__real_pte-stubs-into-hash-4k.h.patch
+powerpc-64s-rewrite-__real_pte-and-__rpte_to_hidx-as.patch
+alsa-hda-realtek-fixup-alc225-depop-procedure.patch
+powerpc-code-patching-fix-kasan-hit-by-not-flagging-.patch
+geneve-fix-use-after-free-in-geneve_find_dev.patch
+alsa-hda-cirrus-correct-the-full-scale-volume-set-lo.patch
+ibmvnic-return-error-code-on-tx-scrq-flush-fail.patch
+ibmvnic-introduce-send-sub-crq-direct.patch
+ibmvnic-add-stat-for-tx-direct-vs-tx-batched.patch
+ibmvnic-don-t-reference-skb-after-sending-to-vios.patch
+gtp-suppress-list-corruption-splat-in-gtp_net_exit_b.patch
+geneve-suppress-list-corruption-splat-in-geneve_dest.patch
+flow_dissector-fix-handling-of-mixed-port-and-port-r.patch
+flow_dissector-fix-port-range-key-handling-in-bpf-co.patch
+net-add-non-rcu-dev_getbyhwaddr-helper.patch
+arp-switch-to-dev_getbyhwaddr-in-arp_req_set_public.patch
+net-axienet-set-mac_managed_pm.patch
+tcp-drop-secpath-at-the-same-time-as-we-currently-dr.patch
--- /dev/null
+From 156e40295aee5a15e74ccc917d283206b6c12668 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Sep 2023 11:55:05 +0200
+Subject: soc/mediatek: mtk-devapc: 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 a129ac3555c0dca6f04ae404dc0f0790656587fb ]
+
+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.
+
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/20230925095532.1984344-15-u.kleine-koenig@pengutronix.de
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Stable-dep-of: c9c0036c1990 ("soc: mediatek: mtk-devapc: Fix leaking IO map on driver remove")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/mediatek/mtk-devapc.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/soc/mediatek/mtk-devapc.c b/drivers/soc/mediatek/mtk-devapc.c
+index c72273aae7c64..226a79f43492f 100644
+--- a/drivers/soc/mediatek/mtk-devapc.c
++++ b/drivers/soc/mediatek/mtk-devapc.c
+@@ -300,18 +300,16 @@ static int mtk_devapc_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+-static int mtk_devapc_remove(struct platform_device *pdev)
++static void mtk_devapc_remove(struct platform_device *pdev)
+ {
+ struct mtk_devapc_context *ctx = platform_get_drvdata(pdev);
+
+ stop_devapc(ctx);
+-
+- return 0;
+ }
+
+ static struct platform_driver mtk_devapc_driver = {
+ .probe = mtk_devapc_probe,
+- .remove = mtk_devapc_remove,
++ .remove_new = mtk_devapc_remove,
+ .driver = {
+ .name = "mtk-devapc",
+ .of_match_table = mtk_devapc_dt_match,
+--
+2.39.5
+
--- /dev/null
+From b5b9f48951b42d02fa3b080947a1eb34d83624ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 4 Jan 2025 15:20:12 +0100
+Subject: soc: mediatek: mtk-devapc: Fix leaking IO map on driver remove
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit c9c0036c1990da8d2dd33563e327e05a775fcf10 ]
+
+Driver removal should fully clean up - unmap the memory.
+
+Fixes: 0890beb22618 ("soc: mediatek: add mt6779 devapc driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20250104142012.115974-2-krzysztof.kozlowski@linaro.org
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/mediatek/mtk-devapc.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/soc/mediatek/mtk-devapc.c b/drivers/soc/mediatek/mtk-devapc.c
+index 226a79f43492f..7269ab8d29b64 100644
+--- a/drivers/soc/mediatek/mtk-devapc.c
++++ b/drivers/soc/mediatek/mtk-devapc.c
+@@ -305,6 +305,7 @@ static void mtk_devapc_remove(struct platform_device *pdev)
+ struct mtk_devapc_context *ctx = platform_get_drvdata(pdev);
+
+ stop_devapc(ctx);
++ iounmap(ctx->infra_base);
+ }
+
+ static struct platform_driver mtk_devapc_driver = {
+--
+2.39.5
+
--- /dev/null
+From e63523e5a83c699b50f45304d44f5260feb03ad9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 4 Jan 2025 15:20:11 +0100
+Subject: soc: mediatek: mtk-devapc: Fix leaking IO map on error paths
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit c0eb059a4575ed57f265d9883a5203799c19982c ]
+
+Error paths of mtk_devapc_probe() should unmap the memory. Reported by
+Smatch:
+
+ drivers/soc/mediatek/mtk-devapc.c:292 mtk_devapc_probe() warn: 'ctx->infra_base' from of_iomap() not released on lines: 277,281,286.
+
+Fixes: 0890beb22618 ("soc: mediatek: add mt6779 devapc driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20250104142012.115974-1-krzysztof.kozlowski@linaro.org
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/mediatek/mtk-devapc.c | 18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/soc/mediatek/mtk-devapc.c b/drivers/soc/mediatek/mtk-devapc.c
+index bad139cb117ea..c72273aae7c64 100644
+--- a/drivers/soc/mediatek/mtk-devapc.c
++++ b/drivers/soc/mediatek/mtk-devapc.c
+@@ -273,23 +273,31 @@ static int mtk_devapc_probe(struct platform_device *pdev)
+ return -EINVAL;
+
+ devapc_irq = irq_of_parse_and_map(node, 0);
+- if (!devapc_irq)
+- return -EINVAL;
++ if (!devapc_irq) {
++ ret = -EINVAL;
++ goto err;
++ }
+
+ ctx->infra_clk = devm_clk_get_enabled(&pdev->dev, "devapc-infra-clock");
+- if (IS_ERR(ctx->infra_clk))
+- return -EINVAL;
++ if (IS_ERR(ctx->infra_clk)) {
++ ret = -EINVAL;
++ goto err;
++ }
+
+ ret = devm_request_irq(&pdev->dev, devapc_irq, devapc_violation_irq,
+ IRQF_TRIGGER_NONE, "devapc", ctx);
+ if (ret)
+- return ret;
++ goto err;
+
+ platform_set_drvdata(pdev, ctx);
+
+ start_devapc(ctx);
+
+ return 0;
++
++err:
++ iounmap(ctx->infra_base);
++ return ret;
+ }
+
+ static int mtk_devapc_remove(struct platform_device *pdev)
+--
+2.39.5
+
--- /dev/null
+From 5e1462b46c786b3f2f9b8eeb7f506cf8642261f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Oct 2022 13:09:35 +0200
+Subject: soc: mediatek: mtk-devapc: Switch to devm_clk_get_enabled()
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+[ Upstream commit 916120df5aa926d65f4666c075ed8d4955ef7bab ]
+
+This driver does exactly devm_clk_get() and clk_prepare_enable() right
+after, which is exactly what devm_clk_get_enabled() does: clean that
+up by switching to the latter.
+
+This commit brings no functional changes.
+
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/20221006110935.59695-1-angelogioacchino.delregno@collabora.com
+Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
+Stable-dep-of: c0eb059a4575 ("soc: mediatek: mtk-devapc: Fix leaking IO map on error paths")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/mediatek/mtk-devapc.c | 11 ++---------
+ 1 file changed, 2 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/soc/mediatek/mtk-devapc.c b/drivers/soc/mediatek/mtk-devapc.c
+index fc13334db1b11..bad139cb117ea 100644
+--- a/drivers/soc/mediatek/mtk-devapc.c
++++ b/drivers/soc/mediatek/mtk-devapc.c
+@@ -276,19 +276,14 @@ static int mtk_devapc_probe(struct platform_device *pdev)
+ if (!devapc_irq)
+ return -EINVAL;
+
+- ctx->infra_clk = devm_clk_get(&pdev->dev, "devapc-infra-clock");
++ ctx->infra_clk = devm_clk_get_enabled(&pdev->dev, "devapc-infra-clock");
+ if (IS_ERR(ctx->infra_clk))
+ return -EINVAL;
+
+- if (clk_prepare_enable(ctx->infra_clk))
+- return -EINVAL;
+-
+ ret = devm_request_irq(&pdev->dev, devapc_irq, devapc_violation_irq,
+ IRQF_TRIGGER_NONE, "devapc", ctx);
+- if (ret) {
+- clk_disable_unprepare(ctx->infra_clk);
++ if (ret)
+ return ret;
+- }
+
+ platform_set_drvdata(pdev, ctx);
+
+@@ -303,8 +298,6 @@ static int mtk_devapc_remove(struct platform_device *pdev)
+
+ stop_devapc(ctx);
+
+- clk_disable_unprepare(ctx->infra_clk);
+-
+ return 0;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From f94dafce8b288f1ee2fe8a321205cc2abc210ede Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Dec 2024 10:12:58 +0100
+Subject: spi: atmel-qspi: Memory barriers after memory-mapped I/O
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Bence Csókás <csokas.bence@prolan.hu>
+
+[ Upstream commit be92ab2de0ee1a13291c3b47b2d7eb24d80c0a2c ]
+
+The QSPI peripheral control and status registers are
+accessible via the SoC's APB bus, whereas MMIO transactions'
+data travels on the AHB bus.
+
+Microchip documentation and even sample code from Atmel
+emphasises the need for a memory barrier before the first
+MMIO transaction to the AHB-connected QSPI, and before the
+last write to its registers via APB. This is achieved by
+the following lines in `atmel_qspi_transfer()`:
+
+ /* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */
+ (void)atmel_qspi_read(aq, QSPI_IFR);
+
+However, the current documentation makes no mention to
+synchronization requirements in the other direction, i.e.
+after the last data written via AHB, and before the first
+register access on APB.
+
+In our case, we were facing an issue where the QSPI peripheral
+would cease to send any new CSR (nCS Rise) interrupts,
+leading to a timeout in `atmel_qspi_wait_for_completion()`
+and ultimately this panic in higher levels:
+
+ ubi0 error: ubi_io_write: error -110 while writing 63108 bytes
+ to PEB 491:128, written 63104 bytes
+
+After months of extensive research of the codebase, fiddling
+around the debugger with kgdb, and back-and-forth with
+Microchip, we came to the conclusion that the issue is
+probably that the peripheral is still busy receiving on AHB
+when the LASTXFER bit is written to its Control Register
+on APB, therefore this write gets lost, and the peripheral
+still thinks there is more data to come in the MMIO transfer.
+This was first formulated when we noticed that doubling the
+write() of QSPI_CR_LASTXFER seemed to solve the problem.
+
+Ultimately, the solution is to introduce memory barriers
+after the AHB-mapped MMIO transfers, to ensure ordering.
+
+Fixes: d5433def3153 ("mtd: spi-nor: atmel-quadspi: Add spi-mem support to atmel-quadspi")
+Cc: Hari.PrasathGE@microchip.com
+Cc: Mahesh.Abotula@microchip.com
+Cc: Marco.Cardellini@microchip.com
+Cc: stable@vger.kernel.org # c0a0203cf579: ("spi: atmel-quadspi: Create `atmel_qspi_ops`"...)
+Cc: stable@vger.kernel.org # 6.x.y
+Signed-off-by: Bence Csókás <csokas.bence@prolan.hu>
+Link: https://patch.msgid.link/20241219091258.395187-1-csokas.bence@prolan.hu
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/atmel-quadspi.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
+index 32fcab2a11885..a62baef08e6a8 100644
+--- a/drivers/spi/atmel-quadspi.c
++++ b/drivers/spi/atmel-quadspi.c
+@@ -454,13 +454,20 @@ static int atmel_qspi_transfer(struct spi_mem *mem,
+ (void)atmel_qspi_read(aq, QSPI_IFR);
+
+ /* Send/Receive data */
+- if (op->data.dir == SPI_MEM_DATA_IN)
++ if (op->data.dir == SPI_MEM_DATA_IN) {
+ memcpy_fromio(op->data.buf.in, aq->mem + offset,
+ op->data.nbytes);
+- else
++
++ /* Synchronize AHB and APB accesses again */
++ rmb();
++ } else {
+ memcpy_toio(aq->mem + offset, op->data.buf.out,
+ op->data.nbytes);
+
++ /* Synchronize AHB and APB accesses again */
++ wmb();
++ }
++
+ /* Release the chip-select */
+ atmel_qspi_write(QSPI_CR_LASTXFER, aq, QSPI_CR);
+
+--
+2.39.5
+
--- /dev/null
+From 0bc9e42a19c041f6000bc5d631310760f9ae4f2c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Nov 2022 12:52:45 +0200
+Subject: spi: atmel-quadspi: Add support for configuring CS timing
+
+From: Tudor Ambarus <tudor.ambarus@microchip.com>
+
+[ Upstream commit f732646d0ccd22f42ed7de5e59c0abb7a848e034 ]
+
+The at91 QSPI IP uses a default value of half of the period of the QSPI
+clock period for the cs-setup time, which is not always enough, an example
+being the sst26vf064b SPI NOR flash which requires a minimum cs-setup time
+of 5 ns. It was observed that none of the at91 SoCs can fulfill the
+minimum CS setup time for the aforementioned flash, as they operate at
+high frequencies and half a period does not suffice for the required CS
+setup time. Add support for configuring the CS timing in the controller.
+
+Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
+Link: https://lore.kernel.org/r/20221117105249.115649-5-tudor.ambarus@microchip.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: be92ab2de0ee ("spi: atmel-qspi: Memory barriers after memory-mapped I/O")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/atmel-quadspi.c | 34 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
+index b5afe5790b1d2..58d5336b954d9 100644
+--- a/drivers/spi/atmel-quadspi.c
++++ b/drivers/spi/atmel-quadspi.c
+@@ -510,6 +510,39 @@ static int atmel_qspi_setup(struct spi_device *spi)
+ return 0;
+ }
+
++static int atmel_qspi_set_cs_timing(struct spi_device *spi)
++{
++ struct spi_controller *ctrl = spi->master;
++ struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
++ unsigned long clk_rate;
++ u32 cs_setup;
++ int delay;
++ int ret;
++
++ delay = spi_delay_to_ns(&spi->cs_setup, NULL);
++ if (delay <= 0)
++ return delay;
++
++ clk_rate = clk_get_rate(aq->pclk);
++ if (!clk_rate)
++ return -EINVAL;
++
++ cs_setup = DIV_ROUND_UP((delay * DIV_ROUND_UP(clk_rate, 1000000)),
++ 1000);
++
++ ret = pm_runtime_resume_and_get(ctrl->dev.parent);
++ if (ret < 0)
++ return ret;
++
++ aq->scr |= QSPI_SCR_DLYBS(cs_setup);
++ atmel_qspi_write(aq->scr, aq, QSPI_SCR);
++
++ pm_runtime_mark_last_busy(ctrl->dev.parent);
++ pm_runtime_put_autosuspend(ctrl->dev.parent);
++
++ return 0;
++}
++
+ static void atmel_qspi_init(struct atmel_qspi *aq)
+ {
+ /* Reset the QSPI controller */
+@@ -555,6 +588,7 @@ static int atmel_qspi_probe(struct platform_device *pdev)
+
+ ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD;
+ ctrl->setup = atmel_qspi_setup;
++ ctrl->set_cs_timing = atmel_qspi_set_cs_timing;
+ ctrl->bus_num = -1;
+ ctrl->mem_ops = &atmel_qspi_mem_ops;
+ ctrl->num_chipselect = 1;
+--
+2.39.5
+
--- /dev/null
+From b619034e9078340186d81e0032a07dcfcdd4ddcb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Nov 2024 18:43:14 +0100
+Subject: spi: atmel-quadspi: Create `atmel_qspi_ops` to support newer SoC
+ families
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Csókás, Bence <csokas.bence@prolan.hu>
+
+[ Upstream commit c0a0203cf57963792d59b3e4317a1d07b73df42a ]
+
+Refactor the code to introduce an ops struct, to prepare for merging
+support for later SoCs, such as SAMA7G5. This code was based on the
+vendor's kernel (linux4microchip). Cc'ing original contributors.
+
+Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu>
+Link: https://patch.msgid.link/20241128174316.3209354-2-csokas.bence@prolan.hu
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: be92ab2de0ee ("spi: atmel-qspi: Memory barriers after memory-mapped I/O")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/atmel-quadspi.c | 111 +++++++++++++++++++++++++-----------
+ 1 file changed, 77 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
+index bc6dfb6d86546..32fcab2a11885 100644
+--- a/drivers/spi/atmel-quadspi.c
++++ b/drivers/spi/atmel-quadspi.c
+@@ -138,11 +138,15 @@
+ #define QSPI_WPSR_WPVSRC_MASK GENMASK(15, 8)
+ #define QSPI_WPSR_WPVSRC(src) (((src) << 8) & QSPI_WPSR_WPVSRC)
+
++#define ATMEL_QSPI_TIMEOUT 1000 /* ms */
++
+ struct atmel_qspi_caps {
+ bool has_qspick;
+ bool has_ricr;
+ };
+
++struct atmel_qspi_ops;
++
+ struct atmel_qspi {
+ void __iomem *regs;
+ void __iomem *mem;
+@@ -150,13 +154,22 @@ struct atmel_qspi {
+ struct clk *qspick;
+ struct platform_device *pdev;
+ const struct atmel_qspi_caps *caps;
++ const struct atmel_qspi_ops *ops;
+ resource_size_t mmap_size;
+ u32 pending;
++ u32 irq_mask;
+ u32 mr;
+ u32 scr;
+ struct completion cmd_completion;
+ };
+
++struct atmel_qspi_ops {
++ int (*set_cfg)(struct atmel_qspi *aq, const struct spi_mem_op *op,
++ u32 *offset);
++ int (*transfer)(struct spi_mem *mem, const struct spi_mem_op *op,
++ u32 offset);
++};
++
+ struct atmel_qspi_mode {
+ u8 cmd_buswidth;
+ u8 addr_buswidth;
+@@ -404,10 +417,60 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
+ return 0;
+ }
+
++static int atmel_qspi_wait_for_completion(struct atmel_qspi *aq, u32 irq_mask)
++{
++ int err = 0;
++ u32 sr;
++
++ /* Poll INSTRuction End status */
++ sr = atmel_qspi_read(aq, QSPI_SR);
++ if ((sr & irq_mask) == irq_mask)
++ return 0;
++
++ /* Wait for INSTRuction End interrupt */
++ reinit_completion(&aq->cmd_completion);
++ aq->pending = sr & irq_mask;
++ aq->irq_mask = irq_mask;
++ atmel_qspi_write(irq_mask, aq, QSPI_IER);
++ if (!wait_for_completion_timeout(&aq->cmd_completion,
++ msecs_to_jiffies(ATMEL_QSPI_TIMEOUT)))
++ err = -ETIMEDOUT;
++ atmel_qspi_write(irq_mask, aq, QSPI_IDR);
++
++ return err;
++}
++
++static int atmel_qspi_transfer(struct spi_mem *mem,
++ const struct spi_mem_op *op, u32 offset)
++{
++ struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->controller);
++
++ /* Skip to the final steps if there is no data */
++ if (!op->data.nbytes)
++ return atmel_qspi_wait_for_completion(aq,
++ QSPI_SR_CMD_COMPLETED);
++
++ /* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */
++ (void)atmel_qspi_read(aq, QSPI_IFR);
++
++ /* Send/Receive data */
++ if (op->data.dir == SPI_MEM_DATA_IN)
++ memcpy_fromio(op->data.buf.in, aq->mem + offset,
++ op->data.nbytes);
++ else
++ memcpy_toio(aq->mem + offset, op->data.buf.out,
++ op->data.nbytes);
++
++ /* Release the chip-select */
++ atmel_qspi_write(QSPI_CR_LASTXFER, aq, QSPI_CR);
++
++ return atmel_qspi_wait_for_completion(aq, QSPI_SR_CMD_COMPLETED);
++}
++
+ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
+ {
+ struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->controller);
+- u32 sr, offset;
++ u32 offset;
+ int err;
+
+ /*
+@@ -416,46 +479,20 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
+ * when the flash memories overrun the controller's memory space.
+ */
+ if (op->addr.val + op->data.nbytes > aq->mmap_size)
+- return -ENOTSUPP;
++ return -EOPNOTSUPP;
++
++ if (op->addr.nbytes > 4)
++ return -EOPNOTSUPP;
+
+ err = pm_runtime_resume_and_get(&aq->pdev->dev);
+ if (err < 0)
+ return err;
+
+- err = atmel_qspi_set_cfg(aq, op, &offset);
++ err = aq->ops->set_cfg(aq, op, &offset);
+ if (err)
+ goto pm_runtime_put;
+
+- /* Skip to the final steps if there is no data */
+- if (op->data.nbytes) {
+- /* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */
+- (void)atmel_qspi_read(aq, QSPI_IFR);
+-
+- /* Send/Receive data */
+- if (op->data.dir == SPI_MEM_DATA_IN)
+- memcpy_fromio(op->data.buf.in, aq->mem + offset,
+- op->data.nbytes);
+- else
+- memcpy_toio(aq->mem + offset, op->data.buf.out,
+- op->data.nbytes);
+-
+- /* Release the chip-select */
+- atmel_qspi_write(QSPI_CR_LASTXFER, aq, QSPI_CR);
+- }
+-
+- /* Poll INSTRuction End status */
+- sr = atmel_qspi_read(aq, QSPI_SR);
+- if ((sr & QSPI_SR_CMD_COMPLETED) == QSPI_SR_CMD_COMPLETED)
+- goto pm_runtime_put;
+-
+- /* Wait for INSTRuction End interrupt */
+- reinit_completion(&aq->cmd_completion);
+- aq->pending = sr & QSPI_SR_CMD_COMPLETED;
+- atmel_qspi_write(QSPI_SR_CMD_COMPLETED, aq, QSPI_IER);
+- if (!wait_for_completion_timeout(&aq->cmd_completion,
+- msecs_to_jiffies(1000)))
+- err = -ETIMEDOUT;
+- atmel_qspi_write(QSPI_SR_CMD_COMPLETED, aq, QSPI_IDR);
++ err = aq->ops->transfer(mem, op, offset);
+
+ pm_runtime_put:
+ pm_runtime_mark_last_busy(&aq->pdev->dev);
+@@ -569,12 +606,17 @@ static irqreturn_t atmel_qspi_interrupt(int irq, void *dev_id)
+ return IRQ_NONE;
+
+ aq->pending |= pending;
+- if ((aq->pending & QSPI_SR_CMD_COMPLETED) == QSPI_SR_CMD_COMPLETED)
++ if ((aq->pending & aq->irq_mask) == aq->irq_mask)
+ complete(&aq->cmd_completion);
+
+ return IRQ_HANDLED;
+ }
+
++static const struct atmel_qspi_ops atmel_qspi_ops = {
++ .set_cfg = atmel_qspi_set_cfg,
++ .transfer = atmel_qspi_transfer,
++};
++
+ static int atmel_qspi_probe(struct platform_device *pdev)
+ {
+ struct spi_controller *ctrl;
+@@ -599,6 +641,7 @@ static int atmel_qspi_probe(struct platform_device *pdev)
+
+ init_completion(&aq->cmd_completion);
+ aq->pdev = pdev;
++ aq->ops = &atmel_qspi_ops;
+
+ /* Map the registers */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_base");
+--
+2.39.5
+
--- /dev/null
+From 188b5b5efa039e045400e9c7972c5362a9fdd038 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Jan 2023 21:18:05 +0800
+Subject: spi: atmel-quadspi: switch to use modern name
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+[ Upstream commit ccbc6554ed66dc37778b8ed823bcaaabfb1731cf ]
+
+Change legacy name master to modern name host or controller.
+
+No functional changed.
+
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+Link: https://lore.kernel.org/r/20230110131805.2827248-4-yangyingliang@huawei.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: be92ab2de0ee ("spi: atmel-qspi: Memory barriers after memory-mapped I/O")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/atmel-quadspi.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
+index 58d5336b954d9..bc6dfb6d86546 100644
+--- a/drivers/spi/atmel-quadspi.c
++++ b/drivers/spi/atmel-quadspi.c
+@@ -406,7 +406,7 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
+
+ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
+ {
+- struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->master);
++ struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->controller);
+ u32 sr, offset;
+ int err;
+
+@@ -476,7 +476,7 @@ static const struct spi_controller_mem_ops atmel_qspi_mem_ops = {
+
+ static int atmel_qspi_setup(struct spi_device *spi)
+ {
+- struct spi_controller *ctrl = spi->master;
++ struct spi_controller *ctrl = spi->controller;
+ struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
+ unsigned long src_rate;
+ u32 scbr;
+@@ -512,7 +512,7 @@ static int atmel_qspi_setup(struct spi_device *spi)
+
+ static int atmel_qspi_set_cs_timing(struct spi_device *spi)
+ {
+- struct spi_controller *ctrl = spi->master;
++ struct spi_controller *ctrl = spi->controller;
+ struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
+ unsigned long clk_rate;
+ u32 cs_setup;
+@@ -582,7 +582,7 @@ static int atmel_qspi_probe(struct platform_device *pdev)
+ struct resource *res;
+ int irq, err = 0;
+
+- ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(*aq));
++ ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(*aq));
+ if (!ctrl)
+ return -ENOMEM;
+
+--
+2.39.5
+
--- /dev/null
+From 57aac95b5e7a8b138108772314b23af40f282b4b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 11:23:35 +0100
+Subject: tcp: drop secpath at the same time as we currently drop dst
+
+From: Sabrina Dubroca <sd@queasysnail.net>
+
+[ Upstream commit 9b6412e6979f6f9e0632075f8f008937b5cd4efd ]
+
+Xiumei reported hitting the WARN in xfrm6_tunnel_net_exit while
+running tests that boil down to:
+ - create a pair of netns
+ - run a basic TCP test over ipcomp6
+ - delete the pair of netns
+
+The xfrm_state found on spi_byaddr was not deleted at the time we
+delete the netns, because we still have a reference on it. This
+lingering reference comes from a secpath (which holds a ref on the
+xfrm_state), which is still attached to an skb. This skb is not
+leaked, it ends up on sk_receive_queue and then gets defer-free'd by
+skb_attempt_defer_free.
+
+The problem happens when we defer freeing an skb (push it on one CPU's
+defer_list), and don't flush that list before the netns is deleted. In
+that case, we still have a reference on the xfrm_state that we don't
+expect at this point.
+
+We already drop the skb's dst in the TCP receive path when it's no
+longer needed, so let's also drop the secpath. At this point,
+tcp_filter has already called into the LSM hooks that may require the
+secpath, so it should not be needed anymore. However, in some of those
+places, the MPTCP extension has just been attached to the skb, so we
+cannot simply drop all extensions.
+
+Fixes: 68822bdf76f1 ("net: generalize skb freeing deferral to per-cpu lists")
+Reported-by: Xiumei Mu <xmu@redhat.com>
+Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/5055ba8f8f72bdcb602faa299faca73c280b7735.1739743613.git.sd@queasysnail.net
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/tcp.h | 14 ++++++++++++++
+ net/ipv4/tcp_fastopen.c | 4 ++--
+ net/ipv4/tcp_input.c | 8 ++++----
+ net/ipv4/tcp_ipv4.c | 2 +-
+ 4 files changed, 21 insertions(+), 7 deletions(-)
+
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index a770210fda9bc..14a00cdd31f42 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -40,6 +40,7 @@
+ #include <net/inet_ecn.h>
+ #include <net/dst.h>
+ #include <net/mptcp.h>
++#include <net/xfrm.h>
+
+ #include <linux/seq_file.h>
+ #include <linux/memcontrol.h>
+@@ -640,6 +641,19 @@ void tcp_fin(struct sock *sk);
+ void tcp_check_space(struct sock *sk);
+ void tcp_sack_compress_send_ack(struct sock *sk);
+
++static inline void tcp_cleanup_skb(struct sk_buff *skb)
++{
++ skb_dst_drop(skb);
++ secpath_reset(skb);
++}
++
++static inline void tcp_add_receive_queue(struct sock *sk, struct sk_buff *skb)
++{
++ DEBUG_NET_WARN_ON_ONCE(skb_dst(skb));
++ DEBUG_NET_WARN_ON_ONCE(secpath_exists(skb));
++ __skb_queue_tail(&sk->sk_receive_queue, skb);
++}
++
+ /* tcp_timer.c */
+ void tcp_init_xmit_timers(struct sock *);
+ static inline void tcp_clear_xmit_timers(struct sock *sk)
+diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c
+index d0b7ded591bd4..cb01c770d8cf5 100644
+--- a/net/ipv4/tcp_fastopen.c
++++ b/net/ipv4/tcp_fastopen.c
+@@ -178,7 +178,7 @@ void tcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb)
+ if (!skb)
+ return;
+
+- skb_dst_drop(skb);
++ tcp_cleanup_skb(skb);
+ /* segs_in has been initialized to 1 in tcp_create_openreq_child().
+ * Hence, reset segs_in to 0 before calling tcp_segs_in()
+ * to avoid double counting. Also, tcp_segs_in() expects
+@@ -195,7 +195,7 @@ void tcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb)
+ TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_SYN;
+
+ tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+- __skb_queue_tail(&sk->sk_receive_queue, skb);
++ tcp_add_receive_queue(sk, skb);
+ tp->syn_data_acked = 1;
+
+ /* u64_stats_update_begin(&tp->syncp) not needed here,
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index 2379ee5511645..3b81f6df829ff 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -4836,7 +4836,7 @@ static void tcp_ofo_queue(struct sock *sk)
+ tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq);
+ fin = TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN;
+ if (!eaten)
+- __skb_queue_tail(&sk->sk_receive_queue, skb);
++ tcp_add_receive_queue(sk, skb);
+ else
+ kfree_skb_partial(skb, fragstolen);
+
+@@ -5027,7 +5027,7 @@ static int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb,
+ skb, fragstolen)) ? 1 : 0;
+ tcp_rcv_nxt_update(tcp_sk(sk), TCP_SKB_CB(skb)->end_seq);
+ if (!eaten) {
+- __skb_queue_tail(&sk->sk_receive_queue, skb);
++ tcp_add_receive_queue(sk, skb);
+ skb_set_owner_r(skb, sk);
+ }
+ return eaten;
+@@ -5110,7 +5110,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
+ __kfree_skb(skb);
+ return;
+ }
+- skb_dst_drop(skb);
++ tcp_cleanup_skb(skb);
+ __skb_pull(skb, tcp_hdr(skb)->doff * 4);
+
+ reason = SKB_DROP_REASON_NOT_SPECIFIED;
+@@ -6041,7 +6041,7 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb)
+ NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPHPHITS);
+
+ /* Bulk data transfer: receiver */
+- skb_dst_drop(skb);
++ tcp_cleanup_skb(skb);
+ __skb_pull(skb, tcp_header_len);
+ eaten = tcp_queue_rcv(sk, skb, &fragstolen);
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 805b1a9eca1c5..7647f1ec0584e 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -1791,7 +1791,7 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb,
+ */
+ skb_condense(skb);
+
+- skb_dst_drop(skb);
++ tcp_cleanup_skb(skb);
+
+ if (unlikely(tcp_checksum_complete(skb))) {
+ bh_unlock_sock(sk);
+--
+2.39.5
+
--- /dev/null
+From 1d89fb48fbca52d3c909fff02f71563f523c7d9a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Dec 2024 17:39:09 +0200
+Subject: tpm: Change to kvalloc() in eventlog/acpi.c
+
+From: Jarkko Sakkinen <jarkko@kernel.org>
+
+[ Upstream commit a3a860bc0fd6c07332e4911cf9a238d20de90173 ]
+
+The following failure was reported on HPE ProLiant D320:
+
+[ 10.693310][ T1] tpm_tis STM0925:00: 2.0 TPM (device-id 0x3, rev-id 0)
+[ 10.848132][ T1] ------------[ cut here ]------------
+[ 10.853559][ T1] WARNING: CPU: 59 PID: 1 at mm/page_alloc.c:4727 __alloc_pages_noprof+0x2ca/0x330
+[ 10.862827][ T1] Modules linked in:
+[ 10.866671][ T1] CPU: 59 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.12.0-lp155.2.g52785e2-default #1 openSUSE Tumbleweed (unreleased) 588cd98293a7c9eba9013378d807364c088c9375
+[ 10.882741][ T1] Hardware name: HPE ProLiant DL320 Gen12/ProLiant DL320 Gen12, BIOS 1.20 10/28/2024
+[ 10.892170][ T1] RIP: 0010:__alloc_pages_noprof+0x2ca/0x330
+[ 10.898103][ T1] Code: 24 08 e9 4a fe ff ff e8 34 36 fa ff e9 88 fe ff ff 83 fe 0a 0f 86 b3 fd ff ff 80 3d 01 e7 ce 01 00 75 09 c6 05 f8 e6 ce 01 01 <0f> 0b 45 31 ff e9 e5 fe ff ff f7 c2 00 00 08 00 75 42 89 d9 80 e1
+[ 10.917750][ T1] RSP: 0000:ffffb7cf40077980 EFLAGS: 00010246
+[ 10.923777][ T1] RAX: 0000000000000000 RBX: 0000000000040cc0 RCX: 0000000000000000
+[ 10.931727][ T1] RDX: 0000000000000000 RSI: 000000000000000c RDI: 0000000000040cc0
+
+The above transcript shows that ACPI pointed a 16 MiB buffer for the log
+events because RSI maps to the 'order' parameter of __alloc_pages_noprof().
+Address the bug by moving from devm_kmalloc() to devm_add_action() and
+kvmalloc() and devm_add_action().
+
+Suggested-by: Ard Biesheuvel <ardb@kernel.org>
+Cc: stable@vger.kernel.org # v2.6.16+
+Fixes: 55a82ab3181b ("[PATCH] tpm: add bios measurement log")
+Reported-by: Andy Liang <andy.liang@hpe.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219495
+Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
+Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Andy Liang <andy.liang@hpe.com>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/tpm/eventlog/acpi.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/char/tpm/eventlog/acpi.c b/drivers/char/tpm/eventlog/acpi.c
+index bd757d836c5cf..1a5644051d310 100644
+--- a/drivers/char/tpm/eventlog/acpi.c
++++ b/drivers/char/tpm/eventlog/acpi.c
+@@ -63,6 +63,11 @@ static bool tpm_is_tpm2_log(void *bios_event_log, u64 len)
+ return n == 0;
+ }
+
++static void tpm_bios_log_free(void *data)
++{
++ kvfree(data);
++}
++
+ /* read binary bios log */
+ int tpm_read_log_acpi(struct tpm_chip *chip)
+ {
+@@ -136,7 +141,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
+ }
+
+ /* malloc EventLog space */
+- log->bios_event_log = devm_kmalloc(&chip->dev, len, GFP_KERNEL);
++ log->bios_event_log = kvmalloc(len, GFP_KERNEL);
+ if (!log->bios_event_log)
+ return -ENOMEM;
+
+@@ -162,10 +167,16 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
+ goto err;
+ }
+
++ ret = devm_add_action(&chip->dev, tpm_bios_log_free, log->bios_event_log);
++ if (ret) {
++ log->bios_event_log = NULL;
++ goto err;
++ }
++
+ return format;
+
+ err:
+- devm_kfree(&chip->dev, log->bios_event_log);
++ tpm_bios_log_free(log->bios_event_log);
+ log->bios_event_log = NULL;
+ return ret;
+ }
+--
+2.39.5
+
--- /dev/null
+From e0d9fc7442296fee38dbeea7a58ddc56c10258b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 26 Jan 2023 15:08:09 -0600
+Subject: tpm: Use managed allocation for bios event log
+
+From: Eddie James <eajames@linux.ibm.com>
+
+[ Upstream commit 441b7152729f4a2bdb100135a58625fa0aeb69e4 ]
+
+Since the bios event log is freed in the device release function,
+let devres handle the deallocation. This will allow other memory
+allocation/mapping functions to be used for the bios event log.
+
+Signed-off-by: Eddie James <eajames@linux.ibm.com>
+Tested-by: Jarkko Sakkinen <jarkko@kernel.org>
+Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Stable-dep-of: a3a860bc0fd6 ("tpm: Change to kvalloc() in eventlog/acpi.c")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/tpm/eventlog/acpi.c | 5 +++--
+ drivers/char/tpm/eventlog/efi.c | 13 +++++++------
+ drivers/char/tpm/eventlog/of.c | 3 ++-
+ drivers/char/tpm/tpm-chip.c | 1 -
+ 4 files changed, 12 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/char/tpm/eventlog/acpi.c b/drivers/char/tpm/eventlog/acpi.c
+index cd266021d0103..bd757d836c5cf 100644
+--- a/drivers/char/tpm/eventlog/acpi.c
++++ b/drivers/char/tpm/eventlog/acpi.c
+@@ -14,6 +14,7 @@
+ * Access to the event log extended by the TCG BIOS of PC platform
+ */
+
++#include <linux/device.h>
+ #include <linux/seq_file.h>
+ #include <linux/fs.h>
+ #include <linux/security.h>
+@@ -135,7 +136,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
+ }
+
+ /* malloc EventLog space */
+- log->bios_event_log = kmalloc(len, GFP_KERNEL);
++ log->bios_event_log = devm_kmalloc(&chip->dev, len, GFP_KERNEL);
+ if (!log->bios_event_log)
+ return -ENOMEM;
+
+@@ -164,7 +165,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
+ return format;
+
+ err:
+- kfree(log->bios_event_log);
++ devm_kfree(&chip->dev, log->bios_event_log);
+ log->bios_event_log = NULL;
+ return ret;
+ }
+diff --git a/drivers/char/tpm/eventlog/efi.c b/drivers/char/tpm/eventlog/efi.c
+index e6cb9d525e30c..4e9d7c2bf32ee 100644
+--- a/drivers/char/tpm/eventlog/efi.c
++++ b/drivers/char/tpm/eventlog/efi.c
+@@ -6,6 +6,7 @@
+ * Thiebaud Weksteen <tweek@google.com>
+ */
+
++#include <linux/device.h>
+ #include <linux/efi.h>
+ #include <linux/tpm_eventlog.h>
+
+@@ -55,7 +56,7 @@ int tpm_read_log_efi(struct tpm_chip *chip)
+ }
+
+ /* malloc EventLog space */
+- log->bios_event_log = kmemdup(log_tbl->log, log_size, GFP_KERNEL);
++ log->bios_event_log = devm_kmemdup(&chip->dev, log_tbl->log, log_size, GFP_KERNEL);
+ if (!log->bios_event_log) {
+ ret = -ENOMEM;
+ goto out;
+@@ -76,7 +77,7 @@ int tpm_read_log_efi(struct tpm_chip *chip)
+ MEMREMAP_WB);
+ if (!final_tbl) {
+ pr_err("Could not map UEFI TPM final log\n");
+- kfree(log->bios_event_log);
++ devm_kfree(&chip->dev, log->bios_event_log);
+ ret = -ENOMEM;
+ goto out;
+ }
+@@ -91,11 +92,11 @@ int tpm_read_log_efi(struct tpm_chip *chip)
+ * Allocate memory for the 'combined log' where we will append the
+ * 'final events log' to.
+ */
+- tmp = krealloc(log->bios_event_log,
+- log_size + final_events_log_size,
+- GFP_KERNEL);
++ tmp = devm_krealloc(&chip->dev, log->bios_event_log,
++ log_size + final_events_log_size,
++ GFP_KERNEL);
+ if (!tmp) {
+- kfree(log->bios_event_log);
++ devm_kfree(&chip->dev, log->bios_event_log);
+ ret = -ENOMEM;
+ goto out;
+ }
+diff --git a/drivers/char/tpm/eventlog/of.c b/drivers/char/tpm/eventlog/of.c
+index a9ce66d09a754..741ab2204b11a 100644
+--- a/drivers/char/tpm/eventlog/of.c
++++ b/drivers/char/tpm/eventlog/of.c
+@@ -10,6 +10,7 @@
+ * Read the event log created by the firmware on PPC64
+ */
+
++#include <linux/device.h>
+ #include <linux/slab.h>
+ #include <linux/of.h>
+ #include <linux/tpm_eventlog.h>
+@@ -65,7 +66,7 @@ int tpm_read_log_of(struct tpm_chip *chip)
+ return -EIO;
+ }
+
+- log->bios_event_log = kmemdup(__va(base), size, GFP_KERNEL);
++ log->bios_event_log = devm_kmemdup(&chip->dev, __va(base), size, GFP_KERNEL);
+ if (!log->bios_event_log)
+ return -ENOMEM;
+
+diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
+index c0759d49fd145..916ee815b1401 100644
+--- a/drivers/char/tpm/tpm-chip.c
++++ b/drivers/char/tpm/tpm-chip.c
+@@ -267,7 +267,6 @@ static void tpm_dev_release(struct device *dev)
+ idr_remove(&dev_nums_idr, chip->dev_num);
+ mutex_unlock(&idr_lock);
+
+- kfree(chip->log.bios_event_log);
+ kfree(chip->work_space.context_buf);
+ kfree(chip->work_space.session_buf);
+ kfree(chip->allocated_banks);
+--
+2.39.5
+
--- /dev/null
+From b1e7b4ac6d8af9f53e3cc4beb2bea5f38caf86ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Mar 2024 03:09:22 +0000
+Subject: USB: gadget: core: create sysfs link between udc and gadget
+
+From: Roy Luo <royluo@google.com>
+
+[ Upstream commit 0ef40f399aa2be8c04aee9b7430705612c104ce5 ]
+
+udc device and gadget device are tightly coupled, yet there's no good
+way to corelate the two. Add a sysfs link in udc that points to the
+corresponding gadget device.
+An example use case: userspace configures a f_midi configfs driver and
+bind the udc device, then it tries to locate the corresponding midi
+device, which is a child device of the gadget device. The gadget device
+that's associated to the udc device has to be identified in order to
+index the midi device. Having a sysfs link would make things much
+easier.
+
+Signed-off-by: Roy Luo <royluo@google.com>
+Link: https://lore.kernel.org/r/20240307030922.3573161-1-royluo@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 399a45e5237c ("usb: gadget: core: flush gadget workqueue after device removal")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/gadget/udc/core.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 6d7f8e98ba2a8..5085580eeb3ad 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1419,8 +1419,16 @@ int usb_add_gadget(struct usb_gadget *gadget)
+ if (ret)
+ goto err_free_id;
+
++ ret = sysfs_create_link(&udc->dev.kobj,
++ &gadget->dev.kobj, "gadget");
++ if (ret)
++ goto err_del_gadget;
++
+ return 0;
+
++ err_del_gadget:
++ device_del(&gadget->dev);
++
+ err_free_id:
+ ida_free(&gadget_id_numbers, gadget->id_number);
+
+@@ -1529,6 +1537,7 @@ void usb_del_gadget(struct usb_gadget *gadget)
+ mutex_unlock(&udc_lock);
+
+ kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
++ sysfs_remove_link(&udc->dev.kobj, "gadget");
+ flush_work(&gadget->work);
+ device_del(&gadget->dev);
+ ida_free(&gadget_id_numbers, gadget->id_number);
+--
+2.39.5
+
--- /dev/null
+From 00a31faf1dff85bee2dc0b804e3631af0b587238 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 23:36:42 +0000
+Subject: usb: gadget: core: flush gadget workqueue after device removal
+
+From: Roy Luo <royluo@google.com>
+
+[ Upstream commit 399a45e5237ca14037120b1b895bd38a3b4492ea ]
+
+device_del() can lead to new work being scheduled in gadget->work
+workqueue. This is observed, for example, with the dwc3 driver with the
+following call stack:
+ device_del()
+ gadget_unbind_driver()
+ usb_gadget_disconnect_locked()
+ dwc3_gadget_pullup()
+ dwc3_gadget_soft_disconnect()
+ usb_gadget_set_state()
+ schedule_work(&gadget->work)
+
+Move flush_work() after device_del() to ensure the workqueue is cleaned
+up.
+
+Fixes: 5702f75375aa9 ("usb: gadget: udc-core: move sysfs_notify() to a workqueue")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Roy Luo <royluo@google.com>
+Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
+Reviewed-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://lore.kernel.org/r/20250204233642.666991-1-royluo@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/gadget/udc/core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 5085580eeb3ad..5adb6e831126a 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1538,8 +1538,8 @@ void usb_del_gadget(struct usb_gadget *gadget)
+
+ kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
+ sysfs_remove_link(&udc->dev.kobj, "gadget");
+- flush_work(&gadget->work);
+ device_del(&gadget->dev);
++ flush_work(&gadget->work);
+ ida_free(&gadget_id_numbers, gadget->id_number);
+ cancel_work_sync(&udc->vbus_work);
+ device_unregister(&udc->dev);
+--
+2.39.5
+
--- /dev/null
+From 868e22af433cbf7467e003c9fb2309acb4dfe308 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Feb 2025 10:48:05 -0700
+Subject: USB: gadget: f_midi: f_midi_complete to call queue_work
+
+From: Jill Donahue <jilliandonahue58@gmail.com>
+
+[ Upstream commit 4ab37fcb42832cdd3e9d5e50653285ca84d6686f ]
+
+When using USB MIDI, a lock is attempted to be acquired twice through a
+re-entrant call to f_midi_transmit, causing a deadlock.
+
+Fix it by using queue_work() to schedule the inner f_midi_transmit() via
+a high priority work queue from the completion handler.
+
+Link: https://lore.kernel.org/all/CAArt=LjxU0fUZOj06X+5tkeGT+6RbXzpWg1h4t4Fwa_KGVAX6g@mail.gmail.com/
+Fixes: d5daf49b58661 ("USB: gadget: midi: add midi function driver")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Jill Donahue <jilliandonahue58@gmail.com>
+Link: https://lore.kernel.org/r/20250211174805.1369265-1-jdonahue@fender.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/gadget/function/f_midi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
+index 1d8521103b661..dd1cfeeffb671 100644
+--- a/drivers/usb/gadget/function/f_midi.c
++++ b/drivers/usb/gadget/function/f_midi.c
+@@ -282,7 +282,7 @@ f_midi_complete(struct usb_ep *ep, struct usb_request *req)
+ /* Our transmit completed. See if there's more to go.
+ * f_midi_transmit eats req, don't queue it again. */
+ req->length = 0;
+- f_midi_transmit(midi);
++ queue_work(system_highpri_wq, &midi->work);
+ return;
+ }
+ break;
+--
+2.39.5
+