--- /dev/null
+From dcd1caaaff431d1837c7eaca7177fc02a11bc718 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Mar 2024 22:59:23 +0100
+Subject: auxdisplay: hd44780: 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 9ea02f7cc39d484d16e8a14f3713fefcd33407c0 ]
+
+The .remove() callback for a platform driver returns an int which makes
+many driver authors wrongly assume it's possible to do error handling by
+returning an error code. However the value returned is ignored (apart
+from emitting a warning) and this typically results in resource leaks.
+
+To improve here there is a quest to make the remove callback return
+void. In the first step of this quest all drivers are converted to
+.remove_new(), which already returns void. Eventually after all drivers
+are converted, .remove_new() will be renamed to .remove().
+
+Trivially convert this driver from always returning zero in the remove
+callback to the void returning variant.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Stable-dep-of: 9b98a7d2e5f4 ("auxdisplay: hd44780: Fix an API misuse in hd44780.c")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/auxdisplay/hd44780.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
+index d56a5d508ccd7..7ac0b1b1d5482 100644
+--- a/drivers/auxdisplay/hd44780.c
++++ b/drivers/auxdisplay/hd44780.c
+@@ -319,7 +319,7 @@ static int hd44780_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+-static int hd44780_remove(struct platform_device *pdev)
++static void hd44780_remove(struct platform_device *pdev)
+ {
+ struct charlcd *lcd = platform_get_drvdata(pdev);
+ struct hd44780_common *hdc = lcd->drvdata;
+@@ -329,7 +329,6 @@ static int hd44780_remove(struct platform_device *pdev)
+ kfree(lcd->drvdata);
+
+ kfree(lcd);
+- return 0;
+ }
+
+ static const struct of_device_id hd44780_of_match[] = {
+@@ -340,7 +339,7 @@ MODULE_DEVICE_TABLE(of, hd44780_of_match);
+
+ static struct platform_driver hd44780_driver = {
+ .probe = hd44780_probe,
+- .remove = hd44780_remove,
++ .remove_new = hd44780_remove,
+ .driver = {
+ .name = "hd44780",
+ .of_match_table = hd44780_of_match,
+--
+2.39.5
+
--- /dev/null
+From dc4e9a3f436ead472118fd10f99873e3f1465936 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 18:15:27 +0800
+Subject: auxdisplay: hd44780: Fix an API misuse in hd44780.c
+
+From: Haoxiang Li <haoxiang_li2024@163.com>
+
+[ Upstream commit 9b98a7d2e5f4e2beeff88f6571da0cdc5883c7fb ]
+
+Variable allocated by charlcd_alloc() should be released
+by charlcd_free(). The following patch changed kfree() to
+charlcd_free() to fix an API misuse.
+
+Fixes: 718e05ed92ec ("auxdisplay: Introduce hd44780_common.[ch]")
+Cc: stable@vger.kernel.org
+Signed-off-by: Haoxiang Li <haoxiang_li2024@163.com>
+Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/auxdisplay/hd44780.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
+index 7ac0b1b1d5482..8b690f59df27d 100644
+--- a/drivers/auxdisplay/hd44780.c
++++ b/drivers/auxdisplay/hd44780.c
+@@ -313,7 +313,7 @@ static int hd44780_probe(struct platform_device *pdev)
+ fail3:
+ kfree(hd);
+ fail2:
+- kfree(lcd);
++ charlcd_free(lcd);
+ fail1:
+ kfree(hdc);
+ return ret;
+@@ -328,7 +328,7 @@ static void hd44780_remove(struct platform_device *pdev)
+ kfree(hdc->hd44780);
+ kfree(lcd->drvdata);
+
+- kfree(lcd);
++ charlcd_free(lcd);
+ }
+
+ static const struct of_device_id hd44780_of_match[] = {
+--
+2.39.5
+
--- /dev/null
+From f9f77860ff83863d73883e773a1e80f9bd319b21 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Mar 2023 08:39:38 +0100
+Subject: backlight: led_bl: 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 c4c4fa57fd3cc00020152baa169337521f90b2ad ]
+
+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 (mostly) ignored
+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.
+
+Trivially convert this driver from always returning zero in the remove
+callback to the void returning variant.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Reviewed-by: Daniel Thompson <daniel.thompson@linaro.org>
+Signed-off-by: Lee Jones <lee@kernel.org>
+Link: https://lore.kernel.org/r/20230308073945.2336302-7-u.kleine-koenig@pengutronix.de
+Stable-dep-of: 276822a00db3 ("backlight: led_bl: Hold led_access lock when calling led_sysfs_disable()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/backlight/led_bl.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c
+index f54d256e2d548..a1b6a2ad73a07 100644
+--- a/drivers/video/backlight/led_bl.c
++++ b/drivers/video/backlight/led_bl.c
+@@ -217,7 +217,7 @@ static int led_bl_probe(struct platform_device *pdev)
+ return 0;
+ }
+
+-static int led_bl_remove(struct platform_device *pdev)
++static void led_bl_remove(struct platform_device *pdev)
+ {
+ struct led_bl_data *priv = platform_get_drvdata(pdev);
+ struct backlight_device *bl = priv->bl_dev;
+@@ -228,8 +228,6 @@ static int led_bl_remove(struct platform_device *pdev)
+ led_bl_power_off(priv);
+ for (i = 0; i < priv->nb_leds; i++)
+ led_sysfs_enable(priv->leds[i]);
+-
+- return 0;
+ }
+
+ static const struct of_device_id led_bl_of_match[] = {
+@@ -245,7 +243,7 @@ static struct platform_driver led_bl_driver = {
+ .of_match_table = of_match_ptr(led_bl_of_match),
+ },
+ .probe = led_bl_probe,
+- .remove = led_bl_remove,
++ .remove_new = led_bl_remove,
+ };
+
+ module_platform_driver(led_bl_driver);
+--
+2.39.5
+
--- /dev/null
+From 1ef5d7abcf559d5250ded7e1b77778a47bc3f980 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jan 2025 10:19:14 +0100
+Subject: backlight: led_bl: Hold led_access lock when calling
+ led_sysfs_disable()
+
+From: Herve Codina <herve.codina@bootlin.com>
+
+[ Upstream commit 276822a00db3c1061382b41e72cafc09d6a0ec30 ]
+
+Lockdep detects the following issue on led-backlight removal:
+ [ 142.315935] ------------[ cut here ]------------
+ [ 142.315954] WARNING: CPU: 2 PID: 292 at drivers/leds/led-core.c:455 led_sysfs_enable+0x54/0x80
+ ...
+ [ 142.500725] Call trace:
+ [ 142.503176] led_sysfs_enable+0x54/0x80 (P)
+ [ 142.507370] led_bl_remove+0x80/0xa8 [led_bl]
+ [ 142.511742] platform_remove+0x30/0x58
+ [ 142.515501] device_remove+0x54/0x90
+ ...
+
+Indeed, led_sysfs_enable() has to be called with the led_access
+lock held.
+
+Hold the lock when calling led_sysfs_disable().
+
+Fixes: ae232e45acf9 ("backlight: add led-backlight driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Herve Codina <herve.codina@bootlin.com>
+Link: https://lore.kernel.org/r/20250122091914.309533-1-herve.codina@bootlin.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/backlight/led_bl.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c
+index a1b6a2ad73a07..589dae9ebb638 100644
+--- a/drivers/video/backlight/led_bl.c
++++ b/drivers/video/backlight/led_bl.c
+@@ -226,8 +226,11 @@ static void led_bl_remove(struct platform_device *pdev)
+ backlight_device_unregister(bl);
+
+ led_bl_power_off(priv);
+- for (i = 0; i < priv->nb_leds; i++)
++ for (i = 0; i < priv->nb_leds; i++) {
++ mutex_lock(&priv->leds[i]->led_access);
+ led_sysfs_enable(priv->leds[i]);
++ mutex_unlock(&priv->leds[i]->led_access);
++ }
+ }
+
+ static const struct of_device_id led_bl_of_match[] = {
+--
+2.39.5
+
--- /dev/null
+From 0a42623ad0e0caf37648e24f283ddee9993423f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Mar 2025 17:28:58 +0300
+Subject: cifs: avoid NULL pointer dereference in dbg call
+
+From: Alexandra Diupina <adiupina@astralinux.ru>
+
+[ Upstream commit b4885bd5935bb26f0a414ad55679a372e53f9b9b ]
+
+cifs_server_dbg() implies server to be non-NULL so
+move call under condition to avoid NULL pointer dereference.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: e79b0332ae06 ("cifs: ignore cached share root handle closing errors")
+Cc: stable@vger.kernel.org
+Signed-off-by: Alexandra Diupina <adiupina@astralinux.ru>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cifs/smb2misc.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
+index 12b6684f2d372..b84e682b4cae2 100644
+--- a/fs/cifs/smb2misc.c
++++ b/fs/cifs/smb2misc.c
+@@ -788,11 +788,12 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
+ WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative");
+ spin_unlock(&cifs_tcp_ses_lock);
+
+- if (tcon->ses)
++ if (tcon->ses) {
+ server = tcon->ses->server;
+-
+- cifs_server_dbg(FYI, "tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n",
+- tcon->tid, persistent_fid, volatile_fid);
++ cifs_server_dbg(FYI,
++ "tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n",
++ tcon->tid, persistent_fid, volatile_fid);
++ }
+
+ return 0;
+ }
+--
+2.39.5
+
--- /dev/null
+From 056ad0c0f89c19c8e975f708ac58a137118776cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Mar 2025 11:22:49 +0300
+Subject: cifs: fix integer overflow in match_server()
+
+From: Roman Smirnov <r.smirnov@omp.ru>
+
+[ Upstream commit 2510859475d7f46ed7940db0853f3342bf1b65ee ]
+
+The echo_interval is not limited in any way during mounting,
+which makes it possible to write a large number to it. This can
+cause an overflow when multiplying ctx->echo_interval by HZ in
+match_server().
+
+Add constraints for echo_interval to smb3_fs_context_parse_param().
+
+Found by Linux Verification Center (linuxtesting.org) with Svace.
+
+Fixes: adfeb3e00e8e1 ("cifs: Make echo interval tunable")
+Cc: stable@vger.kernel.org
+Signed-off-by: Roman Smirnov <r.smirnov@omp.ru>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cifs/fs_context.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c
+index 24c42043a2271..c3a71c69d3395 100644
+--- a/fs/cifs/fs_context.c
++++ b/fs/cifs/fs_context.c
+@@ -1088,6 +1088,11 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
+ ctx->closetimeo = HZ * result.uint_32;
+ break;
+ case Opt_echo_interval:
++ if (result.uint_32 < SMB_ECHO_INTERVAL_MIN ||
++ result.uint_32 > SMB_ECHO_INTERVAL_MAX) {
++ cifs_errorf(fc, "echo interval is out of bounds\n");
++ goto cifs_parse_mount_err;
++ }
+ ctx->echo_interval = result.uint_32;
+ break;
+ case Opt_snapshot:
+--
+2.39.5
+
--- /dev/null
+From bb64d2f3eb1db05f5846ded009ca3ad10f926b08 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 18 May 2022 11:41:04 -0300
+Subject: cifs: print TIDs as hex
+
+From: Enzo Matsumiya <ematsumiya@suse.de>
+
+[ Upstream commit 71081e7ac16c93acdd18afa65daa468620bb1b64 ]
+
+Makes these debug messages easier to read
+
+Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
+Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Stable-dep-of: b4885bd5935b ("cifs: avoid NULL pointer dereference in dbg call")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cifs/connect.c | 2 +-
+ fs/cifs/smb2misc.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
+index 96788385e1e73..51ceaf9ea3151 100644
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -1683,7 +1683,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
+ goto out;
+ }
+
+- cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
++ cifs_dbg(FYI, "IPC tcon rc=%d ipc tid=0x%x\n", rc, tcon->tid);
+
+ ses->tcon_ipc = tcon;
+ out:
+diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
+index 89a2f38f17f37..12b6684f2d372 100644
+--- a/fs/cifs/smb2misc.c
++++ b/fs/cifs/smb2misc.c
+@@ -791,7 +791,7 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
+ if (tcon->ses)
+ server = tcon->ses->server;
+
+- cifs_server_dbg(FYI, "tid=%u: tcon is closing, skipping async close retry of fid %llu %llu\n",
++ cifs_server_dbg(FYI, "tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n",
+ tcon->tid, persistent_fid, volatile_fid);
+
+ return 0;
+--
+2.39.5
+
--- /dev/null
+From a930a106f1b116719164b9bcf3e45393488c583d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Dec 2022 22:33:14 +0530
+Subject: drm/msm/a6xx: Avoid gx gbit halt during rpm suspend
+
+From: Akhil P Oommen <quic_akhilpo@quicinc.com>
+
+[ Upstream commit f4a75b5933c998e60fd812a7680e0971eb1c7cee ]
+
+As per the downstream driver, gx gbif halt is required only during
+recovery sequence. So lets avoid it during regular rpm suspend.
+
+Signed-off-by: Akhil P Oommen <quic_akhilpo@quicinc.com>
+Patchwork: https://patchwork.freedesktop.org/patch/515279/
+Link: https://lore.kernel.org/r/20221216223253.1.Ice9c47bfeb1fddb8dc377a3491a043a3ee7fca7d@changeid
+Signed-off-by: Rob Clark <robdclark@chromium.org>
+Stable-dep-of: f561db72a663 ("drm/msm/a6xx: Fix stale rpmh votes from GPU")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 15 +++++++++------
+ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 7 +++++++
+ drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
+ 3 files changed, 17 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+index 65ba58c712c93..ea59c54437dec 100644
+--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
++++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+@@ -872,7 +872,8 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu)
+ #define GBIF_CLIENT_HALT_MASK BIT(0)
+ #define GBIF_ARB_HALT_MASK BIT(1)
+
+-static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu)
++static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu,
++ bool gx_off)
+ {
+ struct msm_gpu *gpu = &adreno_gpu->base;
+
+@@ -885,9 +886,11 @@ static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu)
+ return;
+ }
+
+- /* Halt the gx side of GBIF */
+- gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 1);
+- spin_until(gpu_read(gpu, REG_A6XX_RBBM_GBIF_HALT_ACK) & 1);
++ if (gx_off) {
++ /* Halt the gx side of GBIF */
++ gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 1);
++ spin_until(gpu_read(gpu, REG_A6XX_RBBM_GBIF_HALT_ACK) & 1);
++ }
+
+ /* Halt new client requests on GBIF */
+ gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK);
+@@ -925,7 +928,7 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu)
+ /* Halt the gmu cm3 core */
+ gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1);
+
+- a6xx_bus_clear_pending_transactions(adreno_gpu);
++ a6xx_bus_clear_pending_transactions(adreno_gpu, true);
+
+ /* Reset GPU core blocks */
+ gpu_write(gpu, REG_A6XX_RBBM_SW_RESET_CMD, 1);
+@@ -1079,7 +1082,7 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu)
+ return;
+ }
+
+- a6xx_bus_clear_pending_transactions(adreno_gpu);
++ a6xx_bus_clear_pending_transactions(adreno_gpu, a6xx_gpu->hung);
+
+ /* tell the GMU we want to slumber */
+ ret = a6xx_gmu_notify_slumber(gmu);
+diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+index a1dff22b02a7a..1c38c3acacbeb 100644
+--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+@@ -1178,6 +1178,12 @@ static void a6xx_recover(struct msm_gpu *gpu)
+ if (hang_debug)
+ a6xx_dump(gpu);
+
++ /*
++ * To handle recovery specific sequences during the rpm suspend we are
++ * about to trigger
++ */
++ a6xx_gpu->hung = true;
++
+ /* Halt SQE first */
+ gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3);
+
+@@ -1191,6 +1197,7 @@ static void a6xx_recover(struct msm_gpu *gpu)
+ gpu->funcs->pm_resume(gpu);
+
+ msm_gpu_hw_init(gpu);
++ a6xx_gpu->hung = false;
+ }
+
+ static const char *a6xx_uche_fault_block(struct msm_gpu *gpu, u32 mid)
+diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+index 86e0a7c3fe6df..79d0cecff8e91 100644
+--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+@@ -32,6 +32,7 @@ struct a6xx_gpu {
+ void *llc_slice;
+ void *htw_llc_slice;
+ bool have_mmu500;
++ bool hung;
+ };
+
+ #define to_a6xx_gpu(x) container_of(x, struct a6xx_gpu, base)
+--
+2.39.5
+
--- /dev/null
+From 35922fea90cbae30295a3cb48ecee7a4e5b4a091 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 01:22:14 +0530
+Subject: drm/msm/a6xx: Fix stale rpmh votes from GPU
+
+From: Akhil P Oommen <quic_akhilpo@quicinc.com>
+
+[ Upstream commit f561db72a663f8a73c2250bf3244ce1ce221bed7 ]
+
+It was observed on sc7180 (A618 gpu) that GPU votes for GX rail and CNOC
+BCM nodes were not removed after GPU suspend. This was because we
+skipped sending 'prepare-slumber' request to gmu during suspend sequence
+in some cases. So, make sure we always call prepare-slumber hfi during
+suspend. Also, calling prepare-slumber without a prior oob-gpu handshake
+messes up gmu firmware's internal state. So, do that when required.
+
+Fixes: 4b565ca5a2cb ("drm/msm: Add A6XX device support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Akhil P Oommen <quic_akhilpo@quicinc.com>
+Patchwork: https://patchwork.freedesktop.org/patch/639569/
+Signed-off-by: Rob Clark <robdclark@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 72 +++++++++++++++------------
+ 1 file changed, 39 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+index ea59c54437dec..f1daa923f3469 100644
+--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
++++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+@@ -1066,49 +1066,50 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu)
+ struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
+ struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+ u32 val;
++ int ret;
+
+ /*
+- * The GMU may still be in slumber unless the GPU started so check and
+- * skip putting it back into slumber if so
++ * GMU firmware's internal power state gets messed up if we send "prepare_slumber" hfi when
++ * oob_gpu handshake wasn't done after the last wake up. So do a dummy handshake here when
++ * required
+ */
+- val = gmu_read(gmu, REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE);
++ if (adreno_gpu->base.needs_hw_init) {
++ if (a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET))
++ goto force_off;
+
+- if (val != 0xf) {
+- int ret = a6xx_gmu_wait_for_idle(gmu);
++ a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
++ }
+
+- /* If the GMU isn't responding assume it is hung */
+- if (ret) {
+- a6xx_gmu_force_off(gmu);
+- return;
+- }
++ ret = a6xx_gmu_wait_for_idle(gmu);
+
+- a6xx_bus_clear_pending_transactions(adreno_gpu, a6xx_gpu->hung);
++ /* If the GMU isn't responding assume it is hung */
++ if (ret)
++ goto force_off;
+
+- /* tell the GMU we want to slumber */
+- ret = a6xx_gmu_notify_slumber(gmu);
+- if (ret) {
+- a6xx_gmu_force_off(gmu);
+- return;
+- }
++ a6xx_bus_clear_pending_transactions(adreno_gpu, a6xx_gpu->hung);
+
+- ret = gmu_poll_timeout(gmu,
+- REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, val,
+- !(val & A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS_GPUBUSYIGNAHB),
+- 100, 10000);
++ /* tell the GMU we want to slumber */
++ ret = a6xx_gmu_notify_slumber(gmu);
++ if (ret)
++ goto force_off;
+
+- /*
+- * Let the user know we failed to slumber but don't worry too
+- * much because we are powering down anyway
+- */
++ ret = gmu_poll_timeout(gmu,
++ REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, val,
++ !(val & A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS_GPUBUSYIGNAHB),
++ 100, 10000);
+
+- if (ret)
+- DRM_DEV_ERROR(gmu->dev,
+- "Unable to slumber GMU: status = 0%x/0%x\n",
+- gmu_read(gmu,
+- REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS),
+- gmu_read(gmu,
+- REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS2));
+- }
++ /*
++ * Let the user know we failed to slumber but don't worry too
++ * much because we are powering down anyway
++ */
++
++ if (ret)
++ DRM_DEV_ERROR(gmu->dev,
++ "Unable to slumber GMU: status = 0%x/0%x\n",
++ gmu_read(gmu,
++ REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS),
++ gmu_read(gmu,
++ REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS2));
+
+ /* Turn off HFI */
+ a6xx_hfi_stop(gmu);
+@@ -1118,6 +1119,11 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu)
+
+ /* Tell RPMh to power off the GPU */
+ a6xx_rpmh_stop(gmu);
++
++ return;
++
++force_off:
++ a6xx_gmu_force_off(gmu);
+ }
+
+
+--
+2.39.5
+
--- /dev/null
+From 6a935b9ca5bf34162c81d039ec73f8dfd8f50cb3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Aug 2022 01:52:15 +0530
+Subject: drm/msm/a6xx: Handle GMU prepare-slumber hfi failure
+
+From: Akhil P Oommen <quic_akhilpo@quicinc.com>
+
+[ Upstream commit d6463fd4e97545ef4f7069d13a5fa3ac0924dae2 ]
+
+When prepare-slumber hfi fails, we should follow a6xx_gmu_force_off()
+sequence.
+
+Signed-off-by: Akhil P Oommen <quic_akhilpo@quicinc.com>
+Patchwork: https://patchwork.freedesktop.org/patch/498401/
+Link: https://lore.kernel.org/r/20220819015030.v5.7.I54815c7c36b80d4725cd054e536365250454452f@changeid
+Signed-off-by: Rob Clark <robdclark@chromium.org>
+Stable-dep-of: f561db72a663 ("drm/msm/a6xx: Fix stale rpmh votes from GPU")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+index db19f3dee6f2b..65ba58c712c93 100644
+--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
++++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+@@ -1082,7 +1082,11 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu)
+ a6xx_bus_clear_pending_transactions(adreno_gpu);
+
+ /* tell the GMU we want to slumber */
+- a6xx_gmu_notify_slumber(gmu);
++ ret = a6xx_gmu_notify_slumber(gmu);
++ if (ret) {
++ a6xx_gmu_force_off(gmu);
++ return;
++ }
+
+ ret = gmu_poll_timeout(gmu,
+ REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, val,
+--
+2.39.5
+
--- /dev/null
+From 8e5b3deaad0eabcf7d9a025ba4c882f978c661b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Aug 2022 01:52:14 +0530
+Subject: drm/msm/a6xx: Improve gpu recovery sequence
+
+From: Akhil P Oommen <quic_akhilpo@quicinc.com>
+
+[ Upstream commit 3a9dd708b902a1a646c3725151554cbef16c2c28 ]
+
+We can do a few more things to improve our chance at a successful gpu
+recovery, especially during a hangcheck timeout:
+1. Halt CP and GMU core
+2. Do RBBM GBIF HALT sequence
+3. Do a soft reset of GPU core
+
+Signed-off-by: Akhil P Oommen <quic_akhilpo@quicinc.com>
+Patchwork: https://patchwork.freedesktop.org/patch/498400/
+Link: https://lore.kernel.org/r/20220819015030.v5.6.Idf2ba51078e87ae7ceb75cc77a5bd4ff2bd31eab@changeid
+Signed-off-by: Rob Clark <robdclark@chromium.org>
+Stable-dep-of: f561db72a663 ("drm/msm/a6xx: Fix stale rpmh votes from GPU")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/adreno/a6xx.xml.h | 4 ++
+ drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 77 ++++++++++++++++-----------
+ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 7 +++
+ 3 files changed, 58 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/gpu/drm/msm/adreno/a6xx.xml.h b/drivers/gpu/drm/msm/adreno/a6xx.xml.h
+index a3cb3d988ba4e..5b1adda08d056 100644
+--- a/drivers/gpu/drm/msm/adreno/a6xx.xml.h
++++ b/drivers/gpu/drm/msm/adreno/a6xx.xml.h
+@@ -1354,6 +1354,10 @@ static inline uint32_t REG_A6XX_RBBM_PERFCTR_RBBM_SEL(uint32_t i0) { return 0x00
+
+ #define REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL 0x00000011
+
++#define REG_A6XX_RBBM_GBIF_HALT 0x00000016
++
++#define REG_A6XX_RBBM_GBIF_HALT_ACK 0x00000017
++
+ #define REG_A6XX_RBBM_WAIT_FOR_GPU_IDLE_CMD 0x0000001c
+ #define A6XX_RBBM_WAIT_FOR_GPU_IDLE_CMD_WAIT_GPU_IDLE 0x00000001
+
+diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+index 8b6fc1b26f049..db19f3dee6f2b 100644
+--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
++++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+@@ -869,9 +869,47 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu)
+ (val & 1), 100, 1000);
+ }
+
++#define GBIF_CLIENT_HALT_MASK BIT(0)
++#define GBIF_ARB_HALT_MASK BIT(1)
++
++static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu)
++{
++ struct msm_gpu *gpu = &adreno_gpu->base;
++
++ if (!a6xx_has_gbif(adreno_gpu)) {
++ gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0xf);
++ spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) &
++ 0xf) == 0xf);
++ gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0);
++
++ return;
++ }
++
++ /* Halt the gx side of GBIF */
++ gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 1);
++ spin_until(gpu_read(gpu, REG_A6XX_RBBM_GBIF_HALT_ACK) & 1);
++
++ /* Halt new client requests on GBIF */
++ gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK);
++ spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) &
++ (GBIF_CLIENT_HALT_MASK)) == GBIF_CLIENT_HALT_MASK);
++
++ /* Halt all AXI requests on GBIF */
++ gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_ARB_HALT_MASK);
++ spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) &
++ (GBIF_ARB_HALT_MASK)) == GBIF_ARB_HALT_MASK);
++
++ /* The GBIF halt needs to be explicitly cleared */
++ gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0);
++}
++
+ /* Force the GMU off in case it isn't responsive */
+ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu)
+ {
++ struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
++ struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
++ struct msm_gpu *gpu = &adreno_gpu->base;
++
+ /* Flush all the queues */
+ a6xx_hfi_stop(gmu);
+
+@@ -883,6 +921,15 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu)
+
+ /* Make sure there are no outstanding RPMh votes */
+ a6xx_gmu_rpmh_off(gmu);
++
++ /* Halt the gmu cm3 core */
++ gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1);
++
++ a6xx_bus_clear_pending_transactions(adreno_gpu);
++
++ /* Reset GPU core blocks */
++ gpu_write(gpu, REG_A6XX_RBBM_SW_RESET_CMD, 1);
++ udelay(100);
+ }
+
+ static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu)
+@@ -1010,36 +1057,6 @@ bool a6xx_gmu_isidle(struct a6xx_gmu *gmu)
+ return true;
+ }
+
+-#define GBIF_CLIENT_HALT_MASK BIT(0)
+-#define GBIF_ARB_HALT_MASK BIT(1)
+-
+-static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu)
+-{
+- struct msm_gpu *gpu = &adreno_gpu->base;
+-
+- if (!a6xx_has_gbif(adreno_gpu)) {
+- gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0xf);
+- spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) &
+- 0xf) == 0xf);
+- gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0);
+-
+- return;
+- }
+-
+- /* Halt new client requests on GBIF */
+- gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK);
+- spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) &
+- (GBIF_CLIENT_HALT_MASK)) == GBIF_CLIENT_HALT_MASK);
+-
+- /* Halt all AXI requests on GBIF */
+- gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_ARB_HALT_MASK);
+- spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) &
+- (GBIF_ARB_HALT_MASK)) == GBIF_ARB_HALT_MASK);
+-
+- /* The GBIF halt needs to be explicitly cleared */
+- gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0);
+-}
+-
+ /* Gracefully try to shut down the GMU and by extension the GPU */
+ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu)
+ {
+diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+index 27fae0dc97040..a1dff22b02a7a 100644
+--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+@@ -891,6 +891,10 @@ static int hw_init(struct msm_gpu *gpu)
+ /* Make sure the GMU keeps the GPU on while we set it up */
+ a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
+
++ /* Clear GBIF halt in case GX domain was not collapsed */
++ if (a6xx_has_gbif(adreno_gpu))
++ gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 0);
++
+ gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_CNTL, 0);
+
+ /*
+@@ -1174,6 +1178,9 @@ static void a6xx_recover(struct msm_gpu *gpu)
+ if (hang_debug)
+ a6xx_dump(gpu);
+
++ /* Halt SQE first */
++ gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3);
++
+ /*
+ * Turn off keep alive that might have been enabled by the hang
+ * interrupt
+--
+2.39.5
+
--- /dev/null
+From 2dbc624472416b78bf4d3017e533ca49117637d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Mar 2025 11:23:49 +0800
+Subject: gpio: tegra186: fix resource handling in ACPI probe path
+
+From: Guixin Liu <kanie@linux.alibaba.com>
+
+[ Upstream commit 8323f3a69de6f6e96bf22f32dd8e2920766050c2 ]
+
+When the Tegra186 GPIO controller is probed through ACPI matching,
+the driver emits two error messages during probing:
+ "tegra186-gpio NVDA0508:00: invalid resource (null)"
+ "tegra186-gpio NVDA0508:00: invalid resource (null)"
+
+Fix this by getting resource first and then do the ioremap.
+
+Fixes: 2606e7c9f5fc ("gpio: tegra186: Add ACPI support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Guixin Liu <kanie@linux.alibaba.com>
+Link: https://lore.kernel.org/r/20250327032349.78809-1-kanie@linux.alibaba.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-tegra186.c | 27 ++++++++++++++-------------
+ 1 file changed, 14 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
+index 52e08bc2f0530..da310b20fad00 100644
+--- a/drivers/gpio/gpio-tegra186.c
++++ b/drivers/gpio/gpio-tegra186.c
+@@ -630,6 +630,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
+ struct gpio_irq_chip *irq;
+ struct tegra_gpio *gpio;
+ struct device_node *np;
++ struct resource *res;
+ char **names;
+ int err;
+
+@@ -649,19 +650,19 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
+ gpio->num_banks++;
+
+ /* get register apertures */
+- gpio->secure = devm_platform_ioremap_resource_byname(pdev, "security");
+- if (IS_ERR(gpio->secure)) {
+- gpio->secure = devm_platform_ioremap_resource(pdev, 0);
+- if (IS_ERR(gpio->secure))
+- return PTR_ERR(gpio->secure);
+- }
+-
+- gpio->base = devm_platform_ioremap_resource_byname(pdev, "gpio");
+- if (IS_ERR(gpio->base)) {
+- gpio->base = devm_platform_ioremap_resource(pdev, 1);
+- if (IS_ERR(gpio->base))
+- return PTR_ERR(gpio->base);
+- }
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "security");
++ if (!res)
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ gpio->secure = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(gpio->secure))
++ return PTR_ERR(gpio->secure);
++
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpio");
++ if (!res)
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ gpio->base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(gpio->base))
++ return PTR_ERR(gpio->base);
+
+ err = platform_irq_count(pdev);
+ if (err < 0)
+--
+2.39.5
+
--- /dev/null
+From 0432966e3f875ef94505f2f98c1c850924803ec6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Sep 2021 12:54:11 +0200
+Subject: gpio: tegra186: Force one interrupt per bank
+
+From: Thierry Reding <treding@nvidia.com>
+
+[ Upstream commit ca038748068f454d20ad1bb120cbe36599f81db6 ]
+
+Newer chips support up to 8 interrupts per bank, which can be useful to
+balance the load and decrease latency. However, it also required a very
+complicated interrupt routing to be set up. To keep things simple for
+now, ensure that a single interrupt per bank is enforced, even if all
+possible interrupts are described in device tree.
+
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
+Stable-dep-of: 8323f3a69de6 ("gpio: tegra186: fix resource handling in ACPI probe path")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-tegra186.c | 68 ++++++++++++++++++++++++++++++++----
+ 1 file changed, 62 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
+index 00762de3d4096..52e08bc2f0530 100644
+--- a/drivers/gpio/gpio-tegra186.c
++++ b/drivers/gpio/gpio-tegra186.c
+@@ -81,6 +81,8 @@ struct tegra_gpio {
+ unsigned int *irq;
+
+ const struct tegra_gpio_soc *soc;
++ unsigned int num_irqs_per_bank;
++ unsigned int num_banks;
+
+ void __iomem *secure;
+ void __iomem *base;
+@@ -600,6 +602,28 @@ static void tegra186_gpio_init_route_mapping(struct tegra_gpio *gpio)
+ }
+ }
+
++static unsigned int tegra186_gpio_irqs_per_bank(struct tegra_gpio *gpio)
++{
++ struct device *dev = gpio->gpio.parent;
++
++ if (gpio->num_irq > gpio->num_banks) {
++ if (gpio->num_irq % gpio->num_banks != 0)
++ goto error;
++ }
++
++ if (gpio->num_irq < gpio->num_banks)
++ goto error;
++
++ gpio->num_irqs_per_bank = gpio->num_irq / gpio->num_banks;
++
++ return 0;
++
++error:
++ dev_err(dev, "invalid number of interrupts (%u) for %u banks\n",
++ gpio->num_irq, gpio->num_banks);
++ return -EINVAL;
++}
++
+ static int tegra186_gpio_probe(struct platform_device *pdev)
+ {
+ unsigned int i, j, offset;
+@@ -614,7 +638,17 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
+ return -ENOMEM;
+
+ gpio->soc = device_get_match_data(&pdev->dev);
++ gpio->gpio.label = gpio->soc->name;
++ gpio->gpio.parent = &pdev->dev;
++
++ /* count the number of banks in the controller */
++ for (i = 0; i < gpio->soc->num_ports; i++)
++ if (gpio->soc->ports[i].bank > gpio->num_banks)
++ gpio->num_banks = gpio->soc->ports[i].bank;
++
++ gpio->num_banks++;
+
++ /* get register apertures */
+ gpio->secure = devm_platform_ioremap_resource_byname(pdev, "security");
+ if (IS_ERR(gpio->secure)) {
+ gpio->secure = devm_platform_ioremap_resource(pdev, 0);
+@@ -635,6 +669,10 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
+
+ gpio->num_irq = err;
+
++ err = tegra186_gpio_irqs_per_bank(gpio);
++ if (err < 0)
++ return err;
++
+ gpio->irq = devm_kcalloc(&pdev->dev, gpio->num_irq, sizeof(*gpio->irq),
+ GFP_KERNEL);
+ if (!gpio->irq)
+@@ -648,9 +686,6 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
+ gpio->irq[i] = err;
+ }
+
+- gpio->gpio.label = gpio->soc->name;
+- gpio->gpio.parent = &pdev->dev;
+-
+ gpio->gpio.request = gpiochip_generic_request;
+ gpio->gpio.free = gpiochip_generic_free;
+ gpio->gpio.get_direction = tegra186_gpio_get_direction;
+@@ -714,7 +749,30 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
+ irq->parent_handler = tegra186_gpio_irq;
+ irq->parent_handler_data = gpio;
+ irq->num_parents = gpio->num_irq;
+- irq->parents = gpio->irq;
++
++ /*
++ * To simplify things, use a single interrupt per bank for now. Some
++ * chips support up to 8 interrupts per bank, which can be useful to
++ * distribute the load and decrease the processing latency for GPIOs
++ * but it also requires a more complicated interrupt routing than we
++ * currently program.
++ */
++ if (gpio->num_irqs_per_bank > 1) {
++ irq->parents = devm_kcalloc(&pdev->dev, gpio->num_banks,
++ sizeof(*irq->parents), GFP_KERNEL);
++ if (!irq->parents)
++ return -ENOMEM;
++
++ for (i = 0; i < gpio->num_banks; i++)
++ irq->parents[i] = gpio->irq[i * gpio->num_irqs_per_bank];
++
++ irq->num_parents = gpio->num_banks;
++ } else {
++ irq->num_parents = gpio->num_irq;
++ irq->parents = gpio->irq;
++ }
++
++ tegra186_gpio_init_route_mapping(gpio);
+
+ np = of_find_matching_node(NULL, tegra186_pmc_of_match);
+ if (np) {
+@@ -725,8 +783,6 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
+ return -EPROBE_DEFER;
+ }
+
+- tegra186_gpio_init_route_mapping(gpio);
+-
+ irq->map = devm_kcalloc(&pdev->dev, gpio->gpio.ngpio,
+ sizeof(*irq->map), GFP_KERNEL);
+ if (!irq->map)
+--
+2.39.5
+
--- /dev/null
+From 4f6a1df0948c036a229d11aa6980a6027ade431d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 18:00:29 -0300
+Subject: iio: adc: ad7768-1: Fix conversion result sign
+
+From: Sergiu Cuciurean <sergiu.cuciurean@analog.com>
+
+[ Upstream commit 8236644f5ecb180e80ad92d691c22bc509b747bb ]
+
+The ad7768-1 ADC output code is two's complement, meaning that the voltage
+conversion result is a signed value.. Since the value is a 24 bit one,
+stored in a 32 bit variable, the sign should be extended in order to get
+the correct representation.
+
+Also the channel description has been updated to signed representation,
+to match the ADC specifications.
+
+Fixes: a5f8c7da3dbe ("iio: adc: Add AD7768-1 ADC basic support")
+Reviewed-by: David Lechner <dlechner@baylibre.com>
+Reviewed-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
+Signed-off-by: Sergiu Cuciurean <sergiu.cuciurean@analog.com>
+Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
+Cc: <Stable@vger.kernel.org>
+Link: https://patch.msgid.link/505994d3b71c2aa38ba714d909a68e021f12124c.1741268122.git.Jonathan.Santos@analog.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/ad7768-1.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c
+index 22c0303587b07..c922faab4a52b 100644
+--- a/drivers/iio/adc/ad7768-1.c
++++ b/drivers/iio/adc/ad7768-1.c
+@@ -142,7 +142,7 @@ static const struct iio_chan_spec ad7768_channels[] = {
+ .channel = 0,
+ .scan_index = 0,
+ .scan_type = {
+- .sign = 'u',
++ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ .shift = 8,
+@@ -374,7 +374,7 @@ static int ad7768_read_raw(struct iio_dev *indio_dev,
+ iio_device_release_direct_mode(indio_dev);
+ if (ret < 0)
+ return ret;
+- *val = ret;
++ *val = sign_extend32(ret, chan->scan_type.realbits - 1);
+
+ return IIO_VAL_INT;
+
+--
+2.39.5
+
--- /dev/null
+From 9abe1c7cf862d22975dbf2f37559bd529cbdd0f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 14:16:12 +0000
+Subject: iio: adc: ad7768-1: Move setting of val a bit later to avoid
+ unnecessary return value check
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+[ Upstream commit 0af1c801a15225304a6328258efbf2bee245c654 ]
+
+The data used is all in local variables so there is no advantage
+in setting *val = ret with the direct mode claim held.
+Move it later to after error check.
+
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20250217141630.897334-13-jic23@kernel.org
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 8236644f5ecb ("iio: adc: ad7768-1: Fix conversion result sign")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/ad7768-1.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c
+index aa42ba759fa1a..22c0303587b07 100644
+--- a/drivers/iio/adc/ad7768-1.c
++++ b/drivers/iio/adc/ad7768-1.c
+@@ -370,12 +370,11 @@ static int ad7768_read_raw(struct iio_dev *indio_dev,
+ return ret;
+
+ ret = ad7768_scan_direct(indio_dev);
+- if (ret >= 0)
+- *val = ret;
+
+ iio_device_release_direct_mode(indio_dev);
+ if (ret < 0)
+ return ret;
++ *val = ret;
+
+ return IIO_VAL_INT;
+
+--
+2.39.5
+
--- /dev/null
+From 5e9525d4cdfd5ad0dedc365daef4f17bc16a8003 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Sep 2022 17:03:59 +0200
+Subject: kmsan: disable strscpy() optimization under KMSAN
+
+From: Alexander Potapenko <glider@google.com>
+
+[ Upstream commit 2de6f3bf75058e35eff04e6fab7ca41533bdb027 ]
+
+Disable the efficient 8-byte reading under KMSAN to avoid false positives.
+
+Link: https://lkml.kernel.org/r/20220915150417.722975-26-glider@google.com
+Signed-off-by: Alexander Potapenko <glider@google.com>
+Cc: Alexander Viro <viro@zeniv.linux.org.uk>
+Cc: Alexei Starovoitov <ast@kernel.org>
+Cc: Andrey Konovalov <andreyknvl@gmail.com>
+Cc: Andrey Konovalov <andreyknvl@google.com>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Christoph Hellwig <hch@lst.de>
+Cc: Christoph Lameter <cl@linux.com>
+Cc: David Rientjes <rientjes@google.com>
+Cc: Dmitry Vyukov <dvyukov@google.com>
+Cc: Eric Biggers <ebiggers@google.com>
+Cc: Eric Biggers <ebiggers@kernel.org>
+Cc: Eric Dumazet <edumazet@google.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: Ilya Leoshkevich <iii@linux.ibm.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jens Axboe <axboe@kernel.dk>
+Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Marco Elver <elver@google.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Matthew Wilcox <willy@infradead.org>
+Cc: Michael S. Tsirkin <mst@redhat.com>
+Cc: Pekka Enberg <penberg@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Petr Mladek <pmladek@suse.com>
+Cc: Stephen Rothwell <sfr@canb.auug.org.au>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Vasily Gorbik <gor@linux.ibm.com>
+Cc: Vegard Nossum <vegard.nossum@oracle.com>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: d94c12bd97d5 ("string: Add load_unaligned_zeropad() code path to sized_strscpy()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ lib/string.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/lib/string.c b/lib/string.c
+index b2de45a581f4f..9fb9be19a95d7 100644
+--- a/lib/string.c
++++ b/lib/string.c
+@@ -202,6 +202,14 @@ ssize_t strscpy(char *dest, const char *src, size_t count)
+ max = 0;
+ #endif
+
++ /*
++ * read_word_at_a_time() below may read uninitialized bytes after the
++ * trailing zero and use them in comparisons. Disable this optimization
++ * under KMSAN to prevent false positive reports.
++ */
++ if (IS_ENABLED(CONFIG_KMSAN))
++ max = 0;
++
+ while (max >= sizeof(unsigned long)) {
+ unsigned long c, data;
+
+--
+2.39.5
+
--- /dev/null
+From 667be2b77036cd45dd4b223fcd4a12ad22bc6458 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Apr 2025 12:04:49 +0300
+Subject: ksmbd: Prevent integer overflow in calculation of deadtime
+
+From: Denis Arefev <arefev@swemel.ru>
+
+[ Upstream commit a93ff742820f75bf8bb3fcf21d9f25ca6eb3d4c6 ]
+
+The user can set any value for 'deadtime'. This affects the arithmetic
+expression 'req->deadtime * SMB_ECHO_INTERVAL', which is subject to
+overflow. The added check makes the server behavior more predictable.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers")
+Cc: stable@vger.kernel.org
+Signed-off-by: Denis Arefev <arefev@swemel.ru>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ksmbd/transport_ipc.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/fs/ksmbd/transport_ipc.c b/fs/ksmbd/transport_ipc.c
+index 0d096a11ba30e..7e6003c6cd9bf 100644
+--- a/fs/ksmbd/transport_ipc.c
++++ b/fs/ksmbd/transport_ipc.c
+@@ -294,7 +294,11 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
+ server_conf.signing = req->signing;
+ server_conf.tcp_port = req->tcp_port;
+ server_conf.ipc_timeout = req->ipc_timeout * HZ;
+- server_conf.deadtime = req->deadtime * SMB_ECHO_INTERVAL;
++ if (check_mul_overflow(req->deadtime, SMB_ECHO_INTERVAL,
++ &server_conf.deadtime)) {
++ ret = -EINVAL;
++ goto out;
++ }
+ server_conf.share_fake_fscaps = req->share_fake_fscaps;
+ ksmbd_init_domain(req->sub_auth);
+
+@@ -317,6 +321,7 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
+ ret |= ksmbd_set_work_group(req->work_group);
+ ret |= ksmbd_tcp_set_interfaces(KSMBD_STARTUP_CONFIG_INTERFACES(req),
+ req->ifc_list_sz);
++out:
+ if (ret) {
+ pr_err("Server configuration error: %s %s %s\n",
+ req->netbios_name, req->server_string,
+--
+2.39.5
+
--- /dev/null
+From 5fac0846d871c15a842cbc1281a2574ed45c5b34 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 13:51:30 +0300
+Subject: media: streamzap: fix race between device disconnection and urb
+ callback
+
+From: Murad Masimov <m.masimov@mt-integration.ru>
+
+[ Upstream commit f656cfbc7a293a039d6a0c7100e1c846845148c1 ]
+
+Syzkaller has reported a general protection fault at function
+ir_raw_event_store_with_filter(). This crash is caused by a NULL pointer
+dereference of dev->raw pointer, even though it is checked for NULL in
+the same function, which means there is a race condition. It occurs due
+to the incorrect order of actions in the streamzap_disconnect() function:
+rc_unregister_device() is called before usb_kill_urb(). The dev->raw
+pointer is freed and set to NULL in rc_unregister_device(), and only
+after that usb_kill_urb() waits for in-progress requests to finish.
+
+If rc_unregister_device() is called while streamzap_callback() handler is
+not finished, this can lead to accessing freed resources. Thus
+rc_unregister_device() should be called after usb_kill_urb().
+
+Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
+
+Fixes: 8e9e60640067 ("V4L/DVB: staging/lirc: port lirc_streamzap to ir-core")
+Cc: stable@vger.kernel.org
+Reported-by: syzbot+34008406ee9a31b13c73@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=34008406ee9a31b13c73
+Signed-off-by: Murad Masimov <m.masimov@mt-integration.ru>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/rc/streamzap.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
+index d4b38532c7b44..d31ee190301b3 100644
+--- a/drivers/media/rc/streamzap.c
++++ b/drivers/media/rc/streamzap.c
+@@ -431,8 +431,8 @@ static void streamzap_disconnect(struct usb_interface *interface)
+ if (!sz)
+ return;
+
+- rc_unregister_device(sz->rdev);
+ usb_kill_urb(sz->urb_in);
++ rc_unregister_device(sz->rdev);
+ usb_free_urb(sz->urb_in);
+ usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in);
+
+--
+2.39.5
+
--- /dev/null
+From 61654c41b52ed21eaeccb97b082b84e914a19d6b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 5 Dec 2021 22:38:20 +0100
+Subject: media: streamzap: less chatter
+
+From: Sean Young <sean@mess.org>
+
+[ Upstream commit 35088717ad24140b6ab0ec00ef357709be607526 ]
+
+Remove superfluous messages which add no information.
+
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Stable-dep-of: f656cfbc7a29 ("media: streamzap: fix race between device disconnection and urb callback")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/rc/streamzap.c | 20 +-------------------
+ 1 file changed, 1 insertion(+), 19 deletions(-)
+
+diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
+index 9ef6260d2dfd2..aff4dfb99a827 100644
+--- a/drivers/media/rc/streamzap.c
++++ b/drivers/media/rc/streamzap.c
+@@ -26,7 +26,6 @@
+ #include <linux/usb/input.h>
+ #include <media/rc-core.h>
+
+-#define DRIVER_VERSION "1.61"
+ #define DRIVER_NAME "streamzap"
+ #define DRIVER_DESC "Streamzap Remote Control driver"
+
+@@ -279,10 +278,8 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)
+ int ret;
+
+ rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+- if (!rdev) {
+- dev_err(dev, "remote dev allocation failed\n");
++ if (!rdev)
+ goto out;
+- }
+
+ usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys));
+ strlcat(sz->phys, "/input0", sizeof(sz->phys));
+@@ -322,7 +319,6 @@ static int streamzap_probe(struct usb_interface *intf,
+ struct usb_device *usbdev = interface_to_usbdev(intf);
+ struct usb_host_interface *iface_host;
+ struct streamzap_ir *sz = NULL;
+- char buf[63], name[128] = "";
+ int retval = -ENOMEM;
+ int pipe, maxp;
+
+@@ -381,17 +377,6 @@ static int streamzap_probe(struct usb_interface *intf,
+ sz->dev = &intf->dev;
+ sz->buf_in_len = maxp;
+
+- if (usbdev->descriptor.iManufacturer
+- && usb_string(usbdev, usbdev->descriptor.iManufacturer,
+- buf, sizeof(buf)) > 0)
+- strscpy(name, buf, sizeof(name));
+-
+- if (usbdev->descriptor.iProduct
+- && usb_string(usbdev, usbdev->descriptor.iProduct,
+- buf, sizeof(buf)) > 0)
+- snprintf(name + strlen(name), sizeof(name) - strlen(name),
+- " %s", buf);
+-
+ sz->rdev = streamzap_init_rc_dev(sz);
+ if (!sz->rdev)
+ goto rc_dev_fail;
+@@ -422,9 +407,6 @@ static int streamzap_probe(struct usb_interface *intf,
+ if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
+ dev_err(sz->dev, "urb submit failed\n");
+
+- dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
+- usbdev->bus->busnum, usbdev->devnum);
+-
+ return 0;
+
+ rc_dev_fail:
+--
+2.39.5
+
--- /dev/null
+From 6170e6aa0d8cc27a42522dad77af4b8a61cd7689 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 5 Dec 2021 18:10:36 +0100
+Subject: media: streamzap: no need for usb pid/vid in device name
+
+From: Sean Young <sean@mess.org>
+
+[ Upstream commit 7a25e6849ad73de5aa01d62da43071bc02b8530c ]
+
+The usb pid/vid can be found elsewhere, the idVendor/idProduct usb sysfs
+files for example.
+
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Stable-dep-of: f656cfbc7a29 ("media: streamzap: fix race between device disconnection and urb callback")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/rc/streamzap.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
+index 938fbc569f505..9ef6260d2dfd2 100644
+--- a/drivers/media/rc/streamzap.c
++++ b/drivers/media/rc/streamzap.c
+@@ -88,7 +88,6 @@ struct streamzap_ir {
+ ktime_t signal_start;
+ bool timeout_enabled;
+
+- char name[128];
+ char phys[64];
+ };
+
+@@ -285,13 +284,10 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)
+ goto out;
+ }
+
+- snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared Receiver (%04x:%04x)",
+- le16_to_cpu(sz->usbdev->descriptor.idVendor),
+- le16_to_cpu(sz->usbdev->descriptor.idProduct));
+ usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys));
+ strlcat(sz->phys, "/input0", sizeof(sz->phys));
+
+- rdev->device_name = sz->name;
++ rdev->device_name = "Streamzap PC Remote Infrared Receiver";
+ rdev->input_phys = sz->phys;
+ usb_to_input_id(sz->usbdev, &rdev->input_id);
+ rdev->dev.parent = dev;
+--
+2.39.5
+
--- /dev/null
+From e18374819368c129f92f8c4868c8cac282e4e92d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 5 Dec 2021 18:06:30 +0100
+Subject: media: streamzap: remove unnecessary ir_raw_event_reset and handle
+
+From: Sean Young <sean@mess.org>
+
+[ Upstream commit 4bed9306050497f49cbe77b842f0d812f4f27593 ]
+
+There is no reason to have a reset after an IR timeout.
+Calling ir_raw_event_handle() twice for the same interrupt has no
+affect.
+
+Fixes: 56b0ec30c4bc ("[media] rc/streamzap: fix reporting response times")
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Stable-dep-of: f656cfbc7a29 ("media: streamzap: fix race between device disconnection and urb callback")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/rc/streamzap.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
+index 3b25b1780f249..938fbc569f505 100644
+--- a/drivers/media/rc/streamzap.c
++++ b/drivers/media/rc/streamzap.c
+@@ -215,8 +215,6 @@ static void sz_process_ir_data(struct streamzap_ir *sz, int len)
+ sz->idle = true;
+ if (sz->timeout_enabled)
+ sz_push(sz, rawir);
+- ir_raw_event_handle(sz->rdev);
+- ir_raw_event_reset(sz->rdev);
+ } else {
+ sz_push_full_space(sz, sz->buf_in[i]);
+ }
+--
+2.39.5
+
--- /dev/null
+From 133b3290f10d9f8f17c7fcd4df666fcaa480536e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Dec 2021 11:59:41 +0100
+Subject: media: streamzap: remove unused struct members
+
+From: Sean Young <sean@mess.org>
+
+[ Upstream commit 4df69e46c352df9bdbe859824da33428a3ce8a1d ]
+
+These struct members do not serve any purpose.
+
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Stable-dep-of: f656cfbc7a29 ("media: streamzap: fix race between device disconnection and urb callback")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/rc/streamzap.c | 37 ++++++++++++++----------------------
+ 1 file changed, 14 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
+index aff4dfb99a827..d4b38532c7b44 100644
+--- a/drivers/media/rc/streamzap.c
++++ b/drivers/media/rc/streamzap.c
+@@ -66,9 +66,6 @@ struct streamzap_ir {
+ struct device *dev;
+
+ /* usb */
+- struct usb_device *usbdev;
+- struct usb_interface *interface;
+- struct usb_endpoint_descriptor *endpoint;
+ struct urb *urb_in;
+
+ /* buffer & dma */
+@@ -85,7 +82,6 @@ struct streamzap_ir {
+ /* start time of signal; necessary for gap tracking */
+ ktime_t signal_last;
+ ktime_t signal_start;
+- bool timeout_enabled;
+
+ char phys[64];
+ };
+@@ -211,8 +207,7 @@ static void sz_process_ir_data(struct streamzap_ir *sz, int len)
+ .duration = sz->rdev->timeout
+ };
+ sz->idle = true;
+- if (sz->timeout_enabled)
+- sz_push(sz, rawir);
++ sz_push(sz, rawir);
+ } else {
+ sz_push_full_space(sz, sz->buf_in[i]);
+ }
+@@ -271,7 +266,8 @@ static void streamzap_callback(struct urb *urb)
+ usb_submit_urb(urb, GFP_ATOMIC);
+ }
+
+-static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)
++static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz,
++ struct usb_device *usbdev)
+ {
+ struct rc_dev *rdev;
+ struct device *dev = sz->dev;
+@@ -281,12 +277,12 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)
+ if (!rdev)
+ goto out;
+
+- usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys));
++ usb_make_path(usbdev, sz->phys, sizeof(sz->phys));
+ strlcat(sz->phys, "/input0", sizeof(sz->phys));
+
+ rdev->device_name = "Streamzap PC Remote Infrared Receiver";
+ rdev->input_phys = sz->phys;
+- usb_to_input_id(sz->usbdev, &rdev->input_id);
++ usb_to_input_id(usbdev, &rdev->input_id);
+ rdev->dev.parent = dev;
+ rdev->priv = sz;
+ rdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
+@@ -317,6 +313,7 @@ static int streamzap_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+ struct usb_device *usbdev = interface_to_usbdev(intf);
++ struct usb_endpoint_descriptor *endpoint;
+ struct usb_host_interface *iface_host;
+ struct streamzap_ir *sz = NULL;
+ int retval = -ENOMEM;
+@@ -327,9 +324,6 @@ static int streamzap_probe(struct usb_interface *intf,
+ if (!sz)
+ return -ENOMEM;
+
+- sz->usbdev = usbdev;
+- sz->interface = intf;
+-
+ /* Check to ensure endpoint information matches requirements */
+ iface_host = intf->cur_altsetting;
+
+@@ -340,22 +334,22 @@ static int streamzap_probe(struct usb_interface *intf,
+ goto free_sz;
+ }
+
+- sz->endpoint = &(iface_host->endpoint[0].desc);
+- if (!usb_endpoint_dir_in(sz->endpoint)) {
++ endpoint = &iface_host->endpoint[0].desc;
++ if (!usb_endpoint_dir_in(endpoint)) {
+ dev_err(&intf->dev, "%s: endpoint doesn't match input device 02%02x\n",
+- __func__, sz->endpoint->bEndpointAddress);
++ __func__, endpoint->bEndpointAddress);
+ retval = -ENODEV;
+ goto free_sz;
+ }
+
+- if (!usb_endpoint_xfer_int(sz->endpoint)) {
++ if (!usb_endpoint_xfer_int(endpoint)) {
+ dev_err(&intf->dev, "%s: endpoint attributes don't match xfer 02%02x\n",
+- __func__, sz->endpoint->bmAttributes);
++ __func__, endpoint->bmAttributes);
+ retval = -ENODEV;
+ goto free_sz;
+ }
+
+- pipe = usb_rcvintpipe(usbdev, sz->endpoint->bEndpointAddress);
++ pipe = usb_rcvintpipe(usbdev, endpoint->bEndpointAddress);
+ maxp = usb_maxpacket(usbdev, pipe, usb_pipeout(pipe));
+
+ if (maxp == 0) {
+@@ -377,14 +371,13 @@ static int streamzap_probe(struct usb_interface *intf,
+ sz->dev = &intf->dev;
+ sz->buf_in_len = maxp;
+
+- sz->rdev = streamzap_init_rc_dev(sz);
++ sz->rdev = streamzap_init_rc_dev(sz, usbdev);
+ if (!sz->rdev)
+ goto rc_dev_fail;
+
+ sz->idle = true;
+ sz->decoder_state = PulseSpace;
+ /* FIXME: don't yet have a way to set this */
+- sz->timeout_enabled = true;
+ sz->rdev->timeout = SZ_TIMEOUT * SZ_RESOLUTION;
+ #if 0
+ /* not yet supported, depends on patches from maxim */
+@@ -397,8 +390,7 @@ static int streamzap_probe(struct usb_interface *intf,
+
+ /* Complete final initialisations */
+ usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in,
+- maxp, (usb_complete_t)streamzap_callback,
+- sz, sz->endpoint->bInterval);
++ maxp, streamzap_callback, sz, endpoint->bInterval);
+ sz->urb_in->transfer_dma = sz->dma_in;
+ sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+@@ -439,7 +431,6 @@ static void streamzap_disconnect(struct usb_interface *interface)
+ if (!sz)
+ return;
+
+- sz->usbdev = NULL;
+ rc_unregister_device(sz->rdev);
+ usb_kill_urb(sz->urb_in);
+ usb_free_urb(sz->urb_in);
+--
+2.39.5
+
--- /dev/null
+From b5c32a3dfac87a4ead5c6f69a8ae21ec3d153da2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Mar 2025 18:32:44 +0100
+Subject: net: dsa: mv88e6xxx: fix VTU methods for 6320 family
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marek Behún <kabel@kernel.org>
+
+[ Upstream commit f9a457722cf5e3534be5ffab549d6b49737fca72 ]
+
+The VTU registers of the 6320 family use the 6352 semantics, not 6185.
+Fix it.
+
+Fixes: b8fee9571063 ("net: dsa: mv88e6xxx: add VLAN Get Next support")
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Cc: <stable@vger.kernel.org> # 5.15.x
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250317173250.28780-2-kabel@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/mv88e6xxx/chip.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
+index 524743393a678..9f7ff54894d4b 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.c
++++ b/drivers/net/dsa/mv88e6xxx/chip.c
+@@ -4621,8 +4621,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
+ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+- .vtu_getnext = mv88e6185_g1_vtu_getnext,
+- .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
++ .vtu_getnext = mv88e6352_g1_vtu_getnext,
++ .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
+ .gpio_ops = &mv88e6352_gpio_ops,
+ .avb_ops = &mv88e6352_avb_ops,
+ .ptp_ops = &mv88e6352_ptp_ops,
+@@ -4667,8 +4667,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
+ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+- .vtu_getnext = mv88e6185_g1_vtu_getnext,
+- .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
++ .vtu_getnext = mv88e6352_g1_vtu_getnext,
++ .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
+ .gpio_ops = &mv88e6352_gpio_ops,
+ .avb_ops = &mv88e6352_avb_ops,
+ .ptp_ops = &mv88e6352_ptp_ops,
+--
+2.39.5
+
--- /dev/null
+From e2e69e2bb0901ca53613fa2931bbeadee8785efa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Jul 2022 20:41:30 +0200
+Subject: PCI: Assign PCI domain IDs by ida_alloc()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit c14f7ccc9f5dcf9d06ddeec706f85405b2c80600 ]
+
+Replace assignment of PCI domain IDs from atomic_inc_return() to
+ida_alloc().
+
+Use two IDAs, one for static domain allocations (those which are defined in
+device tree) and second for dynamic allocations (all other).
+
+During removal of root bus / host bridge, also release the domain ID. The
+released ID can be reused again, for example when dynamically loading and
+unloading native PCI host bridge drivers.
+
+This change also allows to mix static device tree assignment and dynamic by
+kernel as all static allocations are reserved in dynamic pool.
+
+[bhelgaas: set "err" if "bus->domain_nr < 0"]
+Link: https://lore.kernel.org/r/20220714184130.5436-1-pali@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Stable-dep-of: 804443c1f278 ("PCI: Fix reference leak in pci_register_host_bridge()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pci.c | 103 +++++++++++++++++++++++++------------------
+ drivers/pci/probe.c | 7 +++
+ drivers/pci/remove.c | 6 +++
+ include/linux/pci.h | 1 +
+ 4 files changed, 74 insertions(+), 43 deletions(-)
+
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index fbaf9af62bd67..99342ae6ff5ba 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -6709,60 +6709,70 @@ static void pci_no_domains(void)
+ }
+
+ #ifdef CONFIG_PCI_DOMAINS_GENERIC
+-static atomic_t __domain_nr = ATOMIC_INIT(-1);
++static DEFINE_IDA(pci_domain_nr_static_ida);
++static DEFINE_IDA(pci_domain_nr_dynamic_ida);
+
+-static int pci_get_new_domain_nr(void)
++static void of_pci_reserve_static_domain_nr(void)
+ {
+- return atomic_inc_return(&__domain_nr);
++ struct device_node *np;
++ int domain_nr;
++
++ for_each_node_by_type(np, "pci") {
++ domain_nr = of_get_pci_domain_nr(np);
++ if (domain_nr < 0)
++ continue;
++ /*
++ * Permanently allocate domain_nr in dynamic_ida
++ * to prevent it from dynamic allocation.
++ */
++ ida_alloc_range(&pci_domain_nr_dynamic_ida,
++ domain_nr, domain_nr, GFP_KERNEL);
++ }
+ }
+
+ static int of_pci_bus_find_domain_nr(struct device *parent)
+ {
+- static int use_dt_domains = -1;
+- int domain = -1;
++ static bool static_domains_reserved = false;
++ int domain_nr;
+
+- if (parent)
+- domain = of_get_pci_domain_nr(parent->of_node);
++ /* On the first call scan device tree for static allocations. */
++ if (!static_domains_reserved) {
++ of_pci_reserve_static_domain_nr();
++ static_domains_reserved = true;
++ }
++
++ if (parent) {
++ /*
++ * If domain is in DT, allocate it in static IDA. This
++ * prevents duplicate static allocations in case of errors
++ * in DT.
++ */
++ domain_nr = of_get_pci_domain_nr(parent->of_node);
++ if (domain_nr >= 0)
++ return ida_alloc_range(&pci_domain_nr_static_ida,
++ domain_nr, domain_nr,
++ GFP_KERNEL);
++ }
+
+ /*
+- * Check DT domain and use_dt_domains values.
+- *
+- * If DT domain property is valid (domain >= 0) and
+- * use_dt_domains != 0, the DT assignment is valid since this means
+- * we have not previously allocated a domain number by using
+- * pci_get_new_domain_nr(); we should also update use_dt_domains to
+- * 1, to indicate that we have just assigned a domain number from
+- * DT.
+- *
+- * If DT domain property value is not valid (ie domain < 0), and we
+- * have not previously assigned a domain number from DT
+- * (use_dt_domains != 1) we should assign a domain number by
+- * using the:
+- *
+- * pci_get_new_domain_nr()
+- *
+- * API and update the use_dt_domains value to keep track of method we
+- * are using to assign domain numbers (use_dt_domains = 0).
+- *
+- * All other combinations imply we have a platform that is trying
+- * to mix domain numbers obtained from DT and pci_get_new_domain_nr(),
+- * which is a recipe for domain mishandling and it is prevented by
+- * invalidating the domain value (domain = -1) and printing a
+- * corresponding error.
++ * If domain was not specified in DT, choose a free ID from dynamic
++ * allocations. All domain numbers from DT are permanently in
++ * dynamic allocations to prevent assigning them to other DT nodes
++ * without static domain.
+ */
+- if (domain >= 0 && use_dt_domains) {
+- use_dt_domains = 1;
+- } else if (domain < 0 && use_dt_domains != 1) {
+- use_dt_domains = 0;
+- domain = pci_get_new_domain_nr();
+- } else {
+- if (parent)
+- pr_err("Node %pOF has ", parent->of_node);
+- pr_err("Inconsistent \"linux,pci-domain\" property in DT\n");
+- domain = -1;
+- }
++ return ida_alloc(&pci_domain_nr_dynamic_ida, GFP_KERNEL);
++}
+
+- return domain;
++static void of_pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent)
++{
++ if (bus->domain_nr < 0)
++ return;
++
++ /* Release domain from IDA where it was allocated. */
++ if (of_get_pci_domain_nr(parent->of_node) == bus->domain_nr)
++ ida_free(&pci_domain_nr_static_ida, bus->domain_nr);
++ else
++ ida_free(&pci_domain_nr_dynamic_ida, bus->domain_nr);
+ }
+
+ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
+@@ -6770,6 +6780,13 @@ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
+ return acpi_disabled ? of_pci_bus_find_domain_nr(parent) :
+ acpi_pci_bus_find_domain_nr(bus);
+ }
++
++void pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent)
++{
++ if (!acpi_disabled)
++ return;
++ of_pci_bus_release_domain_nr(bus, parent);
++}
+ #endif
+
+ /**
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index 3ed2eb893dcca..f70d7dec3fdde 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -908,6 +908,10 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
+ bus->domain_nr = pci_bus_find_domain_nr(bus, parent);
+ else
+ bus->domain_nr = bridge->domain_nr;
++ if (bus->domain_nr < 0) {
++ err = bus->domain_nr;
++ goto free;
++ }
+ #endif
+
+ b = pci_find_bus(pci_domain_nr(bus), bridge->busnr);
+@@ -1029,6 +1033,9 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
+ device_del(&bridge->dev);
+
+ free:
++#ifdef CONFIG_PCI_DOMAINS_GENERIC
++ pci_bus_release_domain_nr(bus, parent);
++#endif
+ kfree(bus);
+ return err;
+ }
+diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
+index 4c54c75050dc1..0145aef1b9301 100644
+--- a/drivers/pci/remove.c
++++ b/drivers/pci/remove.c
+@@ -160,6 +160,12 @@ void pci_remove_root_bus(struct pci_bus *bus)
+ pci_remove_bus(bus);
+ host_bridge->bus = NULL;
+
++#ifdef CONFIG_PCI_DOMAINS_GENERIC
++ /* Release domain_nr if it was dynamically allocated */
++ if (host_bridge->domain_nr == PCI_DOMAIN_NR_NOT_SET)
++ pci_bus_release_domain_nr(bus, host_bridge->dev.parent);
++#endif
++
+ /* remove the host bridge */
+ device_del(&host_bridge->dev);
+ }
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index a97c2b9885e1b..ccff086316e91 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -1719,6 +1719,7 @@ static inline int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
+ { return 0; }
+ #endif
+ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent);
++void pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent);
+ #endif
+
+ /* Some architectures require additional setup to direct VGA traffic */
+--
+2.39.5
+
--- /dev/null
+From ce8c98b7e330aa8fdbc729c6069a3ef4c94a12b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Jul 2021 20:50:07 +0800
+Subject: PCI: Coalesce host bridge contiguous apertures
+
+From: Kai-Heng Feng <kai.heng.feng@canonical.com>
+
+[ Upstream commit 7c3855c423b17f6ca211858afb0cef20569914c7 ]
+
+Built-in graphics at 07:00.0 on HP EliteDesk 805 G6 doesn't work because
+graphics can't get the BAR it needs. The BIOS configuration is
+correct: BARs 0 and 2 both fit in the 00:08.1 bridge window.
+
+But that 00:08.1 window covers two host bridge apertures from _CRS.
+Previously we assumed this was illegal, so we clipped the window to fit
+into one aperture (see 0f7e7aee2f37 ("PCI: Add pci_bus_clip_resource() to
+clip to fit upstream window")).
+
+ pci_bus 0000:00: root bus resource [mem 0x10020200000-0x100303fffff window]
+ pci_bus 0000:00: root bus resource [mem 0x10030400000-0x100401fffff window]
+
+ pci 0000:00:08.1: bridge window [mem 0x10030000000-0x100401fffff 64bit pref]
+ pci 0000:07:00.0: reg 0x10: [mem 0x10030000000-0x1003fffffff 64bit pref]
+ pci 0000:07:00.0: reg 0x18: [mem 0x10040000000-0x100401fffff 64bit pref]
+
+ pci 0000:00:08.1: can't claim BAR 15 [mem 0x10030000000-0x100401fffff 64bit pref]: no compatible bridge window
+ pci 0000:00:08.1: [mem 0x10030000000-0x100401fffff 64bit pref] clipped to [mem 0x10030000000-0x100303fffff 64bit pref]
+ pci 0000:00:08.1: bridge window [mem 0x10030000000-0x100303fffff 64bit pref]
+
+ pci 0000:07:00.0: can't claim BAR 0 [mem 0x10030000000-0x1003fffffff 64bit pref]: no compatible bridge window
+ pci 0000:07:00.0: can't claim BAR 2 [mem 0x10040000000-0x100401fffff 64bit pref]: no compatible bridge window
+
+However, the host bridge apertures are contiguous, so there's no need to
+clip in this case. Coalesce contiguous apertures so we can allocate from
+the entire contiguous region.
+
+Previous commit 65db04053efe ("PCI: Coalesce host bridge contiguous
+apertures") was similar but sorted the apertures, and Guenter Roeck
+reported a regression in ppc:sam460ex qemu emulation from nvme; see
+https://lore.kernel.org/all/20210709231529.GA3270116@roeck-us.net/
+
+[bhelgaas: commit log]
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=212013
+Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
+Link: https://lore.kernel.org/r/20210713125007.1260304-1-kai.heng.feng@canonical.com
+Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Stable-dep-of: 804443c1f278 ("PCI: Fix reference leak in pci_register_host_bridge()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/probe.c | 31 +++++++++++++++++++++++++++----
+ 1 file changed, 27 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index 3ad0b2839041c..3ed2eb893dcca 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -883,11 +883,11 @@ static void pci_set_bus_msi_domain(struct pci_bus *bus)
+ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
+ {
+ struct device *parent = bridge->dev.parent;
+- struct resource_entry *window, *n;
++ struct resource_entry *window, *next, *n;
+ struct pci_bus *bus, *b;
+- resource_size_t offset;
++ resource_size_t offset, next_offset;
+ LIST_HEAD(resources);
+- struct resource *res;
++ struct resource *res, *next_res;
+ char addr[64], *fmt;
+ const char *name;
+ int err;
+@@ -969,11 +969,34 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
+ if (nr_node_ids > 1 && pcibus_to_node(bus) == NUMA_NO_NODE)
+ dev_warn(&bus->dev, "Unknown NUMA node; performance will be reduced\n");
+
++ /* Coalesce contiguous windows */
++ resource_list_for_each_entry_safe(window, n, &resources) {
++ if (list_is_last(&window->node, &resources))
++ break;
++
++ next = list_next_entry(window, node);
++ offset = window->offset;
++ res = window->res;
++ next_offset = next->offset;
++ next_res = next->res;
++
++ if (res->flags != next_res->flags || offset != next_offset)
++ continue;
++
++ if (res->end + 1 == next_res->start) {
++ next_res->start = res->start;
++ res->flags = res->start = res->end = 0;
++ }
++ }
++
+ /* Add initial resources to the bus */
+ resource_list_for_each_entry_safe(window, n, &resources) {
+- list_move_tail(&window->node, &bridge->windows);
+ offset = window->offset;
+ res = window->res;
++ if (!res->end)
++ continue;
++
++ list_move_tail(&window->node, &bridge->windows);
+
+ if (res->flags & IORESOURCE_BUS)
+ pci_bus_insert_busn_res(bus, bus->number, res->end);
+--
+2.39.5
+
--- /dev/null
+From bac41eeb5c4aad6a53057e542c7a886d66985174 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 10:14:40 +0800
+Subject: PCI: Fix reference leak in pci_register_host_bridge()
+
+From: Ma Ke <make24@iscas.ac.cn>
+
+[ Upstream commit 804443c1f27883926de94c849d91f5b7d7d696e9 ]
+
+If device_register() fails, call put_device() to give up the reference to
+avoid a memory leak, per the comment at device_register().
+
+Found by code review.
+
+Link: https://lore.kernel.org/r/20250225021440.3130264-1-make24@iscas.ac.cn
+Fixes: 37d6a0a6f470 ("PCI: Add pci_register_host_bridge() interface")
+Signed-off-by: Ma Ke <make24@iscas.ac.cn>
+[bhelgaas: squash Dan Carpenter's double free fix from
+https://lore.kernel.org/r/db806a6c-a91b-4e5a-a84b-6b7e01bdac85@stanley.mountain]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/probe.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index f70d7dec3fdde..940336fa73743 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -888,6 +888,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
+ resource_size_t offset, next_offset;
+ LIST_HEAD(resources);
+ struct resource *res, *next_res;
++ bool bus_registered = false;
+ char addr[64], *fmt;
+ const char *name;
+ int err;
+@@ -951,6 +952,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
+ name = dev_name(&bus->dev);
+
+ err = device_register(&bus->dev);
++ bus_registered = true;
+ if (err)
+ goto unregister;
+
+@@ -1031,12 +1033,15 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
+ unregister:
+ put_device(&bridge->dev);
+ device_del(&bridge->dev);
+-
+ free:
+ #ifdef CONFIG_PCI_DOMAINS_GENERIC
+ pci_bus_release_domain_nr(bus, parent);
+ #endif
+- kfree(bus);
++ if (bus_registered)
++ put_device(&bus->dev);
++ else
++ kfree(bus);
++
+ return err;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 4428cbdc160eeeba32a1ad8dd717bc8a7e2eebdd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Apr 2025 17:42:32 +0100
+Subject: selftests/mm: generate a temporary mountpoint for cgroup filesystem
+
+From: Mark Brown <broonie@kernel.org>
+
+[ Upstream commit 9c02223e2d9df5cb37c51aedb78f3960294e09b5 ]
+
+Currently if the filesystem for the cgroups version it wants to use is not
+mounted charge_reserved_hugetlb.sh and hugetlb_reparenting_test.sh tests
+will attempt to mount it on the hard coded path /dev/cgroup/memory,
+deleting that directory when the test finishes. This will fail if there
+is not a preexisting directory at that path, and since the directory is
+deleted subsequent runs of the test will fail. Instead of relying on this
+hard coded directory name use mktemp to generate a temporary directory to
+use as a mountpoint, fixing both the assumption and the disruption caused
+by deleting a preexisting directory.
+
+This means that if the relevant cgroup filesystem is not already mounted
+then we rely on having coreutils (which provides mktemp) installed. I
+suspect that many current users are relying on having things automounted
+by default, and given that the script relies on bash it's probably not an
+unreasonable requirement.
+
+Link: https://lkml.kernel.org/r/20250404-kselftest-mm-cgroup2-detection-v1-1-3dba6d32ba8c@kernel.org
+Fixes: 209376ed2a84 ("selftests/vm: make charge_reserved_hugetlb.sh work with existing cgroup setting")
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Cc: Aishwarya TCV <aishwarya.tcv@arm.com>
+Cc: Mark Brown <broonie@kernel.org>
+Cc: Mina Almasry <almasrymina@google.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Cc: Waiman Long <longman@redhat.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/vm/charge_reserved_hugetlb.sh | 4 ++--
+ tools/testing/selftests/vm/hugetlb_reparenting_test.sh | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
+index 8e00276b4e69b..dc3fc438b3d9e 100644
+--- a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
++++ b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
+@@ -27,7 +27,7 @@ fi
+ if [[ $cgroup2 ]]; then
+ cgroup_path=$(mount -t cgroup2 | head -1 | awk '{print $3}')
+ if [[ -z "$cgroup_path" ]]; then
+- cgroup_path=/dev/cgroup/memory
++ cgroup_path=$(mktemp -d)
+ mount -t cgroup2 none $cgroup_path
+ do_umount=1
+ fi
+@@ -35,7 +35,7 @@ if [[ $cgroup2 ]]; then
+ else
+ cgroup_path=$(mount -t cgroup | grep ",hugetlb" | awk '{print $3}')
+ if [[ -z "$cgroup_path" ]]; then
+- cgroup_path=/dev/cgroup/memory
++ cgroup_path=$(mktemp -d)
+ mount -t cgroup memory,hugetlb $cgroup_path
+ do_umount=1
+ fi
+diff --git a/tools/testing/selftests/vm/hugetlb_reparenting_test.sh b/tools/testing/selftests/vm/hugetlb_reparenting_test.sh
+index 14d26075c8635..302f2c7003f03 100644
+--- a/tools/testing/selftests/vm/hugetlb_reparenting_test.sh
++++ b/tools/testing/selftests/vm/hugetlb_reparenting_test.sh
+@@ -22,7 +22,7 @@ fi
+ if [[ $cgroup2 ]]; then
+ CGROUP_ROOT=$(mount -t cgroup2 | head -1 | awk '{print $3}')
+ if [[ -z "$CGROUP_ROOT" ]]; then
+- CGROUP_ROOT=/dev/cgroup/memory
++ CGROUP_ROOT=$(mktemp -d)
+ mount -t cgroup2 none $CGROUP_ROOT
+ do_umount=1
+ fi
+--
+2.39.5
+
f2fs-add-inline-to-f2fs_build_fault_attr-stub.patch
bluetooth-sco-fix-uaf-on-sco_sock_timeout.patch
module-sign-with-sha512-instead-of-sha1-by-default.patch
+media-streamzap-remove-unnecessary-ir_raw_event_rese.patch
+media-streamzap-no-need-for-usb-pid-vid-in-device-na.patch
+media-streamzap-less-chatter.patch
+media-streamzap-remove-unused-struct-members.patch
+media-streamzap-fix-race-between-device-disconnectio.patch
+auxdisplay-hd44780-convert-to-platform-remove-callba.patch
+auxdisplay-hd44780-fix-an-api-misuse-in-hd44780.c.patch
+net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch
+soc-samsung-exynos-chipid-avoid-soc_device_to_device.patch
+soc-samsung-exynos-chipid-pass-revision-reg-offsets.patch
+soc-samsung-exynos-chipid-add-null-pointer-check-in-.patch
+iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch
+iio-adc-ad7768-1-fix-conversion-result-sign.patch
+backlight-led_bl-convert-to-platform-remove-callback.patch
+backlight-led_bl-hold-led_access-lock-when-calling-l.patch
+cifs-print-tids-as-hex.patch
+cifs-avoid-null-pointer-dereference-in-dbg-call.patch
+cifs-fix-integer-overflow-in-match_server.patch
+gpio-tegra186-force-one-interrupt-per-bank.patch
+gpio-tegra186-fix-resource-handling-in-acpi-probe-pa.patch
+pci-coalesce-host-bridge-contiguous-apertures.patch
+pci-assign-pci-domain-ids-by-ida_alloc.patch
+pci-fix-reference-leak-in-pci_register_host_bridge.patch
+ksmbd-prevent-integer-overflow-in-calculation-of-dea.patch
+selftests-mm-generate-a-temporary-mountpoint-for-cgr.patch
+kmsan-disable-strscpy-optimization-under-kmsan.patch
+string-add-load_unaligned_zeropad-code-path-to-sized.patch
+drm-msm-a6xx-improve-gpu-recovery-sequence.patch
+drm-msm-a6xx-handle-gmu-prepare-slumber-hfi-failure.patch
+drm-msm-a6xx-avoid-gx-gbit-halt-during-rpm-suspend.patch
+drm-msm-a6xx-fix-stale-rpmh-votes-from-gpu.patch
--- /dev/null
+From b1bff8b14f65417f648c762bc300038d4b81d5ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 15:35:18 -0600
+Subject: soc: samsung: exynos-chipid: Add NULL pointer check in
+ exynos_chipid_probe()
+
+From: Chenyuan Yang <chenyuan0y@gmail.com>
+
+[ Upstream commit c8222ef6cf29dd7cad21643228f96535cc02b327 ]
+
+soc_dev_attr->revision could be NULL, thus,
+a pointer check is added to prevent potential NULL pointer dereference.
+This is similar to the fix in commit 3027e7b15b02
+("ice: Fix some null pointer dereference issues in ice_ptp.c").
+
+This issue is found by our static analysis tool.
+
+Signed-off-by: Chenyuan Yang <chenyuan0y@gmail.com>
+Link: https://lore.kernel.org/r/20250212213518.69432-1-chenyuan0y@gmail.com
+Fixes: 3253b7b7cd44 ("soc: samsung: Add exynos chipid driver support")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/samsung/exynos-chipid.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
+index 133654f21251f..edcae687cd2a2 100644
+--- a/drivers/soc/samsung/exynos-chipid.c
++++ b/drivers/soc/samsung/exynos-chipid.c
+@@ -125,6 +125,8 @@ static int exynos_chipid_probe(struct platform_device *pdev)
+
+ soc_dev_attr->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "%x", soc_info.revision);
++ if (!soc_dev_attr->revision)
++ return -ENOMEM;
+ soc_dev_attr->soc_id = product_id_to_soc_id(soc_info.product_id);
+ if (!soc_dev_attr->soc_id) {
+ pr_err("Unknown SoC\n");
+--
+2.39.5
+
--- /dev/null
+From 97c48506b55ca0aa7eafb61279ed82cd70c9d235 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 19 Sep 2021 11:31:12 +0200
+Subject: soc: samsung: exynos-chipid: avoid soc_device_to_device()
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+[ Upstream commit d1141886c8d72ad77920e6e4b617d366e6e3ee8a ]
+
+soc_device_to_device() seems to be discouraged [1] so remove it in favor
+of printing info message with platform device. This will only change
+the prefix in the info message from "soc soc0: " to "exynos-chipid
+10000000.chipid:".
+
+[1] https://lore.kernel.org/lkml/20191111052741.GB3176397@kroah.com/
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+Reviewed-by: Sylwester Nawrocki <snawrocki@kernel.org>
+Tested-by: Sylwester Nawrocki <snawrocki@kernel.org>
+Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
+Tested-by: Alim Akhtar <alim.akhtar@samsung.com>
+Link: https://lore.kernel.org/r/20210919093114.35987-2-krzysztof.kozlowski@canonical.com
+Stable-dep-of: c8222ef6cf29 ("soc: samsung: exynos-chipid: Add NULL pointer check in exynos_chipid_probe()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/samsung/exynos-chipid.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
+index 5c1d0f97f7664..dcd9a08ce7065 100644
+--- a/drivers/soc/samsung/exynos-chipid.c
++++ b/drivers/soc/samsung/exynos-chipid.c
+@@ -104,8 +104,7 @@ static int exynos_chipid_probe(struct platform_device *pdev)
+
+ platform_set_drvdata(pdev, soc_dev);
+
+- dev_info(soc_device_to_device(soc_dev),
+- "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n",
++ dev_info(&pdev->dev, "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n",
+ soc_dev_attr->soc_id, product_id, revision);
+
+ return 0;
+--
+2.39.5
+
--- /dev/null
+From bd0ccafa27fdf0b006d7631b5327ad54fe7649d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Oct 2021 16:35:06 +0300
+Subject: soc: samsung: exynos-chipid: Pass revision reg offsets
+
+From: Sam Protsenko <semen.protsenko@linaro.org>
+
+[ Upstream commit c072c4ef7ef09e1d6470c48cf52570487589b76a ]
+
+Old Exynos SoCs have both Product ID and Revision ID in one single
+register, while new SoCs tend to have two separate registers for those
+IDs. Implement handling of both cases by passing Revision ID register
+offsets in driver data.
+
+Previously existing macros for Exynos4210 (removed in this patch) were
+incorrect:
+
+ #define EXYNOS_SUBREV_MASK (0xf << 4)
+ #define EXYNOS_MAINREV_MASK (0xf << 0)
+
+Actual format of PRO_ID register in Exynos4210 (offset 0x0):
+
+ [31:12] Product ID
+ [9:8] Package information
+ [7:4] Main Revision Number
+ [3:0] Sub Revision Number
+
+This patch doesn't change the behavior on existing platforms, so
+'/sys/devices/soc0/revision' will show the same string as before.
+
+Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org>
+Tested-by: Henrik Grimler <henrik@grimler.se>
+Link: https://lore.kernel.org/r/20211014133508.1210-1-semen.protsenko@linaro.org
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+Stable-dep-of: c8222ef6cf29 ("soc: samsung: exynos-chipid: Add NULL pointer check in exynos_chipid_probe()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/samsung/exynos-chipid.c | 69 +++++++++++++++++++----
+ include/linux/soc/samsung/exynos-chipid.h | 6 +-
+ 2 files changed, 60 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
+index dcd9a08ce7065..133654f21251f 100644
+--- a/drivers/soc/samsung/exynos-chipid.c
++++ b/drivers/soc/samsung/exynos-chipid.c
+@@ -16,6 +16,7 @@
+ #include <linux/errno.h>
+ #include <linux/mfd/syscon.h>
+ #include <linux/of.h>
++#include <linux/of_device.h>
+ #include <linux/platform_device.h>
+ #include <linux/regmap.h>
+ #include <linux/slab.h>
+@@ -24,6 +25,17 @@
+
+ #include "exynos-asv.h"
+
++struct exynos_chipid_variant {
++ unsigned int rev_reg; /* revision register offset */
++ unsigned int main_rev_shift; /* main revision offset in rev_reg */
++ unsigned int sub_rev_shift; /* sub revision offset in rev_reg */
++};
++
++struct exynos_chipid_info {
++ u32 product_id;
++ u32 revision;
++};
++
+ static const struct exynos_soc_id {
+ const char *name;
+ unsigned int id;
+@@ -49,31 +61,57 @@ static const char *product_id_to_soc_id(unsigned int product_id)
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(soc_ids); i++)
+- if ((product_id & EXYNOS_MASK) == soc_ids[i].id)
++ if (product_id == soc_ids[i].id)
+ return soc_ids[i].name;
+ return NULL;
+ }
+
++static int exynos_chipid_get_chipid_info(struct regmap *regmap,
++ const struct exynos_chipid_variant *data,
++ struct exynos_chipid_info *soc_info)
++{
++ int ret;
++ unsigned int val, main_rev, sub_rev;
++
++ ret = regmap_read(regmap, EXYNOS_CHIPID_REG_PRO_ID, &val);
++ if (ret < 0)
++ return ret;
++ soc_info->product_id = val & EXYNOS_MASK;
++
++ if (data->rev_reg != EXYNOS_CHIPID_REG_PRO_ID) {
++ ret = regmap_read(regmap, data->rev_reg, &val);
++ if (ret < 0)
++ return ret;
++ }
++ main_rev = (val >> data->main_rev_shift) & EXYNOS_REV_PART_MASK;
++ sub_rev = (val >> data->sub_rev_shift) & EXYNOS_REV_PART_MASK;
++ soc_info->revision = (main_rev << EXYNOS_REV_PART_SHIFT) | sub_rev;
++
++ return 0;
++}
++
+ static int exynos_chipid_probe(struct platform_device *pdev)
+ {
++ const struct exynos_chipid_variant *drv_data;
++ struct exynos_chipid_info soc_info;
+ struct soc_device_attribute *soc_dev_attr;
+ struct soc_device *soc_dev;
+ struct device_node *root;
+ struct regmap *regmap;
+- u32 product_id;
+- u32 revision;
+ int ret;
+
++ drv_data = of_device_get_match_data(&pdev->dev);
++ if (!drv_data)
++ return -EINVAL;
++
+ regmap = device_node_to_regmap(pdev->dev.of_node);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+- ret = regmap_read(regmap, EXYNOS_CHIPID_REG_PRO_ID, &product_id);
++ ret = exynos_chipid_get_chipid_info(regmap, drv_data, &soc_info);
+ if (ret < 0)
+ return ret;
+
+- revision = product_id & EXYNOS_REV_MASK;
+-
+ soc_dev_attr = devm_kzalloc(&pdev->dev, sizeof(*soc_dev_attr),
+ GFP_KERNEL);
+ if (!soc_dev_attr)
+@@ -86,8 +124,8 @@ static int exynos_chipid_probe(struct platform_device *pdev)
+ of_node_put(root);
+
+ soc_dev_attr->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+- "%x", revision);
+- soc_dev_attr->soc_id = product_id_to_soc_id(product_id);
++ "%x", soc_info.revision);
++ soc_dev_attr->soc_id = product_id_to_soc_id(soc_info.product_id);
+ if (!soc_dev_attr->soc_id) {
+ pr_err("Unknown SoC\n");
+ return -ENODEV;
+@@ -105,7 +143,7 @@ static int exynos_chipid_probe(struct platform_device *pdev)
+ platform_set_drvdata(pdev, soc_dev);
+
+ dev_info(&pdev->dev, "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n",
+- soc_dev_attr->soc_id, product_id, revision);
++ soc_dev_attr->soc_id, soc_info.product_id, soc_info.revision);
+
+ return 0;
+
+@@ -124,9 +162,18 @@ static int exynos_chipid_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++static const struct exynos_chipid_variant exynos4210_chipid_drv_data = {
++ .rev_reg = 0x0,
++ .main_rev_shift = 4,
++ .sub_rev_shift = 0,
++};
++
+ static const struct of_device_id exynos_chipid_of_device_ids[] = {
+- { .compatible = "samsung,exynos4210-chipid" },
+- {}
++ {
++ .compatible = "samsung,exynos4210-chipid",
++ .data = &exynos4210_chipid_drv_data,
++ },
++ { }
+ };
+
+ static struct platform_driver exynos_chipid_driver = {
+diff --git a/include/linux/soc/samsung/exynos-chipid.h b/include/linux/soc/samsung/exynos-chipid.h
+index 8bca6763f99c1..62f0e25310687 100644
+--- a/include/linux/soc/samsung/exynos-chipid.h
++++ b/include/linux/soc/samsung/exynos-chipid.h
+@@ -9,10 +9,8 @@
+ #define __LINUX_SOC_EXYNOS_CHIPID_H
+
+ #define EXYNOS_CHIPID_REG_PRO_ID 0x00
+-#define EXYNOS_SUBREV_MASK (0xf << 4)
+-#define EXYNOS_MAINREV_MASK (0xf << 0)
+-#define EXYNOS_REV_MASK (EXYNOS_SUBREV_MASK | \
+- EXYNOS_MAINREV_MASK)
++#define EXYNOS_REV_PART_MASK 0xf
++#define EXYNOS_REV_PART_SHIFT 4
+ #define EXYNOS_MASK 0xfffff000
+
+ #define EXYNOS_CHIPID_REG_PKG_ID 0x04
+--
+2.39.5
+
--- /dev/null
+From 16241f20458f12b43104cb71eaa8f7f7d06d44c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Apr 2025 17:06:59 -0700
+Subject: string: Add load_unaligned_zeropad() code path to sized_strscpy()
+
+From: Peter Collingbourne <pcc@google.com>
+
+[ Upstream commit d94c12bd97d567de342fd32599e7cd9e50bfa140 ]
+
+The call to read_word_at_a_time() in sized_strscpy() is problematic
+with MTE because it may trigger a tag check fault when reading
+across a tag granule (16 bytes) boundary. To make this code
+MTE compatible, let's start using load_unaligned_zeropad()
+on architectures where it is available (i.e. architectures that
+define CONFIG_DCACHE_WORD_ACCESS). Because load_unaligned_zeropad()
+takes care of page boundaries as well as tag granule boundaries,
+also disable the code preventing crossing page boundaries when using
+load_unaligned_zeropad().
+
+Signed-off-by: Peter Collingbourne <pcc@google.com>
+Link: https://linux-review.googlesource.com/id/If4b22e43b5a4ca49726b4bf98ada827fdf755548
+Fixes: 94ab5b61ee16 ("kasan, arm64: enable CONFIG_KASAN_HW_TAGS")
+Cc: stable@vger.kernel.org
+Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
+Link: https://lore.kernel.org/r/20250403000703.2584581-2-pcc@google.com
+Signed-off-by: Kees Cook <kees@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ lib/string.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/lib/string.c b/lib/string.c
+index 9fb9be19a95d7..7c0c69bb5b689 100644
+--- a/lib/string.c
++++ b/lib/string.c
+@@ -186,6 +186,7 @@ ssize_t strscpy(char *dest, const char *src, size_t count)
+ if (count == 0 || WARN_ON_ONCE(count > INT_MAX))
+ return -E2BIG;
+
++#ifndef CONFIG_DCACHE_WORD_ACCESS
+ #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+ /*
+ * If src is unaligned, don't cross a page boundary,
+@@ -200,12 +201,14 @@ ssize_t strscpy(char *dest, const char *src, size_t count)
+ /* If src or dest is unaligned, don't do word-at-a-time. */
+ if (((long) dest | (long) src) & (sizeof(long) - 1))
+ max = 0;
++#endif
+ #endif
+
+ /*
+- * read_word_at_a_time() below may read uninitialized bytes after the
+- * trailing zero and use them in comparisons. Disable this optimization
+- * under KMSAN to prevent false positive reports.
++ * load_unaligned_zeropad() or read_word_at_a_time() below may read
++ * uninitialized bytes after the trailing zero and use them in
++ * comparisons. Disable this optimization under KMSAN to prevent
++ * false positive reports.
+ */
+ if (IS_ENABLED(CONFIG_KMSAN))
+ max = 0;
+@@ -213,7 +216,11 @@ ssize_t strscpy(char *dest, const char *src, size_t count)
+ while (max >= sizeof(unsigned long)) {
+ unsigned long c, data;
+
++#ifdef CONFIG_DCACHE_WORD_ACCESS
++ c = load_unaligned_zeropad(src+res);
++#else
+ c = read_word_at_a_time(src+res);
++#endif
+ if (has_zero(c, &data, &constants)) {
+ data = prep_zero_mask(c, data, &constants);
+ data = create_zero_mask(data);
+--
+2.39.5
+