--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
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
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
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
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
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
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
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
--- /dev/null
+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
+
io_uring-net-avoid-msghdr-on-op_connect-op_bind-asyn.patch
+net-stmmac-fix-stm32-and-potentially-others-resume-r.patch
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
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
--- /dev/null
+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 = ¤t->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
+
io_uring-net-avoid-msghdr-on-op_connect-op_bind-asyn.patch
+arm64-entry-fix-arm64-specific-rseq-brokenness.patch