]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for all trees master
authorSasha Levin <sashal@kernel.org>
Sat, 20 Jun 2026 11:54:30 +0000 (07:54 -0400)
committerSasha Levin <sashal@kernel.org>
Sat, 20 Jun 2026 11:54:30 +0000 (07:54 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
37 files changed:
queue-5.10/drm-amd-display-bound-vbios-record-chain-walk-loops.patch [new file with mode: 0644]
queue-5.10/drm-amd-display-use-krealloc_array-in-dal_vector_res.patch [new file with mode: 0644]
queue-5.10/ip6_vti-set-netns_immutable-on-the-fallback-device.patch [new file with mode: 0644]
queue-5.10/net-9p-fix-refcount-leak-in-p9_read_work-error-handl.patch [new file with mode: 0644]
queue-5.10/net-add-skb_header_pointer_careful-helper.patch [new file with mode: 0644]
queue-5.10/net-sched-cls_u32-use-skb_header_pointer_careful.patch [new file with mode: 0644]
queue-5.10/netdevsim-fix-memory-leak-of-nsim_dev-fa_cookie.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/slimbus-qcom-ngd-ctrl-register-callbacks-after-creat.patch [new file with mode: 0644]
queue-5.15/drm-amd-display-bound-vbios-record-chain-walk-loops.patch [new file with mode: 0644]
queue-5.15/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch [new file with mode: 0644]
queue-5.15/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch [new file with mode: 0644]
queue-5.15/ip6_vti-set-netns_immutable-on-the-fallback-device.patch [new file with mode: 0644]
queue-5.15/series
queue-6.1/drm-amd-display-bound-vbios-record-chain-walk-loops.patch [new file with mode: 0644]
queue-6.1/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch [new file with mode: 0644]
queue-6.1/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch [new file with mode: 0644]
queue-6.1/ip6_vti-set-netns_immutable-on-the-fallback-device.patch [new file with mode: 0644]
queue-6.1/netfilter-nf_tables-always-increment-set-element-cou.patch [new file with mode: 0644]
queue-6.1/netfilter-nf_tables-fix-set-size-with-rbtree-backend.patch [new file with mode: 0644]
queue-6.1/netfilter-nf_tables-unconditionally-bump-set-nelems-.patch [new file with mode: 0644]
queue-6.1/selftests-bpf-check-for-timeout-in-perf_link-test.patch [new file with mode: 0644]
queue-6.1/selftests-bpf-move-get_time_ns-to-testing_helpers.h.patch [new file with mode: 0644]
queue-6.1/series
queue-6.12/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch [new file with mode: 0644]
queue-6.12/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch [new file with mode: 0644]
queue-6.12/drm-xe-display-fix-oops-in-suspend-shutdown-without-.patch [new file with mode: 0644]
queue-6.12/series
queue-6.18/net-stmmac-fix-stm32-and-potentially-others-resume-r.patch [new file with mode: 0644]
queue-6.18/series
queue-6.6/drm-amd-display-bound-vbios-record-chain-walk-loops.patch [new file with mode: 0644]
queue-6.6/drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch [new file with mode: 0644]
queue-6.6/drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch [new file with mode: 0644]
queue-6.6/ip6_vti-set-netns_immutable-on-the-fallback-device.patch [new file with mode: 0644]
queue-6.6/series
queue-7.0/arm64-entry-fix-arm64-specific-rseq-brokenness.patch [new file with mode: 0644]
queue-7.0/series

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