From: Sasha Levin Date: Sat, 26 Apr 2025 13:23:10 +0000 (-0400) Subject: Fixes for 5.15 X-Git-Tag: v5.4.293~87 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b2b504f2971128e904618f75f2587eb64d796561;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/auxdisplay-hd44780-convert-to-platform-remove-callba.patch b/queue-5.15/auxdisplay-hd44780-convert-to-platform-remove-callba.patch new file mode 100644 index 0000000000..20563e88d3 --- /dev/null +++ b/queue-5.15/auxdisplay-hd44780-convert-to-platform-remove-callba.patch @@ -0,0 +1,68 @@ +From dcd1caaaff431d1837c7eaca7177fc02a11bc718 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Andy Shevchenko +Stable-dep-of: 9b98a7d2e5f4 ("auxdisplay: hd44780: Fix an API misuse in hd44780.c") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/auxdisplay-hd44780-fix-an-api-misuse-in-hd44780.c.patch b/queue-5.15/auxdisplay-hd44780-fix-an-api-misuse-in-hd44780.c.patch new file mode 100644 index 0000000000..8e652abb53 --- /dev/null +++ b/queue-5.15/auxdisplay-hd44780-fix-an-api-misuse-in-hd44780.c.patch @@ -0,0 +1,48 @@ +From dc4e9a3f436ead472118fd10f99873e3f1465936 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 18:15:27 +0800 +Subject: auxdisplay: hd44780: Fix an API misuse in hd44780.c + +From: Haoxiang Li + +[ 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 +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Andy Shevchenko +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/backlight-led_bl-convert-to-platform-remove-callback.patch b/queue-5.15/backlight-led_bl-convert-to-platform-remove-callback.patch new file mode 100644 index 0000000000..60b59c029b --- /dev/null +++ b/queue-5.15/backlight-led_bl-convert-to-platform-remove-callback.patch @@ -0,0 +1,67 @@ +From f9f77860ff83863d73883e773a1e80f9bd319b21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Daniel Thompson +Signed-off-by: Lee Jones +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 +--- + 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 + diff --git a/queue-5.15/backlight-led_bl-hold-led_access-lock-when-calling-l.patch b/queue-5.15/backlight-led_bl-hold-led_access-lock-when-calling-l.patch new file mode 100644 index 0000000000..2ff50c53b7 --- /dev/null +++ b/queue-5.15/backlight-led_bl-hold-led_access-lock-when-calling-l.patch @@ -0,0 +1,56 @@ +From 1ef5d7abcf559d5250ded7e1b77778a47bc3f980 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20250122091914.309533-1-herve.codina@bootlin.com +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/cifs-avoid-null-pointer-dereference-in-dbg-call.patch b/queue-5.15/cifs-avoid-null-pointer-dereference-in-dbg-call.patch new file mode 100644 index 0000000000..b8ae74a99b --- /dev/null +++ b/queue-5.15/cifs-avoid-null-pointer-dereference-in-dbg-call.patch @@ -0,0 +1,47 @@ +From 0a42623ad0e0caf37648e24f283ddee9993423f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 17:28:58 +0300 +Subject: cifs: avoid NULL pointer dereference in dbg call + +From: Alexandra Diupina + +[ 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 +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/cifs-fix-integer-overflow-in-match_server.patch b/queue-5.15/cifs-fix-integer-overflow-in-match_server.patch new file mode 100644 index 0000000000..68b27cddf3 --- /dev/null +++ b/queue-5.15/cifs-fix-integer-overflow-in-match_server.patch @@ -0,0 +1,46 @@ +From 056ad0c0f89c19c8e975f708ac58a137118776cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 11:22:49 +0300 +Subject: cifs: fix integer overflow in match_server() + +From: Roman Smirnov + +[ 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 +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/cifs-print-tids-as-hex.patch b/queue-5.15/cifs-print-tids-as-hex.patch new file mode 100644 index 0000000000..f14736ac51 --- /dev/null +++ b/queue-5.15/cifs-print-tids-as-hex.patch @@ -0,0 +1,50 @@ +From bb64d2f3eb1db05f5846ded009ca3ad10f926b08 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 May 2022 11:41:04 -0300 +Subject: cifs: print TIDs as hex + +From: Enzo Matsumiya + +[ Upstream commit 71081e7ac16c93acdd18afa65daa468620bb1b64 ] + +Makes these debug messages easier to read + +Signed-off-by: Enzo Matsumiya +Reviewed-by: Paulo Alcantara (SUSE) +Signed-off-by: Steve French +Stable-dep-of: b4885bd5935b ("cifs: avoid NULL pointer dereference in dbg call") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-msm-a6xx-avoid-gx-gbit-halt-during-rpm-suspend.patch b/queue-5.15/drm-msm-a6xx-avoid-gx-gbit-halt-during-rpm-suspend.patch new file mode 100644 index 0000000000..b114ce367a --- /dev/null +++ b/queue-5.15/drm-msm-a6xx-avoid-gx-gbit-halt-during-rpm-suspend.patch @@ -0,0 +1,111 @@ +From a930a106f1b116719164b9bcf3e45393488c583d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Dec 2022 22:33:14 +0530 +Subject: drm/msm/a6xx: Avoid gx gbit halt during rpm suspend + +From: Akhil P Oommen + +[ 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 +Patchwork: https://patchwork.freedesktop.org/patch/515279/ +Link: https://lore.kernel.org/r/20221216223253.1.Ice9c47bfeb1fddb8dc377a3491a043a3ee7fca7d@changeid +Signed-off-by: Rob Clark +Stable-dep-of: f561db72a663 ("drm/msm/a6xx: Fix stale rpmh votes from GPU") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-msm-a6xx-fix-stale-rpmh-votes-from-gpu.patch b/queue-5.15/drm-msm-a6xx-fix-stale-rpmh-votes-from-gpu.patch new file mode 100644 index 0000000000..411bfa2472 --- /dev/null +++ b/queue-5.15/drm-msm-a6xx-fix-stale-rpmh-votes-from-gpu.patch @@ -0,0 +1,129 @@ +From 35922fea90cbae30295a3cb48ecee7a4e5b4a091 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 01:22:14 +0530 +Subject: drm/msm/a6xx: Fix stale rpmh votes from GPU + +From: Akhil P Oommen + +[ 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 +Patchwork: https://patchwork.freedesktop.org/patch/639569/ +Signed-off-by: Rob Clark +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-msm-a6xx-handle-gmu-prepare-slumber-hfi-failure.patch b/queue-5.15/drm-msm-a6xx-handle-gmu-prepare-slumber-hfi-failure.patch new file mode 100644 index 0000000000..827f26bf7e --- /dev/null +++ b/queue-5.15/drm-msm-a6xx-handle-gmu-prepare-slumber-hfi-failure.patch @@ -0,0 +1,42 @@ +From 6a935b9ca5bf34162c81d039ec73f8dfd8f50cb3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Aug 2022 01:52:15 +0530 +Subject: drm/msm/a6xx: Handle GMU prepare-slumber hfi failure + +From: Akhil P Oommen + +[ Upstream commit d6463fd4e97545ef4f7069d13a5fa3ac0924dae2 ] + +When prepare-slumber hfi fails, we should follow a6xx_gmu_force_off() +sequence. + +Signed-off-by: Akhil P Oommen +Patchwork: https://patchwork.freedesktop.org/patch/498401/ +Link: https://lore.kernel.org/r/20220819015030.v5.7.I54815c7c36b80d4725cd054e536365250454452f@changeid +Signed-off-by: Rob Clark +Stable-dep-of: f561db72a663 ("drm/msm/a6xx: Fix stale rpmh votes from GPU") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-msm-a6xx-improve-gpu-recovery-sequence.patch b/queue-5.15/drm-msm-a6xx-improve-gpu-recovery-sequence.patch new file mode 100644 index 0000000000..a6f11f7c84 --- /dev/null +++ b/queue-5.15/drm-msm-a6xx-improve-gpu-recovery-sequence.patch @@ -0,0 +1,175 @@ +From 8e5b3deaad0eabcf7d9a025ba4c882f978c661b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Aug 2022 01:52:14 +0530 +Subject: drm/msm/a6xx: Improve gpu recovery sequence + +From: Akhil P Oommen + +[ 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 +Patchwork: https://patchwork.freedesktop.org/patch/498400/ +Link: https://lore.kernel.org/r/20220819015030.v5.6.Idf2ba51078e87ae7ceb75cc77a5bd4ff2bd31eab@changeid +Signed-off-by: Rob Clark +Stable-dep-of: f561db72a663 ("drm/msm/a6xx: Fix stale rpmh votes from GPU") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/gpio-tegra186-fix-resource-handling-in-acpi-probe-pa.patch b/queue-5.15/gpio-tegra186-fix-resource-handling-in-acpi-probe-pa.patch new file mode 100644 index 0000000000..e3dbb9a0dd --- /dev/null +++ b/queue-5.15/gpio-tegra186-fix-resource-handling-in-acpi-probe-pa.patch @@ -0,0 +1,74 @@ +From 2dbc624472416b78bf4d3017e533ca49117637d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 11:23:49 +0800 +Subject: gpio: tegra186: fix resource handling in ACPI probe path + +From: Guixin Liu + +[ 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 +Link: https://lore.kernel.org/r/20250327032349.78809-1-kanie@linux.alibaba.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/gpio-tegra186-force-one-interrupt-per-bank.patch b/queue-5.15/gpio-tegra186-force-one-interrupt-per-bank.patch new file mode 100644 index 0000000000..b2540c82ad --- /dev/null +++ b/queue-5.15/gpio-tegra186-force-one-interrupt-per-bank.patch @@ -0,0 +1,149 @@ +From 0432966e3f875ef94505f2f98c1c850924803ec6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Sep 2021 12:54:11 +0200 +Subject: gpio: tegra186: Force one interrupt per bank + +From: Thierry Reding + +[ 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 +Reviewed-by: Linus Walleij +Signed-off-by: Bartosz Golaszewski +Stable-dep-of: 8323f3a69de6 ("gpio: tegra186: fix resource handling in ACPI probe path") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/iio-adc-ad7768-1-fix-conversion-result-sign.patch b/queue-5.15/iio-adc-ad7768-1-fix-conversion-result-sign.patch new file mode 100644 index 0000000000..7865cf8d44 --- /dev/null +++ b/queue-5.15/iio-adc-ad7768-1-fix-conversion-result-sign.patch @@ -0,0 +1,55 @@ +From 4f6a1df0948c036a229d11aa6980a6027ade431d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 18:00:29 -0300 +Subject: iio: adc: ad7768-1: Fix conversion result sign + +From: Sergiu Cuciurean + +[ 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 +Reviewed-by: Marcelo Schmitt +Signed-off-by: Sergiu Cuciurean +Signed-off-by: Jonathan Santos +Cc: +Link: https://patch.msgid.link/505994d3b71c2aa38ba714d909a68e021f12124c.1741268122.git.Jonathan.Santos@analog.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch b/queue-5.15/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch new file mode 100644 index 0000000000..1c0a3c809b --- /dev/null +++ b/queue-5.15/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch @@ -0,0 +1,47 @@ +From 9abe1c7cf862d22975dbf2f37559bd529cbdd0f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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á +Link: https://patch.msgid.link/20250217141630.897334-13-jic23@kernel.org +Signed-off-by: Jonathan Cameron +Stable-dep-of: 8236644f5ecb ("iio: adc: ad7768-1: Fix conversion result sign") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/kmsan-disable-strscpy-optimization-under-kmsan.patch b/queue-5.15/kmsan-disable-strscpy-optimization-under-kmsan.patch new file mode 100644 index 0000000000..df1cdc3c9e --- /dev/null +++ b/queue-5.15/kmsan-disable-strscpy-optimization-under-kmsan.patch @@ -0,0 +1,76 @@ +From 5e9525d4cdfd5ad0dedc365daef4f17bc16a8003 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Sep 2022 17:03:59 +0200 +Subject: kmsan: disable strscpy() optimization under KMSAN + +From: Alexander Potapenko + +[ 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 +Cc: Alexander Viro +Cc: Alexei Starovoitov +Cc: Andrey Konovalov +Cc: Andrey Konovalov +Cc: Andy Lutomirski +Cc: Arnd Bergmann +Cc: Borislav Petkov +Cc: Christoph Hellwig +Cc: Christoph Lameter +Cc: David Rientjes +Cc: Dmitry Vyukov +Cc: Eric Biggers +Cc: Eric Biggers +Cc: Eric Dumazet +Cc: Greg Kroah-Hartman +Cc: Herbert Xu +Cc: Ilya Leoshkevich +Cc: Ingo Molnar +Cc: Jens Axboe +Cc: Joonsoo Kim +Cc: Kees Cook +Cc: Marco Elver +Cc: Mark Rutland +Cc: Matthew Wilcox +Cc: Michael S. Tsirkin +Cc: Pekka Enberg +Cc: Peter Zijlstra +Cc: Petr Mladek +Cc: Stephen Rothwell +Cc: Steven Rostedt +Cc: Thomas Gleixner +Cc: Vasily Gorbik +Cc: Vegard Nossum +Cc: Vlastimil Babka +Signed-off-by: Andrew Morton +Stable-dep-of: d94c12bd97d5 ("string: Add load_unaligned_zeropad() code path to sized_strscpy()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ksmbd-prevent-integer-overflow-in-calculation-of-dea.patch b/queue-5.15/ksmbd-prevent-integer-overflow-in-calculation-of-dea.patch new file mode 100644 index 0000000000..6012c15bf4 --- /dev/null +++ b/queue-5.15/ksmbd-prevent-integer-overflow-in-calculation-of-dea.patch @@ -0,0 +1,53 @@ +From 667be2b77036cd45dd4b223fcd4a12ad22bc6458 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Apr 2025 12:04:49 +0300 +Subject: ksmbd: Prevent integer overflow in calculation of deadtime + +From: Denis Arefev + +[ 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 +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-streamzap-fix-race-between-device-disconnectio.patch b/queue-5.15/media-streamzap-fix-race-between-device-disconnectio.patch new file mode 100644 index 0000000000..ddac7d3abd --- /dev/null +++ b/queue-5.15/media-streamzap-fix-race-between-device-disconnectio.patch @@ -0,0 +1,54 @@ +From 5fac0846d871c15a842cbc1281a2574ed45c5b34 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 13:51:30 +0300 +Subject: media: streamzap: fix race between device disconnection and urb + callback + +From: Murad Masimov + +[ 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 +Signed-off-by: Sean Young +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-streamzap-less-chatter.patch b/queue-5.15/media-streamzap-less-chatter.patch new file mode 100644 index 0000000000..70ccd06458 --- /dev/null +++ b/queue-5.15/media-streamzap-less-chatter.patch @@ -0,0 +1,82 @@ +From 61654c41b52ed21eaeccb97b082b84e914a19d6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Dec 2021 22:38:20 +0100 +Subject: media: streamzap: less chatter + +From: Sean Young + +[ Upstream commit 35088717ad24140b6ab0ec00ef357709be607526 ] + +Remove superfluous messages which add no information. + +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: f656cfbc7a29 ("media: streamzap: fix race between device disconnection and urb callback") +Signed-off-by: Sasha Levin +--- + 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 + #include + +-#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 + diff --git a/queue-5.15/media-streamzap-no-need-for-usb-pid-vid-in-device-na.patch b/queue-5.15/media-streamzap-no-need-for-usb-pid-vid-in-device-na.patch new file mode 100644 index 0000000000..0cf966c050 --- /dev/null +++ b/queue-5.15/media-streamzap-no-need-for-usb-pid-vid-in-device-na.patch @@ -0,0 +1,50 @@ +From 6170e6aa0d8cc27a42522dad77af4b8a61cd7689 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Dec 2021 18:10:36 +0100 +Subject: media: streamzap: no need for usb pid/vid in device name + +From: Sean Young + +[ Upstream commit 7a25e6849ad73de5aa01d62da43071bc02b8530c ] + +The usb pid/vid can be found elsewhere, the idVendor/idProduct usb sysfs +files for example. + +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: f656cfbc7a29 ("media: streamzap: fix race between device disconnection and urb callback") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-streamzap-remove-unnecessary-ir_raw_event_rese.patch b/queue-5.15/media-streamzap-remove-unnecessary-ir_raw_event_rese.patch new file mode 100644 index 0000000000..e49953cb16 --- /dev/null +++ b/queue-5.15/media-streamzap-remove-unnecessary-ir_raw_event_rese.patch @@ -0,0 +1,38 @@ +From e18374819368c129f92f8c4868c8cac282e4e92d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Dec 2021 18:06:30 +0100 +Subject: media: streamzap: remove unnecessary ir_raw_event_reset and handle + +From: Sean Young + +[ 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 +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: f656cfbc7a29 ("media: streamzap: fix race between device disconnection and urb callback") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-streamzap-remove-unused-struct-members.patch b/queue-5.15/media-streamzap-remove-unused-struct-members.patch new file mode 100644 index 0000000000..c2ff2f59dc --- /dev/null +++ b/queue-5.15/media-streamzap-remove-unused-struct-members.patch @@ -0,0 +1,160 @@ +From 133b3290f10d9f8f17c7fcd4df666fcaa480536e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Dec 2021 11:59:41 +0100 +Subject: media: streamzap: remove unused struct members + +From: Sean Young + +[ Upstream commit 4df69e46c352df9bdbe859824da33428a3ce8a1d ] + +These struct members do not serve any purpose. + +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: f656cfbc7a29 ("media: streamzap: fix race between device disconnection and urb callback") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch b/queue-5.15/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch new file mode 100644 index 0000000000..d95cf5682a --- /dev/null +++ b/queue-5.15/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch @@ -0,0 +1,55 @@ +From b5c32a3dfac87a4ead5c6f69a8ae21ec3d153da2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: # 5.15.x +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250317173250.28780-2-kabel@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/pci-assign-pci-domain-ids-by-ida_alloc.patch b/queue-5.15/pci-assign-pci-domain-ids-by-ida_alloc.patch new file mode 100644 index 0000000000..b5af740e86 --- /dev/null +++ b/queue-5.15/pci-assign-pci-domain-ids-by-ida_alloc.patch @@ -0,0 +1,227 @@ +From e2e69e2bb0901ca53613fa2931bbeadee8785efa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Bjorn Helgaas +Stable-dep-of: 804443c1f278 ("PCI: Fix reference leak in pci_register_host_bridge()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/pci-coalesce-host-bridge-contiguous-apertures.patch b/queue-5.15/pci-coalesce-host-bridge-contiguous-apertures.patch new file mode 100644 index 0000000000..9f9094808f --- /dev/null +++ b/queue-5.15/pci-coalesce-host-bridge-contiguous-apertures.patch @@ -0,0 +1,112 @@ +From ce8c98b7e330aa8fdbc729c6069a3ef4c94a12b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Jul 2021 20:50:07 +0800 +Subject: PCI: Coalesce host bridge contiguous apertures + +From: Kai-Heng Feng + +[ 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 +Link: https://lore.kernel.org/r/20210713125007.1260304-1-kai.heng.feng@canonical.com +Signed-off-by: Kai-Heng Feng +Signed-off-by: Bjorn Helgaas +Cc: Guenter Roeck +Stable-dep-of: 804443c1f278 ("PCI: Fix reference leak in pci_register_host_bridge()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/pci-fix-reference-leak-in-pci_register_host_bridge.patch b/queue-5.15/pci-fix-reference-leak-in-pci_register_host_bridge.patch new file mode 100644 index 0000000000..b0d37b5ba9 --- /dev/null +++ b/queue-5.15/pci-fix-reference-leak-in-pci_register_host_bridge.patch @@ -0,0 +1,67 @@ +From bac41eeb5c4aad6a53057e542c7a886d66985174 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 10:14:40 +0800 +Subject: PCI: Fix reference leak in pci_register_host_bridge() + +From: Ma Ke + +[ 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 +[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 +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/selftests-mm-generate-a-temporary-mountpoint-for-cgr.patch b/queue-5.15/selftests-mm-generate-a-temporary-mountpoint-for-cgr.patch new file mode 100644 index 0000000000..cc236e1a99 --- /dev/null +++ b/queue-5.15/selftests-mm-generate-a-temporary-mountpoint-for-cgr.patch @@ -0,0 +1,79 @@ +From 4428cbdc160eeeba32a1ad8dd717bc8a7e2eebdd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Apr 2025 17:42:32 +0100 +Subject: selftests/mm: generate a temporary mountpoint for cgroup filesystem + +From: Mark Brown + +[ 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 +Cc: Aishwarya TCV +Cc: Mark Brown +Cc: Mina Almasry +Cc: Shuah Khan +Cc: Waiman Long +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/series b/queue-5.15/series index 3f474667c8..53a57a3414 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -253,3 +253,34 @@ scsi-lpfc-fix-null-pointer-dereference-after-failing-to-issue-flogi-and-plogi.pa 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 diff --git a/queue-5.15/soc-samsung-exynos-chipid-add-null-pointer-check-in-.patch b/queue-5.15/soc-samsung-exynos-chipid-add-null-pointer-check-in-.patch new file mode 100644 index 0000000000..59cfeeb4c1 --- /dev/null +++ b/queue-5.15/soc-samsung-exynos-chipid-add-null-pointer-check-in-.patch @@ -0,0 +1,43 @@ +From b1bff8b14f65417f648c762bc300038d4b81d5ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20250212213518.69432-1-chenyuan0y@gmail.com +Fixes: 3253b7b7cd44 ("soc: samsung: Add exynos chipid driver support") +Cc: +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/soc-samsung-exynos-chipid-avoid-soc_device_to_device.patch b/queue-5.15/soc-samsung-exynos-chipid-avoid-soc_device_to_device.patch new file mode 100644 index 0000000000..00d7ac94b8 --- /dev/null +++ b/queue-5.15/soc-samsung-exynos-chipid-avoid-soc_device_to_device.patch @@ -0,0 +1,45 @@ +From 97c48506b55ca0aa7eafb61279ed82cd70c9d235 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 19 Sep 2021 11:31:12 +0200 +Subject: soc: samsung: exynos-chipid: avoid soc_device_to_device() + +From: Krzysztof Kozlowski + +[ 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 +Reviewed-by: Sylwester Nawrocki +Tested-by: Sylwester Nawrocki +Reviewed-by: Alim Akhtar +Tested-by: Alim Akhtar +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 +--- + 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 + diff --git a/queue-5.15/soc-samsung-exynos-chipid-pass-revision-reg-offsets.patch b/queue-5.15/soc-samsung-exynos-chipid-pass-revision-reg-offsets.patch new file mode 100644 index 0000000000..3110cb28c6 --- /dev/null +++ b/queue-5.15/soc-samsung-exynos-chipid-pass-revision-reg-offsets.patch @@ -0,0 +1,196 @@ +From bd0ccafa27fdf0b006d7631b5327ad54fe7649d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Oct 2021 16:35:06 +0300 +Subject: soc: samsung: exynos-chipid: Pass revision reg offsets + +From: Sam Protsenko + +[ 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 +Tested-by: Henrik Grimler +Link: https://lore.kernel.org/r/20211014133508.1210-1-semen.protsenko@linaro.org +Signed-off-by: Krzysztof Kozlowski +Stable-dep-of: c8222ef6cf29 ("soc: samsung: exynos-chipid: Add NULL pointer check in exynos_chipid_probe()") +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 + diff --git a/queue-5.15/string-add-load_unaligned_zeropad-code-path-to-sized.patch b/queue-5.15/string-add-load_unaligned_zeropad-code-path-to-sized.patch new file mode 100644 index 0000000000..f1acd50543 --- /dev/null +++ b/queue-5.15/string-add-load_unaligned_zeropad-code-path-to-sized.patch @@ -0,0 +1,76 @@ +From 16241f20458f12b43104cb71eaa8f7f7d06d44c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Apr 2025 17:06:59 -0700 +Subject: string: Add load_unaligned_zeropad() code path to sized_strscpy() + +From: Peter Collingbourne + +[ 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 +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 +Link: https://lore.kernel.org/r/20250403000703.2584581-2-pcc@google.com +Signed-off-by: Kees Cook +Signed-off-by: Sasha Levin +--- + 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 +