From: Sasha Levin Date: Mon, 13 Jan 2025 14:02:56 +0000 (-0500) Subject: Fixes for 6.6 X-Git-Tag: v6.1.125~18 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=25407bc4f7040d647f0e769b42991308716ddec1;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.6 Signed-off-by: Sasha Levin --- diff --git a/queue-6.6/arm-dts-imxrt1050-fix-clocks-for-mmc.patch b/queue-6.6/arm-dts-imxrt1050-fix-clocks-for-mmc.patch new file mode 100644 index 00000000000..8329d1c1b8a --- /dev/null +++ b/queue-6.6/arm-dts-imxrt1050-fix-clocks-for-mmc.patch @@ -0,0 +1,36 @@ +From 00d774255f0968a35bffc69538ee47c3b263b8b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Nov 2024 10:36:41 -0500 +Subject: ARM: dts: imxrt1050: Fix clocks for mmc + +From: Jesse Taube + +[ Upstream commit 5f122030061db3e5d2bddd9cf5c583deaa6c54ff ] + +One of the usdhc1 controller's clocks should be IMXRT1050_CLK_AHB_PODF not +IMXRT1050_CLK_OSC. + +Fixes: 1c4f01be3490 ("ARM: dts: imx: Add i.MXRT1050-EVK support") +Signed-off-by: Jesse Taube +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/nxp/imx/imxrt1050.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/nxp/imx/imxrt1050.dtsi b/arch/arm/boot/dts/nxp/imx/imxrt1050.dtsi +index dd714d235d5f..b0bad0d1ba36 100644 +--- a/arch/arm/boot/dts/nxp/imx/imxrt1050.dtsi ++++ b/arch/arm/boot/dts/nxp/imx/imxrt1050.dtsi +@@ -87,7 +87,7 @@ + reg = <0x402c0000 0x4000>; + interrupts = <110>; + clocks = <&clks IMXRT1050_CLK_IPG_PDOF>, +- <&clks IMXRT1050_CLK_OSC>, ++ <&clks IMXRT1050_CLK_AHB_PODF>, + <&clks IMXRT1050_CLK_USDHC1>; + clock-names = "ipg", "ahb", "per"; + bus-width = <4>; +-- +2.39.5 + diff --git a/queue-6.6/arm64-dts-rockchip-add-hevc-power-domain-clock-to-rk.patch b/queue-6.6/arm64-dts-rockchip-add-hevc-power-domain-clock-to-rk.patch new file mode 100644 index 00000000000..517bd0d3e4f --- /dev/null +++ b/queue-6.6/arm64-dts-rockchip-add-hevc-power-domain-clock-to-rk.patch @@ -0,0 +1,76 @@ +From 7339b9770da729494327ccf73b0b9cd91b57acaf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Dec 2024 22:43:39 +0000 +Subject: arm64: dts: rockchip: add hevc power domain clock to rk3328 + +From: Peter Geis + +[ Upstream commit 3699f2c43ea9984e00d70463f8c29baaf260ea97 ] + +There is a race condition at startup between disabling power domains not +used and disabling clocks not used on the rk3328. When the clocks are +disabled first, the hevc power domain fails to shut off leading to a +splat of failures. Add the hevc core clock to the rk3328 power domain +node to prevent this condition. + +rcu: INFO: rcu_sched detected expedited stalls on CPUs/tasks: { 3-.... } +1087 jiffies s: 89 root: 0x8/. +rcu: blocking rcu_node structures (internal RCU debug): +Sending NMI from CPU 0 to CPUs 3: +NMI backtrace for cpu 3 +CPU: 3 UID: 0 PID: 86 Comm: kworker/3:3 Not tainted 6.12.0-rc5+ #53 +Hardware name: Firefly ROC-RK3328-CC (DT) +Workqueue: pm genpd_power_off_work_fn +pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) +pc : regmap_unlock_spinlock+0x18/0x30 +lr : regmap_read+0x60/0x88 +sp : ffff800081123c00 +x29: ffff800081123c00 x28: ffff2fa4c62cad80 x27: 0000000000000000 +x26: ffffd74e6e660eb8 x25: ffff2fa4c62cae00 x24: 0000000000000040 +x23: ffffd74e6d2f3ab8 x22: 0000000000000001 x21: ffff800081123c74 +x20: 0000000000000000 x19: ffff2fa4c0412000 x18: 0000000000000000 +x17: 77202c31203d2065 x16: 6c6469203a72656c x15: 6c6f72746e6f632d +x14: 7265776f703a6e6f x13: 2063766568206e69 x12: 616d6f64202c3431 +x11: 347830206f742030 x10: 3430303034783020 x9 : ffffd74e6c7369e0 +x8 : 3030316666206e69 x7 : 205d383738353733 x6 : 332e31202020205b +x5 : ffffd74e6c73fc88 x4 : ffffd74e6c73fcd4 x3 : ffffd74e6c740b40 +x2 : ffff800080015484 x1 : 0000000000000000 x0 : ffff2fa4c0412000 +Call trace: +regmap_unlock_spinlock+0x18/0x30 +rockchip_pmu_set_idle_request+0xac/0x2c0 +rockchip_pd_power+0x144/0x5f8 +rockchip_pd_power_off+0x1c/0x30 +_genpd_power_off+0x9c/0x180 +genpd_power_off.part.0.isra.0+0x130/0x2a8 +genpd_power_off_work_fn+0x6c/0x98 +process_one_work+0x170/0x3f0 +worker_thread+0x290/0x4a8 +kthread+0xec/0xf8 +ret_from_fork+0x10/0x20 +rockchip-pm-domain ff100000.syscon:power-controller: failed to get ack on domain 'hevc', val=0x88220 + +Fixes: 52e02d377a72 ("arm64: dts: rockchip: add core dtsi file for RK3328 SoCs") +Signed-off-by: Peter Geis +Reviewed-by: Dragan Simic +Link: https://lore.kernel.org/r/20241214224339.24674-1-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +index 5d47acbf4a24..82eb7c49e825 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -304,6 +304,7 @@ + + power-domain@RK3328_PD_HEVC { + reg = ; ++ clocks = <&cru SCLK_VENC_CORE>; + #power-domain-cells = <0>; + }; + power-domain@RK3328_PD_VIDEO { +-- +2.39.5 + diff --git a/queue-6.6/block-bfq-fix-waker_bfqq-uaf-after-bfq_split_bfqq.patch b/queue-6.6/block-bfq-fix-waker_bfqq-uaf-after-bfq_split_bfqq.patch new file mode 100644 index 00000000000..cb4387829c3 --- /dev/null +++ b/queue-6.6/block-bfq-fix-waker_bfqq-uaf-after-bfq_split_bfqq.patch @@ -0,0 +1,199 @@ +From d58c17f4eed498e0e867147029b36b4bd8cd59c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 16:41:48 +0800 +Subject: block, bfq: fix waker_bfqq UAF after bfq_split_bfqq() + +From: Yu Kuai + +[ Upstream commit fcede1f0a043ccefe9bc6ad57f12718e42f63f1d ] + +Our syzkaller report a following UAF for v6.6: + +BUG: KASAN: slab-use-after-free in bfq_init_rq+0x175d/0x17a0 block/bfq-iosched.c:6958 +Read of size 8 at addr ffff8881b57147d8 by task fsstress/232726 + +CPU: 2 PID: 232726 Comm: fsstress Not tainted 6.6.0-g3629d1885222 #39 +Call Trace: + + __dump_stack lib/dump_stack.c:88 [inline] + dump_stack_lvl+0x91/0xf0 lib/dump_stack.c:106 + print_address_description.constprop.0+0x66/0x300 mm/kasan/report.c:364 + print_report+0x3e/0x70 mm/kasan/report.c:475 + kasan_report+0xb8/0xf0 mm/kasan/report.c:588 + hlist_add_head include/linux/list.h:1023 [inline] + bfq_init_rq+0x175d/0x17a0 block/bfq-iosched.c:6958 + bfq_insert_request.isra.0+0xe8/0xa20 block/bfq-iosched.c:6271 + bfq_insert_requests+0x27f/0x390 block/bfq-iosched.c:6323 + blk_mq_insert_request+0x290/0x8f0 block/blk-mq.c:2660 + blk_mq_submit_bio+0x1021/0x15e0 block/blk-mq.c:3143 + __submit_bio+0xa0/0x6b0 block/blk-core.c:639 + __submit_bio_noacct_mq block/blk-core.c:718 [inline] + submit_bio_noacct_nocheck+0x5b7/0x810 block/blk-core.c:747 + submit_bio_noacct+0xca0/0x1990 block/blk-core.c:847 + __ext4_read_bh fs/ext4/super.c:205 [inline] + ext4_read_bh+0x15e/0x2e0 fs/ext4/super.c:230 + __read_extent_tree_block+0x304/0x6f0 fs/ext4/extents.c:567 + ext4_find_extent+0x479/0xd20 fs/ext4/extents.c:947 + ext4_ext_map_blocks+0x1a3/0x2680 fs/ext4/extents.c:4182 + ext4_map_blocks+0x929/0x15a0 fs/ext4/inode.c:660 + ext4_iomap_begin_report+0x298/0x480 fs/ext4/inode.c:3569 + iomap_iter+0x3dd/0x1010 fs/iomap/iter.c:91 + iomap_fiemap+0x1f4/0x360 fs/iomap/fiemap.c:80 + ext4_fiemap+0x181/0x210 fs/ext4/extents.c:5051 + ioctl_fiemap.isra.0+0x1b4/0x290 fs/ioctl.c:220 + do_vfs_ioctl+0x31c/0x11a0 fs/ioctl.c:811 + __do_sys_ioctl fs/ioctl.c:869 [inline] + __se_sys_ioctl+0xae/0x190 fs/ioctl.c:857 + do_syscall_x64 arch/x86/entry/common.c:51 [inline] + do_syscall_64+0x70/0x120 arch/x86/entry/common.c:81 + entry_SYSCALL_64_after_hwframe+0x78/0xe2 + +Allocated by task 232719: + kasan_save_stack+0x22/0x50 mm/kasan/common.c:45 + kasan_set_track+0x25/0x30 mm/kasan/common.c:52 + __kasan_slab_alloc+0x87/0x90 mm/kasan/common.c:328 + kasan_slab_alloc include/linux/kasan.h:188 [inline] + slab_post_alloc_hook mm/slab.h:768 [inline] + slab_alloc_node mm/slub.c:3492 [inline] + kmem_cache_alloc_node+0x1b8/0x6f0 mm/slub.c:3537 + bfq_get_queue+0x215/0x1f00 block/bfq-iosched.c:5869 + bfq_get_bfqq_handle_split+0x167/0x5f0 block/bfq-iosched.c:6776 + bfq_init_rq+0x13a4/0x17a0 block/bfq-iosched.c:6938 + bfq_insert_request.isra.0+0xe8/0xa20 block/bfq-iosched.c:6271 + bfq_insert_requests+0x27f/0x390 block/bfq-iosched.c:6323 + blk_mq_insert_request+0x290/0x8f0 block/blk-mq.c:2660 + blk_mq_submit_bio+0x1021/0x15e0 block/blk-mq.c:3143 + __submit_bio+0xa0/0x6b0 block/blk-core.c:639 + __submit_bio_noacct_mq block/blk-core.c:718 [inline] + submit_bio_noacct_nocheck+0x5b7/0x810 block/blk-core.c:747 + submit_bio_noacct+0xca0/0x1990 block/blk-core.c:847 + __ext4_read_bh fs/ext4/super.c:205 [inline] + ext4_read_bh_nowait+0x15a/0x240 fs/ext4/super.c:217 + ext4_read_bh_lock+0xac/0xd0 fs/ext4/super.c:242 + ext4_bread_batch+0x268/0x500 fs/ext4/inode.c:958 + __ext4_find_entry+0x448/0x10f0 fs/ext4/namei.c:1671 + ext4_lookup_entry fs/ext4/namei.c:1774 [inline] + ext4_lookup.part.0+0x359/0x6f0 fs/ext4/namei.c:1842 + ext4_lookup+0x72/0x90 fs/ext4/namei.c:1839 + __lookup_slow+0x257/0x480 fs/namei.c:1696 + lookup_slow fs/namei.c:1713 [inline] + walk_component+0x454/0x5c0 fs/namei.c:2004 + link_path_walk.part.0+0x773/0xda0 fs/namei.c:2331 + link_path_walk fs/namei.c:3826 [inline] + path_openat+0x1b9/0x520 fs/namei.c:3826 + do_filp_open+0x1b7/0x400 fs/namei.c:3857 + do_sys_openat2+0x5dc/0x6e0 fs/open.c:1428 + do_sys_open fs/open.c:1443 [inline] + __do_sys_openat fs/open.c:1459 [inline] + __se_sys_openat fs/open.c:1454 [inline] + __x64_sys_openat+0x148/0x200 fs/open.c:1454 + do_syscall_x64 arch/x86/entry/common.c:51 [inline] + do_syscall_64+0x70/0x120 arch/x86/entry/common.c:81 + entry_SYSCALL_64_after_hwframe+0x78/0xe2 + +Freed by task 232726: + kasan_save_stack+0x22/0x50 mm/kasan/common.c:45 + kasan_set_track+0x25/0x30 mm/kasan/common.c:52 + kasan_save_free_info+0x2b/0x50 mm/kasan/generic.c:522 + ____kasan_slab_free mm/kasan/common.c:236 [inline] + __kasan_slab_free+0x12a/0x1b0 mm/kasan/common.c:244 + kasan_slab_free include/linux/kasan.h:164 [inline] + slab_free_hook mm/slub.c:1827 [inline] + slab_free_freelist_hook mm/slub.c:1853 [inline] + slab_free mm/slub.c:3820 [inline] + kmem_cache_free+0x110/0x760 mm/slub.c:3842 + bfq_put_queue+0x6a7/0xfb0 block/bfq-iosched.c:5428 + bfq_forget_entity block/bfq-wf2q.c:634 [inline] + bfq_put_idle_entity+0x142/0x240 block/bfq-wf2q.c:645 + bfq_forget_idle+0x189/0x1e0 block/bfq-wf2q.c:671 + bfq_update_vtime block/bfq-wf2q.c:1280 [inline] + __bfq_lookup_next_entity block/bfq-wf2q.c:1374 [inline] + bfq_lookup_next_entity+0x350/0x480 block/bfq-wf2q.c:1433 + bfq_update_next_in_service+0x1c0/0x4f0 block/bfq-wf2q.c:128 + bfq_deactivate_entity+0x10a/0x240 block/bfq-wf2q.c:1188 + bfq_deactivate_bfqq block/bfq-wf2q.c:1592 [inline] + bfq_del_bfqq_busy+0x2e8/0xad0 block/bfq-wf2q.c:1659 + bfq_release_process_ref+0x1cc/0x220 block/bfq-iosched.c:3139 + bfq_split_bfqq+0x481/0xdf0 block/bfq-iosched.c:6754 + bfq_init_rq+0xf29/0x17a0 block/bfq-iosched.c:6934 + bfq_insert_request.isra.0+0xe8/0xa20 block/bfq-iosched.c:6271 + bfq_insert_requests+0x27f/0x390 block/bfq-iosched.c:6323 + blk_mq_insert_request+0x290/0x8f0 block/blk-mq.c:2660 + blk_mq_submit_bio+0x1021/0x15e0 block/blk-mq.c:3143 + __submit_bio+0xa0/0x6b0 block/blk-core.c:639 + __submit_bio_noacct_mq block/blk-core.c:718 [inline] + submit_bio_noacct_nocheck+0x5b7/0x810 block/blk-core.c:747 + submit_bio_noacct+0xca0/0x1990 block/blk-core.c:847 + __ext4_read_bh fs/ext4/super.c:205 [inline] + ext4_read_bh+0x15e/0x2e0 fs/ext4/super.c:230 + __read_extent_tree_block+0x304/0x6f0 fs/ext4/extents.c:567 + ext4_find_extent+0x479/0xd20 fs/ext4/extents.c:947 + ext4_ext_map_blocks+0x1a3/0x2680 fs/ext4/extents.c:4182 + ext4_map_blocks+0x929/0x15a0 fs/ext4/inode.c:660 + ext4_iomap_begin_report+0x298/0x480 fs/ext4/inode.c:3569 + iomap_iter+0x3dd/0x1010 fs/iomap/iter.c:91 + iomap_fiemap+0x1f4/0x360 fs/iomap/fiemap.c:80 + ext4_fiemap+0x181/0x210 fs/ext4/extents.c:5051 + ioctl_fiemap.isra.0+0x1b4/0x290 fs/ioctl.c:220 + do_vfs_ioctl+0x31c/0x11a0 fs/ioctl.c:811 + __do_sys_ioctl fs/ioctl.c:869 [inline] + __se_sys_ioctl+0xae/0x190 fs/ioctl.c:857 + do_syscall_x64 arch/x86/entry/common.c:51 [inline] + do_syscall_64+0x70/0x120 arch/x86/entry/common.c:81 + entry_SYSCALL_64_after_hwframe+0x78/0xe2 + +commit 1ba0403ac644 ("block, bfq: fix uaf for accessing waker_bfqq after +splitting") fix the problem that if waker_bfqq is in the merge chain, +and current is the only procress, waker_bfqq can be freed from +bfq_split_bfqq(). However, the case that waker_bfqq is not in the merge +chain is missed, and if the procress reference of waker_bfqq is 0, +waker_bfqq can be freed as well. + +Fix the problem by checking procress reference if waker_bfqq is not in +the merge_chain. + +Fixes: 1ba0403ac644 ("block, bfq: fix uaf for accessing waker_bfqq after splitting") +Signed-off-by: Hou Tao +Signed-off-by: Yu Kuai +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20250108084148.1549973-1-yukuai1@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/bfq-iosched.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c +index dd8ca3f7ba60..617d6802b8a0 100644 +--- a/block/bfq-iosched.c ++++ b/block/bfq-iosched.c +@@ -6843,16 +6843,24 @@ static struct bfq_queue *bfq_waker_bfqq(struct bfq_queue *bfqq) + if (new_bfqq == waker_bfqq) { + /* + * If waker_bfqq is in the merge chain, and current +- * is the only procress. ++ * is the only process, waker_bfqq can be freed. + */ + if (bfqq_process_refs(waker_bfqq) == 1) + return NULL; +- break; ++ ++ return waker_bfqq; + } + + new_bfqq = new_bfqq->new_bfqq; + } + ++ /* ++ * If waker_bfqq is not in the merge chain, and it's procress reference ++ * is 0, waker_bfqq can be freed. ++ */ ++ if (bfqq_process_refs(waker_bfqq) == 0) ++ return NULL; ++ + return waker_bfqq; + } + +-- +2.39.5 + diff --git a/queue-6.6/drm-mediatek-only-touch-disp_reg_ovl_pitch_msb-if-af.patch b/queue-6.6/drm-mediatek-only-touch-disp_reg_ovl_pitch_msb-if-af.patch new file mode 100644 index 00000000000..9cb92461cc7 --- /dev/null +++ b/queue-6.6/drm-mediatek-only-touch-disp_reg_ovl_pitch_msb-if-af.patch @@ -0,0 +1,128 @@ +From 78d03682615cae6825c520bb51887a2e011e13ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Dec 2024 01:18:01 +0000 +Subject: drm/mediatek: Only touch DISP_REG_OVL_PITCH_MSB if AFBC is supported + +From: Daniel Golle + +[ Upstream commit f8d9b91739e1fb436447c437a346a36deb676a36 ] + +Touching DISP_REG_OVL_PITCH_MSB leads to video overlay on MT2701, MT7623N +and probably other older SoCs being broken. + +Move setting up AFBC layer configuration into a separate function only +being called on hardware which actually supports AFBC which restores the +behavior as it was before commit c410fa9b07c3 ("drm/mediatek: Add AFBC +support to Mediatek DRM driver") on non-AFBC hardware. + +Fixes: c410fa9b07c3 ("drm/mediatek: Add AFBC support to Mediatek DRM driver") +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Golle +Reviewed-by: CK Hu +Link: https://patchwork.kernel.org/project/dri-devel/patch/c7fbd3c3e633c0b7dd6d1cd78ccbdded31e1ca0f.1734397800.git.daniel@makrotopia.org/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 57 +++++++++++++------------ + 1 file changed, 29 insertions(+), 28 deletions(-) + +diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +index 6f15069da8b0..ce0f441e3f13 100644 +--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c ++++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +@@ -403,6 +403,29 @@ static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt) + } + } + ++static void mtk_ovl_afbc_layer_config(struct mtk_disp_ovl *ovl, ++ unsigned int idx, ++ struct mtk_plane_pending_state *pending, ++ struct cmdq_pkt *cmdq_pkt) ++{ ++ unsigned int pitch_msb = pending->pitch >> 16; ++ unsigned int hdr_pitch = pending->hdr_pitch; ++ unsigned int hdr_addr = pending->hdr_addr; ++ ++ if (pending->modifier != DRM_FORMAT_MOD_LINEAR) { ++ mtk_ddp_write_relaxed(cmdq_pkt, hdr_addr, &ovl->cmdq_reg, ovl->regs, ++ DISP_REG_OVL_HDR_ADDR(ovl, idx)); ++ mtk_ddp_write_relaxed(cmdq_pkt, ++ OVL_PITCH_MSB_2ND_SUBBUF | pitch_msb, ++ &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx)); ++ mtk_ddp_write_relaxed(cmdq_pkt, hdr_pitch, &ovl->cmdq_reg, ovl->regs, ++ DISP_REG_OVL_HDR_PITCH(ovl, idx)); ++ } else { ++ mtk_ddp_write_relaxed(cmdq_pkt, pitch_msb, ++ &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx)); ++ } ++} ++ + void mtk_ovl_layer_config(struct device *dev, unsigned int idx, + struct mtk_plane_state *state, + struct cmdq_pkt *cmdq_pkt) +@@ -410,24 +433,12 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, + struct mtk_disp_ovl *ovl = dev_get_drvdata(dev); + struct mtk_plane_pending_state *pending = &state->pending; + unsigned int addr = pending->addr; +- unsigned int hdr_addr = pending->hdr_addr; +- unsigned int pitch = pending->pitch; +- unsigned int hdr_pitch = pending->hdr_pitch; ++ unsigned int pitch_lsb = pending->pitch & GENMASK(15, 0); + unsigned int fmt = pending->format; + unsigned int offset = (pending->y << 16) | pending->x; + unsigned int src_size = (pending->height << 16) | pending->width; + unsigned int ignore_pixel_alpha = 0; + unsigned int con; +- bool is_afbc = pending->modifier != DRM_FORMAT_MOD_LINEAR; +- union overlay_pitch { +- struct split_pitch { +- u16 lsb; +- u16 msb; +- } split_pitch; +- u32 pitch; +- } overlay_pitch; +- +- overlay_pitch.pitch = pitch; + + if (!pending->enable) { + mtk_ovl_layer_off(dev, idx, cmdq_pkt); +@@ -457,11 +468,12 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, + } + + if (ovl->data->supports_afbc) +- mtk_ovl_set_afbc(ovl, cmdq_pkt, idx, is_afbc); ++ mtk_ovl_set_afbc(ovl, cmdq_pkt, idx, ++ pending->modifier != DRM_FORMAT_MOD_LINEAR); + + mtk_ddp_write_relaxed(cmdq_pkt, con, &ovl->cmdq_reg, ovl->regs, + DISP_REG_OVL_CON(idx)); +- mtk_ddp_write_relaxed(cmdq_pkt, overlay_pitch.split_pitch.lsb | ignore_pixel_alpha, ++ mtk_ddp_write_relaxed(cmdq_pkt, pitch_lsb | ignore_pixel_alpha, + &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH(idx)); + mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs, + DISP_REG_OVL_SRC_SIZE(idx)); +@@ -470,19 +482,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, + mtk_ddp_write_relaxed(cmdq_pkt, addr, &ovl->cmdq_reg, ovl->regs, + DISP_REG_OVL_ADDR(ovl, idx)); + +- if (is_afbc) { +- mtk_ddp_write_relaxed(cmdq_pkt, hdr_addr, &ovl->cmdq_reg, ovl->regs, +- DISP_REG_OVL_HDR_ADDR(ovl, idx)); +- mtk_ddp_write_relaxed(cmdq_pkt, +- OVL_PITCH_MSB_2ND_SUBBUF | overlay_pitch.split_pitch.msb, +- &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx)); +- mtk_ddp_write_relaxed(cmdq_pkt, hdr_pitch, &ovl->cmdq_reg, ovl->regs, +- DISP_REG_OVL_HDR_PITCH(ovl, idx)); +- } else { +- mtk_ddp_write_relaxed(cmdq_pkt, +- overlay_pitch.split_pitch.msb, +- &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx)); +- } ++ if (ovl->data->supports_afbc) ++ mtk_ovl_afbc_layer_config(ovl, idx, pending, cmdq_pkt); + + mtk_ovl_set_bit_depth(dev, idx, fmt, cmdq_pkt); + mtk_ovl_layer_on(dev, idx, cmdq_pkt); +-- +2.39.5 + diff --git a/queue-6.6/fs-kconfig-make-hugetlbfs-a-menuconfig.patch b/queue-6.6/fs-kconfig-make-hugetlbfs-a-menuconfig.patch new file mode 100644 index 00000000000..2d0ab928f5f --- /dev/null +++ b/queue-6.6/fs-kconfig-make-hugetlbfs-a-menuconfig.patch @@ -0,0 +1,78 @@ +From dccc8cbea0c13d2b0befc4569f7482477b270017 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Nov 2023 10:19:02 -0500 +Subject: fs/Kconfig: make hugetlbfs a menuconfig + +From: Peter Xu + +[ Upstream commit cddba0af0b7919e93134469f6fdf29a7d362768a ] + +Hugetlb vmemmap default option (HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON) +is a sub-option to hugetlbfs, but it shows in the same level as hugetlbfs +itself, under "Pesudo filesystems". + +Make the vmemmap option a sub-option to hugetlbfs, by changing hugetlbfs +into a menuconfig. When moving it, fix a typo 'v' spot by Randy. + +Link: https://lkml.kernel.org/r/20231124151902.1075697-1-peterx@redhat.com +Signed-off-by: Peter Xu +Reviewed-by: Muchun Song +Cc: Mike Kravetz +Cc: Randy Dunlap +Signed-off-by: Andrew Morton +Stable-dep-of: 59d9094df3d7 ("mm: hugetlb: independent PMD page table shared count") +Signed-off-by: Sasha Levin +--- + fs/Kconfig | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/fs/Kconfig b/fs/Kconfig +index aa7e03cc1941..0ad3c7c7e984 100644 +--- a/fs/Kconfig ++++ b/fs/Kconfig +@@ -253,7 +253,7 @@ config TMPFS_QUOTA + config ARCH_SUPPORTS_HUGETLBFS + def_bool n + +-config HUGETLBFS ++menuconfig HUGETLBFS + bool "HugeTLB file system support" + depends on X86 || IA64 || SPARC64 || ARCH_SUPPORTS_HUGETLBFS || BROKEN + depends on (SYSFS || SYSCTL) +@@ -265,22 +265,24 @@ config HUGETLBFS + + If unsure, say N. + +-config HUGETLB_PAGE +- def_bool HUGETLBFS +- +-config HUGETLB_PAGE_OPTIMIZE_VMEMMAP +- def_bool HUGETLB_PAGE +- depends on ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP +- depends on SPARSEMEM_VMEMMAP +- ++if HUGETLBFS + config HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON + bool "HugeTLB Vmemmap Optimization (HVO) defaults to on" + default n + depends on HUGETLB_PAGE_OPTIMIZE_VMEMMAP + help +- The HugeTLB VmemmapvOptimization (HVO) defaults to off. Say Y here to ++ The HugeTLB Vmemmap Optimization (HVO) defaults to off. Say Y here to + enable HVO by default. It can be disabled via hugetlb_free_vmemmap=off + (boot command line) or hugetlb_optimize_vmemmap (sysctl). ++endif # HUGETLBFS ++ ++config HUGETLB_PAGE ++ def_bool HUGETLBFS ++ ++config HUGETLB_PAGE_OPTIMIZE_VMEMMAP ++ def_bool HUGETLB_PAGE ++ depends on ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP ++ depends on SPARSEMEM_VMEMMAP + + config ARCH_HAS_GIGANTIC_PAGE + bool +-- +2.39.5 + diff --git a/queue-6.6/hwmon-drivetemp-fix-driver-producing-garbage-data-wh.patch b/queue-6.6/hwmon-drivetemp-fix-driver-producing-garbage-data-wh.patch new file mode 100644 index 00000000000..275c2e2f775 --- /dev/null +++ b/queue-6.6/hwmon-drivetemp-fix-driver-producing-garbage-data-wh.patch @@ -0,0 +1,70 @@ +From 7bc6649b366d33621fe09abda5ba89caef84248b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jan 2025 21:36:18 +0000 +Subject: hwmon: (drivetemp) Fix driver producing garbage data when SCSI errors + occur + +From: Daniil Stas + +[ Upstream commit 82163d63ae7a4c36142cd252388737205bb7e4b9 ] + +scsi_execute_cmd() function can return both negative (linux codes) and +positive (scsi_cmnd result field) error codes. + +Currently the driver just passes error codes of scsi_execute_cmd() to +hwmon core, which is incorrect because hwmon only checks for negative +error codes. This leads to hwmon reporting uninitialized data to +userspace in case of SCSI errors (for example if the disk drive was +disconnected). + +This patch checks scsi_execute_cmd() output and returns -EIO if it's +error code is positive. + +Fixes: 5b46903d8bf37 ("hwmon: Driver for disk and solid state drives with temperature sensors") +Signed-off-by: Daniil Stas +Cc: Guenter Roeck +Cc: Chris Healy +Cc: Linus Walleij +Cc: Martin K. Petersen +Cc: Bart Van Assche +Cc: linux-kernel@vger.kernel.org +Cc: linux-scsi@vger.kernel.org +Cc: linux-ide@vger.kernel.org +Cc: linux-hwmon@vger.kernel.org +Link: https://lore.kernel.org/r/20250105213618.531691-1-daniil.stas@posteo.net +[groeck: Avoid inline variable declaration for portability] +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/drivetemp.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/hwmon/drivetemp.c b/drivers/hwmon/drivetemp.c +index 6bdd21aa005a..2a4ec55ddb47 100644 +--- a/drivers/hwmon/drivetemp.c ++++ b/drivers/hwmon/drivetemp.c +@@ -165,6 +165,7 @@ static int drivetemp_scsi_command(struct drivetemp_data *st, + { + u8 scsi_cmd[MAX_COMMAND_SIZE]; + enum req_op op; ++ int err; + + memset(scsi_cmd, 0, sizeof(scsi_cmd)); + scsi_cmd[0] = ATA_16; +@@ -192,8 +193,11 @@ static int drivetemp_scsi_command(struct drivetemp_data *st, + scsi_cmd[12] = lba_high; + scsi_cmd[14] = ata_command; + +- return scsi_execute_cmd(st->sdev, scsi_cmd, op, st->smartdata, +- ATA_SECT_SIZE, HZ, 5, NULL); ++ err = scsi_execute_cmd(st->sdev, scsi_cmd, op, st->smartdata, ++ ATA_SECT_SIZE, HZ, 5, NULL); ++ if (err > 0) ++ err = -EIO; ++ return err; + } + + static int drivetemp_ata_command(struct drivetemp_data *st, u8 feature, +-- +2.39.5 + diff --git a/queue-6.6/mm-hugetlb-enforce-that-pmd-pt-sharing-has-split-pmd.patch b/queue-6.6/mm-hugetlb-enforce-that-pmd-pt-sharing-has-split-pmd.patch new file mode 100644 index 00000000000..318d271c0d7 --- /dev/null +++ b/queue-6.6/mm-hugetlb-enforce-that-pmd-pt-sharing-has-split-pmd.patch @@ -0,0 +1,125 @@ +From 3433b20607ba1bb4b7386cf1bd3372975f9346e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Jul 2024 17:07:27 +0200 +Subject: mm/hugetlb: enforce that PMD PT sharing has split PMD PT locks + +From: David Hildenbrand + +[ Upstream commit 188cac58a8bcdf82c7f63275b68f7a46871e45d6 ] + +Sharing page tables between processes but falling back to per-MM page +table locks cannot possibly work. + +So, let's make sure that we do have split PMD locks by adding a new +Kconfig option and letting that depend on CONFIG_SPLIT_PMD_PTLOCKS. + +Link: https://lkml.kernel.org/r/20240726150728.3159964-3-david@redhat.com +Signed-off-by: David Hildenbrand +Acked-by: Mike Rapoport (Microsoft) +Cc: Alexander Viro +Cc: Borislav Petkov +Cc: Boris Ostrovsky +Cc: Christian Brauner +Cc: Christophe Leroy +Cc: Dave Hansen +Cc: "H. Peter Anvin" +Cc: Ingo Molnar +Cc: Juergen Gross +Cc: Michael Ellerman +Cc: Muchun Song +Cc: "Naveen N. Rao" +Cc: Nicholas Piggin +Cc: Oscar Salvador +Cc: Peter Xu +Cc: Russell King +Cc: Thomas Gleixner +Signed-off-by: Andrew Morton +Stable-dep-of: 59d9094df3d7 ("mm: hugetlb: independent PMD page table shared count") +Signed-off-by: Sasha Levin +--- + fs/Kconfig | 4 ++++ + include/linux/hugetlb.h | 5 ++--- + mm/hugetlb.c | 8 ++++---- + 3 files changed, 10 insertions(+), 7 deletions(-) + +diff --git a/fs/Kconfig b/fs/Kconfig +index 0ad3c7c7e984..02a9237807a7 100644 +--- a/fs/Kconfig ++++ b/fs/Kconfig +@@ -284,6 +284,10 @@ config HUGETLB_PAGE_OPTIMIZE_VMEMMAP + depends on ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP + depends on SPARSEMEM_VMEMMAP + ++config HUGETLB_PMD_PAGE_TABLE_SHARING ++ def_bool HUGETLB_PAGE ++ depends on ARCH_WANT_HUGE_PMD_SHARE && SPLIT_PMD_PTLOCKS ++ + config ARCH_HAS_GIGANTIC_PAGE + bool + +diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h +index 0c50c4fceb95..0ca93c7574ad 100644 +--- a/include/linux/hugetlb.h ++++ b/include/linux/hugetlb.h +@@ -1239,7 +1239,7 @@ static inline __init void hugetlb_cma_reserve(int order) + } + #endif + +-#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE ++#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING + static inline bool hugetlb_pmd_shared(pte_t *pte) + { + return page_count(virt_to_page(pte)) > 1; +@@ -1275,8 +1275,7 @@ bool __vma_private_lock(struct vm_area_struct *vma); + static inline pte_t * + hugetlb_walk(struct vm_area_struct *vma, unsigned long addr, unsigned long sz) + { +-#if defined(CONFIG_HUGETLB_PAGE) && \ +- defined(CONFIG_ARCH_WANT_HUGE_PMD_SHARE) && defined(CONFIG_LOCKDEP) ++#if defined(CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING) && defined(CONFIG_LOCKDEP) + struct hugetlb_vma_lock *vma_lock = vma->vm_private_data; + + /* +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 92b955cc5a41..5b8cc558ab6e 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -6907,7 +6907,7 @@ long hugetlb_unreserve_pages(struct inode *inode, long start, long end, + return 0; + } + +-#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE ++#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING + static unsigned long page_table_shareable(struct vm_area_struct *svma, + struct vm_area_struct *vma, + unsigned long addr, pgoff_t idx) +@@ -7069,7 +7069,7 @@ int huge_pmd_unshare(struct mm_struct *mm, struct vm_area_struct *vma, + return 1; + } + +-#else /* !CONFIG_ARCH_WANT_HUGE_PMD_SHARE */ ++#else /* !CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING */ + + pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma, + unsigned long addr, pud_t *pud) +@@ -7092,7 +7092,7 @@ bool want_pmd_share(struct vm_area_struct *vma, unsigned long addr) + { + return false; + } +-#endif /* CONFIG_ARCH_WANT_HUGE_PMD_SHARE */ ++#endif /* CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING */ + + #ifdef CONFIG_ARCH_WANT_GENERAL_HUGETLB + pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -7190,7 +7190,7 @@ unsigned long hugetlb_mask_last_page(struct hstate *h) + /* See description above. Architectures can provide their own version. */ + __weak unsigned long hugetlb_mask_last_page(struct hstate *h) + { +-#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE ++#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING + if (huge_page_size(h) == PMD_SIZE) + return PUD_SIZE - PMD_SIZE; + #endif +-- +2.39.5 + diff --git a/queue-6.6/mm-hugetlb-independent-pmd-page-table-shared-count.patch b/queue-6.6/mm-hugetlb-independent-pmd-page-table-shared-count.patch new file mode 100644 index 00000000000..a81748d955f --- /dev/null +++ b/queue-6.6/mm-hugetlb-independent-pmd-page-table-shared-count.patch @@ -0,0 +1,206 @@ +From f7eb229fcc93826ed4782e0f16540efd3e9ae689 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Dec 2024 15:11:47 +0800 +Subject: mm: hugetlb: independent PMD page table shared count + +From: Liu Shixin + +[ Upstream commit 59d9094df3d79443937add8700b2ef1a866b1081 ] + +The folio refcount may be increased unexpectly through try_get_folio() by +caller such as split_huge_pages. In huge_pmd_unshare(), we use refcount +to check whether a pmd page table is shared. The check is incorrect if +the refcount is increased by the above caller, and this can cause the page +table leaked: + + BUG: Bad page state in process sh pfn:109324 + page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x66 pfn:0x109324 + flags: 0x17ffff800000000(node=0|zone=2|lastcpupid=0xfffff) + page_type: f2(table) + raw: 017ffff800000000 0000000000000000 0000000000000000 0000000000000000 + raw: 0000000000000066 0000000000000000 00000000f2000000 0000000000000000 + page dumped because: nonzero mapcount + ... + CPU: 31 UID: 0 PID: 7515 Comm: sh Kdump: loaded Tainted: G B 6.13.0-rc2master+ #7 + Tainted: [B]=BAD_PAGE + Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015 + Call trace: + show_stack+0x20/0x38 (C) + dump_stack_lvl+0x80/0xf8 + dump_stack+0x18/0x28 + bad_page+0x8c/0x130 + free_page_is_bad_report+0xa4/0xb0 + free_unref_page+0x3cc/0x620 + __folio_put+0xf4/0x158 + split_huge_pages_all+0x1e0/0x3e8 + split_huge_pages_write+0x25c/0x2d8 + full_proxy_write+0x64/0xd8 + vfs_write+0xcc/0x280 + ksys_write+0x70/0x110 + __arm64_sys_write+0x24/0x38 + invoke_syscall+0x50/0x120 + el0_svc_common.constprop.0+0xc8/0xf0 + do_el0_svc+0x24/0x38 + el0_svc+0x34/0x128 + el0t_64_sync_handler+0xc8/0xd0 + el0t_64_sync+0x190/0x198 + +The issue may be triggered by damon, offline_page, page_idle, etc, which +will increase the refcount of page table. + +1. The page table itself will be discarded after reporting the + "nonzero mapcount". + +2. The HugeTLB page mapped by the page table miss freeing since we + treat the page table as shared and a shared page table will not be + unmapped. + +Fix it by introducing independent PMD page table shared count. As +described by comment, pt_index/pt_mm/pt_frag_refcount are used for s390 +gmap, x86 pgds and powerpc, pt_share_count is used for x86/arm64/riscv +pmds, so we can reuse the field as pt_share_count. + +Link: https://lkml.kernel.org/r/20241216071147.3984217-1-liushixin2@huawei.com +Fixes: 39dde65c9940 ("[PATCH] shared page table for hugetlb page") +Signed-off-by: Liu Shixin +Cc: Kefeng Wang +Cc: Ken Chen +Cc: Muchun Song +Cc: Nanyong Sun +Cc: Jane Chu +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + include/linux/mm.h | 1 + + include/linux/mm_types.h | 30 ++++++++++++++++++++++++++++++ + mm/hugetlb.c | 16 +++++++--------- + 3 files changed, 38 insertions(+), 9 deletions(-) + +diff --git a/include/linux/mm.h b/include/linux/mm.h +index b6a4d6471b4a..209370f64436 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -3031,6 +3031,7 @@ static inline bool pagetable_pmd_ctor(struct ptdesc *ptdesc) + if (!pmd_ptlock_init(ptdesc)) + return false; + __folio_set_pgtable(folio); ++ ptdesc_pmd_pts_init(ptdesc); + lruvec_stat_add_folio(folio, NR_PAGETABLE); + return true; + } +diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h +index 1f224c55fb58..e77d4a5c0bac 100644 +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -399,6 +399,7 @@ FOLIO_MATCH(compound_head, _head_2a); + * @__page_mapping: Aliases with page->mapping. Unused for page tables. + * @pt_mm: Used for x86 pgds. + * @pt_frag_refcount: For fragmented page table tracking. Powerpc only. ++ * @pt_share_count: Used for HugeTLB PMD page table share count. + * @_pt_pad_2: Padding to ensure proper alignment. + * @ptl: Lock for the page table. + * @__page_type: Same as page->page_type. Unused for page tables. +@@ -424,6 +425,9 @@ struct ptdesc { + union { + struct mm_struct *pt_mm; + atomic_t pt_frag_refcount; ++#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING ++ atomic_t pt_share_count; ++#endif + }; + + union { +@@ -468,6 +472,32 @@ static_assert(sizeof(struct ptdesc) <= sizeof(struct page)); + const struct page *: (const struct ptdesc *)(p), \ + struct page *: (struct ptdesc *)(p))) + ++#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING ++static inline void ptdesc_pmd_pts_init(struct ptdesc *ptdesc) ++{ ++ atomic_set(&ptdesc->pt_share_count, 0); ++} ++ ++static inline void ptdesc_pmd_pts_inc(struct ptdesc *ptdesc) ++{ ++ atomic_inc(&ptdesc->pt_share_count); ++} ++ ++static inline void ptdesc_pmd_pts_dec(struct ptdesc *ptdesc) ++{ ++ atomic_dec(&ptdesc->pt_share_count); ++} ++ ++static inline int ptdesc_pmd_pts_count(struct ptdesc *ptdesc) ++{ ++ return atomic_read(&ptdesc->pt_share_count); ++} ++#else ++static inline void ptdesc_pmd_pts_init(struct ptdesc *ptdesc) ++{ ++} ++#endif ++ + /* + * Used for sizing the vmemmap region on some architectures + */ +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 5b8cc558ab6e..21c12519a7ef 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -7014,7 +7014,7 @@ pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma, + spte = hugetlb_walk(svma, saddr, + vma_mmu_pagesize(svma)); + if (spte) { +- get_page(virt_to_page(spte)); ++ ptdesc_pmd_pts_inc(virt_to_ptdesc(spte)); + break; + } + } +@@ -7029,7 +7029,7 @@ pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma, + (pmd_t *)((unsigned long)spte & PAGE_MASK)); + mm_inc_nr_pmds(mm); + } else { +- put_page(virt_to_page(spte)); ++ ptdesc_pmd_pts_dec(virt_to_ptdesc(spte)); + } + spin_unlock(&mm->page_table_lock); + out: +@@ -7041,10 +7041,6 @@ pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma, + /* + * unmap huge page backed by shared pte. + * +- * Hugetlb pte page is ref counted at the time of mapping. If pte is shared +- * indicated by page_count > 1, unmap is achieved by clearing pud and +- * decrementing the ref count. If count == 1, the pte page is not shared. +- * + * Called with page table lock held. + * + * returns: 1 successfully unmapped a shared pte page +@@ -7053,18 +7049,20 @@ pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma, + int huge_pmd_unshare(struct mm_struct *mm, struct vm_area_struct *vma, + unsigned long addr, pte_t *ptep) + { ++ unsigned long sz = huge_page_size(hstate_vma(vma)); + pgd_t *pgd = pgd_offset(mm, addr); + p4d_t *p4d = p4d_offset(pgd, addr); + pud_t *pud = pud_offset(p4d, addr); + + i_mmap_assert_write_locked(vma->vm_file->f_mapping); + hugetlb_vma_assert_locked(vma); +- BUG_ON(page_count(virt_to_page(ptep)) == 0); +- if (page_count(virt_to_page(ptep)) == 1) ++ if (sz != PMD_SIZE) ++ return 0; ++ if (!ptdesc_pmd_pts_count(virt_to_ptdesc(ptep))) + return 0; + + pud_clear(pud); +- put_page(virt_to_page(ptep)); ++ ptdesc_pmd_pts_dec(virt_to_ptdesc(ptep)); + mm_dec_nr_pmds(mm); + return 1; + } +-- +2.39.5 + diff --git a/queue-6.6/pgtable-fix-s390-ptdesc-field-comments.patch b/queue-6.6/pgtable-fix-s390-ptdesc-field-comments.patch new file mode 100644 index 00000000000..ade112279bb --- /dev/null +++ b/queue-6.6/pgtable-fix-s390-ptdesc-field-comments.patch @@ -0,0 +1,50 @@ +From f93562157e55623c398010b4132ed0d645bd94f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Nov 2023 20:43:49 +0100 +Subject: pgtable: fix s390 ptdesc field comments + +From: Alexander Gordeev + +[ Upstream commit 38ca8a185389716e9f7566bce4bb0085f71da61d ] + +Patch series "minor ptdesc updates", v3. + +This patch (of 2): + +Since commit d08d4e7cd6bf ("s390/mm: use full 4KB page for 2KB PTE") there +is no fragmented page tracking on s390. Fix the corresponding comments. + +Link: https://lkml.kernel.org/r/cover.1700594815.git.agordeev@linux.ibm.com +Link: https://lkml.kernel.org/r/2eead241f3a45bed26c7911cf66bded1e35670b8.1700594815.git.agordeev@linux.ibm.com +Signed-off-by: Alexander Gordeev +Suggested-by: Heiko Carstens +Cc: Gerald Schaefer +Cc: Vishal Moola (Oracle) +Signed-off-by: Andrew Morton +Stable-dep-of: 59d9094df3d7 ("mm: hugetlb: independent PMD page table shared count") +Signed-off-by: Sasha Levin +--- + include/linux/mm_types.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h +index 20c96ce98751..1f224c55fb58 100644 +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -398,11 +398,11 @@ FOLIO_MATCH(compound_head, _head_2a); + * @pmd_huge_pte: Protected by ptdesc->ptl, used for THPs. + * @__page_mapping: Aliases with page->mapping. Unused for page tables. + * @pt_mm: Used for x86 pgds. +- * @pt_frag_refcount: For fragmented page table tracking. Powerpc and s390 only. ++ * @pt_frag_refcount: For fragmented page table tracking. Powerpc only. + * @_pt_pad_2: Padding to ensure proper alignment. + * @ptl: Lock for the page table. + * @__page_type: Same as page->page_type. Unused for page tables. +- * @_refcount: Same as page refcount. Used for s390 page tables. ++ * @_refcount: Same as page refcount. + * @pt_memcg_data: Memcg data. Tracked for page tables here. + * + * This struct overlays struct page for now. Do not modify without a good +-- +2.39.5 + diff --git a/queue-6.6/pmdomain-imx-gpcv2-fix-an-of-node-reference-leak-in-.patch b/queue-6.6/pmdomain-imx-gpcv2-fix-an-of-node-reference-leak-in-.patch new file mode 100644 index 00000000000..226ca0922d0 --- /dev/null +++ b/queue-6.6/pmdomain-imx-gpcv2-fix-an-of-node-reference-leak-in-.patch @@ -0,0 +1,49 @@ +From d9d195cfa7d24b24136ff740018acb5bfda88a76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Dec 2024 12:01:59 +0900 +Subject: pmdomain: imx: gpcv2: fix an OF node reference leak in + imx_gpcv2_probe() + +From: Joe Hattori + +[ Upstream commit 469c0682e03d67d8dc970ecaa70c2d753057c7c0 ] + +imx_gpcv2_probe() leaks an OF node reference obtained by +of_get_child_by_name(). Fix it by declaring the device node with the +__free(device_node) cleanup construct. + +This bug was found by an experimental static analysis tool that I am +developing. + +Fixes: 03aa12629fc4 ("soc: imx: Add GPCv2 power gating driver") +Signed-off-by: Joe Hattori +Cc: stable@vger.kernel.org +Message-ID: <20241215030159.1526624-1-joe@pf.is.s.u-tokyo.ac.jp> +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/pmdomain/imx/gpcv2.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pmdomain/imx/gpcv2.c b/drivers/pmdomain/imx/gpcv2.c +index ec789bf92274..13fce2b134f6 100644 +--- a/drivers/pmdomain/imx/gpcv2.c ++++ b/drivers/pmdomain/imx/gpcv2.c +@@ -1449,12 +1449,12 @@ static int imx_gpcv2_probe(struct platform_device *pdev) + .max_register = SZ_4K, + }; + struct device *dev = &pdev->dev; +- struct device_node *pgc_np; ++ struct device_node *pgc_np __free(device_node) = ++ of_get_child_by_name(dev->of_node, "pgc"); + struct regmap *regmap; + void __iomem *base; + int ret; + +- pgc_np = of_get_child_by_name(dev->of_node, "pgc"); + if (!pgc_np) { + dev_err(dev, "No power domains specified in DT\n"); + return -EINVAL; +-- +2.39.5 + diff --git a/queue-6.6/pmdomain-imx-gpcv2-simplify-with-scoped-for-each-of-.patch b/queue-6.6/pmdomain-imx-gpcv2-simplify-with-scoped-for-each-of-.patch new file mode 100644 index 00000000000..2ebb2763068 --- /dev/null +++ b/queue-6.6/pmdomain-imx-gpcv2-simplify-with-scoped-for-each-of-.patch @@ -0,0 +1,78 @@ +From e32600438e4a014b04d003c86e4a638bca5378ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Aug 2024 14:51:08 +0200 +Subject: pmdomain: imx: gpcv2: Simplify with scoped for each OF child loop + +From: Krzysztof Kozlowski + +[ Upstream commit 13bd778c900537f3fff7cfb671ff2eb0e92feee6 ] + +Use scoped for_each_child_of_node_scoped() when iterating over device +nodes to make code a bit simpler. + +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20240823-cleanup-h-guard-pm-domain-v1-4-8320722eaf39@linaro.org +Signed-off-by: Ulf Hansson +Stable-dep-of: 469c0682e03d ("pmdomain: imx: gpcv2: fix an OF node reference leak in imx_gpcv2_probe()") +Signed-off-by: Sasha Levin +--- + drivers/pmdomain/imx/gpcv2.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/pmdomain/imx/gpcv2.c b/drivers/pmdomain/imx/gpcv2.c +index fbd3d92f8cd8..ec789bf92274 100644 +--- a/drivers/pmdomain/imx/gpcv2.c ++++ b/drivers/pmdomain/imx/gpcv2.c +@@ -1449,7 +1449,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev) + .max_register = SZ_4K, + }; + struct device *dev = &pdev->dev; +- struct device_node *pgc_np, *np; ++ struct device_node *pgc_np; + struct regmap *regmap; + void __iomem *base; + int ret; +@@ -1471,7 +1471,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev) + return ret; + } + +- for_each_child_of_node(pgc_np, np) { ++ for_each_child_of_node_scoped(pgc_np, np) { + struct platform_device *pd_pdev; + struct imx_pgc_domain *domain; + u32 domain_index; +@@ -1482,7 +1482,6 @@ static int imx_gpcv2_probe(struct platform_device *pdev) + ret = of_property_read_u32(np, "reg", &domain_index); + if (ret) { + dev_err(dev, "Failed to read 'reg' property\n"); +- of_node_put(np); + return ret; + } + +@@ -1497,7 +1496,6 @@ static int imx_gpcv2_probe(struct platform_device *pdev) + domain_index); + if (!pd_pdev) { + dev_err(dev, "Failed to allocate platform device\n"); +- of_node_put(np); + return -ENOMEM; + } + +@@ -1506,7 +1504,6 @@ static int imx_gpcv2_probe(struct platform_device *pdev) + sizeof(domain_data->domains[domain_index])); + if (ret) { + platform_device_put(pd_pdev); +- of_node_put(np); + return ret; + } + +@@ -1523,7 +1520,6 @@ static int imx_gpcv2_probe(struct platform_device *pdev) + ret = platform_device_add(pd_pdev); + if (ret) { + platform_device_put(pd_pdev); +- of_node_put(np); + return ret; + } + } +-- +2.39.5 + diff --git a/queue-6.6/riscv-fix-text-patching-when-ipi-are-used.patch b/queue-6.6/riscv-fix-text-patching-when-ipi-are-used.patch new file mode 100644 index 00000000000..290443b98cb --- /dev/null +++ b/queue-6.6/riscv-fix-text-patching-when-ipi-are-used.patch @@ -0,0 +1,172 @@ +From 941481db4a1d865e2a28886ec9ef36d52a878989 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Feb 2024 13:10:56 +0100 +Subject: riscv: Fix text patching when IPI are used +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alexandre Ghiti + +[ Upstream commit c97bf629963e52b205ed5fbaf151e5bd342f9c63 ] + +For now, we use stop_machine() to patch the text and when we use IPIs for +remote icache flushes (which is emitted in patch_text_nosync()), the system +hangs. + +So instead, make sure every CPU executes the stop_machine() patching +function and emit a local icache flush there. + +Co-developed-by: Björn Töpel +Signed-off-by: Björn Töpel +Signed-off-by: Alexandre Ghiti +Reviewed-by: Andrea Parri +Link: https://lore.kernel.org/r/20240229121056.203419-3-alexghiti@rivosinc.com +Signed-off-by: Palmer Dabbelt +Stable-dep-of: 13134cc94914 ("riscv: kprobes: Fix incorrect address calculation") +Signed-off-by: Sasha Levin +--- + arch/riscv/include/asm/patch.h | 1 + + arch/riscv/kernel/ftrace.c | 44 ++++++++++++++++++++++++++++++---- + arch/riscv/kernel/patch.c | 16 +++++++++---- + 3 files changed, 53 insertions(+), 8 deletions(-) + +diff --git a/arch/riscv/include/asm/patch.h b/arch/riscv/include/asm/patch.h +index e88b52d39eac..9f5d6e14c405 100644 +--- a/arch/riscv/include/asm/patch.h ++++ b/arch/riscv/include/asm/patch.h +@@ -6,6 +6,7 @@ + #ifndef _ASM_RISCV_PATCH_H + #define _ASM_RISCV_PATCH_H + ++int patch_insn_write(void *addr, const void *insn, size_t len); + int patch_text_nosync(void *addr, const void *insns, size_t len); + int patch_text_set_nosync(void *addr, u8 c, size_t len); + int patch_text(void *addr, u32 *insns, int ninsns); +diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c +index 03a6434a8cdd..6ede2bcce238 100644 +--- a/arch/riscv/kernel/ftrace.c ++++ b/arch/riscv/kernel/ftrace.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -75,8 +76,7 @@ static int __ftrace_modify_call(unsigned long hook_pos, unsigned long target, + make_call_t0(hook_pos, target, call); + + /* Replace the auipc-jalr pair at once. Return -EPERM on write error. */ +- if (patch_text_nosync +- ((void *)hook_pos, enable ? call : nops, MCOUNT_INSN_SIZE)) ++ if (patch_insn_write((void *)hook_pos, enable ? call : nops, MCOUNT_INSN_SIZE)) + return -EPERM; + + return 0; +@@ -88,7 +88,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) + + make_call_t0(rec->ip, addr, call); + +- if (patch_text_nosync((void *)rec->ip, call, MCOUNT_INSN_SIZE)) ++ if (patch_insn_write((void *)rec->ip, call, MCOUNT_INSN_SIZE)) + return -EPERM; + + return 0; +@@ -99,7 +99,7 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, + { + unsigned int nops[2] = {NOP4, NOP4}; + +- if (patch_text_nosync((void *)rec->ip, nops, MCOUNT_INSN_SIZE)) ++ if (patch_insn_write((void *)rec->ip, nops, MCOUNT_INSN_SIZE)) + return -EPERM; + + return 0; +@@ -134,6 +134,42 @@ int ftrace_update_ftrace_func(ftrace_func_t func) + + return ret; + } ++ ++struct ftrace_modify_param { ++ int command; ++ atomic_t cpu_count; ++}; ++ ++static int __ftrace_modify_code(void *data) ++{ ++ struct ftrace_modify_param *param = data; ++ ++ if (atomic_inc_return(¶m->cpu_count) == num_online_cpus()) { ++ ftrace_modify_all_code(param->command); ++ /* ++ * Make sure the patching store is effective *before* we ++ * increment the counter which releases all waiting CPUs ++ * by using the release variant of atomic increment. The ++ * release pairs with the call to local_flush_icache_all() ++ * on the waiting CPU. ++ */ ++ atomic_inc_return_release(¶m->cpu_count); ++ } else { ++ while (atomic_read(¶m->cpu_count) <= num_online_cpus()) ++ cpu_relax(); ++ } ++ ++ local_flush_icache_all(); ++ ++ return 0; ++} ++ ++void arch_ftrace_update_code(int command) ++{ ++ struct ftrace_modify_param param = { command, ATOMIC_INIT(0) }; ++ ++ stop_machine(__ftrace_modify_code, ¶m, cpu_online_mask); ++} + #endif + + #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS +diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c +index 30e12b310cab..78387d843aa5 100644 +--- a/arch/riscv/kernel/patch.c ++++ b/arch/riscv/kernel/patch.c +@@ -196,7 +196,7 @@ int patch_text_set_nosync(void *addr, u8 c, size_t len) + } + NOKPROBE_SYMBOL(patch_text_set_nosync); + +-static int patch_insn_write(void *addr, const void *insn, size_t len) ++int patch_insn_write(void *addr, const void *insn, size_t len) + { + size_t patched = 0; + size_t size; +@@ -240,16 +240,24 @@ static int patch_text_cb(void *data) + if (atomic_inc_return(&patch->cpu_count) == num_online_cpus()) { + for (i = 0; ret == 0 && i < patch->ninsns; i++) { + len = GET_INSN_LENGTH(patch->insns[i]); +- ret = patch_text_nosync(patch->addr + i * len, +- &patch->insns[i], len); ++ ret = patch_insn_write(patch->addr + i * len, &patch->insns[i], len); + } +- atomic_inc(&patch->cpu_count); ++ /* ++ * Make sure the patching store is effective *before* we ++ * increment the counter which releases all waiting CPUs ++ * by using the release variant of atomic increment. The ++ * release pairs with the call to local_flush_icache_all() ++ * on the waiting CPU. ++ */ ++ atomic_inc_return_release(&patch->cpu_count); + } else { + while (atomic_read(&patch->cpu_count) <= num_online_cpus()) + cpu_relax(); + smp_mb(); + } + ++ local_flush_icache_all(); ++ + return ret; + } + NOKPROBE_SYMBOL(patch_text_cb); +-- +2.39.5 + diff --git a/queue-6.6/series b/queue-6.6/series index d6712b0cc5c..38e47c43d18 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -114,3 +114,18 @@ iio-inkern-call-iio_device_put-only-on-mapped-devices.patch iio-adc-ad7124-disable-all-channels-at-probe-time.patch riscv-kprobes-fix-incorrect-address-calculation.patch io_uring-eventfd-ensure-io_eventfd_signal-defers-another-rcu-period.patch +arm-dts-imxrt1050-fix-clocks-for-mmc.patch +hwmon-drivetemp-fix-driver-producing-garbage-data-wh.patch +block-bfq-fix-waker_bfqq-uaf-after-bfq_split_bfqq.patch +arm64-dts-rockchip-add-hevc-power-domain-clock-to-rk.patch +pmdomain-imx-gpcv2-simplify-with-scoped-for-each-of-.patch +pmdomain-imx-gpcv2-fix-an-of-node-reference-leak-in-.patch +workqueue-add-rcu-lock-check-at-the-end-of-work-item.patch +workqueue-update-lock-debugging-code.patch +workqueue-do-not-warn-when-cancelling-wq_mem_reclaim.patch +pgtable-fix-s390-ptdesc-field-comments.patch +fs-kconfig-make-hugetlbfs-a-menuconfig.patch +mm-hugetlb-enforce-that-pmd-pt-sharing-has-split-pmd.patch +mm-hugetlb-independent-pmd-page-table-shared-count.patch +riscv-fix-text-patching-when-ipi-are-used.patch +drm-mediatek-only-touch-disp_reg_ovl_pitch_msb-if-af.patch diff --git a/queue-6.6/workqueue-add-rcu-lock-check-at-the-end-of-work-item.patch b/queue-6.6/workqueue-add-rcu-lock-check-at-the-end-of-work-item.patch new file mode 100644 index 00000000000..8ce9559927e --- /dev/null +++ b/queue-6.6/workqueue-add-rcu-lock-check-at-the-end-of-work-item.patch @@ -0,0 +1,58 @@ +From a2edf6676650ed3f2e0a747da328bb0355bc225d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jan 2024 11:27:24 +0800 +Subject: workqueue: Add rcu lock check at the end of work item execution + +From: Xuewen Yan + +[ Upstream commit 1a65a6d17cbc58e1aeffb2be962acce49efbef9c ] + +Currently the workqueue just checks the atomic and locking states after work +execution ends. However, sometimes, a work item may not unlock rcu after +acquiring rcu_read_lock(). And as a result, it would cause rcu stall, but +the rcu stall warning can not dump the work func, because the work has +finished. + +In order to quickly discover those works that do not call rcu_read_unlock() +after rcu_read_lock(), add the rcu lock check. + +Use rcu_preempt_depth() to check the work's rcu status. Normally, this value +is 0. If this value is bigger than 0, it means the work are still holding +rcu lock. If so, print err info and the work func. + +tj: Reworded the description for clarity. Minor formatting tweak. + +Signed-off-by: Xuewen Yan +Reviewed-by: Lai Jiangshan +Reviewed-by: Waiman Long +Signed-off-by: Tejun Heo +Stable-dep-of: de35994ecd2d ("workqueue: Do not warn when cancelling WQ_MEM_RECLAIM work from !WQ_MEM_RECLAIM worker") +Signed-off-by: Sasha Levin +--- + kernel/workqueue.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index 7fa1c7c9151a..2d85f232c675 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -2638,11 +2638,12 @@ __acquires(&pool->lock) + lock_map_release(&lockdep_map); + lock_map_release(&pwq->wq->lockdep_map); + +- if (unlikely(in_atomic() || lockdep_depth(current) > 0)) { +- pr_err("BUG: workqueue leaked lock or atomic: %s/0x%08x/%d\n" ++ if (unlikely(in_atomic() || lockdep_depth(current) > 0 || ++ rcu_preempt_depth() > 0)) { ++ pr_err("BUG: workqueue leaked lock or atomic: %s/0x%08x/%d/%d\n" + " last function: %ps\n", +- current->comm, preempt_count(), task_pid_nr(current), +- worker->current_func); ++ current->comm, preempt_count(), rcu_preempt_depth(), ++ task_pid_nr(current), worker->current_func); + debug_show_held_locks(current); + dump_stack(); + } +-- +2.39.5 + diff --git a/queue-6.6/workqueue-do-not-warn-when-cancelling-wq_mem_reclaim.patch b/queue-6.6/workqueue-do-not-warn-when-cancelling-wq_mem_reclaim.patch new file mode 100644 index 00000000000..4b95dcf000c --- /dev/null +++ b/queue-6.6/workqueue-do-not-warn-when-cancelling-wq_mem_reclaim.patch @@ -0,0 +1,124 @@ +From 7ccf278afad0f56ad044b774e2de183520108092 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Dec 2024 09:30:30 +0000 +Subject: workqueue: Do not warn when cancelling WQ_MEM_RECLAIM work from + !WQ_MEM_RECLAIM worker +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Tvrtko Ursulin + +[ Upstream commit de35994ecd2dd6148ab5a6c5050a1670a04dec77 ] + +After commit +746ae46c1113 ("drm/sched: Mark scheduler work queues with WQ_MEM_RECLAIM") +amdgpu started seeing the following warning: + + [ ] workqueue: WQ_MEM_RECLAIM sdma0:drm_sched_run_job_work [gpu_sched] is flushing !WQ_MEM_RECLAIM events:amdgpu_device_delay_enable_gfx_off [amdgpu] +... + [ ] Workqueue: sdma0 drm_sched_run_job_work [gpu_sched] +... + [ ] Call Trace: + [ ] +... + [ ] ? check_flush_dependency+0xf5/0x110 +... + [ ] cancel_delayed_work_sync+0x6e/0x80 + [ ] amdgpu_gfx_off_ctrl+0xab/0x140 [amdgpu] + [ ] amdgpu_ring_alloc+0x40/0x50 [amdgpu] + [ ] amdgpu_ib_schedule+0xf4/0x810 [amdgpu] + [ ] ? drm_sched_run_job_work+0x22c/0x430 [gpu_sched] + [ ] amdgpu_job_run+0xaa/0x1f0 [amdgpu] + [ ] drm_sched_run_job_work+0x257/0x430 [gpu_sched] + [ ] process_one_work+0x217/0x720 +... + [ ] + +The intent of the verifcation done in check_flush_depedency is to ensure +forward progress during memory reclaim, by flagging cases when either a +memory reclaim process, or a memory reclaim work item is flushed from a +context not marked as memory reclaim safe. + +This is correct when flushing, but when called from the +cancel(_delayed)_work_sync() paths it is a false positive because work is +either already running, or will not be running at all. Therefore +cancelling it is safe and we can relax the warning criteria by letting the +helper know of the calling context. + +Signed-off-by: Tvrtko Ursulin +Fixes: fca839c00a12 ("workqueue: warn if memory reclaim tries to flush !WQ_MEM_RECLAIM workqueue") +References: 746ae46c1113 ("drm/sched: Mark scheduler work queues with WQ_MEM_RECLAIM") +Cc: Tejun Heo +Cc: Peter Zijlstra +Cc: Lai Jiangshan +Cc: Alex Deucher +Cc: Christian König +Cc: # v4.5+ +Signed-off-by: Tejun Heo +Signed-off-by: Sasha Levin +--- + kernel/workqueue.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index da5750246a92..59b6efb2a11c 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -2947,23 +2947,27 @@ static int rescuer_thread(void *__rescuer) + * check_flush_dependency - check for flush dependency sanity + * @target_wq: workqueue being flushed + * @target_work: work item being flushed (NULL for workqueue flushes) ++ * @from_cancel: are we called from the work cancel path + * + * %current is trying to flush the whole @target_wq or @target_work on it. +- * If @target_wq doesn't have %WQ_MEM_RECLAIM, verify that %current is not +- * reclaiming memory or running on a workqueue which doesn't have +- * %WQ_MEM_RECLAIM as that can break forward-progress guarantee leading to +- * a deadlock. ++ * If this is not the cancel path (which implies work being flushed is either ++ * already running, or will not be at all), check if @target_wq doesn't have ++ * %WQ_MEM_RECLAIM and verify that %current is not reclaiming memory or running ++ * on a workqueue which doesn't have %WQ_MEM_RECLAIM as that can break forward- ++ * progress guarantee leading to a deadlock. + */ + static void check_flush_dependency(struct workqueue_struct *target_wq, +- struct work_struct *target_work) ++ struct work_struct *target_work, ++ bool from_cancel) + { +- work_func_t target_func = target_work ? target_work->func : NULL; ++ work_func_t target_func; + struct worker *worker; + +- if (target_wq->flags & WQ_MEM_RECLAIM) ++ if (from_cancel || target_wq->flags & WQ_MEM_RECLAIM) + return; + + worker = current_wq_worker(); ++ target_func = target_work ? target_work->func : NULL; + + WARN_ONCE(current->flags & PF_MEMALLOC, + "workqueue: PF_MEMALLOC task %d(%s) is flushing !WQ_MEM_RECLAIM %s:%ps", +@@ -3208,7 +3212,7 @@ void __flush_workqueue(struct workqueue_struct *wq) + list_add_tail(&this_flusher.list, &wq->flusher_overflow); + } + +- check_flush_dependency(wq, NULL); ++ check_flush_dependency(wq, NULL, false); + + mutex_unlock(&wq->mutex); + +@@ -3385,7 +3389,7 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr, + } + + wq = pwq->wq; +- check_flush_dependency(wq, work); ++ check_flush_dependency(wq, work, from_cancel); + + insert_wq_barrier(pwq, barr, work, worker); + raw_spin_unlock_irq(&pool->lock); +-- +2.39.5 + diff --git a/queue-6.6/workqueue-update-lock-debugging-code.patch b/queue-6.6/workqueue-update-lock-debugging-code.patch new file mode 100644 index 00000000000..0909bc36f8a --- /dev/null +++ b/queue-6.6/workqueue-update-lock-debugging-code.patch @@ -0,0 +1,156 @@ +From 125f6c2f1b7408d78fc4568e7c6a951b85184a6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Feb 2024 11:28:06 -1000 +Subject: workqueue: Update lock debugging code + +From: Tejun Heo + +[ Upstream commit c35aea39d1e106f61fd2130f0d32a3bac8bd4570 ] + +These changes are in preparation of BH workqueue which will execute work +items from BH context. + +- Update lock and RCU depth checks in process_one_work() so that it + remembers and checks against the starting depths and prints out the depth + changes. + +- Factor out lockdep annotations in the flush paths into + touch_{wq|work}_lockdep_map(). The work->lockdep_map touching is moved + from __flush_work() to its callee - start_flush_work(). This brings it + closer to the wq counterpart and will allow testing the associated wq's + flags which will be needed to support BH workqueues. This is not expected + to cause any functional changes. + +Signed-off-by: Tejun Heo +Tested-by: Allen Pais +Stable-dep-of: de35994ecd2d ("workqueue: Do not warn when cancelling WQ_MEM_RECLAIM work from !WQ_MEM_RECLAIM worker") +Signed-off-by: Sasha Levin +--- + kernel/workqueue.c | 51 ++++++++++++++++++++++++++++++---------------- + 1 file changed, 34 insertions(+), 17 deletions(-) + +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index 2d85f232c675..da5750246a92 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -2541,6 +2541,7 @@ __acquires(&pool->lock) + struct pool_workqueue *pwq = get_work_pwq(work); + struct worker_pool *pool = worker->pool; + unsigned long work_data; ++ int lockdep_start_depth, rcu_start_depth; + #ifdef CONFIG_LOCKDEP + /* + * It is permissible to free the struct work_struct from +@@ -2603,6 +2604,8 @@ __acquires(&pool->lock) + pwq->stats[PWQ_STAT_STARTED]++; + raw_spin_unlock_irq(&pool->lock); + ++ rcu_start_depth = rcu_preempt_depth(); ++ lockdep_start_depth = lockdep_depth(current); + lock_map_acquire(&pwq->wq->lockdep_map); + lock_map_acquire(&lockdep_map); + /* +@@ -2638,12 +2641,15 @@ __acquires(&pool->lock) + lock_map_release(&lockdep_map); + lock_map_release(&pwq->wq->lockdep_map); + +- if (unlikely(in_atomic() || lockdep_depth(current) > 0 || +- rcu_preempt_depth() > 0)) { +- pr_err("BUG: workqueue leaked lock or atomic: %s/0x%08x/%d/%d\n" +- " last function: %ps\n", +- current->comm, preempt_count(), rcu_preempt_depth(), +- task_pid_nr(current), worker->current_func); ++ if (unlikely((worker->task && in_atomic()) || ++ lockdep_depth(current) != lockdep_start_depth || ++ rcu_preempt_depth() != rcu_start_depth)) { ++ pr_err("BUG: workqueue leaked atomic, lock or RCU: %s[%d]\n" ++ " preempt=0x%08x lock=%d->%d RCU=%d->%d workfn=%ps\n", ++ current->comm, task_pid_nr(current), preempt_count(), ++ lockdep_start_depth, lockdep_depth(current), ++ rcu_start_depth, rcu_preempt_depth(), ++ worker->current_func); + debug_show_held_locks(current); + dump_stack(); + } +@@ -3123,6 +3129,19 @@ static bool flush_workqueue_prep_pwqs(struct workqueue_struct *wq, + return wait; + } + ++static void touch_wq_lockdep_map(struct workqueue_struct *wq) ++{ ++ lock_map_acquire(&wq->lockdep_map); ++ lock_map_release(&wq->lockdep_map); ++} ++ ++static void touch_work_lockdep_map(struct work_struct *work, ++ struct workqueue_struct *wq) ++{ ++ lock_map_acquire(&work->lockdep_map); ++ lock_map_release(&work->lockdep_map); ++} ++ + /** + * __flush_workqueue - ensure that any scheduled work has run to completion. + * @wq: workqueue to flush +@@ -3142,8 +3161,7 @@ void __flush_workqueue(struct workqueue_struct *wq) + if (WARN_ON(!wq_online)) + return; + +- lock_map_acquire(&wq->lockdep_map); +- lock_map_release(&wq->lockdep_map); ++ touch_wq_lockdep_map(wq); + + mutex_lock(&wq->mutex); + +@@ -3342,6 +3360,7 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr, + struct worker *worker = NULL; + struct worker_pool *pool; + struct pool_workqueue *pwq; ++ struct workqueue_struct *wq; + + might_sleep(); + +@@ -3365,11 +3384,14 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr, + pwq = worker->current_pwq; + } + +- check_flush_dependency(pwq->wq, work); ++ wq = pwq->wq; ++ check_flush_dependency(wq, work); + + insert_wq_barrier(pwq, barr, work, worker); + raw_spin_unlock_irq(&pool->lock); + ++ touch_work_lockdep_map(work, wq); ++ + /* + * Force a lock recursion deadlock when using flush_work() inside a + * single-threaded or rescuer equipped workqueue. +@@ -3379,11 +3401,9 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr, + * workqueues the deadlock happens when the rescuer stalls, blocking + * forward progress. + */ +- if (!from_cancel && +- (pwq->wq->saved_max_active == 1 || pwq->wq->rescuer)) { +- lock_map_acquire(&pwq->wq->lockdep_map); +- lock_map_release(&pwq->wq->lockdep_map); +- } ++ if (!from_cancel && (wq->saved_max_active == 1 || wq->rescuer)) ++ touch_wq_lockdep_map(wq); ++ + rcu_read_unlock(); + return true; + already_gone: +@@ -3402,9 +3422,6 @@ static bool __flush_work(struct work_struct *work, bool from_cancel) + if (WARN_ON(!work->func)) + return false; + +- lock_map_acquire(&work->lockdep_map); +- lock_map_release(&work->lockdep_map); +- + if (start_flush_work(work, &barr, from_cancel)) { + wait_for_completion(&barr.done); + destroy_work_on_stack(&barr.work); +-- +2.39.5 +