Fixes for all trees

Signed-off-by: Sasha Levin <sashal@kernel.org>
diff --git a/queue-5.10/drm-amd-display-bound-vbios-record-chain-walk-loops.patch b/queue-5.10/drm-amd-display-bound-vbios-record-chain-walk-loops.patch
new file mode 100644
index 0000000..a28866c
--- /dev/null
+++ b/queue-5.10/drm-amd-display-bound-vbios-record-chain-walk-loops.patch
@@ -0,0 +1,215 @@
+From 0eb4b39a7355d0afe95d896b3280d8bce03224b7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 May 2026 15:24:22 -0400
+Subject: drm/amd/display: Bound VBIOS record-chain walk loops
+
+From: Harry Wentland <harry.wentland@amd.com>
+
+[ Upstream commit ff287df16a1a58aca78b08d1f3ee09fc44da0351 ]
+
+[Why & How]
+All record-chain walk loops in bios_parser.c and bios_parser2.c use
+for(;;) and only terminate on a 0xFF record_type sentinel or zero
+record_size. A malformed VBIOS image missing the terminator record
+causes unbounded iteration at probe time, potentially hundreds of
+thousands of iterations with record_size=1. In the final iterations
+near the BIOS image boundary, struct casts beyond the 2-byte header
+validated by GET_IMAGE can also read out of bounds.
+
+Cap all 14 record-chain walk loops to BIOS_MAX_NUM_RECORD (256)
+iterations. The atombios.h defines up to 22 distinct record types
+and atomfirmware.h has 13. Assuming an average of less than 10
+records per type (which is reasonable since most are connector-
+based) 256 is a generous upper bound.
+
+Fixes: 4562236b3bc0 ("drm/amd/dc: Add dc display driver (v2)")
+Assisted-by: Copilot:claude-opus-4.6 Mythos
+Reviewed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Ray Wu <ray.wu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 95700a3d660287ed657d6892f7be9ffc0e294a93)
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 15 ++++++++++-----
+ .../gpu/drm/amd/display/dc/bios/bios_parser2.c    | 12 ++++++++----
+ .../drm/amd/display/dc/bios/bios_parser_helper.h  |  5 +++++
+ 3 files changed, 23 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+index d37ee8277480dc..b7b9e4c99537b7 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+@@ -223,6 +223,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	ATOM_I2C_RECORD *record;
+ 	struct bios_parser *bp = BP_FROM_DCB(dcb);
++	int i;
+ 
+ 	if (!info)
+ 		return BP_RESULT_BADINPUT;
+@@ -235,7 +236,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -294,11 +295,12 @@ static enum bp_result bios_parser_get_device_tag_record(
+ {
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -870,6 +872,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
+ {
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -879,7 +882,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -1576,6 +1579,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
+ {
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -1585,7 +1589,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 					+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -2667,6 +2671,7 @@ enum bp_result update_slot_layout_info(
+ 	unsigned int record_offset)
+ {
+ 	unsigned int j;
++	unsigned int n;
+ 	struct bios_parser *bp;
+ 	ATOM_BRACKET_LAYOUT_RECORD *record;
+ 	ATOM_COMMON_RECORD_HEADER *record_header;
+@@ -2676,7 +2681,7 @@ enum bp_result update_slot_layout_info(
+ 	record = NULL;
+ 	record_header = NULL;
+ 
+-	for (;;) {
++	for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
+ 
+ 		record_header = (ATOM_COMMON_RECORD_HEADER *)
+ 			GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+index 2ad36721212404..9e9476f87f6190 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+@@ -296,6 +296,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 	struct atom_i2c_record *record;
+ 	struct atom_i2c_record dummy_record = {0};
+ 	struct bios_parser *bp = BP_FROM_DCB(dcb);
++	int i;
+ 
+ 	if (!info)
+ 		return BP_RESULT_BADINPUT;
+@@ -316,7 +317,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 
+ 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -446,6 +447,7 @@ static struct atom_hpd_int_record *get_hpd_record(
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -455,7 +457,7 @@ static struct atom_hpd_int_record *get_hpd_record(
+ 	offset = le16_to_cpu(object->disp_recordoffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -1423,6 +1425,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -1431,7 +1434,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
+ 
+ 	offset = object->encoder_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -1870,6 +1873,7 @@ static enum bp_result update_slot_layout_info(
+ {
+ 	unsigned int record_offset;
+ 	unsigned int j;
++	unsigned int n;
+ 	struct atom_display_object_path_v2 *object;
+ 	struct atom_bracket_layout_record *record;
+ 	struct atom_common_record_header *record_header;
+@@ -1891,7 +1895,7 @@ static enum bp_result update_slot_layout_info(
+ 		(object->disp_recordoffset) +
+ 		(unsigned int)(bp->object_info_tbl_offset);
+ 
+-	for (;;) {
++	for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
+ 
+ 		record_header = (struct atom_common_record_header *)
+ 			GET_IMAGE(struct atom_common_record_header,
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
+index 75a29e68fb2782..991bbca950978e 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
+@@ -38,4 +38,9 @@ uint32_t bios_get_vga_enabled_displays(struct dc_bios *bios);
+ 
+ #define GET_IMAGE(type, offset) ((type *) bios_get_image(&bp->base, offset, sizeof(type)))
+ 
++/* Upper bound on the number of records in a VBIOS record chain. Prevents
++ * unbounded looping if the VBIOS image is malformed and lacks a terminator.
++ */
++#define BIOS_MAX_NUM_RECORD 256
++
+ #endif
+-- 
+2.53.0
+
diff --git a/queue-5.10/drm-amd-display-use-krealloc_array-in-dal_vector_res.patch b/queue-5.10/drm-amd-display-use-krealloc_array-in-dal_vector_res.patch
new file mode 100644
index 0000000..3de5b22
--- /dev/null
+++ b/queue-5.10/drm-amd-display-use-krealloc_array-in-dal_vector_res.patch
@@ -0,0 +1,50 @@
+From 4952ea016121522daf0f95da1644ff8313a58456 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Jun 2026 08:55:08 -0400
+Subject: drm/amd/display: Use krealloc_array() in dal_vector_reserve()
+
+From: Harry Wentland <harry.wentland@amd.com>
+
+[ Upstream commit da48bc4461b8a5ebfb9264c9b191a701d8e99009 ]
+
+[Why & How]
+dal_vector_reserve() computes the allocation size as
+"capacity * vector->struct_size" using uint32_t arithmetic, which can
+silently wrap to a small value on overflow. This would cause krealloc to
+return a smaller buffer than expected, leading to heap overflows on
+subsequent vector appends.
+
+Replace krealloc() with krealloc_array() which performs an internal
+overflow check and returns NULL on wrap, preventing the issue.
+
+Fixes: 2004f45ef83f ("drm/amd/display: Use kernel alloc/free")
+Assisted-by: Copilot:claude-opus-4.6
+Reviewed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Ray Wu <ray.wu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 37668568641ccc4cc1dbca4923d0a16609dd5707)
+Cc: stable@vger.kernel.org
+[ changed `krealloc_array(p, capacity, struct_size)` to `krealloc(p, array_size(capacity, struct_size))` since krealloc_array() is absent in 5.10 ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/basics/vector.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/basics/vector.c b/drivers/gpu/drm/amd/display/dc/basics/vector.c
+index 8f93d25f91ee2b..68c34a4e253ac1 100644
+--- a/drivers/gpu/drm/amd/display/dc/basics/vector.c
++++ b/drivers/gpu/drm/amd/display/dc/basics/vector.c
+@@ -292,7 +292,7 @@ bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
+ 		return true;
+ 
+ 	new_container = krealloc(vector->container,
+-				 capacity * vector->struct_size, GFP_KERNEL);
++				 array_size(capacity, vector->struct_size), GFP_KERNEL);
+ 
+ 	if (new_container) {
+ 		vector->container = new_container;
+-- 
+2.53.0
+
diff --git a/queue-5.10/ip6_vti-set-netns_immutable-on-the-fallback-device.patch b/queue-5.10/ip6_vti-set-netns_immutable-on-the-fallback-device.patch
new file mode 100644
index 0000000..85d580e
--- /dev/null
+++ b/queue-5.10/ip6_vti-set-netns_immutable-on-the-fallback-device.patch
@@ -0,0 +1,49 @@
+From e4271332158bb94a0b1788f083b88a5898331f99 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Jun 2026 15:59:18 +0000
+Subject: ip6_vti: set netns_immutable on the fallback device.
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d289d5307762d1838aaece22c6b6fcad9e8865f9 ]
+
+john1988 and Noam Rathaus reported that vti6_init_net() does not set the
+netns_immutable flag on the per-netns fallback tunnel device (ip6_vti0).
+
+Other similar tunnel drivers (like ip6_tunnel, sit, ip6_gre, and ip_tunnel)
+correctly set this flag during their fallback device initialization to
+prevent them from being moved to another network namespace.
+
+Fixes: 61220ab34948 ("vti6: Enable namespace changing")
+Reported-by: Noam Rathaus <noamr@ssd-disclosure.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Steffen Klassert <steffen.klassert@secunet.com>
+Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260608155918.787644-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[Salvatore Bonaccorso: Backport for version without 0c493da86374 ("net:
+rename netns_local to netns_immutable") in v6.15-rc1 and without
+05c1280a2bcf ("netdev_features: convert NETIF_F_NETNS_LOCAL to
+dev->netns_local") in v6.12-rc1 and use NETIF_F_NETNS_LOCAL device
+feature.]
+Signed-off-by: Salvatore Bonaccorso <carnil@debian.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/ip6_vti.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
+index e471a5821b0de5..a67c9d6fbf7712 100644
+--- a/net/ipv6/ip6_vti.c
++++ b/net/ipv6/ip6_vti.c
+@@ -1163,6 +1163,7 @@ static int __net_init vti6_init_net(struct net *net)
+ 		goto err_alloc_dev;
+ 	dev_net_set(ip6n->fb_tnl_dev, net);
+ 	ip6n->fb_tnl_dev->rtnl_link_ops = &vti6_link_ops;
++	ip6n->fb_tnl_dev->features |= NETIF_F_NETNS_LOCAL;
+ 
+ 	err = vti6_fb_tnl_dev_init(ip6n->fb_tnl_dev);
+ 	if (err < 0)
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-9p-fix-refcount-leak-in-p9_read_work-error-handl.patch b/queue-5.10/net-9p-fix-refcount-leak-in-p9_read_work-error-handl.patch
new file mode 100644
index 0000000..94112d6
--- /dev/null
+++ b/queue-5.10/net-9p-fix-refcount-leak-in-p9_read_work-error-handl.patch
@@ -0,0 +1,40 @@
+From d89f35d726d8b12b78a0b4d0cd2263cf0ca0473c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Jun 2026 15:19:21 +0000
+Subject: net: 9p: fix refcount leak in p9_read_work() error handling
+
+From: Hangyu Hua <hbh25y@gmail.com>
+
+commit 4ac7573e1f9333073fa8d303acc941c9b7ab7f61 upstream.
+
+p9_req_put need to be called when m->rreq->rc.sdata is NULL to avoid
+temporary refcount leak.
+
+Link: https://lkml.kernel.org/r/20220712104438.30800-1-hbh25y@gmail.com
+Fixes: 728356dedeff ("9p: Add refcount to p9_req_t")
+Signed-off-by: Hangyu Hua <hbh25y@gmail.com>
+[Dominique: commit wording adjustments, p9_req_put argument fixes for rebase]
+Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
+[Alexander: this branch doesn't contain 8b11ff098af4 ("9p: Add client parameter
+ to p9_req_put()"), therefore the parameter is removed from the added line]
+Signed-off-by: Alexander Martyniuk <alexevgmart@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/9p/trans_fd.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
+index 40d458c438df1e..a75668534c81c3 100644
+--- a/net/9p/trans_fd.c
++++ b/net/9p/trans_fd.c
+@@ -346,6 +346,7 @@ static void p9_read_work(struct work_struct *work)
+ 			p9_debug(P9_DEBUG_ERROR,
+ 				 "No recv fcall for tag %d (req %p), disconnecting!\n",
+ 				 m->rc.tag, m->rreq);
++			p9_req_put(m->rreq);
+ 			m->rreq = NULL;
+ 			err = -EIO;
+ 			goto error;
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-add-skb_header_pointer_careful-helper.patch b/queue-5.10/net-add-skb_header_pointer_careful-helper.patch
new file mode 100644
index 0000000..20efa13
--- /dev/null
+++ b/queue-5.10/net-add-skb_header_pointer_careful-helper.patch
@@ -0,0 +1,54 @@
+From d6f941a8a1f7daf42358641d187c42cfa5746739 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Jun 2026 01:08:06 -0700
+Subject: net: add skb_header_pointer_careful() helper
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 13e00fdc9236bd4d0bff4109d2983171fbcb74c4 ]
+
+This variant of skb_header_pointer() should be used in contexts
+where @offset argument is user-controlled and could be negative.
+
+Negative offsets are supported, as long as the zone starts
+between skb->head and skb->data.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260128141539.3404400-2-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Adjust context ]
+Signed-off-by: Bin Lan <lanbincn@139.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[ Shivani: Modified to apply on 5.10.y ]
+Signed-off-by: Shivani Agarwal <shivani.agarwal@broadcom.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/skbuff.h | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index 4b5731245bf15b..667de403b2ebbd 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -3686,6 +3686,18 @@ skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer)
+ 				    skb_headlen(skb), buffer);
+ }
+ 
++/* Variant of skb_header_pointer() where @offset is user-controlled
++ * and potentially negative.
++ */
++static inline void * __must_check
++skb_header_pointer_careful(const struct sk_buff *skb, int offset,
++			   int len, void *buffer)
++{
++	if (unlikely(offset < 0 && -offset > skb_headroom(skb)))
++		return NULL;
++	return skb_header_pointer(skb, offset, len, buffer);
++}
++
+ /**
+  *	skb_needs_linearize - check if we need to linearize a given skb
+  *			      depending on the given device features.
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-sched-cls_u32-use-skb_header_pointer_careful.patch b/queue-5.10/net-sched-cls_u32-use-skb_header_pointer_careful.patch
new file mode 100644
index 0000000..7f271c2
--- /dev/null
+++ b/queue-5.10/net-sched-cls_u32-use-skb_header_pointer_careful.patch
@@ -0,0 +1,74 @@
+From 4c9221fac64d28ed5f8d470d48af0e4715f7cfb3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Jun 2026 01:08:07 -0700
+Subject: net/sched: cls_u32: use skb_header_pointer_careful()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit cabd1a976375780dabab888784e356f574bbaed8 ]
+
+skb_header_pointer() does not fully validate negative @offset values.
+
+Use skb_header_pointer_careful() instead.
+
+GangMin Kim provided a report and a repro fooling u32_classify():
+
+BUG: KASAN: slab-out-of-bounds in u32_classify+0x1180/0x11b0
+net/sched/cls_u32.c:221
+
+Fixes: fbc2e7d9cf49 ("cls_u32: use skb_header_pointer() to dereference data safely")
+Reported-by: GangMin Kim <km.kim1503@gmail.com>
+Closes: https://lore.kernel.org/netdev/CANn89iJkyUZ=mAzLzC4GdcAgLuPnUoivdLaOs6B9rq5_erj76w@mail.gmail.com/T/
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260128141539.3404400-3-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Bin Lan <lanbincn@139.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[ Shivani: Modified to apply on 5.10.y ]
+Signed-off-by: Shivani Agarwal <shivani.agarwal@broadcom.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_u32.c | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
+index f2a0c10682fc81..e501390ccd7585 100644
+--- a/net/sched/cls_u32.c
++++ b/net/sched/cls_u32.c
+@@ -149,10 +149,8 @@ static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp,
+ 			int toff = off + key->off + (off2 & key->offmask);
+ 			__be32 *data, hdata;
+ 
+-			if (skb_headroom(skb) + toff > INT_MAX)
+-				goto out;
+-
+-			data = skb_header_pointer(skb, toff, 4, &hdata);
++			data = skb_header_pointer_careful(skb, toff, 4,
++							  &hdata);
+ 			if (!data)
+ 				goto out;
+ 			if ((*data ^ key->val) & key->mask) {
+@@ -202,8 +200,9 @@ static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp,
+ 		if (ht->divisor) {
+ 			__be32 *data, hdata;
+ 
+-			data = skb_header_pointer(skb, off + n->sel.hoff, 4,
+-						  &hdata);
++			data = skb_header_pointer_careful(skb,
++							  off + n->sel.hoff,
++							  4, &hdata);
+ 			if (!data)
+ 				goto out;
+ 			sel = ht->divisor & u32_hash_fold(*data, &n->sel,
+@@ -217,7 +216,7 @@ static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp,
+ 			if (n->sel.flags & TC_U32_VAROFFSET) {
+ 				__be16 *data, hdata;
+ 
+-				data = skb_header_pointer(skb,
++				data = skb_header_pointer_careful(skb,
+ 							  off + n->sel.offoff,
+ 							  2, &hdata);
+ 				if (!data)
+-- 
+2.53.0
+
diff --git a/queue-5.10/netdevsim-fix-memory-leak-of-nsim_dev-fa_cookie.patch b/queue-5.10/netdevsim-fix-memory-leak-of-nsim_dev-fa_cookie.patch
new file mode 100644
index 0000000..76c308f
--- /dev/null
+++ b/queue-5.10/netdevsim-fix-memory-leak-of-nsim_dev-fa_cookie.patch
@@ -0,0 +1,64 @@
+From 2fb4fe605a3f03b9480e43ca4d612a1731ac6182 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 12:15:06 +0300
+Subject: netdevsim: Fix memory leak of nsim_dev->fa_cookie
+
+From: Wang Yufen <wangyufen@huawei.com>
+
+commit 064bc7312bd09a48798418663090be0c776183db upstream.
+
+kmemleak reports this issue:
+
+unreferenced object 0xffff8881bac872d0 (size 8):
+  comm "sh", pid 58603, jiffies 4481524462 (age 68.065s)
+  hex dump (first 8 bytes):
+    04 00 00 00 de ad be ef                          ........
+  backtrace:
+    [<00000000c80b8577>] __kmalloc+0x49/0x150
+    [<000000005292b8c6>] nsim_dev_trap_fa_cookie_write+0xc1/0x210 [netdevsim]
+    [<0000000093d78e77>] full_proxy_write+0xf3/0x180
+    [<000000005a662c16>] vfs_write+0x1c5/0xaf0
+    [<000000007aabf84a>] ksys_write+0xed/0x1c0
+    [<000000005f1d2e47>] do_syscall_64+0x3b/0x90
+    [<000000006001c6ec>] entry_SYSCALL_64_after_hwframe+0x63/0xcd
+
+The issue occurs in the following scenarios:
+
+nsim_dev_trap_fa_cookie_write()
+  kmalloc() fa_cookie
+  nsim_dev->fa_cookie = fa_cookie
+..
+nsim_drv_remove()
+
+The fa_cookie allocked in nsim_dev_trap_fa_cookie_write() is not freed. To
+fix, add kfree(nsim_dev->fa_cookie) to nsim_drv_remove().
+
+Fixes: d3cbb907ae57 ("netdevsim: add ACL trap reporting cookie as a metadata")
+Signed-off-by: Wang Yufen <wangyufen@huawei.com>
+Cc: Jiri Pirko <jiri@mellanox.com>
+Link: https://lore.kernel.org/r/1668504625-14698-1-git-send-email-wangyufen@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ The context change is due to the commit 5e388f3dc38c
+("netdevsim: move vfconfig to nsim_dev") in v5.16
+which is irrelevant to the logic of this patch. ]
+Signed-off-by: Mikhail Dmitrichenko <mdmitrichenko@astralinux.ru>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/netdevsim/dev.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c
+index c8834ea84732bd..a106365ce485e3 100644
+--- a/drivers/net/netdevsim/dev.c
++++ b/drivers/net/netdevsim/dev.c
+@@ -1173,6 +1173,7 @@ void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev)
+ 				  ARRAY_SIZE(nsim_devlink_params));
+ 	devlink_unregister(devlink);
+ 	devlink_resources_unregister(devlink, NULL);
++	kfree(nsim_dev->fa_cookie);
+ 	devlink_free(devlink);
+ }
+ 
+-- 
+2.53.0
+
diff --git a/queue-5.10/series b/queue-5.10/series
index 2153636..aa62c35 100644
--- a/queue-5.10/series
+++ b/queue-5.10/series
@@ -8,3 +8,11 @@
 net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch
 net-sched-act_pedit-free-pedit-keys-on-bail-from-off.patch
 fuse-limit-fuse_notify_retrieve-to-uptodate-folios.patch
+slimbus-qcom-ngd-ctrl-register-callbacks-after-creat.patch
+drm-amd-display-bound-vbios-record-chain-walk-loops.patch
+ip6_vti-set-netns_immutable-on-the-fallback-device.patch
+net-add-skb_header_pointer_careful-helper.patch
+net-sched-cls_u32-use-skb_header_pointer_careful.patch
+drm-amd-display-use-krealloc_array-in-dal_vector_res.patch
+net-9p-fix-refcount-leak-in-p9_read_work-error-handl.patch
+netdevsim-fix-memory-leak-of-nsim_dev-fa_cookie.patch
diff --git a/queue-5.10/slimbus-qcom-ngd-ctrl-register-callbacks-after-creat.patch b/queue-5.10/slimbus-qcom-ngd-ctrl-register-callbacks-after-creat.patch
new file mode 100644
index 0000000..43c162d
--- /dev/null
+++ b/queue-5.10/slimbus-qcom-ngd-ctrl-register-callbacks-after-creat.patch
@@ -0,0 +1,84 @@
+From 47bdb4381f628d4b5b7559efeb63a6c8f33419d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Jun 2026 22:19:09 -0400
+Subject: slimbus: qcom-ngd-ctrl: Register callbacks after creating the ngd
+
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+
+[ Upstream commit 2a9d50e9ea406e0c8735938484adc20515ef1b47 ]
+
+When the remoteproc starts in parallel with the NGD driver being probed,
+or the remoteproc is already up when the PDR lookup is being registered,
+or in the theoretical event that we get an interrupt from the hardware,
+these callbacks will operate on uninitialized data. This result in
+issues to boot the affected boards.
+
+One such example can be seen in the following fault, where
+qcom_slim_ngd_ssr_pdr_notify() schedules work on the NULL ngd_up_work.
+
+[   21.858578] ------------[ cut here ]------------
+[   21.858745] WARNING: kernel/workqueue.c:2338 at __queue_work+0x5e0/0x790, CPU#2: kworker/2:2/116
+...
+[   21.859251] Call trace:
+[   21.859255]  __queue_work+0x5e0/0x790 (P)
+[   21.859265]  queue_work_on+0x6c/0xf0
+[   21.859273]  qcom_slim_ngd_ssr_pdr_notify+0x110/0x150 [slim_qcom_ngd_ctrl]
+[   21.859304]  qcom_slim_ngd_ssr_notify+0x24/0x40 [slim_qcom_ngd_ctrl]
+[   21.859318]  notifier_call_chain+0xa4/0x230
+[   21.859329]  srcu_notifier_call_chain+0x64/0xb8
+[   21.859338]  ssr_notify_start+0x40/0x78 [qcom_common]
+[   21.859355]  rproc_start+0x130/0x230
+[   21.859367]  rproc_boot+0x3d4/0x518
+...
+
+Move the enablement of interrupts, and the registration of SSR and PDR
+until after the NGD device has been registered.
+
+This could be further refined by moving initialization to the control
+driver probe and by removing the platform driver model from the picture.
+
+Fixes: 917809e2280b ("slimbus: ngd: Add qcom SLIMBus NGD driver")
+Cc: stable@vger.kernel.org
+Reviewed-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
+Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
+Link: https://patch.msgid.link/20260530204421.116824-6-srini@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[ dropped absent PDR/SSR registration block and kept 5.10's `res->start`/`dev_err` IRQ idiom, adding only `IRQF_NO_AUTOEN` plus a deferred `enable_irq(res->start)` after `of_qcom_slim_ngd_register()` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/slimbus/qcom-ngd-ctrl.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c
+index 8384f55ccd43e3..0c864bb2d4bdb1 100644
+--- a/drivers/slimbus/qcom-ngd-ctrl.c
++++ b/drivers/slimbus/qcom-ngd-ctrl.c
+@@ -1444,7 +1444,8 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	ret = devm_request_irq(dev, res->start, qcom_slim_ngd_interrupt,
+-			       IRQF_TRIGGER_HIGH, "slim-ngd", ctrl);
++			       IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN,
++			       "slim-ngd", ctrl);
+ 	if (ret) {
+ 		dev_err(&pdev->dev, "request IRQ failed\n");
+ 		return ret;
+@@ -1468,7 +1469,13 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
+ 	init_completion(&ctrl->qmi.qmi_comp);
+ 
+ 	platform_driver_register(&qcom_slim_ngd_driver);
+-	return of_qcom_slim_ngd_register(dev, ctrl);
++	ret = of_qcom_slim_ngd_register(dev, ctrl);
++	if (ret)
++		return ret;
++
++	enable_irq(res->start);
++
++	return 0;
+ }
+ 
+ static int qcom_slim_ngd_ctrl_remove(struct platform_device *pdev)
+-- 
+2.53.0
+
diff --git a/queue-5.15/drm-amd-display-bound-vbios-record-chain-walk-loops.patch b/queue-5.15/drm-amd-display-bound-vbios-record-chain-walk-loops.patch
new file mode 100644
index 0000000..30774ed
--- /dev/null
+++ b/queue-5.15/drm-amd-display-bound-vbios-record-chain-walk-loops.patch
@@ -0,0 +1,232 @@
+From 6621af3956b6ff02855171bbdbc7c46f8fe4e0e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 May 2026 15:24:22 -0400
+Subject: drm/amd/display: Bound VBIOS record-chain walk loops
+
+From: Harry Wentland <harry.wentland@amd.com>
+
+[ Upstream commit ff287df16a1a58aca78b08d1f3ee09fc44da0351 ]
+
+[Why & How]
+All record-chain walk loops in bios_parser.c and bios_parser2.c use
+for(;;) and only terminate on a 0xFF record_type sentinel or zero
+record_size. A malformed VBIOS image missing the terminator record
+causes unbounded iteration at probe time, potentially hundreds of
+thousands of iterations with record_size=1. In the final iterations
+near the BIOS image boundary, struct casts beyond the 2-byte header
+validated by GET_IMAGE can also read out of bounds.
+
+Cap all 14 record-chain walk loops to BIOS_MAX_NUM_RECORD (256)
+iterations. The atombios.h defines up to 22 distinct record types
+and atomfirmware.h has 13. Assuming an average of less than 10
+records per type (which is reasonable since most are connector-
+based) 256 is a generous upper bound.
+
+Fixes: 4562236b3bc0 ("drm/amd/dc: Add dc display driver (v2)")
+Assisted-by: Copilot:claude-opus-4.6 Mythos
+Reviewed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Ray Wu <ray.wu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 95700a3d660287ed657d6892f7be9ffc0e294a93)
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 15 ++++++++++-----
+ .../gpu/drm/amd/display/dc/bios/bios_parser2.c    | 15 ++++++++++-----
+ .../drm/amd/display/dc/bios/bios_parser_helper.h  |  5 +++++
+ 3 files changed, 25 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+index d8982aca8ef680..d2730af8e8030f 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+@@ -223,6 +223,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	ATOM_I2C_RECORD *record;
+ 	struct bios_parser *bp = BP_FROM_DCB(dcb);
++	int i;
+ 
+ 	if (!info)
+ 		return BP_RESULT_BADINPUT;
+@@ -235,7 +236,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -294,11 +295,12 @@ static enum bp_result bios_parser_get_device_tag_record(
+ {
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -870,6 +872,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
+ {
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -879,7 +882,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -1572,6 +1575,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
+ {
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -1581,7 +1585,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 					+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -2665,6 +2669,7 @@ static enum bp_result update_slot_layout_info(
+ 	unsigned int record_offset)
+ {
+ 	unsigned int j;
++	unsigned int n;
+ 	struct bios_parser *bp;
+ 	ATOM_BRACKET_LAYOUT_RECORD *record;
+ 	ATOM_COMMON_RECORD_HEADER *record_header;
+@@ -2674,7 +2679,7 @@ static enum bp_result update_slot_layout_info(
+ 	record = NULL;
+ 	record_header = NULL;
+ 
+-	for (;;) {
++	for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
+ 
+ 		record_header = (ATOM_COMMON_RECORD_HEADER *)
+ 			GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+index e186d4daae55b6..2192b2597edbc3 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+@@ -296,6 +296,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 	struct atom_i2c_record *record;
+ 	struct atom_i2c_record dummy_record = {0};
+ 	struct bios_parser *bp = BP_FROM_DCB(dcb);
++	int i;
+ 
+ 	if (!info)
+ 		return BP_RESULT_BADINPUT;
+@@ -316,7 +317,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 
+ 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -446,6 +447,7 @@ static struct atom_hpd_int_record *get_hpd_record(
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -455,7 +457,7 @@ static struct atom_hpd_int_record *get_hpd_record(
+ 	offset = le16_to_cpu(object->disp_recordoffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -1614,6 +1616,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -1622,7 +1625,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
+ 
+ 	offset = object->encoder_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -1651,6 +1654,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -1659,7 +1663,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
+ 
+ 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -2420,6 +2424,7 @@ static enum bp_result update_slot_layout_info(
+ {
+ 	unsigned int record_offset;
+ 	unsigned int j;
++	unsigned int n;
+ 	struct atom_display_object_path_v2 *object;
+ 	struct atom_bracket_layout_record *record;
+ 	struct atom_common_record_header *record_header;
+@@ -2441,7 +2446,7 @@ static enum bp_result update_slot_layout_info(
+ 		(object->disp_recordoffset) +
+ 		(unsigned int)(bp->object_info_tbl_offset);
+ 
+-	for (;;) {
++	for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
+ 
+ 		record_header = (struct atom_common_record_header *)
+ 			GET_IMAGE(struct atom_common_record_header,
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
+index e1b4a40a353db1..da1e30de3c59a0 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
+@@ -38,4 +38,9 @@ uint32_t bios_get_vga_enabled_displays(struct dc_bios *bios);
+ 
+ #define GET_IMAGE(type, offset) ((type *) bios_get_image(&bp->base, offset, sizeof(type)))
+ 
++/* Upper bound on the number of records in a VBIOS record chain. Prevents
++ * unbounded looping if the VBIOS image is malformed and lacks a terminator.
++ */
++#define BIOS_MAX_NUM_RECORD 256
++
+ #endif
+-- 
+2.53.0
+
diff --git a/queue-5.15/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch b/queue-5.15/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
new file mode 100644
index 0000000..bbeb7cb
--- /dev/null
+++ b/queue-5.15/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
@@ -0,0 +1,63 @@
+From bc7a7e67b3e9a69d3f828200c9ff5623076eec2a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 14:50:15 -0300
+Subject: drm/v3d: Skip CSD when it has zeroed workgroups
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Maíra Canal <mcanal@igalia.com>
+
+[ Upstream commit 7f93fad5ea0affc9e1505dd0f7596c0fdb496213 ]
+
+A compute shader dispatch encodes its workgroup counts in the CFG0..CFG2
+registers. Kicking off a dispatch with a zero count in any of the three
+dimensions is invalid. First, the hardware will process 0 as 65536,
+while the user-space driver exposes a maximum of 65535. Over that, a
+submission with a zeroed workgroup dimension should be a no-op.
+
+These zeroed counts can reach the dispatch path through an indirect CSD
+job, whose workgroup counts are only known once the indirect buffer is
+read and may legitimately be zero, but such scenario should only result in
+a no-op.
+
+Overwrite the indirect CSD job workgroup counts with the indirect BO
+ones, even if they are zeroed, and don't submit the job to the hardware
+when any of the workgroup counts is zero, so the job completes immediately
+instead of running the shader.
+
+Cc: stable@vger.kernel.org
+Fixes: d223f98f0209 ("drm/v3d: Add support for compute shader dispatch.")
+Suggested-by: Jose Maria Casanova Crespo <jmcasanova@igalia.com>
+Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
+Link: https://patch.msgid.link/20260602-v3d-fix-indirect-csd-v4-2-654309e32bc0@igalia.com
+Signed-off-by: Maíra Canal <mcanal@igalia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/v3d/v3d_sched.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
+index db98855741ee85..46c52d89cb2498 100644
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -257,6 +257,16 @@ v3d_csd_job_run(struct drm_sched_job *sched_job)
+ 		return NULL;
+ 	}
+ 
++	/* The HW interprets a workgroup size of 0 as 65536; however, the
++	 * user-space driver exposes a maximum of 65535. Therefore, a 0 in
++	 * any dimension means that we have no workgroups and the compute
++	 * shader should not be dispatched.
++	 */
++	if (!V3D_GET_FIELD(job->args.cfg[0], V3D_CSD_QUEUED_CFG0_NUM_WGS_X) ||
++	    !V3D_GET_FIELD(job->args.cfg[1], V3D_CSD_QUEUED_CFG1_NUM_WGS_Y) ||
++	    !V3D_GET_FIELD(job->args.cfg[2], V3D_CSD_QUEUED_CFG2_NUM_WGS_Z))
++		return NULL;
++
+ 	v3d->queue[V3D_CSD].active_job = &job->base;
+ 
+ 	v3d_invalidate_caches(v3d);
+-- 
+2.53.0
+
diff --git a/queue-5.15/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch b/queue-5.15/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
new file mode 100644
index 0000000..a872bbf
--- /dev/null
+++ b/queue-5.15/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
@@ -0,0 +1,237 @@
+From ebf76d23b3b78375e30d09ba43944d0c67f4ee79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Aug 2025 11:18:59 -0300
+Subject: drm/v3d: Store the active job inside the queue's state
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Maíra Canal <mcanal@igalia.com>
+
+[ Upstream commit 0d3768826d38c0ac740f8b45cd13346630535f2b ]
+
+Instead of storing the queue's active job in four different variables,
+store the active job inside the queue's state. This way, it's possible
+to access all active jobs using an index based in `enum v3d_queue`.
+
+Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
+Reviewed-by: Melissa Wen <mwen@igalia.com>
+Link: https://lore.kernel.org/r/20250826-v3d-queue-lock-v3-2-979efc43e490@igalia.com
+Signed-off-by: Maíra Canal <mcanal@igalia.com>
+Stable-dep-of: 7f93fad5ea0a ("drm/v3d: Skip CSD when it has zeroed workgroups")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/v3d/v3d_drv.h   |  8 +++-----
+ drivers/gpu/drm/v3d/v3d_gem.c   |  5 +++--
+ drivers/gpu/drm/v3d/v3d_irq.c   | 24 ++++++++++++++----------
+ drivers/gpu/drm/v3d/v3d_sched.c | 26 ++++++++++++++++++--------
+ 4 files changed, 38 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
+index 0d551b1d9b05d4..14002d2b4add36 100644
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -35,6 +35,9 @@ struct v3d_queue_state {
+ 
+ 	u64 fence_context;
+ 	u64 emit_seqno;
++
++	/* Currently active job for this queue */
++	struct v3d_job *active_job;
+ };
+ 
+ /* Performance monitor object. The perform lifetime is controlled by userspace
+@@ -119,11 +122,6 @@ struct v3d_dev {
+ 
+ 	struct work_struct overflow_mem_work;
+ 
+-	struct v3d_bin_job *bin_job;
+-	struct v3d_render_job *render_job;
+-	struct v3d_tfu_job *tfu_job;
+-	struct v3d_csd_job *csd_job;
+-
+ 	struct v3d_queue_state queue[V3D_MAX_QUEUES];
+ 
+ 	/* Spinlock used to synchronize the overflow memory
+diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
+index ecd03ad9699a08..3911550f72c22f 100644
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -950,14 +950,15 @@ void
+ v3d_gem_destroy(struct drm_device *dev)
+ {
+ 	struct v3d_dev *v3d = to_v3d_dev(dev);
++	enum v3d_queue q;
+ 
+ 	v3d_sched_fini(v3d);
+ 
+ 	/* Waiting for jobs to finish would need to be done before
+ 	 * unregistering V3D.
+ 	 */
+-	WARN_ON(v3d->bin_job);
+-	WARN_ON(v3d->render_job);
++	for (q = 0; q < V3D_MAX_QUEUES; q++)
++		WARN_ON(v3d->queue[q].active_job);
+ 
+ 	drm_mm_takedown(&v3d->mm);
+ 
+diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c
+index 9aba78e6d7a5a6..3d5505159ff5e8 100644
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -40,6 +40,8 @@ v3d_overflow_mem_work(struct work_struct *work)
+ 		container_of(work, struct v3d_dev, overflow_mem_work);
+ 	struct drm_device *dev = &v3d->drm;
+ 	struct v3d_bo *bo = v3d_bo_create(dev, NULL /* XXX: GMP */, 256 * 1024);
++	struct v3d_queue_state *queue = &v3d->queue[V3D_BIN];
++	struct v3d_bin_job *bin_job;
+ 	struct drm_gem_object *obj;
+ 	unsigned long irqflags;
+ 
+@@ -59,13 +61,15 @@ v3d_overflow_mem_work(struct work_struct *work)
+ 	 * some binner pool anyway.
+ 	 */
+ 	spin_lock_irqsave(&v3d->job_lock, irqflags);
+-	if (!v3d->bin_job) {
++	bin_job = (struct v3d_bin_job *)queue->active_job;
++
++	if (!bin_job) {
+ 		spin_unlock_irqrestore(&v3d->job_lock, irqflags);
+ 		goto out;
+ 	}
+ 
+ 	drm_gem_object_get(obj);
+-	list_add_tail(&bo->unref_head, &v3d->bin_job->render->unref_list);
++	list_add_tail(&bo->unref_head, &bin_job->render->unref_list);
+ 	spin_unlock_irqrestore(&v3d->job_lock, irqflags);
+ 
+ 	V3D_CORE_WRITE(0, V3D_PTB_BPOA, bo->node.start << PAGE_SHIFT);
+@@ -99,11 +103,11 @@ v3d_irq(int irq, void *arg)
+ 
+ 	if (intsts & V3D_INT_FLDONE) {
+ 		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->bin_job->base.irq_fence);
++			to_v3d_fence(v3d->queue[V3D_BIN].active_job->irq_fence);
+ 
+ 		trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
+ 
+-		v3d->bin_job = NULL;
++		v3d->queue[V3D_BIN].active_job = NULL;
+ 		dma_fence_signal(&fence->base);
+ 
+ 		status = IRQ_HANDLED;
+@@ -111,11 +115,11 @@ v3d_irq(int irq, void *arg)
+ 
+ 	if (intsts & V3D_INT_FRDONE) {
+ 		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->render_job->base.irq_fence);
++			to_v3d_fence(v3d->queue[V3D_RENDER].active_job->irq_fence);
+ 
+ 		trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
+ 
+-		v3d->render_job = NULL;
++		v3d->queue[V3D_RENDER].active_job = NULL;
+ 		dma_fence_signal(&fence->base);
+ 
+ 		status = IRQ_HANDLED;
+@@ -123,11 +127,11 @@ v3d_irq(int irq, void *arg)
+ 
+ 	if (intsts & V3D_INT_CSDDONE) {
+ 		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->csd_job->base.irq_fence);
++			to_v3d_fence(v3d->queue[V3D_CSD].active_job->irq_fence);
+ 
+ 		trace_v3d_csd_irq(&v3d->drm, fence->seqno);
+ 
+-		v3d->csd_job = NULL;
++		v3d->queue[V3D_CSD].active_job = NULL;
+ 		dma_fence_signal(&fence->base);
+ 
+ 		status = IRQ_HANDLED;
+@@ -162,11 +166,11 @@ v3d_hub_irq(int irq, void *arg)
+ 
+ 	if (intsts & V3D_HUB_INT_TFUC) {
+ 		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->tfu_job->base.irq_fence);
++			to_v3d_fence(v3d->queue[V3D_TFU].active_job->irq_fence);
+ 
+ 		trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
+ 
+-		v3d->tfu_job = NULL;
++		v3d->queue[V3D_TFU].active_job = NULL;
+ 		dma_fence_signal(&fence->base);
+ 
+ 		status = IRQ_HANDLED;
+diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
+index c357229256b73a..db98855741ee85 100644
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -103,14 +103,18 @@ static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
+ 	struct dma_fence *fence;
+ 	unsigned long irqflags;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		spin_lock_irqsave(&v3d->job_lock, irqflags);
++		v3d->queue[V3D_BIN].active_job = NULL;
++		spin_unlock_irqrestore(&v3d->job_lock, irqflags);
+ 		return NULL;
++	}
+ 
+ 	/* Lock required around bin_job update vs
+ 	 * v3d_overflow_mem_work().
+ 	 */
+ 	spin_lock_irqsave(&v3d->job_lock, irqflags);
+-	v3d->bin_job = job;
++	v3d->queue[V3D_BIN].active_job = &job->base;
+ 	/* Clear out the overflow allocation, so we don't
+ 	 * reuse the overflow attached to a previous job.
+ 	 */
+@@ -157,10 +161,12 @@ static struct dma_fence *v3d_render_job_run(struct drm_sched_job *sched_job)
+ 	struct drm_device *dev = &v3d->drm;
+ 	struct dma_fence *fence;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		v3d->queue[V3D_RENDER].active_job = NULL;
+ 		return NULL;
++	}
+ 
+-	v3d->render_job = job;
++	v3d->queue[V3D_RENDER].active_job = &job->base;
+ 
+ 	/* Can we avoid this flush?  We need to be careful of
+ 	 * scheduling, though -- imagine job0 rendering to texture and
+@@ -202,10 +208,12 @@ v3d_tfu_job_run(struct drm_sched_job *sched_job)
+ 	struct drm_device *dev = &v3d->drm;
+ 	struct dma_fence *fence;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		v3d->queue[V3D_TFU].active_job = NULL;
+ 		return NULL;
++	}
+ 
+-	v3d->tfu_job = job;
++	v3d->queue[V3D_TFU].active_job = &job->base;
+ 
+ 	fence = v3d_fence_create(v3d, V3D_TFU);
+ 	if (IS_ERR(fence))
+@@ -244,10 +252,12 @@ v3d_csd_job_run(struct drm_sched_job *sched_job)
+ 	struct dma_fence *fence;
+ 	int i;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		v3d->queue[V3D_CSD].active_job = NULL;
+ 		return NULL;
++	}
+ 
+-	v3d->csd_job = job;
++	v3d->queue[V3D_CSD].active_job = &job->base;
+ 
+ 	v3d_invalidate_caches(v3d);
+ 
+-- 
+2.53.0
+
diff --git a/queue-5.15/ip6_vti-set-netns_immutable-on-the-fallback-device.patch b/queue-5.15/ip6_vti-set-netns_immutable-on-the-fallback-device.patch
new file mode 100644
index 0000000..a1dc351
--- /dev/null
+++ b/queue-5.15/ip6_vti-set-netns_immutable-on-the-fallback-device.patch
@@ -0,0 +1,49 @@
+From 4a3a34db67a0944cc5c0af57fa06628f754fbbd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Jun 2026 15:59:18 +0000
+Subject: ip6_vti: set netns_immutable on the fallback device.
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d289d5307762d1838aaece22c6b6fcad9e8865f9 ]
+
+john1988 and Noam Rathaus reported that vti6_init_net() does not set the
+netns_immutable flag on the per-netns fallback tunnel device (ip6_vti0).
+
+Other similar tunnel drivers (like ip6_tunnel, sit, ip6_gre, and ip_tunnel)
+correctly set this flag during their fallback device initialization to
+prevent them from being moved to another network namespace.
+
+Fixes: 61220ab34948 ("vti6: Enable namespace changing")
+Reported-by: Noam Rathaus <noamr@ssd-disclosure.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Steffen Klassert <steffen.klassert@secunet.com>
+Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260608155918.787644-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[Salvatore Bonaccorso: Backport for version without 0c493da86374 ("net:
+rename netns_local to netns_immutable") in v6.15-rc1 and without
+05c1280a2bcf ("netdev_features: convert NETIF_F_NETNS_LOCAL to
+dev->netns_local") in v6.12-rc1 and use NETIF_F_NETNS_LOCAL device
+feature.]
+Signed-off-by: Salvatore Bonaccorso <carnil@debian.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/ip6_vti.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
+index 077aae4b1bb332..e5f3293d190d39 100644
+--- a/net/ipv6/ip6_vti.c
++++ b/net/ipv6/ip6_vti.c
+@@ -1167,6 +1167,7 @@ static int __net_init vti6_init_net(struct net *net)
+ 		goto err_alloc_dev;
+ 	dev_net_set(ip6n->fb_tnl_dev, net);
+ 	ip6n->fb_tnl_dev->rtnl_link_ops = &vti6_link_ops;
++	ip6n->fb_tnl_dev->features |= NETIF_F_NETNS_LOCAL;
+ 
+ 	err = vti6_fb_tnl_dev_init(ip6n->fb_tnl_dev);
+ 	if (err < 0)
+-- 
+2.53.0
+
diff --git a/queue-5.15/series b/queue-5.15/series
index b9e0218..eb8c434 100644
--- a/queue-5.15/series
+++ b/queue-5.15/series
@@ -3,3 +3,7 @@
 net-sched-act_pedit-rate-limit-datapath-messages.patch
 net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch
 net-sched-act_pedit-free-pedit-keys-on-bail-from-off.patch
+drm-amd-display-bound-vbios-record-chain-walk-loops.patch
+ip6_vti-set-netns_immutable-on-the-fallback-device.patch
+drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
+drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
diff --git a/queue-6.1/drm-amd-display-bound-vbios-record-chain-walk-loops.patch b/queue-6.1/drm-amd-display-bound-vbios-record-chain-walk-loops.patch
new file mode 100644
index 0000000..7795c1c
--- /dev/null
+++ b/queue-6.1/drm-amd-display-bound-vbios-record-chain-walk-loops.patch
@@ -0,0 +1,300 @@
+From f10326a60adc6b1ce0d51994bbd18deb31fe02a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 May 2026 15:24:22 -0400
+Subject: drm/amd/display: Bound VBIOS record-chain walk loops
+
+From: Harry Wentland <harry.wentland@amd.com>
+
+[ Upstream commit ff287df16a1a58aca78b08d1f3ee09fc44da0351 ]
+
+[Why & How]
+All record-chain walk loops in bios_parser.c and bios_parser2.c use
+for(;;) and only terminate on a 0xFF record_type sentinel or zero
+record_size. A malformed VBIOS image missing the terminator record
+causes unbounded iteration at probe time, potentially hundreds of
+thousands of iterations with record_size=1. In the final iterations
+near the BIOS image boundary, struct casts beyond the 2-byte header
+validated by GET_IMAGE can also read out of bounds.
+
+Cap all 14 record-chain walk loops to BIOS_MAX_NUM_RECORD (256)
+iterations. The atombios.h defines up to 22 distinct record types
+and atomfirmware.h has 13. Assuming an average of less than 10
+records per type (which is reasonable since most are connector-
+based) 256 is a generous upper bound.
+
+Fixes: 4562236b3bc0 ("drm/amd/dc: Add dc display driver (v2)")
+Assisted-by: Copilot:claude-opus-4.6 Mythos
+Reviewed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Ray Wu <ray.wu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 95700a3d660287ed657d6892f7be9ffc0e294a93)
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/bios/bios_parser.c | 15 +++++++----
+ .../drm/amd/display/dc/bios/bios_parser2.c    | 27 ++++++++++++-------
+ .../amd/display/dc/bios/bios_parser_helper.h  |  5 ++++
+ 3 files changed, 33 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+index d8982aca8ef680..d2730af8e8030f 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+@@ -223,6 +223,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	ATOM_I2C_RECORD *record;
+ 	struct bios_parser *bp = BP_FROM_DCB(dcb);
++	int i;
+ 
+ 	if (!info)
+ 		return BP_RESULT_BADINPUT;
+@@ -235,7 +236,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -294,11 +295,12 @@ static enum bp_result bios_parser_get_device_tag_record(
+ {
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -870,6 +872,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
+ {
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -879,7 +882,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -1572,6 +1575,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
+ {
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -1581,7 +1585,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 					+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -2665,6 +2669,7 @@ static enum bp_result update_slot_layout_info(
+ 	unsigned int record_offset)
+ {
+ 	unsigned int j;
++	unsigned int n;
+ 	struct bios_parser *bp;
+ 	ATOM_BRACKET_LAYOUT_RECORD *record;
+ 	ATOM_COMMON_RECORD_HEADER *record_header;
+@@ -2674,7 +2679,7 @@ static enum bp_result update_slot_layout_info(
+ 	record = NULL;
+ 	record_header = NULL;
+ 
+-	for (;;) {
++	for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
+ 
+ 		record_header = (ATOM_COMMON_RECORD_HEADER *)
+ 			GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+index af8c6682e6bee1..5d6428b2e4f5c8 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+@@ -393,6 +393,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 	struct atom_i2c_record *record;
+ 	struct atom_i2c_record dummy_record = {0};
+ 	struct bios_parser *bp = BP_FROM_DCB(dcb);
++	int i;
+ 
+ 	if (!info)
+ 		return BP_RESULT_BADINPUT;
+@@ -426,7 +427,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 		break;
+ 	}
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -532,6 +533,7 @@ static struct atom_hpd_int_record *get_hpd_record_for_path_v3(
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -540,7 +542,7 @@ static struct atom_hpd_int_record *get_hpd_record_for_path_v3(
+ 
+ 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -610,6 +612,7 @@ static struct atom_hpd_int_record *get_hpd_record(
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -619,7 +622,7 @@ static struct atom_hpd_int_record *get_hpd_record(
+ 	offset = le16_to_cpu(object->disp_recordoffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -2127,6 +2130,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -2135,7 +2139,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
+ 
+ 	offset = object->encoder_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -2164,6 +2168,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -2172,7 +2177,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
+ 
+ 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -2201,6 +2206,7 @@ static struct atom_connector_caps_record *get_connector_caps_record(
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -2209,7 +2215,7 @@ static struct atom_connector_caps_record *get_connector_caps_record(
+ 
+ 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -2290,6 +2296,7 @@ static struct atom_connector_speed_record *get_connector_speed_cap_record(
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -2298,7 +2305,7 @@ static struct atom_connector_speed_record *get_connector_speed_cap_record(
+ 
+ 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -3162,6 +3169,7 @@ static enum bp_result update_slot_layout_info(
+ {
+ 	unsigned int record_offset;
+ 	unsigned int j;
++	unsigned int n;
+ 	struct atom_display_object_path_v2 *object;
+ 	struct atom_bracket_layout_record *record;
+ 	struct atom_common_record_header *record_header;
+@@ -3183,7 +3191,7 @@ static enum bp_result update_slot_layout_info(
+ 		(object->disp_recordoffset) +
+ 		(unsigned int)(bp->object_info_tbl_offset);
+ 
+-	for (;;) {
++	for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
+ 
+ 		record_header = (struct atom_common_record_header *)
+ 			GET_IMAGE(struct atom_common_record_header,
+@@ -3277,6 +3285,7 @@ static enum bp_result update_slot_layout_info_v2(
+ 	struct slot_layout_info *slot_layout_info)
+ {
+ 	unsigned int record_offset;
++	unsigned int n;
+ 	struct atom_display_object_path_v3 *object;
+ 	struct atom_bracket_layout_record_v2 *record;
+ 	struct atom_common_record_header *record_header;
+@@ -3299,7 +3308,7 @@ static enum bp_result update_slot_layout_info_v2(
+ 		(object->disp_recordoffset) +
+ 		(unsigned int)(bp->object_info_tbl_offset);
+ 
+-	for (;;) {
++	for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
+ 
+ 		record_header = (struct atom_common_record_header *)
+ 			GET_IMAGE(struct atom_common_record_header,
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
+index e1b4a40a353db1..da1e30de3c59a0 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
+@@ -38,4 +38,9 @@ uint32_t bios_get_vga_enabled_displays(struct dc_bios *bios);
+ 
+ #define GET_IMAGE(type, offset) ((type *) bios_get_image(&bp->base, offset, sizeof(type)))
+ 
++/* Upper bound on the number of records in a VBIOS record chain. Prevents
++ * unbounded looping if the VBIOS image is malformed and lacks a terminator.
++ */
++#define BIOS_MAX_NUM_RECORD 256
++
+ #endif
+-- 
+2.53.0
+
diff --git a/queue-6.1/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch b/queue-6.1/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
new file mode 100644
index 0000000..7c3d484
--- /dev/null
+++ b/queue-6.1/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
@@ -0,0 +1,63 @@
+From afce05038bc0bfe4fc1bd590e8381d4e04e8739e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 14:50:15 -0300
+Subject: drm/v3d: Skip CSD when it has zeroed workgroups
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Maíra Canal <mcanal@igalia.com>
+
+[ Upstream commit 7f93fad5ea0affc9e1505dd0f7596c0fdb496213 ]
+
+A compute shader dispatch encodes its workgroup counts in the CFG0..CFG2
+registers. Kicking off a dispatch with a zero count in any of the three
+dimensions is invalid. First, the hardware will process 0 as 65536,
+while the user-space driver exposes a maximum of 65535. Over that, a
+submission with a zeroed workgroup dimension should be a no-op.
+
+These zeroed counts can reach the dispatch path through an indirect CSD
+job, whose workgroup counts are only known once the indirect buffer is
+read and may legitimately be zero, but such scenario should only result in
+a no-op.
+
+Overwrite the indirect CSD job workgroup counts with the indirect BO
+ones, even if they are zeroed, and don't submit the job to the hardware
+when any of the workgroup counts is zero, so the job completes immediately
+instead of running the shader.
+
+Cc: stable@vger.kernel.org
+Fixes: d223f98f0209 ("drm/v3d: Add support for compute shader dispatch.")
+Suggested-by: Jose Maria Casanova Crespo <jmcasanova@igalia.com>
+Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
+Link: https://patch.msgid.link/20260602-v3d-fix-indirect-csd-v4-2-654309e32bc0@igalia.com
+Signed-off-by: Maíra Canal <mcanal@igalia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/v3d/v3d_sched.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
+index ff91cdb75bb912..ab872bc818004a 100644
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -234,6 +234,16 @@ v3d_csd_job_run(struct drm_sched_job *sched_job)
+ 		return NULL;
+ 	}
+ 
++	/* The HW interprets a workgroup size of 0 as 65536; however, the
++	 * user-space driver exposes a maximum of 65535. Therefore, a 0 in
++	 * any dimension means that we have no workgroups and the compute
++	 * shader should not be dispatched.
++	 */
++	if (!V3D_GET_FIELD(job->args.cfg[0], V3D_CSD_QUEUED_CFG0_NUM_WGS_X) ||
++	    !V3D_GET_FIELD(job->args.cfg[1], V3D_CSD_QUEUED_CFG1_NUM_WGS_Y) ||
++	    !V3D_GET_FIELD(job->args.cfg[2], V3D_CSD_QUEUED_CFG2_NUM_WGS_Z))
++		return NULL;
++
+ 	v3d->queue[V3D_CSD].active_job = &job->base;
+ 
+ 	v3d_invalidate_caches(v3d);
+-- 
+2.53.0
+
diff --git a/queue-6.1/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch b/queue-6.1/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
new file mode 100644
index 0000000..daaec4e
--- /dev/null
+++ b/queue-6.1/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
@@ -0,0 +1,237 @@
+From c30a79f3770963840a5b11b23aa8b35fccaeff88 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Aug 2025 11:18:59 -0300
+Subject: drm/v3d: Store the active job inside the queue's state
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Maíra Canal <mcanal@igalia.com>
+
+[ Upstream commit 0d3768826d38c0ac740f8b45cd13346630535f2b ]
+
+Instead of storing the queue's active job in four different variables,
+store the active job inside the queue's state. This way, it's possible
+to access all active jobs using an index based in `enum v3d_queue`.
+
+Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
+Reviewed-by: Melissa Wen <mwen@igalia.com>
+Link: https://lore.kernel.org/r/20250826-v3d-queue-lock-v3-2-979efc43e490@igalia.com
+Signed-off-by: Maíra Canal <mcanal@igalia.com>
+Stable-dep-of: 7f93fad5ea0a ("drm/v3d: Skip CSD when it has zeroed workgroups")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/v3d/v3d_drv.h   |  8 +++-----
+ drivers/gpu/drm/v3d/v3d_gem.c   |  5 +++--
+ drivers/gpu/drm/v3d/v3d_irq.c   | 24 ++++++++++++++----------
+ drivers/gpu/drm/v3d/v3d_sched.c | 26 ++++++++++++++++++--------
+ 4 files changed, 38 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
+index a366ea208787df..c1e389635de816 100644
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -26,6 +26,9 @@ struct v3d_queue_state {
+ 
+ 	u64 fence_context;
+ 	u64 emit_seqno;
++
++	/* Currently active job for this queue */
++	struct v3d_job *active_job;
+ };
+ 
+ /* Performance monitor object. The perform lifetime is controlled by userspace
+@@ -110,11 +113,6 @@ struct v3d_dev {
+ 
+ 	struct work_struct overflow_mem_work;
+ 
+-	struct v3d_bin_job *bin_job;
+-	struct v3d_render_job *render_job;
+-	struct v3d_tfu_job *tfu_job;
+-	struct v3d_csd_job *csd_job;
+-
+ 	struct v3d_queue_state queue[V3D_MAX_QUEUES];
+ 
+ 	/* Spinlock used to synchronize the overflow memory
+diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
+index 97755a6b556335..71019a57958ba3 100644
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -1120,14 +1120,15 @@ void
+ v3d_gem_destroy(struct drm_device *dev)
+ {
+ 	struct v3d_dev *v3d = to_v3d_dev(dev);
++	enum v3d_queue q;
+ 
+ 	v3d_sched_fini(v3d);
+ 
+ 	/* Waiting for jobs to finish would need to be done before
+ 	 * unregistering V3D.
+ 	 */
+-	WARN_ON(v3d->bin_job);
+-	WARN_ON(v3d->render_job);
++	for (q = 0; q < V3D_MAX_QUEUES; q++)
++		WARN_ON(v3d->queue[q].active_job);
+ 
+ 	drm_mm_takedown(&v3d->mm);
+ 
+diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c
+index 641315dbee8b29..1717504742a665 100644
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -40,6 +40,8 @@ v3d_overflow_mem_work(struct work_struct *work)
+ 		container_of(work, struct v3d_dev, overflow_mem_work);
+ 	struct drm_device *dev = &v3d->drm;
+ 	struct v3d_bo *bo = v3d_bo_create(dev, NULL /* XXX: GMP */, 256 * 1024);
++	struct v3d_queue_state *queue = &v3d->queue[V3D_BIN];
++	struct v3d_bin_job *bin_job;
+ 	struct drm_gem_object *obj;
+ 	unsigned long irqflags;
+ 
+@@ -59,13 +61,15 @@ v3d_overflow_mem_work(struct work_struct *work)
+ 	 * some binner pool anyway.
+ 	 */
+ 	spin_lock_irqsave(&v3d->job_lock, irqflags);
+-	if (!v3d->bin_job) {
++	bin_job = (struct v3d_bin_job *)queue->active_job;
++
++	if (!bin_job) {
+ 		spin_unlock_irqrestore(&v3d->job_lock, irqflags);
+ 		goto out;
+ 	}
+ 
+ 	drm_gem_object_get(obj);
+-	list_add_tail(&bo->unref_head, &v3d->bin_job->render->unref_list);
++	list_add_tail(&bo->unref_head, &bin_job->render->unref_list);
+ 	spin_unlock_irqrestore(&v3d->job_lock, irqflags);
+ 
+ 	V3D_CORE_WRITE(0, V3D_PTB_BPOA, bo->node.start << PAGE_SHIFT);
+@@ -99,11 +103,11 @@ v3d_irq(int irq, void *arg)
+ 
+ 	if (intsts & V3D_INT_FLDONE) {
+ 		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->bin_job->base.irq_fence);
++			to_v3d_fence(v3d->queue[V3D_BIN].active_job->irq_fence);
+ 
+ 		trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
+ 
+-		v3d->bin_job = NULL;
++		v3d->queue[V3D_BIN].active_job = NULL;
+ 		dma_fence_signal(&fence->base);
+ 
+ 		status = IRQ_HANDLED;
+@@ -111,11 +115,11 @@ v3d_irq(int irq, void *arg)
+ 
+ 	if (intsts & V3D_INT_FRDONE) {
+ 		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->render_job->base.irq_fence);
++			to_v3d_fence(v3d->queue[V3D_RENDER].active_job->irq_fence);
+ 
+ 		trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
+ 
+-		v3d->render_job = NULL;
++		v3d->queue[V3D_RENDER].active_job = NULL;
+ 		dma_fence_signal(&fence->base);
+ 
+ 		status = IRQ_HANDLED;
+@@ -123,11 +127,11 @@ v3d_irq(int irq, void *arg)
+ 
+ 	if (intsts & V3D_INT_CSDDONE) {
+ 		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->csd_job->base.irq_fence);
++			to_v3d_fence(v3d->queue[V3D_CSD].active_job->irq_fence);
+ 
+ 		trace_v3d_csd_irq(&v3d->drm, fence->seqno);
+ 
+-		v3d->csd_job = NULL;
++		v3d->queue[V3D_CSD].active_job = NULL;
+ 		dma_fence_signal(&fence->base);
+ 
+ 		status = IRQ_HANDLED;
+@@ -162,11 +166,11 @@ v3d_hub_irq(int irq, void *arg)
+ 
+ 	if (intsts & V3D_HUB_INT_TFUC) {
+ 		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->tfu_job->base.irq_fence);
++			to_v3d_fence(v3d->queue[V3D_TFU].active_job->irq_fence);
+ 
+ 		trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
+ 
+-		v3d->tfu_job = NULL;
++		v3d->queue[V3D_TFU].active_job = NULL;
+ 		dma_fence_signal(&fence->base);
+ 
+ 		status = IRQ_HANDLED;
+diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
+index 41493cf3d03b81..ff91cdb75bb912 100644
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -80,14 +80,18 @@ static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
+ 	struct dma_fence *fence;
+ 	unsigned long irqflags;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		spin_lock_irqsave(&v3d->job_lock, irqflags);
++		v3d->queue[V3D_BIN].active_job = NULL;
++		spin_unlock_irqrestore(&v3d->job_lock, irqflags);
+ 		return NULL;
++	}
+ 
+ 	/* Lock required around bin_job update vs
+ 	 * v3d_overflow_mem_work().
+ 	 */
+ 	spin_lock_irqsave(&v3d->job_lock, irqflags);
+-	v3d->bin_job = job;
++	v3d->queue[V3D_BIN].active_job = &job->base;
+ 	/* Clear out the overflow allocation, so we don't
+ 	 * reuse the overflow attached to a previous job.
+ 	 */
+@@ -134,10 +138,12 @@ static struct dma_fence *v3d_render_job_run(struct drm_sched_job *sched_job)
+ 	struct drm_device *dev = &v3d->drm;
+ 	struct dma_fence *fence;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		v3d->queue[V3D_RENDER].active_job = NULL;
+ 		return NULL;
++	}
+ 
+-	v3d->render_job = job;
++	v3d->queue[V3D_RENDER].active_job = &job->base;
+ 
+ 	/* Can we avoid this flush?  We need to be careful of
+ 	 * scheduling, though -- imagine job0 rendering to texture and
+@@ -179,10 +185,12 @@ v3d_tfu_job_run(struct drm_sched_job *sched_job)
+ 	struct drm_device *dev = &v3d->drm;
+ 	struct dma_fence *fence;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		v3d->queue[V3D_TFU].active_job = NULL;
+ 		return NULL;
++	}
+ 
+-	v3d->tfu_job = job;
++	v3d->queue[V3D_TFU].active_job = &job->base;
+ 
+ 	fence = v3d_fence_create(v3d, V3D_TFU);
+ 	if (IS_ERR(fence))
+@@ -221,10 +229,12 @@ v3d_csd_job_run(struct drm_sched_job *sched_job)
+ 	struct dma_fence *fence;
+ 	int i;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		v3d->queue[V3D_CSD].active_job = NULL;
+ 		return NULL;
++	}
+ 
+-	v3d->csd_job = job;
++	v3d->queue[V3D_CSD].active_job = &job->base;
+ 
+ 	v3d_invalidate_caches(v3d);
+ 
+-- 
+2.53.0
+
diff --git a/queue-6.1/ip6_vti-set-netns_immutable-on-the-fallback-device.patch b/queue-6.1/ip6_vti-set-netns_immutable-on-the-fallback-device.patch
new file mode 100644
index 0000000..434444d
--- /dev/null
+++ b/queue-6.1/ip6_vti-set-netns_immutable-on-the-fallback-device.patch
@@ -0,0 +1,49 @@
+From 3fd8f6d9ae3d423f2d5f06851a208b859300b0eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Jun 2026 15:59:18 +0000
+Subject: ip6_vti: set netns_immutable on the fallback device.
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d289d5307762d1838aaece22c6b6fcad9e8865f9 ]
+
+john1988 and Noam Rathaus reported that vti6_init_net() does not set the
+netns_immutable flag on the per-netns fallback tunnel device (ip6_vti0).
+
+Other similar tunnel drivers (like ip6_tunnel, sit, ip6_gre, and ip_tunnel)
+correctly set this flag during their fallback device initialization to
+prevent them from being moved to another network namespace.
+
+Fixes: 61220ab34948 ("vti6: Enable namespace changing")
+Reported-by: Noam Rathaus <noamr@ssd-disclosure.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Steffen Klassert <steffen.klassert@secunet.com>
+Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260608155918.787644-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[Salvatore Bonaccorso: Backport for version without 0c493da86374 ("net:
+rename netns_local to netns_immutable") in v6.15-rc1 and without
+05c1280a2bcf ("netdev_features: convert NETIF_F_NETNS_LOCAL to
+dev->netns_local") in v6.12-rc1 and use NETIF_F_NETNS_LOCAL device
+feature.]
+Signed-off-by: Salvatore Bonaccorso <carnil@debian.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/ip6_vti.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
+index 8808067df5168c..aa37ce710cf49a 100644
+--- a/net/ipv6/ip6_vti.c
++++ b/net/ipv6/ip6_vti.c
+@@ -1168,6 +1168,7 @@ static int __net_init vti6_init_net(struct net *net)
+ 		goto err_alloc_dev;
+ 	dev_net_set(ip6n->fb_tnl_dev, net);
+ 	ip6n->fb_tnl_dev->rtnl_link_ops = &vti6_link_ops;
++	ip6n->fb_tnl_dev->features |= NETIF_F_NETNS_LOCAL;
+ 
+ 	err = vti6_fb_tnl_dev_init(ip6n->fb_tnl_dev);
+ 	if (err < 0)
+-- 
+2.53.0
+
diff --git a/queue-6.1/netfilter-nf_tables-always-increment-set-element-cou.patch b/queue-6.1/netfilter-nf_tables-always-increment-set-element-cou.patch
new file mode 100644
index 0000000..9227aa7
--- /dev/null
+++ b/queue-6.1/netfilter-nf_tables-always-increment-set-element-cou.patch
@@ -0,0 +1,52 @@
+From f78323c471860f7b9b7445f03f1825b0321199cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 02:28:48 -0700
+Subject: netfilter: nf_tables: always increment set element count
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit d4b7f29eb85c93893bc27388b37709efbc3c9a0e ]
+
+At this time, set->nelems counter only increments when the set has
+a maximum size.
+
+All set elements decrement the counter unconditionally, this is
+confusing.
+
+Increment the counter unconditionally to make this symmetrical.
+This would also allow changing the set maximum size after set creation
+in a later patch.
+
+Signed-off-by: Florian Westphal <fw@strlen.de>
+[ Shivani: Modified to apply on 6.1.y ]
+Signed-off-by: Shivani Agarwal <shivani.agarwal@broadcom.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 201e2cc0453992..b6b7b0b3539dc9 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -6699,10 +6699,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
+ 		goto err_element_clash;
+ 	}
+ 
+-	if (!(flags & NFT_SET_ELEM_CATCHALL) && set->size &&
+-	    !atomic_add_unless(&set->nelems, 1, set->size + set->ndeact)) {
+-		err = -ENFILE;
+-		goto err_set_full;
++	if (!(flags & NFT_SET_ELEM_CATCHALL)) {
++		unsigned int max = set->size ? set->size + set->ndeact : UINT_MAX;
++
++		if (!atomic_add_unless(&set->nelems, 1, max)) {
++			err = -ENFILE;
++			goto err_set_full;
++		}
+ 	}
+ 
+ 	nft_trans_elem(trans) = elem;
+-- 
+2.53.0
+
diff --git a/queue-6.1/netfilter-nf_tables-fix-set-size-with-rbtree-backend.patch b/queue-6.1/netfilter-nf_tables-fix-set-size-with-rbtree-backend.patch
new file mode 100644
index 0000000..0cdf911
--- /dev/null
+++ b/queue-6.1/netfilter-nf_tables-fix-set-size-with-rbtree-backend.patch
@@ -0,0 +1,220 @@
+From f238a9690304b92e342f798e21f64de513ff5ca1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 02:28:49 -0700
+Subject: netfilter: nf_tables: fix set size with rbtree backend
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit 8d738c1869f611955d91d8d0fd0012d9ef207201 ]
+
+The existing rbtree implementation uses singleton elements to represent
+ranges, however, userspace provides a set size according to the number
+of ranges in the set.
+
+Adjust provided userspace set size to the number of singleton elements
+in the kernel by multiplying the range by two.
+
+Check if the no-match all-zero element is already in the set, in such
+case release one slot in the set size.
+
+Fixes: 0ed6389c483d ("netfilter: nf_tables: rename set implementations")
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+[ Shivani: Modified to apply on 6.1.y ]
+Signed-off-by: Shivani Agarwal <shivani.agarwal@broadcom.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_tables.h |  6 ++++
+ net/netfilter/nf_tables_api.c     | 49 +++++++++++++++++++++++++++++--
+ net/netfilter/nft_set_rbtree.c    | 43 +++++++++++++++++++++++++++
+ 3 files changed, 96 insertions(+), 2 deletions(-)
+
+diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
+index dafa0a32e6e1df..3329c2eaea9f07 100644
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -422,6 +422,9 @@ struct nft_set_ext;
+  *	@remove: remove element from set
+  *	@walk: iterate over all set elements
+  *	@get: get set elements
++ *	@ksize: kernel set size
++ *	@usize: userspace set size
++ *	@adjust_maxsize: delta to adjust maximum set size
+  *	@privsize: function to return size of set private data
+  *	@init: initialize private data of new set instance
+  *	@destroy: destroy private data of set instance
+@@ -470,6 +473,9 @@ struct nft_set_ops {
+ 					       const struct nft_set *set,
+ 					       const struct nft_set_elem *elem,
+ 					       unsigned int flags);
++	u32				(*ksize)(u32 size);
++	u32				(*usize)(u32 size);
++	u32				(*adjust_maxsize)(const struct nft_set *set);
+ 	void				(*commit)(struct nft_set *set);
+ 	void				(*abort)(const struct nft_set *set);
+ 	u64				(*privsize)(const struct nlattr * const nla[],
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index b6b7b0b3539dc9..0d406dab5cac19 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -4277,6 +4277,14 @@ static int nf_tables_fill_set_concat(struct sk_buff *skb,
+ 	return 0;
+ }
+ 
++static u32 nft_set_userspace_size(const struct nft_set_ops *ops, u32 size)
++{
++	if (ops->usize)
++		return ops->usize(size);
++
++	return size;
++}
++
+ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
+ 			      const struct nft_set *set, u16 event, u16 flags)
+ {
+@@ -4341,7 +4349,8 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
+ 	if (!nest)
+ 		goto nla_put_failure;
+ 	if (set->size &&
+-	    nla_put_be32(skb, NFTA_SET_DESC_SIZE, htonl(set->size)))
++	    nla_put_be32(skb, NFTA_SET_DESC_SIZE,
++			 htonl(nft_set_userspace_size(set->ops, set->size))))
+ 		goto nla_put_failure;
+ 
+ 	if (set->field_count > 1 &&
+@@ -4711,6 +4720,15 @@ static bool nft_set_is_same(const struct nft_set *set,
+ 	return true;
+ }
+ 
++static u32 nft_set_kernel_size(const struct nft_set_ops *ops,
++			       const struct nft_set_desc *desc)
++{
++	if (ops->ksize)
++		return ops->ksize(desc->size);
++
++	return desc->size;
++}
++
+ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
+ 			    const struct nlattr * const nla[])
+ {
+@@ -4893,6 +4911,9 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
+ 		if (err < 0)
+ 			return err;
+ 
++		if (desc.size)
++			desc.size = nft_set_kernel_size(set->ops, &desc);
++
+ 		err = 0;
+ 		if (!nft_set_is_same(set, &desc, exprs, num_exprs, flags)) {
+ 			NL_SET_BAD_ATTR(extack, nla[NFTA_SET_NAME]);
+@@ -4915,6 +4936,9 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
+ 	if (IS_ERR(ops))
+ 		return PTR_ERR(ops);
+ 
++	if (desc.size)
++		desc.size = nft_set_kernel_size(ops, &desc);
++
+ 	udlen = 0;
+ 	if (nla[NFTA_SET_USERDATA])
+ 		udlen = nla_len(nla[NFTA_SET_USERDATA]);
+@@ -6356,6 +6380,27 @@ static bool nft_setelem_valid_key_end(const struct nft_set *set,
+ 	return true;
+ }
+ 
++static u32 nft_set_maxsize(const struct nft_set *set)
++{
++	u32 maxsize, delta;
++
++	if (!set->size)
++		return UINT_MAX;
++
++	if (set->ops->adjust_maxsize)
++		delta = set->ops->adjust_maxsize(set);
++	else
++		delta = 0;
++
++	if (check_add_overflow(set->size, set->ndeact, &maxsize))
++		return UINT_MAX;
++
++	if (check_add_overflow(maxsize, delta, &maxsize))
++		return UINT_MAX;
++
++	return maxsize;
++}
++
+ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
+ 			    const struct nlattr *attr, u32 nlmsg_flags)
+ {
+@@ -6700,7 +6745,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
+ 	}
+ 
+ 	if (!(flags & NFT_SET_ELEM_CATCHALL)) {
+-		unsigned int max = set->size ? set->size + set->ndeact : UINT_MAX;
++		unsigned int max = nft_set_maxsize(set);
+ 
+ 		if (!atomic_add_unless(&set->nelems, 1, max)) {
+ 			err = -ENFILE;
+diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
+index 23e4e656f7f0cb..433094c4200f97 100644
+--- a/net/netfilter/nft_set_rbtree.c
++++ b/net/netfilter/nft_set_rbtree.c
+@@ -773,6 +773,46 @@ static bool nft_rbtree_estimate(const struct nft_set_desc *desc, u32 features,
+ 	return true;
+ }
+ 
++/* rbtree stores ranges as singleton elements, each range is composed of two
++ * elements ...
++ */
++static u32 nft_rbtree_ksize(u32 size)
++{
++	return size * 2;
++}
++
++/* ... hide this detail to userspace. */
++static u32 nft_rbtree_usize(u32 size)
++{
++	if (!size)
++		return 0;
++
++	return size / 2;
++}
++
++static u32 nft_rbtree_adjust_maxsize(const struct nft_set *set)
++{
++	struct nft_rbtree *priv = nft_set_priv(set);
++	struct nft_rbtree_elem *rbe;
++	struct rb_node *node;
++	const void *key;
++
++	node = rb_last(&priv->root);
++	if (!node)
++		return 0;
++
++	rbe = rb_entry(node, struct nft_rbtree_elem, node);
++	if (!nft_rbtree_interval_end(rbe))
++		return 0;
++
++	key = nft_set_ext_key(&rbe->ext);
++	if (memchr(key, 1, set->klen))
++		return 0;
++
++	/* this is the all-zero no-match element. */
++	return 1;
++}
++
+ const struct nft_set_type nft_set_rbtree_type = {
+ 	.features	= NFT_SET_INTERVAL | NFT_SET_MAP | NFT_SET_OBJECT | NFT_SET_TIMEOUT,
+ 	.ops		= {
+@@ -789,5 +829,8 @@ const struct nft_set_type nft_set_rbtree_type = {
+ 		.lookup		= nft_rbtree_lookup,
+ 		.walk		= nft_rbtree_walk,
+ 		.get		= nft_rbtree_get,
++		.ksize		= nft_rbtree_ksize,
++		.usize		= nft_rbtree_usize,
++		.adjust_maxsize = nft_rbtree_adjust_maxsize,
+ 	},
+ };
+-- 
+2.53.0
+
diff --git a/queue-6.1/netfilter-nf_tables-unconditionally-bump-set-nelems-.patch b/queue-6.1/netfilter-nf_tables-unconditionally-bump-set-nelems-.patch
new file mode 100644
index 0000000..ca7f92d
--- /dev/null
+++ b/queue-6.1/netfilter-nf_tables-unconditionally-bump-set-nelems-.patch
@@ -0,0 +1,102 @@
+From ec6344bdb904b27fcd1082ef2f4ac46a53401180 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 02:28:50 -0700
+Subject: netfilter: nf_tables: unconditionally bump set->nelems before
+ insertion
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit def602e498a4f951da95c95b1b8ce8ae68aa733a ]
+
+In case that the set is full, a new element gets published then removed
+without waiting for the RCU grace period, while RCU reader can be
+walking over it already.
+
+To address this issue, add the element transaction even if set is full,
+but toggle the set_full flag to report -ENFILE so the abort path safely
+unwinds the set to its previous state.
+
+As for element updates, decrement set->nelems to restore it.
+
+A simpler fix is to call synchronize_rcu() in the error path.
+However, with a large batch adding elements to already maxed-out set,
+this could cause noticeable slowdown of such batches.
+
+Fixes: 35d0ac9070ef ("netfilter: nf_tables: fix set->nelems counting with no NLM_F_EXCL")
+Reported-by: Inseo An <y0un9sa@gmail.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+[ Minor conflict resolved. ]
+Signed-off-by: Li hongliang <1468888505@139.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+[ Shivani: Modified to apply on 6.1.y ]
+Signed-off-by: Shivani Agarwal <shivani.agarwal@broadcom.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 28 +++++++++++++++-------------
+ 1 file changed, 15 insertions(+), 13 deletions(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 0d406dab5cac19..735c0210104076 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -6417,6 +6417,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
+ 	struct nft_data_desc desc;
+ 	enum nft_registers dreg;
+ 	struct nft_trans *trans;
++	bool set_full = false;
+ 	u64 timeout;
+ 	u64 expiration;
+ 	int err, i;
+@@ -6709,10 +6710,18 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
+ 	if (err < 0)
+ 		goto err_elem_free;
+ 
++	if (!(flags & NFT_SET_ELEM_CATCHALL)) {
++		unsigned int max = nft_set_maxsize(set), nelems;
++
++		nelems = atomic_inc_return(&set->nelems);
++		if (nelems > max)
++			set_full = true;
++	}
++
+ 	trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set);
+ 	if (trans == NULL) {
+ 		err = -ENOMEM;
+-		goto err_elem_free;
++		goto err_set_size;
+ 	}
+ 
+ 	ext->genmask = nft_genmask_cur(ctx->net);
+@@ -6744,23 +6753,16 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
+ 		goto err_element_clash;
+ 	}
+ 
+-	if (!(flags & NFT_SET_ELEM_CATCHALL)) {
+-		unsigned int max = nft_set_maxsize(set);
+-
+-		if (!atomic_add_unless(&set->nelems, 1, max)) {
+-			err = -ENFILE;
+-			goto err_set_full;
+-		}
+-	}
+-
+ 	nft_trans_elem(trans) = elem;
+ 	nft_trans_commit_list_add_tail(ctx->net, trans);
+-	return 0;
+ 
+-err_set_full:
+-	nft_setelem_remove(ctx->net, set, &elem);
++	return set_full ? -ENFILE : 0;
++
+ err_element_clash:
+ 	kfree(trans);
++err_set_size:
++	if (!(flags & NFT_SET_ELEM_CATCHALL))
++		atomic_dec(&set->nelems);
+ err_elem_free:
+ 	nf_tables_set_elem_destroy(ctx, set, elem.priv);
+ err_parse_data:
+-- 
+2.53.0
+
diff --git a/queue-6.1/selftests-bpf-check-for-timeout-in-perf_link-test.patch b/queue-6.1/selftests-bpf-check-for-timeout-in-perf_link-test.patch
new file mode 100644
index 0000000..fffe3dc
--- /dev/null
+++ b/queue-6.1/selftests-bpf-check-for-timeout-in-perf_link-test.patch
@@ -0,0 +1,77 @@
+From ba722512da7e1ed5cc6d9f67e432ee8da4493864 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 12:59:48 +0800
+Subject: selftests/bpf: Check for timeout in perf_link test
+
+From: Ihor Solodrai <ihor.solodrai@pm.me>
+
+commit e6c209da7e0e9aaf955a7b59e91ed78c2b6c96fb upstream.
+
+Recently perf_link test started unreliably failing on libbpf CI:
+  * https://github.com/libbpf/libbpf/actions/runs/11260672407/job/31312405473
+  * https://github.com/libbpf/libbpf/actions/runs/11260992334/job/31315514626
+  * https://github.com/libbpf/libbpf/actions/runs/11263162459/job/31320458251
+
+Part of the test is running a dummy loop for a while and then checking
+for a counter incremented by the test program.
+
+Instead of waiting for an arbitrary number of loop iterations once,
+check for the test counter in a loop and use get_time_ns() helper to
+enforce a 100ms timeout.
+
+v1: https://lore.kernel.org/bpf/zuRd072x9tumn2iN4wDNs5av0nu5nekMNV4PkR-YwCT10eFFTrUtZBRkLWFbrcCe7guvLStGQlhibo8qWojCO7i2-NGajes5GYIyynexD-w=@pm.me/
+
+Signed-off-by: Ihor Solodrai <ihor.solodrai@pm.me>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20241011153104.249800-1-ihor.solodrai@pm.me
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../testing/selftests/bpf/prog_tests/perf_link.c  | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/perf_link.c b/tools/testing/selftests/bpf/prog_tests/perf_link.c
+index 224eba6fef2ee1..d734526d6a16b1 100644
+--- a/tools/testing/selftests/bpf/prog_tests/perf_link.c
++++ b/tools/testing/selftests/bpf/prog_tests/perf_link.c
+@@ -4,8 +4,12 @@
+ #include <pthread.h>
+ #include <sched.h>
+ #include <test_progs.h>
++#include "testing_helpers.h"
+ #include "test_perf_link.skel.h"
+ 
++#define BURN_TIMEOUT_MS 100
++#define BURN_TIMEOUT_NS BURN_TIMEOUT_MS * 1000000
++
+ static void burn_cpu(void)
+ {
+ 	volatile int j = 0;
+@@ -32,6 +36,7 @@ void serial_test_perf_link(void)
+ 	int run_cnt_before, run_cnt_after;
+ 	struct bpf_link_info info;
+ 	__u32 info_len = sizeof(info);
++	__u64 timeout_time_ns;
+ 
+ 	/* create perf event */
+ 	memset(&attr, 0, sizeof(attr));
+@@ -63,8 +68,14 @@ void serial_test_perf_link(void)
+ 	ASSERT_GT(info.prog_id, 0, "link_prog_id");
+ 
+ 	/* ensure we get at least one perf_event prog execution */
+-	burn_cpu();
+-	ASSERT_GT(skel->bss->run_cnt, 0, "run_cnt");
++	timeout_time_ns = get_time_ns() + BURN_TIMEOUT_NS;
++	while (true) {
++		burn_cpu();
++		if (skel->bss->run_cnt > 0)
++			break;
++	        if (!ASSERT_LT(get_time_ns(), timeout_time_ns, "run_cnt_timeout"))
++			break;
++	}
+ 
+ 	/* perf_event is still active, but we close link and BPF program
+ 	 * shouldn't be executed anymore
+-- 
+2.53.0
+
diff --git a/queue-6.1/selftests-bpf-move-get_time_ns-to-testing_helpers.h.patch b/queue-6.1/selftests-bpf-move-get_time_ns-to-testing_helpers.h.patch
new file mode 100644
index 0000000..59e2989
--- /dev/null
+++ b/queue-6.1/selftests-bpf-move-get_time_ns-to-testing_helpers.h.patch
@@ -0,0 +1,96 @@
+From bbf381823f990ea60ba5a71f70d83a1ed4d1e563 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 12:59:47 +0800
+Subject: selftests/bpf: Move get_time_ns to testing_helpers.h
+
+From: Jiri Olsa <jolsa@kernel.org>
+
+commit 3830d04a7401f277185e4439eb259c1b13e76788 upstream.
+
+We'd like to have single copy of get_time_ns used b bench and test_progs,
+but we can't just include bench.h, because of conflicting 'struct env'
+objects.
+
+Moving get_time_ns to testing_helpers.h which is being included by both
+bench and test_progs objects.
+
+Signed-off-by: Jiri Olsa <jolsa@kernel.org>
+Link: https://lore.kernel.org/r/20230809083440.3209381-19-jolsa@kernel.org
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Stable-dep-of: e6c209da7e0e ("selftests/bpf: Check for timeout in perf_link test")
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/bpf/bench.h                    |  9 ---------
+ .../selftests/bpf/prog_tests/kprobe_multi_test.c       |  8 --------
+ tools/testing/selftests/bpf/testing_helpers.h          | 10 ++++++++++
+ 3 files changed, 10 insertions(+), 17 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/bench.h b/tools/testing/selftests/bpf/bench.h
+index 66959387148375..2c94c57885af85 100644
+--- a/tools/testing/selftests/bpf/bench.h
++++ b/tools/testing/selftests/bpf/bench.h
+@@ -79,15 +79,6 @@ void grace_period_latency_basic_stats(struct bench_res res[], int res_cnt,
+ void grace_period_ticks_basic_stats(struct bench_res res[], int res_cnt,
+ 				    struct basic_stats *gp_stat);
+ 
+-static inline __u64 get_time_ns(void)
+-{
+-	struct timespec t;
+-
+-	clock_gettime(CLOCK_MONOTONIC, &t);
+-
+-	return (u64)t.tv_sec * 1000000000 + t.tv_nsec;
+-}
+-
+ static inline void atomic_inc(long *value)
+ {
+ 	(void)__atomic_add_fetch(value, 1, __ATOMIC_RELAXED);
+diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
+index 0d82e28aed1ac0..8086e28346466f 100644
+--- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
++++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
+@@ -304,14 +304,6 @@ static void test_attach_api_fails(void)
+ 	kprobe_multi__destroy(skel);
+ }
+ 
+-static inline __u64 get_time_ns(void)
+-{
+-	struct timespec t;
+-
+-	clock_gettime(CLOCK_MONOTONIC, &t);
+-	return (__u64) t.tv_sec * 1000000000 + t.tv_nsec;
+-}
+-
+ static size_t symbol_hash(const void *key, void *ctx __maybe_unused)
+ {
+ 	return str_hash((const char *) key);
+diff --git a/tools/testing/selftests/bpf/testing_helpers.h b/tools/testing/selftests/bpf/testing_helpers.h
+index f72fb24f8e90fb..ba4f205e7bc757 100644
+--- a/tools/testing/selftests/bpf/testing_helpers.h
++++ b/tools/testing/selftests/bpf/testing_helpers.h
+@@ -7,6 +7,7 @@
+ #include <stdbool.h>
+ #include <bpf/bpf.h>
+ #include <bpf/libbpf.h>
++#include <time.h>
+ 
+ int parse_num_list(const char *s, bool **set, int *set_len);
+ __u32 link_info_prog_id(const struct bpf_link *link, struct bpf_link_info *info);
+@@ -30,4 +31,13 @@ int load_bpf_testmod(bool verbose);
+ void unload_bpf_testmod(bool verbose);
+ int kern_sync_rcu(void);
+ 
++static inline __u64 get_time_ns(void)
++{
++	struct timespec t;
++
++	clock_gettime(CLOCK_MONOTONIC, &t);
++
++	return (u64)t.tv_sec * 1000000000 + t.tv_nsec;
++}
++
+ #endif /* __TESTING_HELPERS_H */
+-- 
+2.53.0
+
diff --git a/queue-6.1/series b/queue-6.1/series
index 5be7863..33d9e82 100644
--- a/queue-6.1/series
+++ b/queue-6.1/series
@@ -5,3 +5,12 @@
 net-sched-act_pedit-free-pedit-keys-on-bail-from-off.patch
 selftests-bpf-move-sys-macro-into-the-test_progs.h.patch
 kvm-vmx-make-vmread_error_trampoline-uncallable-from.patch
+drm-amd-display-bound-vbios-record-chain-walk-loops.patch
+ip6_vti-set-netns_immutable-on-the-fallback-device.patch
+netfilter-nf_tables-always-increment-set-element-cou.patch
+netfilter-nf_tables-fix-set-size-with-rbtree-backend.patch
+netfilter-nf_tables-unconditionally-bump-set-nelems-.patch
+selftests-bpf-move-get_time_ns-to-testing_helpers.h.patch
+selftests-bpf-check-for-timeout-in-perf_link-test.patch
+drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
+drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
diff --git a/queue-6.12/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch b/queue-6.12/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
new file mode 100644
index 0000000..e0d2425
--- /dev/null
+++ b/queue-6.12/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
@@ -0,0 +1,80 @@
+From 8a0b8e4ab12bb62db9880c6dc558e0cbd466fa14 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 14:50:15 -0300
+Subject: drm/v3d: Skip CSD when it has zeroed workgroups
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Maíra Canal <mcanal@igalia.com>
+
+[ Upstream commit 7f93fad5ea0affc9e1505dd0f7596c0fdb496213 ]
+
+A compute shader dispatch encodes its workgroup counts in the CFG0..CFG2
+registers. Kicking off a dispatch with a zero count in any of the three
+dimensions is invalid. First, the hardware will process 0 as 65536,
+while the user-space driver exposes a maximum of 65535. Over that, a
+submission with a zeroed workgroup dimension should be a no-op.
+
+These zeroed counts can reach the dispatch path through an indirect CSD
+job, whose workgroup counts are only known once the indirect buffer is
+read and may legitimately be zero, but such scenario should only result in
+a no-op.
+
+Overwrite the indirect CSD job workgroup counts with the indirect BO
+ones, even if they are zeroed, and don't submit the job to the hardware
+when any of the workgroup counts is zero, so the job completes immediately
+instead of running the shader.
+
+Cc: stable@vger.kernel.org
+Fixes: d223f98f0209 ("drm/v3d: Add support for compute shader dispatch.")
+Suggested-by: Jose Maria Casanova Crespo <jmcasanova@igalia.com>
+Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
+Link: https://patch.msgid.link/20260602-v3d-fix-indirect-csd-v4-2-654309e32bc0@igalia.com
+Signed-off-by: Maíra Canal <mcanal@igalia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/v3d/v3d_sched.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
+index f2a2c17a58c687..f2bac920af899d 100644
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -368,6 +368,16 @@ v3d_csd_job_run(struct drm_sched_job *sched_job)
+ 		return NULL;
+ 	}
+ 
++	/* The HW interprets a workgroup size of 0 as 65536; however, the
++	 * user-space driver exposes a maximum of 65535. Therefore, a 0 in
++	 * any dimension means that we have no workgroups and the compute
++	 * shader should not be dispatched.
++	 */
++	if (!V3D_GET_FIELD(job->args.cfg[0], V3D_CSD_QUEUED_CFG0_NUM_WGS_X) ||
++	    !V3D_GET_FIELD(job->args.cfg[1], V3D_CSD_QUEUED_CFG1_NUM_WGS_Y) ||
++	    !V3D_GET_FIELD(job->args.cfg[2], V3D_CSD_QUEUED_CFG2_NUM_WGS_Z))
++		return NULL;
++
+ 	v3d->queue[V3D_CSD].active_job = &job->base;
+ 
+ 	v3d_invalidate_caches(v3d);
+@@ -418,13 +428,13 @@ v3d_rewrite_csd_job_wg_counts_from_indirect(struct v3d_cpu_job *job)
+ 
+ 	wg_counts = (uint32_t *)(bo->vaddr + indirect_csd->offset);
+ 
+-	if (wg_counts[0] == 0 || wg_counts[1] == 0 || wg_counts[2] == 0)
+-		goto unmap_bo;
+-
+ 	args->cfg[0] = wg_counts[0] << V3D_CSD_CFG012_WG_COUNT_SHIFT;
+ 	args->cfg[1] = wg_counts[1] << V3D_CSD_CFG012_WG_COUNT_SHIFT;
+ 	args->cfg[2] = wg_counts[2] << V3D_CSD_CFG012_WG_COUNT_SHIFT;
+ 
++	if (wg_counts[0] == 0 || wg_counts[1] == 0 || wg_counts[2] == 0)
++		goto unmap_bo;
++
+ 	num_batches = DIV_ROUND_UP(indirect_csd->wg_size, 16) *
+ 		      (wg_counts[0] * wg_counts[1] * wg_counts[2]);
+ 
+-- 
+2.53.0
+
diff --git a/queue-6.12/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch b/queue-6.12/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
new file mode 100644
index 0000000..631c11a
--- /dev/null
+++ b/queue-6.12/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
@@ -0,0 +1,265 @@
+From 34da1e3b182ae0bf1af3d625686d6e74254cbd45 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Aug 2025 11:18:59 -0300
+Subject: drm/v3d: Store the active job inside the queue's state
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Maíra Canal <mcanal@igalia.com>
+
+[ Upstream commit 0d3768826d38c0ac740f8b45cd13346630535f2b ]
+
+Instead of storing the queue's active job in four different variables,
+store the active job inside the queue's state. This way, it's possible
+to access all active jobs using an index based in `enum v3d_queue`.
+
+Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
+Reviewed-by: Melissa Wen <mwen@igalia.com>
+Link: https://lore.kernel.org/r/20250826-v3d-queue-lock-v3-2-979efc43e490@igalia.com
+Signed-off-by: Maíra Canal <mcanal@igalia.com>
+Stable-dep-of: 7f93fad5ea0a ("drm/v3d: Skip CSD when it has zeroed workgroups")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/v3d/v3d_drv.h   |  7 ++--
+ drivers/gpu/drm/v3d/v3d_gem.c   |  7 ++--
+ drivers/gpu/drm/v3d/v3d_irq.c   | 62 +++++++++++++--------------------
+ drivers/gpu/drm/v3d/v3d_sched.c | 26 +++++++++-----
+ 4 files changed, 48 insertions(+), 54 deletions(-)
+
+diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
+index d4b0549205c29e..b6e11968fba47b 100644
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -59,6 +59,9 @@ struct v3d_queue_state {
+ 
+ 	/* Stores the GPU stats for this queue in the global context. */
+ 	struct v3d_stats stats;
++
++	/* Currently active job for this queue */
++	struct v3d_job *active_job;
+ };
+ 
+ /* Performance monitor object. The perform lifetime is controlled by userspace
+@@ -147,10 +150,6 @@ struct v3d_dev {
+ 
+ 	struct work_struct overflow_mem_work;
+ 
+-	struct v3d_bin_job *bin_job;
+-	struct v3d_render_job *render_job;
+-	struct v3d_tfu_job *tfu_job;
+-	struct v3d_csd_job *csd_job;
+ 	struct v3d_cpu_job *cpu_job;
+ 
+ 	struct v3d_queue_state queue[V3D_MAX_QUEUES];
+diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
+index 6b6ba7a68fcb40..cf3b93101429c2 100644
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -304,16 +304,15 @@ void
+ v3d_gem_destroy(struct drm_device *dev)
+ {
+ 	struct v3d_dev *v3d = to_v3d_dev(dev);
++	enum v3d_queue q;
+ 
+ 	v3d_sched_fini(v3d);
+ 
+ 	/* Waiting for jobs to finish would need to be done before
+ 	 * unregistering V3D.
+ 	 */
+-	WARN_ON(v3d->bin_job);
+-	WARN_ON(v3d->render_job);
+-	WARN_ON(v3d->tfu_job);
+-	WARN_ON(v3d->csd_job);
++	for (q = 0; q < V3D_MAX_QUEUES; q++)
++		WARN_ON(v3d->queue[q].active_job);
+ 
+ 	drm_mm_takedown(&v3d->mm);
+ 
+diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c
+index b98e1a4b33c71c..2464ea4d935d04 100644
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -42,6 +42,8 @@ v3d_overflow_mem_work(struct work_struct *work)
+ 		container_of(work, struct v3d_dev, overflow_mem_work);
+ 	struct drm_device *dev = &v3d->drm;
+ 	struct v3d_bo *bo = v3d_bo_create(dev, NULL /* XXX: GMP */, 256 * 1024);
++	struct v3d_queue_state *queue = &v3d->queue[V3D_BIN];
++	struct v3d_bin_job *bin_job;
+ 	struct drm_gem_object *obj;
+ 	unsigned long irqflags;
+ 
+@@ -61,13 +63,15 @@ v3d_overflow_mem_work(struct work_struct *work)
+ 	 * some binner pool anyway.
+ 	 */
+ 	spin_lock_irqsave(&v3d->job_lock, irqflags);
+-	if (!v3d->bin_job) {
++	bin_job = (struct v3d_bin_job *)queue->active_job;
++
++	if (!bin_job) {
+ 		spin_unlock_irqrestore(&v3d->job_lock, irqflags);
+ 		goto out;
+ 	}
+ 
+ 	drm_gem_object_get(obj);
+-	list_add_tail(&bo->unref_head, &v3d->bin_job->render->unref_list);
++	list_add_tail(&bo->unref_head, &bin_job->render->unref_list);
+ 	spin_unlock_irqrestore(&v3d->job_lock, irqflags);
+ 
+ 	v3d_mmu_flush_all(v3d);
+@@ -79,6 +83,20 @@ v3d_overflow_mem_work(struct work_struct *work)
+ 	drm_gem_object_put(obj);
+ }
+ 
++static void
++v3d_irq_signal_fence(struct v3d_dev *v3d, enum v3d_queue q,
++		     void (*trace_irq)(struct drm_device *, uint64_t))
++{
++	struct v3d_queue_state *queue = &v3d->queue[q];
++	struct v3d_fence *fence = to_v3d_fence(queue->active_job->irq_fence);
++
++	v3d_job_update_stats(queue->active_job, q);
++	trace_irq(&v3d->drm, fence->seqno);
++
++	queue->active_job = NULL;
++	dma_fence_signal(&fence->base);
++}
++
+ static irqreturn_t
+ v3d_irq(int irq, void *arg)
+ {
+@@ -102,41 +120,17 @@ v3d_irq(int irq, void *arg)
+ 	}
+ 
+ 	if (intsts & V3D_INT_FLDONE) {
+-		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->bin_job->base.irq_fence);
+-
+-		v3d_job_update_stats(&v3d->bin_job->base, V3D_BIN);
+-		trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
+-
+-		v3d->bin_job = NULL;
+-		dma_fence_signal(&fence->base);
+-
++		v3d_irq_signal_fence(v3d, V3D_BIN, trace_v3d_bcl_irq);
+ 		status = IRQ_HANDLED;
+ 	}
+ 
+ 	if (intsts & V3D_INT_FRDONE) {
+-		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->render_job->base.irq_fence);
+-
+-		v3d_job_update_stats(&v3d->render_job->base, V3D_RENDER);
+-		trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
+-
+-		v3d->render_job = NULL;
+-		dma_fence_signal(&fence->base);
+-
++		v3d_irq_signal_fence(v3d, V3D_RENDER, trace_v3d_rcl_irq);
+ 		status = IRQ_HANDLED;
+ 	}
+ 
+ 	if (intsts & V3D_INT_CSDDONE(v3d->ver)) {
+-		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->csd_job->base.irq_fence);
+-
+-		v3d_job_update_stats(&v3d->csd_job->base, V3D_CSD);
+-		trace_v3d_csd_irq(&v3d->drm, fence->seqno);
+-
+-		v3d->csd_job = NULL;
+-		dma_fence_signal(&fence->base);
+-
++		v3d_irq_signal_fence(v3d, V3D_CSD, trace_v3d_csd_irq);
+ 		status = IRQ_HANDLED;
+ 	}
+ 
+@@ -168,15 +162,7 @@ v3d_hub_irq(int irq, void *arg)
+ 	V3D_WRITE(V3D_HUB_INT_CLR, intsts);
+ 
+ 	if (intsts & V3D_HUB_INT_TFUC) {
+-		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->tfu_job->base.irq_fence);
+-
+-		v3d_job_update_stats(&v3d->tfu_job->base, V3D_TFU);
+-		trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
+-
+-		v3d->tfu_job = NULL;
+-		dma_fence_signal(&fence->base);
+-
++		v3d_irq_signal_fence(v3d, V3D_TFU, trace_v3d_tfu_irq);
+ 		status = IRQ_HANDLED;
+ 	}
+ 
+diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
+index 8e3c8ffc2a428f..f2a2c17a58c687 100644
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -208,14 +208,18 @@ static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
+ 	struct dma_fence *fence;
+ 	unsigned long irqflags;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		spin_lock_irqsave(&v3d->job_lock, irqflags);
++		v3d->queue[V3D_BIN].active_job = NULL;
++		spin_unlock_irqrestore(&v3d->job_lock, irqflags);
+ 		return NULL;
++	}
+ 
+ 	/* Lock required around bin_job update vs
+ 	 * v3d_overflow_mem_work().
+ 	 */
+ 	spin_lock_irqsave(&v3d->job_lock, irqflags);
+-	v3d->bin_job = job;
++	v3d->queue[V3D_BIN].active_job = &job->base;
+ 	/* Clear out the overflow allocation, so we don't
+ 	 * reuse the overflow attached to a previous job.
+ 	 */
+@@ -263,10 +267,12 @@ static struct dma_fence *v3d_render_job_run(struct drm_sched_job *sched_job)
+ 	struct drm_device *dev = &v3d->drm;
+ 	struct dma_fence *fence;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		v3d->queue[V3D_RENDER].active_job = NULL;
+ 		return NULL;
++	}
+ 
+-	v3d->render_job = job;
++	v3d->queue[V3D_RENDER].active_job = &job->base;
+ 
+ 	/* Can we avoid this flush?  We need to be careful of
+ 	 * scheduling, though -- imagine job0 rendering to texture and
+@@ -309,10 +315,12 @@ v3d_tfu_job_run(struct drm_sched_job *sched_job)
+ 	struct drm_device *dev = &v3d->drm;
+ 	struct dma_fence *fence;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		v3d->queue[V3D_TFU].active_job = NULL;
+ 		return NULL;
++	}
+ 
+-	v3d->tfu_job = job;
++	v3d->queue[V3D_TFU].active_job = &job->base;
+ 
+ 	fence = v3d_fence_create(v3d, V3D_TFU);
+ 	if (IS_ERR(fence))
+@@ -355,10 +363,12 @@ v3d_csd_job_run(struct drm_sched_job *sched_job)
+ 	struct dma_fence *fence;
+ 	int i, csd_cfg0_reg;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		v3d->queue[V3D_CSD].active_job = NULL;
+ 		return NULL;
++	}
+ 
+-	v3d->csd_job = job;
++	v3d->queue[V3D_CSD].active_job = &job->base;
+ 
+ 	v3d_invalidate_caches(v3d);
+ 
+-- 
+2.53.0
+
diff --git a/queue-6.12/drm-xe-display-fix-oops-in-suspend-shutdown-without-.patch b/queue-6.12/drm-xe-display-fix-oops-in-suspend-shutdown-without-.patch
new file mode 100644
index 0000000..87b8932
--- /dev/null
+++ b/queue-6.12/drm-xe-display-fix-oops-in-suspend-shutdown-without-.patch
@@ -0,0 +1,85 @@
+From 272ce010d7b652f900c9c62b3ce2acd7402a04f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 May 2026 19:09:20 +0300
+Subject: drm/xe/display: fix oops in suspend/shutdown without display
+
+From: Jani Nikula <jani.nikula@intel.com>
+
+[ Upstream commit 68938cc08e23a94fd881e845837ff918de005ce7 ]
+
+The xe driver keeps track of whether to probe display, and whether
+display hardware is there, using xe->info.probe_display. It gets set to
+false if there's no display after intel_display_device_probe(). However,
+the display may also be disabled via fuses, detected at a later time in
+intel_display_device_info_runtime_init().
+
+In this case, the xe driver does for_each_intel_crtc() on uninitialized
+mode config in xe_display_flush_cleanup_work(), leading to a NULL
+pointer dereference, and generally calls display code with display info
+cleared.
+
+Check for intel_display_device_present() after
+intel_display_device_info_runtime_init(), and reset
+xe->info.probe_display as necessary. Also do unset_display_features()
+for completeness, although display runtime init has already done
+that. This will need to be unified across all cases later.
+
+Move intel_display_device_info_runtime_init() call slightly earlier,
+similar to i915, to avoid a bunch of unnecessary setup for no display
+cases.
+
+Note #1: The xe driver has no business doing low level display plumbing
+like for_each_intel_crtc() to begin with. It all needs to happen in
+display code.
+
+Note #2: The actual bug is present already in commit 44e694958b95
+("drm/xe/display: Implement display support"), but the oops was likely
+introduced later at commit ddf6492e0e50 ("drm/xe/display: Make display
+suspend/resume work on discrete").
+
+Fixes: 44e694958b95 ("drm/xe/display: Implement display support")
+Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/7904
+Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/6150
+Cc: stable@vger.kernel.org # v6.8+
+Reviewed-by: Suraj Kandpal <suraj.kandpal@intel.com>
+Link: https://patch.msgid.link/20260515160920.1082842-1-jani.nikula@intel.com
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit 7c3eb9f47533220888a67266448185fd0775d4da)
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/display/xe_display.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c
+index e164e2d71e1157..de1fd4dff0e869 100644
+--- a/drivers/gpu/drm/xe/display/xe_display.c
++++ b/drivers/gpu/drm/xe/display/xe_display.c
+@@ -148,6 +148,15 @@ int xe_display_init_noirq(struct xe_device *xe)
+ 
+ 	intel_display_driver_early_probe(xe);
+ 
++	intel_display_device_info_runtime_init(xe);
++
++	/* Display may have been disabled at runtime init */
++	if (!has_display(xe)) {
++		xe->info.probe_display = false;
++		unset_display_features(xe);
++		return 0;
++	}
++
+ 	/* Early display init.. */
+ 	intel_opregion_setup(display);
+ 
+@@ -159,8 +168,6 @@ int xe_display_init_noirq(struct xe_device *xe)
+ 
+ 	intel_bw_init_hw(xe);
+ 
+-	intel_display_device_info_runtime_init(xe);
+-
+ 	err = intel_display_driver_probe_noirq(xe);
+ 	if (err) {
+ 		intel_opregion_cleanup(display);
+-- 
+2.53.0
+
diff --git a/queue-6.12/series b/queue-6.12/series
index 6e61e56..fd23016 100644
--- a/queue-6.12/series
+++ b/queue-6.12/series
@@ -6,3 +6,6 @@
 gpiolib-remove-redundant-assignment-of-return-variab.patch
 gpio-fix-resource-leaks-on-errors-in-gpiochip_add_da.patch
 io_uring-net-avoid-msghdr-on-op_connect-op_bind-asyn.patch
+drm-xe-display-fix-oops-in-suspend-shutdown-without-.patch
+drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
+drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
diff --git a/queue-6.18/net-stmmac-fix-stm32-and-potentially-others-resume-r.patch b/queue-6.18/net-stmmac-fix-stm32-and-potentially-others-resume-r.patch
new file mode 100644
index 0000000..136f6c8
--- /dev/null
+++ b/queue-6.18/net-stmmac-fix-stm32-and-potentially-others-resume-r.patch
@@ -0,0 +1,69 @@
+From 7d997cd44502aa7c30de86fa52726122fb75ae37 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 30 Jan 2026 20:04:57 +0000
+Subject: net: stmmac: fix stm32 (and potentially others) resume regression
+
+From: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+
+[ Upstream commit dbbec8c5a79f4c7aa8d07da8c0b5a34d76c50699 ]
+
+Marek reported that suspending stm32 causes the following errors when
+the interface is administratively down:
+
+	$ echo devices > /sys/power/pm_test
+	$ echo mem > /sys/power/state
+	...
+	ck_ker_eth2stp already disabled
+	...
+	ck_ker_eth2stp already unprepared
+	...
+
+On suspend, stm32 starts the eth2stp clock in its suspend method, and
+stops it in the resume method. This is because the blamed commit omits
+the call to the platform glue ->suspend() method, but does make the
+call to the platform glue ->resume() method.
+
+This problem affects all other converted drivers as well - e.g. looking
+at the PCIe drivers, pci_save_state() will not be called, but
+pci_restore_state() will be. Similar issues affect all other drivers.
+
+Fix this by always calling the ->suspend() method, even when the network
+interface is down. This fixes all the conversions to the platform glue
+->suspend() and ->resume() methods.
+
+Link: https://lore.kernel.org/r/20260114081809.12758-1-marex@nabladev.com
+Fixes: 07bbbfe7addf ("net: stmmac: add suspend()/resume() platform ops")
+Reported-by: Marek Vasut <marex@nabladev.com>
+Tested-by: Marek Vasut <marex@nabladev.com>
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Link: https://patch.msgid.link/E1vlujh-00000007Hkw-2p6r@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 41b270a486308a..1ceedd74e42908 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -7760,7 +7760,7 @@ int stmmac_suspend(struct device *dev)
+ 	u32 chan;
+ 
+ 	if (!ndev || !netif_running(ndev))
+-		return 0;
++		goto suspend_bsp;
+ 
+ 	mutex_lock(&priv->lock);
+ 
+@@ -7803,6 +7803,7 @@ int stmmac_suspend(struct device *dev)
+ 	if (stmmac_fpe_supported(priv))
+ 		ethtool_mmsv_stop(&priv->fpe_cfg.mmsv);
+ 
++suspend_bsp:
+ 	if (priv->plat->suspend)
+ 		return priv->plat->suspend(dev, priv->plat->bsp_priv);
+ 
+-- 
+2.53.0
+
diff --git a/queue-6.18/series b/queue-6.18/series
index 7dd13f0..b06f471 100644
--- a/queue-6.18/series
+++ b/queue-6.18/series
@@ -1 +1,2 @@
 io_uring-net-avoid-msghdr-on-op_connect-op_bind-asyn.patch
+net-stmmac-fix-stm32-and-potentially-others-resume-r.patch
diff --git a/queue-6.6/drm-amd-display-bound-vbios-record-chain-walk-loops.patch b/queue-6.6/drm-amd-display-bound-vbios-record-chain-walk-loops.patch
new file mode 100644
index 0000000..21a2c71
--- /dev/null
+++ b/queue-6.6/drm-amd-display-bound-vbios-record-chain-walk-loops.patch
@@ -0,0 +1,300 @@
+From e734b5cafdb7b3374c44d42e04ca06574fcb621e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 May 2026 15:24:22 -0400
+Subject: drm/amd/display: Bound VBIOS record-chain walk loops
+
+From: Harry Wentland <harry.wentland@amd.com>
+
+[ Upstream commit ff287df16a1a58aca78b08d1f3ee09fc44da0351 ]
+
+[Why & How]
+All record-chain walk loops in bios_parser.c and bios_parser2.c use
+for(;;) and only terminate on a 0xFF record_type sentinel or zero
+record_size. A malformed VBIOS image missing the terminator record
+causes unbounded iteration at probe time, potentially hundreds of
+thousands of iterations with record_size=1. In the final iterations
+near the BIOS image boundary, struct casts beyond the 2-byte header
+validated by GET_IMAGE can also read out of bounds.
+
+Cap all 14 record-chain walk loops to BIOS_MAX_NUM_RECORD (256)
+iterations. The atombios.h defines up to 22 distinct record types
+and atomfirmware.h has 13. Assuming an average of less than 10
+records per type (which is reasonable since most are connector-
+based) 256 is a generous upper bound.
+
+Fixes: 4562236b3bc0 ("drm/amd/dc: Add dc display driver (v2)")
+Assisted-by: Copilot:claude-opus-4.6 Mythos
+Reviewed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Ray Wu <ray.wu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 95700a3d660287ed657d6892f7be9ffc0e294a93)
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/bios/bios_parser.c | 15 +++++++----
+ .../drm/amd/display/dc/bios/bios_parser2.c    | 27 ++++++++++++-------
+ .../amd/display/dc/bios/bios_parser_helper.h  |  5 ++++
+ 3 files changed, 33 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+index ac2a71e80723d1..fa8fcbcc421aba 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+@@ -225,6 +225,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	ATOM_I2C_RECORD *record;
+ 	struct bios_parser *bp = BP_FROM_DCB(dcb);
++	int i;
+ 
+ 	if (!info)
+ 		return BP_RESULT_BADINPUT;
+@@ -237,7 +238,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -296,11 +297,12 @@ static enum bp_result bios_parser_get_device_tag_record(
+ {
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -873,6 +875,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
+ {
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -882,7 +885,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -1577,6 +1580,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
+ {
+ 	ATOM_COMMON_RECORD_HEADER *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -1586,7 +1590,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
+ 	offset = le16_to_cpu(object->usRecordOffset)
+ 					+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+ 
+ 		if (!header)
+@@ -2675,6 +2679,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb,
+ 					      unsigned int record_offset)
+ {
+ 	unsigned int j;
++	unsigned int n;
+ 	struct bios_parser *bp;
+ 	ATOM_BRACKET_LAYOUT_RECORD *record;
+ 	ATOM_COMMON_RECORD_HEADER *record_header;
+@@ -2684,7 +2689,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb,
+ 	record = NULL;
+ 	record_header = NULL;
+ 
+-	for (;;) {
++	for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
+ 
+ 		record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
+ 		if (record_header == NULL) {
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+index ed8f669a9a3e15..33142f1c37462b 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+@@ -391,6 +391,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 	struct atom_i2c_record *record;
+ 	struct atom_i2c_record dummy_record = {0};
+ 	struct bios_parser *bp = BP_FROM_DCB(dcb);
++	int i;
+ 
+ 	if (!info)
+ 		return BP_RESULT_BADINPUT;
+@@ -424,7 +425,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+ 		break;
+ 	}
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -529,6 +530,7 @@ static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -537,7 +539,7 @@ static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser
+ 
+ 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -607,6 +609,7 @@ static struct atom_hpd_int_record *get_hpd_record(
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -616,7 +619,7 @@ static struct atom_hpd_int_record *get_hpd_record(
+ 	offset = le16_to_cpu(object->disp_recordoffset)
+ 			+ bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -2125,6 +2128,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -2133,7 +2137,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
+ 
+ 	offset = object->encoder_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -2162,6 +2166,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -2170,7 +2175,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
+ 
+ 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -2198,6 +2203,7 @@ static struct atom_connector_caps_record *get_connector_caps_record(struct bios_
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -2206,7 +2212,7 @@ static struct atom_connector_caps_record *get_connector_caps_record(struct bios_
+ 
+ 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -2286,6 +2292,7 @@ static struct atom_connector_speed_record *get_connector_speed_cap_record(struct
+ {
+ 	struct atom_common_record_header *header;
+ 	uint32_t offset;
++	int i;
+ 
+ 	if (!object) {
+ 		BREAK_TO_DEBUGGER(); /* Invalid object */
+@@ -2294,7 +2301,7 @@ static struct atom_connector_speed_record *get_connector_speed_cap_record(struct
+ 
+ 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+ 
+-	for (;;) {
++	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
+ 		header = GET_IMAGE(struct atom_common_record_header, offset);
+ 
+ 		if (!header)
+@@ -3154,6 +3161,7 @@ static enum bp_result update_slot_layout_info(
+ {
+ 	unsigned int record_offset;
+ 	unsigned int j;
++	unsigned int n;
+ 	struct atom_display_object_path_v2 *object;
+ 	struct atom_bracket_layout_record *record;
+ 	struct atom_common_record_header *record_header;
+@@ -3175,7 +3183,7 @@ static enum bp_result update_slot_layout_info(
+ 		(object->disp_recordoffset) +
+ 		(unsigned int)(bp->object_info_tbl_offset);
+ 
+-	for (;;) {
++	for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
+ 
+ 		record_header = (struct atom_common_record_header *)
+ 			GET_IMAGE(struct atom_common_record_header,
+@@ -3269,6 +3277,7 @@ static enum bp_result update_slot_layout_info_v2(
+ 	struct slot_layout_info *slot_layout_info)
+ {
+ 	unsigned int record_offset;
++	unsigned int n;
+ 	struct atom_display_object_path_v3 *object;
+ 	struct atom_bracket_layout_record_v2 *record;
+ 	struct atom_common_record_header *record_header;
+@@ -3291,7 +3300,7 @@ static enum bp_result update_slot_layout_info_v2(
+ 		(object->disp_recordoffset) +
+ 		(unsigned int)(bp->object_info_tbl_offset);
+ 
+-	for (;;) {
++	for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
+ 
+ 		record_header = (struct atom_common_record_header *)
+ 			GET_IMAGE(struct atom_common_record_header,
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
+index e1b4a40a353db1..da1e30de3c59a0 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
+@@ -38,4 +38,9 @@ uint32_t bios_get_vga_enabled_displays(struct dc_bios *bios);
+ 
+ #define GET_IMAGE(type, offset) ((type *) bios_get_image(&bp->base, offset, sizeof(type)))
+ 
++/* Upper bound on the number of records in a VBIOS record chain. Prevents
++ * unbounded looping if the VBIOS image is malformed and lacks a terminator.
++ */
++#define BIOS_MAX_NUM_RECORD 256
++
+ #endif
+-- 
+2.53.0
+
diff --git a/queue-6.6/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch b/queue-6.6/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
new file mode 100644
index 0000000..97d57c3
--- /dev/null
+++ b/queue-6.6/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
@@ -0,0 +1,63 @@
+From 0e818f17826d30aa7afd0b445265f2016481ae3a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 14:50:15 -0300
+Subject: drm/v3d: Skip CSD when it has zeroed workgroups
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Maíra Canal <mcanal@igalia.com>
+
+[ Upstream commit 7f93fad5ea0affc9e1505dd0f7596c0fdb496213 ]
+
+A compute shader dispatch encodes its workgroup counts in the CFG0..CFG2
+registers. Kicking off a dispatch with a zero count in any of the three
+dimensions is invalid. First, the hardware will process 0 as 65536,
+while the user-space driver exposes a maximum of 65535. Over that, a
+submission with a zeroed workgroup dimension should be a no-op.
+
+These zeroed counts can reach the dispatch path through an indirect CSD
+job, whose workgroup counts are only known once the indirect buffer is
+read and may legitimately be zero, but such scenario should only result in
+a no-op.
+
+Overwrite the indirect CSD job workgroup counts with the indirect BO
+ones, even if they are zeroed, and don't submit the job to the hardware
+when any of the workgroup counts is zero, so the job completes immediately
+instead of running the shader.
+
+Cc: stable@vger.kernel.org
+Fixes: d223f98f0209 ("drm/v3d: Add support for compute shader dispatch.")
+Suggested-by: Jose Maria Casanova Crespo <jmcasanova@igalia.com>
+Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
+Link: https://patch.msgid.link/20260602-v3d-fix-indirect-csd-v4-2-654309e32bc0@igalia.com
+Signed-off-by: Maíra Canal <mcanal@igalia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/v3d/v3d_sched.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
+index ff91cdb75bb912..ab872bc818004a 100644
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -234,6 +234,16 @@ v3d_csd_job_run(struct drm_sched_job *sched_job)
+ 		return NULL;
+ 	}
+ 
++	/* The HW interprets a workgroup size of 0 as 65536; however, the
++	 * user-space driver exposes a maximum of 65535. Therefore, a 0 in
++	 * any dimension means that we have no workgroups and the compute
++	 * shader should not be dispatched.
++	 */
++	if (!V3D_GET_FIELD(job->args.cfg[0], V3D_CSD_QUEUED_CFG0_NUM_WGS_X) ||
++	    !V3D_GET_FIELD(job->args.cfg[1], V3D_CSD_QUEUED_CFG1_NUM_WGS_Y) ||
++	    !V3D_GET_FIELD(job->args.cfg[2], V3D_CSD_QUEUED_CFG2_NUM_WGS_Z))
++		return NULL;
++
+ 	v3d->queue[V3D_CSD].active_job = &job->base;
+ 
+ 	v3d_invalidate_caches(v3d);
+-- 
+2.53.0
+
diff --git a/queue-6.6/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch b/queue-6.6/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
new file mode 100644
index 0000000..f6bacdd
--- /dev/null
+++ b/queue-6.6/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
@@ -0,0 +1,237 @@
+From a1f8c052790ca504293f974ba90e731f223f4dfd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Aug 2025 11:18:59 -0300
+Subject: drm/v3d: Store the active job inside the queue's state
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Maíra Canal <mcanal@igalia.com>
+
+[ Upstream commit 0d3768826d38c0ac740f8b45cd13346630535f2b ]
+
+Instead of storing the queue's active job in four different variables,
+store the active job inside the queue's state. This way, it's possible
+to access all active jobs using an index based in `enum v3d_queue`.
+
+Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
+Reviewed-by: Melissa Wen <mwen@igalia.com>
+Link: https://lore.kernel.org/r/20250826-v3d-queue-lock-v3-2-979efc43e490@igalia.com
+Signed-off-by: Maíra Canal <mcanal@igalia.com>
+Stable-dep-of: 7f93fad5ea0a ("drm/v3d: Skip CSD when it has zeroed workgroups")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/v3d/v3d_drv.h   |  8 +++-----
+ drivers/gpu/drm/v3d/v3d_gem.c   |  5 +++--
+ drivers/gpu/drm/v3d/v3d_irq.c   | 24 ++++++++++++++----------
+ drivers/gpu/drm/v3d/v3d_sched.c | 26 ++++++++++++++++++--------
+ 4 files changed, 38 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
+index bcef978ba9c4ca..91ea0a80879a9b 100644
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -26,6 +26,9 @@ struct v3d_queue_state {
+ 
+ 	u64 fence_context;
+ 	u64 emit_seqno;
++
++	/* Currently active job for this queue */
++	struct v3d_job *active_job;
+ };
+ 
+ /* Performance monitor object. The perform lifetime is controlled by userspace
+@@ -110,11 +113,6 @@ struct v3d_dev {
+ 
+ 	struct work_struct overflow_mem_work;
+ 
+-	struct v3d_bin_job *bin_job;
+-	struct v3d_render_job *render_job;
+-	struct v3d_tfu_job *tfu_job;
+-	struct v3d_csd_job *csd_job;
+-
+ 	struct v3d_queue_state queue[V3D_MAX_QUEUES];
+ 
+ 	/* Spinlock used to synchronize the overflow memory
+diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
+index 057f9525a8a422..f14c9f7143355c 100644
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -1071,14 +1071,15 @@ void
+ v3d_gem_destroy(struct drm_device *dev)
+ {
+ 	struct v3d_dev *v3d = to_v3d_dev(dev);
++	enum v3d_queue q;
+ 
+ 	v3d_sched_fini(v3d);
+ 
+ 	/* Waiting for jobs to finish would need to be done before
+ 	 * unregistering V3D.
+ 	 */
+-	WARN_ON(v3d->bin_job);
+-	WARN_ON(v3d->render_job);
++	for (q = 0; q < V3D_MAX_QUEUES; q++)
++		WARN_ON(v3d->queue[q].active_job);
+ 
+ 	drm_mm_takedown(&v3d->mm);
+ 
+diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c
+index 641315dbee8b29..1717504742a665 100644
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -40,6 +40,8 @@ v3d_overflow_mem_work(struct work_struct *work)
+ 		container_of(work, struct v3d_dev, overflow_mem_work);
+ 	struct drm_device *dev = &v3d->drm;
+ 	struct v3d_bo *bo = v3d_bo_create(dev, NULL /* XXX: GMP */, 256 * 1024);
++	struct v3d_queue_state *queue = &v3d->queue[V3D_BIN];
++	struct v3d_bin_job *bin_job;
+ 	struct drm_gem_object *obj;
+ 	unsigned long irqflags;
+ 
+@@ -59,13 +61,15 @@ v3d_overflow_mem_work(struct work_struct *work)
+ 	 * some binner pool anyway.
+ 	 */
+ 	spin_lock_irqsave(&v3d->job_lock, irqflags);
+-	if (!v3d->bin_job) {
++	bin_job = (struct v3d_bin_job *)queue->active_job;
++
++	if (!bin_job) {
+ 		spin_unlock_irqrestore(&v3d->job_lock, irqflags);
+ 		goto out;
+ 	}
+ 
+ 	drm_gem_object_get(obj);
+-	list_add_tail(&bo->unref_head, &v3d->bin_job->render->unref_list);
++	list_add_tail(&bo->unref_head, &bin_job->render->unref_list);
+ 	spin_unlock_irqrestore(&v3d->job_lock, irqflags);
+ 
+ 	V3D_CORE_WRITE(0, V3D_PTB_BPOA, bo->node.start << PAGE_SHIFT);
+@@ -99,11 +103,11 @@ v3d_irq(int irq, void *arg)
+ 
+ 	if (intsts & V3D_INT_FLDONE) {
+ 		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->bin_job->base.irq_fence);
++			to_v3d_fence(v3d->queue[V3D_BIN].active_job->irq_fence);
+ 
+ 		trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
+ 
+-		v3d->bin_job = NULL;
++		v3d->queue[V3D_BIN].active_job = NULL;
+ 		dma_fence_signal(&fence->base);
+ 
+ 		status = IRQ_HANDLED;
+@@ -111,11 +115,11 @@ v3d_irq(int irq, void *arg)
+ 
+ 	if (intsts & V3D_INT_FRDONE) {
+ 		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->render_job->base.irq_fence);
++			to_v3d_fence(v3d->queue[V3D_RENDER].active_job->irq_fence);
+ 
+ 		trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
+ 
+-		v3d->render_job = NULL;
++		v3d->queue[V3D_RENDER].active_job = NULL;
+ 		dma_fence_signal(&fence->base);
+ 
+ 		status = IRQ_HANDLED;
+@@ -123,11 +127,11 @@ v3d_irq(int irq, void *arg)
+ 
+ 	if (intsts & V3D_INT_CSDDONE) {
+ 		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->csd_job->base.irq_fence);
++			to_v3d_fence(v3d->queue[V3D_CSD].active_job->irq_fence);
+ 
+ 		trace_v3d_csd_irq(&v3d->drm, fence->seqno);
+ 
+-		v3d->csd_job = NULL;
++		v3d->queue[V3D_CSD].active_job = NULL;
+ 		dma_fence_signal(&fence->base);
+ 
+ 		status = IRQ_HANDLED;
+@@ -162,11 +166,11 @@ v3d_hub_irq(int irq, void *arg)
+ 
+ 	if (intsts & V3D_HUB_INT_TFUC) {
+ 		struct v3d_fence *fence =
+-			to_v3d_fence(v3d->tfu_job->base.irq_fence);
++			to_v3d_fence(v3d->queue[V3D_TFU].active_job->irq_fence);
+ 
+ 		trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
+ 
+-		v3d->tfu_job = NULL;
++		v3d->queue[V3D_TFU].active_job = NULL;
+ 		dma_fence_signal(&fence->base);
+ 
+ 		status = IRQ_HANDLED;
+diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
+index 41493cf3d03b81..ff91cdb75bb912 100644
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -80,14 +80,18 @@ static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
+ 	struct dma_fence *fence;
+ 	unsigned long irqflags;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		spin_lock_irqsave(&v3d->job_lock, irqflags);
++		v3d->queue[V3D_BIN].active_job = NULL;
++		spin_unlock_irqrestore(&v3d->job_lock, irqflags);
+ 		return NULL;
++	}
+ 
+ 	/* Lock required around bin_job update vs
+ 	 * v3d_overflow_mem_work().
+ 	 */
+ 	spin_lock_irqsave(&v3d->job_lock, irqflags);
+-	v3d->bin_job = job;
++	v3d->queue[V3D_BIN].active_job = &job->base;
+ 	/* Clear out the overflow allocation, so we don't
+ 	 * reuse the overflow attached to a previous job.
+ 	 */
+@@ -134,10 +138,12 @@ static struct dma_fence *v3d_render_job_run(struct drm_sched_job *sched_job)
+ 	struct drm_device *dev = &v3d->drm;
+ 	struct dma_fence *fence;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		v3d->queue[V3D_RENDER].active_job = NULL;
+ 		return NULL;
++	}
+ 
+-	v3d->render_job = job;
++	v3d->queue[V3D_RENDER].active_job = &job->base;
+ 
+ 	/* Can we avoid this flush?  We need to be careful of
+ 	 * scheduling, though -- imagine job0 rendering to texture and
+@@ -179,10 +185,12 @@ v3d_tfu_job_run(struct drm_sched_job *sched_job)
+ 	struct drm_device *dev = &v3d->drm;
+ 	struct dma_fence *fence;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		v3d->queue[V3D_TFU].active_job = NULL;
+ 		return NULL;
++	}
+ 
+-	v3d->tfu_job = job;
++	v3d->queue[V3D_TFU].active_job = &job->base;
+ 
+ 	fence = v3d_fence_create(v3d, V3D_TFU);
+ 	if (IS_ERR(fence))
+@@ -221,10 +229,12 @@ v3d_csd_job_run(struct drm_sched_job *sched_job)
+ 	struct dma_fence *fence;
+ 	int i;
+ 
+-	if (unlikely(job->base.base.s_fence->finished.error))
++	if (unlikely(job->base.base.s_fence->finished.error)) {
++		v3d->queue[V3D_CSD].active_job = NULL;
+ 		return NULL;
++	}
+ 
+-	v3d->csd_job = job;
++	v3d->queue[V3D_CSD].active_job = &job->base;
+ 
+ 	v3d_invalidate_caches(v3d);
+ 
+-- 
+2.53.0
+
diff --git a/queue-6.6/ip6_vti-set-netns_immutable-on-the-fallback-device.patch b/queue-6.6/ip6_vti-set-netns_immutable-on-the-fallback-device.patch
new file mode 100644
index 0000000..9e938de
--- /dev/null
+++ b/queue-6.6/ip6_vti-set-netns_immutable-on-the-fallback-device.patch
@@ -0,0 +1,49 @@
+From 0dbd97c588c0c85fd82d1a21dc6c2057f68926f6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Jun 2026 15:59:18 +0000
+Subject: ip6_vti: set netns_immutable on the fallback device.
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d289d5307762d1838aaece22c6b6fcad9e8865f9 ]
+
+john1988 and Noam Rathaus reported that vti6_init_net() does not set the
+netns_immutable flag on the per-netns fallback tunnel device (ip6_vti0).
+
+Other similar tunnel drivers (like ip6_tunnel, sit, ip6_gre, and ip_tunnel)
+correctly set this flag during their fallback device initialization to
+prevent them from being moved to another network namespace.
+
+Fixes: 61220ab34948 ("vti6: Enable namespace changing")
+Reported-by: Noam Rathaus <noamr@ssd-disclosure.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Steffen Klassert <steffen.klassert@secunet.com>
+Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260608155918.787644-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[Salvatore Bonaccorso: Backport for version without 0c493da86374 ("net:
+rename netns_local to netns_immutable") in v6.15-rc1 and without
+05c1280a2bcf ("netdev_features: convert NETIF_F_NETNS_LOCAL to
+dev->netns_local") in v6.12-rc1 and use NETIF_F_NETNS_LOCAL device
+feature.]
+Signed-off-by: Salvatore Bonaccorso <carnil@debian.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/ip6_vti.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
+index 67cf616c1499a4..95cf8c52953c2f 100644
+--- a/net/ipv6/ip6_vti.c
++++ b/net/ipv6/ip6_vti.c
+@@ -1166,6 +1166,7 @@ static int __net_init vti6_init_net(struct net *net)
+ 		goto err_alloc_dev;
+ 	dev_net_set(ip6n->fb_tnl_dev, net);
+ 	ip6n->fb_tnl_dev->rtnl_link_ops = &vti6_link_ops;
++	ip6n->fb_tnl_dev->features |= NETIF_F_NETNS_LOCAL;
+ 
+ 	err = vti6_fb_tnl_dev_init(ip6n->fb_tnl_dev);
+ 	if (err < 0)
+-- 
+2.53.0
+
diff --git a/queue-6.6/series b/queue-6.6/series
index bef91ff..a07ea87 100644
--- a/queue-6.6/series
+++ b/queue-6.6/series
@@ -1,2 +1,6 @@
 fuse-limit-fuse_notify_retrieve-to-uptodate-folios.patch
 net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch
+drm-amd-display-bound-vbios-record-chain-walk-loops.patch
+ip6_vti-set-netns_immutable-on-the-fallback-device.patch
+drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
+drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
diff --git a/queue-7.0/arm64-entry-fix-arm64-specific-rseq-brokenness.patch b/queue-7.0/arm64-entry-fix-arm64-specific-rseq-brokenness.patch
new file mode 100644
index 0000000..00621c7
--- /dev/null
+++ b/queue-7.0/arm64-entry-fix-arm64-specific-rseq-brokenness.patch
@@ -0,0 +1,217 @@
+From 1ef7ce634a34929b43c99937f674cf9f02b41fb8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Jun 2026 16:14:26 +0100
+Subject: arm64/entry: Fix arm64-specific rseq brokenness
+
+From: Mark Rutland <mark.rutland@arm.com>
+
+commit 411c1cf430392c905e39f12bc305dd994da0b426 upstream.
+
+Mathias Stearn reports that since v6.19, there are two big issues
+affecting rseq:
+
+(1) On arm64 specifically, rseq critical sections aren't aborted when
+    they should be.
+
+(2) The 'cpu_id_start' field is no longer written by the kernel in all
+    cases it used to be, including some cases where TCMalloc depends on
+    the kernel clobbering the field.
+
+This patch fixes issue #1. This patch DOES NOT fix issue #2, which will
+need to be addressed by other patches.
+
+The arm64-specific brokenness is a result of commits:
+
+  2fc0e4b4126c ("rseq: Record interrupt from user space")
+  39a167560a61 ("rseq: Optimize event setting")
+
+The first commit failed to add a call to rseq_note_user_irq_entry() on
+arm64. Thus arm64 never sets rseq_event::user_irq to record that it may
+be necessary to abort an active rseq critical section upon return to
+userspace. On its own, this commit had no functional impact as the value
+of rseq_event::user_irq was not consumed.
+
+The second commit relied upon rseq_event::user_irq to determine whether
+or not to bother to perform rseq work when returning to userspace. As
+rseq_event::user_irq wasn't set on arm64, this work would be skipped,
+and consequently an active rseq critical section would not be aborted.
+
+Fix this by giving arm64 syscall-specific entry/exit paths, and
+performing the relevant logic in syscall and non-syscall paths,
+including calling rseq_note_user_irq_entry() for non-syscall entry.
+
+Currently arm64 cannot use syscall_enter_from_user_mode(),
+syscall_exit_to_user_mode(), and irqentry_exit_to_user_mode(), due to
+ordering constraints with exception masking, and risk of ABI breakage
+for syscall tracing/audit/etc. For the moment the entry/exit logic is
+left as arm64-specific, directly using enter_from_user_mode() and
+exit_to_user_mode(), but mirroring the generic code.
+
+I intend to follow up with refactoring/cleanup, as we did for kernel
+mode entry paths in commit:
+
+  041aa7a85390 ("entry: Split preemption from irqentry_exit_to_kernel_mode()")
+
+... which will allow arm64 to use the GENERIC_IRQ_ENTRY functions directly.
+
+Fixes: 39a167560a61 ("rseq: Optimize event setting")
+Reported-by: Mathias Stearn <mathias@mongodb.com>
+Signed-off-by: Mark Rutland <mark.rutland@arm.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Acked-by: Catalin Marinas <catalin.marinas@arm.com>
+Link: https://lore.kernel.org/regressions/CAHnCjA25b+nO2n5CeifknSKHssJpPrjnf+dtr7UgzRw4Zgu=oA@mail.gmail.com/
+Link: https://patch.msgid.link/20260508142023.3268622-1-mark.rutland@arm.com
+[Mark: fix conflicts in entry-common.c & irq-entry-common.h]
+Signed-off-by: Mark Rutland <mark.rutland@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/kernel/entry-common.c | 29 ++++++++++++++++++++++-------
+ include/linux/irq-entry-common.h |  8 --------
+ include/linux/rseq_entry.h       | 19 -------------------
+ 3 files changed, 22 insertions(+), 34 deletions(-)
+
+diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
+index 3625797e9ee8f9..e3614cedaf23e7 100644
+--- a/arch/arm64/kernel/entry-common.c
++++ b/arch/arm64/kernel/entry-common.c
+@@ -58,6 +58,12 @@ static void noinstr exit_to_kernel_mode(struct pt_regs *regs,
+ 	irqentry_exit(regs, state);
+ }
+ 
++static __always_inline void arm64_syscall_enter_from_user_mode(struct pt_regs *regs)
++{
++	enter_from_user_mode(regs);
++	mte_disable_tco_entry(current);
++}
++
+ /*
+  * Handle IRQ/context state management when entering from user mode.
+  * Before this function is called it is not safe to call regular kernel code,
+@@ -66,19 +72,28 @@ static void noinstr exit_to_kernel_mode(struct pt_regs *regs,
+ static __always_inline void arm64_enter_from_user_mode(struct pt_regs *regs)
+ {
+ 	enter_from_user_mode(regs);
++	rseq_note_user_irq_entry();
+ 	mte_disable_tco_entry(current);
+ }
+ 
++static __always_inline void arm64_syscall_exit_to_user_mode(struct pt_regs *regs)
++{
++	local_irq_disable();
++	syscall_exit_to_user_mode_prepare(regs);
++	local_daif_mask();
++	mte_check_tfsr_exit();
++	exit_to_user_mode();
++}
++
+ /*
+  * Handle IRQ/context state management when exiting to user mode.
+  * After this function returns it is not safe to call regular kernel code,
+  * instrumentable code, or any code which may trigger an exception.
+  */
+-
+ static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs)
+ {
+ 	local_irq_disable();
+-	exit_to_user_mode_prepare_legacy(regs);
++	irqentry_exit_to_user_mode_prepare(regs);
+ 	local_daif_mask();
+ 	mte_check_tfsr_exit();
+ 	exit_to_user_mode();
+@@ -86,7 +101,7 @@ static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs)
+ 
+ asmlinkage void noinstr asm_exit_to_user_mode(struct pt_regs *regs)
+ {
+-	arm64_exit_to_user_mode(regs);
++	arm64_syscall_exit_to_user_mode(regs);
+ }
+ 
+ /*
+@@ -717,12 +732,12 @@ static void noinstr el0_brk64(struct pt_regs *regs, unsigned long esr)
+ 
+ static void noinstr el0_svc(struct pt_regs *regs)
+ {
+-	arm64_enter_from_user_mode(regs);
++	arm64_syscall_enter_from_user_mode(regs);
+ 	cortex_a76_erratum_1463225_svc_handler();
+ 	fpsimd_syscall_enter();
+ 	local_daif_restore(DAIF_PROCCTX);
+ 	do_el0_svc(regs);
+-	arm64_exit_to_user_mode(regs);
++	arm64_syscall_exit_to_user_mode(regs);
+ 	fpsimd_syscall_exit();
+ }
+ 
+@@ -869,11 +884,11 @@ static void noinstr el0_cp15(struct pt_regs *regs, unsigned long esr)
+ 
+ static void noinstr el0_svc_compat(struct pt_regs *regs)
+ {
+-	arm64_enter_from_user_mode(regs);
++	arm64_syscall_enter_from_user_mode(regs);
+ 	cortex_a76_erratum_1463225_svc_handler();
+ 	local_daif_restore(DAIF_PROCCTX);
+ 	do_el0_svc_compat(regs);
+-	arm64_exit_to_user_mode(regs);
++	arm64_syscall_exit_to_user_mode(regs);
+ }
+ 
+ static void noinstr el0_bkpt32(struct pt_regs *regs, unsigned long esr)
+diff --git a/include/linux/irq-entry-common.h b/include/linux/irq-entry-common.h
+index d26d1b1bcbfb97..6519b4a30dc1dd 100644
+--- a/include/linux/irq-entry-common.h
++++ b/include/linux/irq-entry-common.h
+@@ -236,14 +236,6 @@ static __always_inline void __exit_to_user_mode_validate(void)
+ 	lockdep_sys_exit();
+ }
+ 
+-/* Temporary workaround to keep ARM64 alive */
+-static __always_inline void exit_to_user_mode_prepare_legacy(struct pt_regs *regs)
+-{
+-	__exit_to_user_mode_prepare(regs);
+-	rseq_exit_to_user_mode_legacy();
+-	__exit_to_user_mode_validate();
+-}
+-
+ /**
+  * syscall_exit_to_user_mode_prepare - call exit_to_user_mode_loop() if required
+  * @regs:	Pointer to pt_regs on entry stack
+diff --git a/include/linux/rseq_entry.h b/include/linux/rseq_entry.h
+index 69bdb93951b904..bbe190269f79aa 100644
+--- a/include/linux/rseq_entry.h
++++ b/include/linux/rseq_entry.h
+@@ -740,24 +740,6 @@ static __always_inline void rseq_irqentry_exit_to_user_mode(void)
+ 	ev->events = 0;
+ }
+ 
+-/* Required to keep ARM64 working */
+-static __always_inline void rseq_exit_to_user_mode_legacy(void)
+-{
+-	struct rseq_event *ev = &current->rseq.event;
+-
+-	rseq_stat_inc(rseq_stats.exit);
+-
+-	if (static_branch_unlikely(&rseq_debug_enabled))
+-		WARN_ON_ONCE(ev->sched_switch);
+-
+-	/*
+-	 * Ensure that event (especially user_irq) is cleared when the
+-	 * interrupt did not result in a schedule and therefore the
+-	 * rseq processing did not clear it.
+-	 */
+-	ev->events = 0;
+-}
+-
+ void __rseq_debug_syscall_return(struct pt_regs *regs);
+ 
+ static __always_inline void rseq_debug_syscall_return(struct pt_regs *regs)
+@@ -773,7 +755,6 @@ static inline bool rseq_exit_to_user_mode_restart(struct pt_regs *regs, unsigned
+ }
+ static inline void rseq_syscall_exit_to_user_mode(void) { }
+ static inline void rseq_irqentry_exit_to_user_mode(void) { }
+-static inline void rseq_exit_to_user_mode_legacy(void) { }
+ static inline void rseq_debug_syscall_return(struct pt_regs *regs) { }
+ static inline bool rseq_grant_slice_extension(bool work_pending) { return false; }
+ #endif /* !CONFIG_RSEQ */
+-- 
+2.53.0
+
diff --git a/queue-7.0/series b/queue-7.0/series
index 7dd13f0..b09b947 100644
--- a/queue-7.0/series
+++ b/queue-7.0/series
@@ -1 +1,2 @@
 io_uring-net-avoid-msghdr-on-op_connect-op_bind-asyn.patch
+arm64-entry-fix-arm64-specific-rseq-brokenness.patch