From: Sasha Levin Date: Sat, 30 Aug 2025 16:55:51 +0000 (-0400) Subject: Fixes for all trees X-Git-Tag: v5.4.298~25 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d04c473acc168e1de56a675f81bacb4cd3c207d4;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch b/queue-5.10/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch new file mode 100644 index 0000000000..f84882061f --- /dev/null +++ b/queue-5.10/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch @@ -0,0 +1,192 @@ +From feb6a428abd6148be60e7e5789455671b7111e0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Aug 2025 02:18:24 +0000 +Subject: atm: atmtcp: Prevent arbitrary write in atmtcp_recv_control(). + +From: Kuniyuki Iwashima + +[ Upstream commit ec79003c5f9d2c7f9576fc69b8dbda80305cbe3a ] + +syzbot reported the splat below. [0] + +When atmtcp_v_open() or atmtcp_v_close() is called via connect() +or close(), atmtcp_send_control() is called to send an in-kernel +special message. + +The message has ATMTCP_HDR_MAGIC in atmtcp_control.hdr.length. +Also, a pointer of struct atm_vcc is set to atmtcp_control.vcc. + +The notable thing is struct atmtcp_control is uAPI but has a +space for an in-kernel pointer. + + struct atmtcp_control { + struct atmtcp_hdr hdr; /* must be first */ + ... + atm_kptr_t vcc; /* both directions */ + ... + } __ATM_API_ALIGN; + + typedef struct { unsigned char _[8]; } __ATM_API_ALIGN atm_kptr_t; + +The special message is processed in atmtcp_recv_control() called +from atmtcp_c_send(). + +atmtcp_c_send() is vcc->dev->ops->send() and called from 2 paths: + + 1. .ndo_start_xmit() (vcc->send() == atm_send_aal0()) + 2. vcc_sendmsg() + +The problem is sendmsg() does not validate the message length and +userspace can abuse atmtcp_recv_control() to overwrite any kptr +by atmtcp_control. + +Let's add a new ->pre_send() hook to validate messages from sendmsg(). + +[0]: +Oops: general protection fault, probably for non-canonical address 0xdffffc00200000ab: 0000 [#1] SMP KASAN PTI +KASAN: probably user-memory-access in range [0x0000000100000558-0x000000010000055f] +CPU: 0 UID: 0 PID: 5865 Comm: syz-executor331 Not tainted 6.17.0-rc1-syzkaller-00215-gbab3ce404553 #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/12/2025 +RIP: 0010:atmtcp_recv_control drivers/atm/atmtcp.c:93 [inline] +RIP: 0010:atmtcp_c_send+0x1da/0x950 drivers/atm/atmtcp.c:297 +Code: 4d 8d 75 1a 4c 89 f0 48 c1 e8 03 42 0f b6 04 20 84 c0 0f 85 15 06 00 00 41 0f b7 1e 4d 8d b7 60 05 00 00 4c 89 f0 48 c1 e8 03 <42> 0f b6 04 20 84 c0 0f 85 13 06 00 00 66 41 89 1e 4d 8d 75 1c 4c +RSP: 0018:ffffc90003f5f810 EFLAGS: 00010203 +RAX: 00000000200000ab RBX: 0000000000000000 RCX: 0000000000000000 +RDX: ffff88802a510000 RSI: 00000000ffffffff RDI: ffff888030a6068c +RBP: ffff88802699fb40 R08: ffff888030a606eb R09: 1ffff1100614c0dd +R10: dffffc0000000000 R11: ffffffff8718fc40 R12: dffffc0000000000 +R13: ffff888030a60680 R14: 000000010000055f R15: 00000000ffffffff +FS: 00007f8d7e9236c0(0000) GS:ffff888125c1c000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 000000000045ad50 CR3: 0000000075bde000 CR4: 00000000003526f0 +Call Trace: + + vcc_sendmsg+0xa10/0xc60 net/atm/common.c:645 + sock_sendmsg_nosec net/socket.c:714 [inline] + __sock_sendmsg+0x219/0x270 net/socket.c:729 + ____sys_sendmsg+0x505/0x830 net/socket.c:2614 + ___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668 + __sys_sendmsg net/socket.c:2700 [inline] + __do_sys_sendmsg net/socket.c:2705 [inline] + __se_sys_sendmsg net/socket.c:2703 [inline] + __x64_sys_sendmsg+0x19b/0x260 net/socket.c:2703 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +RIP: 0033:0x7f8d7e96a4a9 +Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 51 18 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f8d7e923198 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +RAX: ffffffffffffffda RBX: 00007f8d7e9f4308 RCX: 00007f8d7e96a4a9 +RDX: 0000000000000000 RSI: 0000200000000240 RDI: 0000000000000005 +RBP: 00007f8d7e9f4300 R08: 65732f636f72702f R09: 65732f636f72702f +R10: 65732f636f72702f R11: 0000000000000246 R12: 00007f8d7e9c10ac +R13: 00007f8d7e9231a0 R14: 0000200000000200 R15: 0000200000000250 + +Modules linked in: + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+1741b56d54536f4ec349@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68a6767c.050a0220.3d78fd.0011.GAE@google.com/ +Tested-by: syzbot+1741b56d54536f4ec349@syzkaller.appspotmail.com +Signed-off-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250821021901.2814721-1-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/atm/atmtcp.c | 17 ++++++++++++++--- + include/linux/atmdev.h | 1 + + net/atm/common.c | 15 ++++++++++++--- + 3 files changed, 27 insertions(+), 6 deletions(-) + +diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c +index ff558908897f3..9c83fb29b2f1b 100644 +--- a/drivers/atm/atmtcp.c ++++ b/drivers/atm/atmtcp.c +@@ -279,6 +279,19 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) + return NULL; + } + ++static int atmtcp_c_pre_send(struct atm_vcc *vcc, struct sk_buff *skb) ++{ ++ struct atmtcp_hdr *hdr; ++ ++ if (skb->len < sizeof(struct atmtcp_hdr)) ++ return -EINVAL; ++ ++ hdr = (struct atmtcp_hdr *)skb->data; ++ if (hdr->length == ATMTCP_HDR_MAGIC) ++ return -EINVAL; ++ ++ return 0; ++} + + static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + { +@@ -288,9 +301,6 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + struct sk_buff *new_skb; + int result = 0; + +- if (skb->len < sizeof(struct atmtcp_hdr)) +- goto done; +- + dev = vcc->dev_data; + hdr = (struct atmtcp_hdr *) skb->data; + if (hdr->length == ATMTCP_HDR_MAGIC) { +@@ -347,6 +357,7 @@ static const struct atmdev_ops atmtcp_v_dev_ops = { + + static const struct atmdev_ops atmtcp_c_dev_ops = { + .close = atmtcp_c_close, ++ .pre_send = atmtcp_c_pre_send, + .send = atmtcp_c_send + }; + +diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h +index bc24d19ec2b37..8cbb992f6293c 100644 +--- a/include/linux/atmdev.h ++++ b/include/linux/atmdev.h +@@ -185,6 +185,7 @@ struct atmdev_ops { /* only send is required */ + int (*compat_ioctl)(struct atm_dev *dev,unsigned int cmd, + void __user *arg); + #endif ++ int (*pre_send)(struct atm_vcc *vcc, struct sk_buff *skb); + int (*send)(struct atm_vcc *vcc,struct sk_buff *skb); + int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags); + void (*phy_put)(struct atm_dev *dev,unsigned char value, +diff --git a/net/atm/common.c b/net/atm/common.c +index 930eb302cd10f..38ed7b985f655 100644 +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -635,18 +635,27 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size) + + skb->dev = NULL; /* for paths shared with net_device interfaces */ + if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) { +- atm_return_tx(vcc, skb); +- kfree_skb(skb); + error = -EFAULT; +- goto out; ++ goto free_skb; + } + if (eff != size) + memset(skb->data + size, 0, eff-size); ++ ++ if (vcc->dev->ops->pre_send) { ++ error = vcc->dev->ops->pre_send(vcc, skb); ++ if (error) ++ goto free_skb; ++ } ++ + error = vcc->dev->ops->send(vcc, skb); + error = error ? error : size; + out: + release_sock(sk); + return error; ++free_skb: ++ atm_return_tx(vcc, skb); ++ kfree_skb(skb); ++ goto out; + } + + __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait) +-- +2.50.1 + diff --git a/queue-5.10/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch b/queue-5.10/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch new file mode 100644 index 0000000000..2312ebcb4c --- /dev/null +++ b/queue-5.10/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch @@ -0,0 +1,47 @@ +From c32f5b807b15b29b9216e66837ae79ead6b3d1ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Aug 2025 17:04:00 -0400 +Subject: Bluetooth: hci_event: Detect if HCI_EV_NUM_COMP_PKTS is unbalanced + +From: Luiz Augusto von Dentz + +[ Upstream commit 15bf2c6391bafb14a3020d06ec0761bce0803463 ] + +This attempts to detect if HCI_EV_NUM_COMP_PKTS contain an unbalanced +(more than currently considered outstanding) number of packets otherwise +it could cause the hcon->sent to underflow and loop around breaking the +tracking of the outstanding packets pending acknowledgment. + +Fixes: f42809185896 ("Bluetooth: Simplify num_comp_pkts_evt function") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 7f26c1aab9a06..c6dbb4aebfbc1 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -3811,7 +3811,17 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) + if (!conn) + continue; + +- conn->sent -= count; ++ /* Check if there is really enough packets outstanding before ++ * attempting to decrease the sent counter otherwise it could ++ * underflow.. ++ */ ++ if (conn->sent >= count) { ++ conn->sent -= count; ++ } else { ++ bt_dev_warn(hdev, "hcon %p sent %u < count %u", ++ conn, conn->sent, count); ++ conn->sent = 0; ++ } + + switch (conn->type) { + case ACL_LINK: +-- +2.50.1 + diff --git a/queue-5.10/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch b/queue-5.10/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch new file mode 100644 index 0000000000..4a2c47b159 --- /dev/null +++ b/queue-5.10/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch @@ -0,0 +1,77 @@ +From 46f2e902822a9af3b36ff11a7d7ec6f19e059c7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 15:39:54 +0800 +Subject: efivarfs: Fix slab-out-of-bounds in efivarfs_d_compare + +From: Li Nan + +[ Upstream commit a6358f8cf64850f3f27857b8ed8c1b08cfc4685c ] + +Observed on kernel 6.6 (present on master as well): + + BUG: KASAN: slab-out-of-bounds in memcmp+0x98/0xd0 + Call trace: + kasan_check_range+0xe8/0x190 + __asan_loadN+0x1c/0x28 + memcmp+0x98/0xd0 + efivarfs_d_compare+0x68/0xd8 + __d_lookup_rcu_op_compare+0x178/0x218 + __d_lookup_rcu+0x1f8/0x228 + d_alloc_parallel+0x150/0x648 + lookup_open.isra.0+0x5f0/0x8d0 + open_last_lookups+0x264/0x828 + path_openat+0x130/0x3f8 + do_filp_open+0x114/0x248 + do_sys_openat2+0x340/0x3c0 + __arm64_sys_openat+0x120/0x1a0 + +If dentry->d_name.len < EFI_VARIABLE_GUID_LEN , 'guid' can become +negative, leadings to oob. The issue can be triggered by parallel +lookups using invalid filename: + + T1 T2 + lookup_open + ->lookup + simple_lookup + d_add + // invalid dentry is added to hash list + + lookup_open + d_alloc_parallel + __d_lookup_rcu + __d_lookup_rcu_op_compare + hlist_bl_for_each_entry_rcu + // invalid dentry can be retrieved + ->d_compare + efivarfs_d_compare + // oob + +Fix it by checking 'guid' before cmp. + +Fixes: da27a24383b2 ("efivarfs: guid part of filenames are case-insensitive") +Signed-off-by: Li Nan +Signed-off-by: Wu Guanghao +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + fs/efivarfs/super.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c +index 99d002438008b..124db520b2bd6 100644 +--- a/fs/efivarfs/super.c ++++ b/fs/efivarfs/super.c +@@ -47,6 +47,10 @@ static int efivarfs_d_compare(const struct dentry *dentry, + { + int guid = len - EFI_VARIABLE_GUID_LEN; + ++ /* Parallel lookups may produce a temporary invalid filename */ ++ if (guid <= 0) ++ return 1; ++ + if (name->len != len) + return 1; + +-- +2.50.1 + diff --git a/queue-5.10/net-dlink-fix-multicast-stats-being-counted-incorrec.patch b/queue-5.10/net-dlink-fix-multicast-stats-being-counted-incorrec.patch new file mode 100644 index 0000000000..12a6aa1f46 --- /dev/null +++ b/queue-5.10/net-dlink-fix-multicast-stats-being-counted-incorrec.patch @@ -0,0 +1,46 @@ +From 3fe83a12405c50dbc0093f021716355383bb1239 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Aug 2025 03:29:24 +0900 +Subject: net: dlink: fix multicast stats being counted incorrectly + +From: Yeounsu Moon + +[ Upstream commit 007a5ffadc4fd51739527f1503b7cf048f31c413 ] + +`McstFramesRcvdOk` counts the number of received multicast packets, and +it reports the value correctly. + +However, reading `McstFramesRcvdOk` clears the register to zero. As a +result, the driver was reporting only the packets since the last read, +instead of the accumulated total. + +Fix this by updating the multicast statistics accumulatively instaed of +instantaneously. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Tested-on: D-Link DGE-550T Rev-A3 +Signed-off-by: Yeounsu Moon +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250823182927.6063-3-yyyynoom@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/dlink/dl2k.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c +index b7f992103da3c..af1e96e0209fc 100644 +--- a/drivers/net/ethernet/dlink/dl2k.c ++++ b/drivers/net/ethernet/dlink/dl2k.c +@@ -1095,7 +1095,7 @@ get_stats (struct net_device *dev) + dev->stats.rx_bytes += dr32(OctetRcvOk); + dev->stats.tx_bytes += dr32(OctetXmtOk); + +- dev->stats.multicast = dr32(McstFramesRcvdOk); ++ dev->stats.multicast += dr32(McstFramesRcvdOk); + dev->stats.collisions += dr32(SingleColFrames) + + dr32(MultiColFrames); + +-- +2.50.1 + diff --git a/queue-5.10/net-ipv4-fix-regression-in-local-broadcast-routes.patch b/queue-5.10/net-ipv4-fix-regression-in-local-broadcast-routes.patch new file mode 100644 index 0000000000..5cd7e2aecc --- /dev/null +++ b/queue-5.10/net-ipv4-fix-regression-in-local-broadcast-routes.patch @@ -0,0 +1,57 @@ +From 8c68cde06a0e806946122a7dc33ae099c05b6902 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 08:23:21 +0200 +Subject: net: ipv4: fix regression in local-broadcast routes + +From: Oscar Maes + +[ Upstream commit 5189446ba995556eaa3755a6e875bc06675b88bd ] + +Commit 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") +introduced a regression where local-broadcast packets would have their +gateway set in __mkroute_output, which was caused by fi = NULL being +removed. + +Fix this by resetting the fib_info for local-broadcast packets. This +preserves the intended changes for directed-broadcast packets. + +Cc: stable@vger.kernel.org +Fixes: 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") +Reported-by: Brett A C Sheffield +Closes: https://lore.kernel.org/regressions/20250822165231.4353-4-bacs@librecast.net +Signed-off-by: Oscar Maes +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20250827062322.4807-1-oscmaes92@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/route.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 7c4479adbf325..fbaed08600f0f 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -2452,12 +2452,16 @@ static struct rtable *__mkroute_output(const struct fib_result *res, + !netif_is_l3_master(dev_out)) + return ERR_PTR(-EINVAL); + +- if (ipv4_is_lbcast(fl4->daddr)) ++ if (ipv4_is_lbcast(fl4->daddr)) { + type = RTN_BROADCAST; +- else if (ipv4_is_multicast(fl4->daddr)) ++ ++ /* reset fi to prevent gateway resolution */ ++ fi = NULL; ++ } else if (ipv4_is_multicast(fl4->daddr)) { + type = RTN_MULTICAST; +- else if (ipv4_is_zeronet(fl4->daddr)) ++ } else if (ipv4_is_zeronet(fl4->daddr)) { + return ERR_PTR(-EINVAL); ++ } + + if (dev_out->flags & IFF_LOOPBACK) + flags |= RTCF_LOCAL; +-- +2.50.1 + diff --git a/queue-5.10/net-mlx5e-set-local-xoff-after-fw-update.patch b/queue-5.10/net-mlx5e-set-local-xoff-after-fw-update.patch new file mode 100644 index 0000000000..0f527c4285 --- /dev/null +++ b/queue-5.10/net-mlx5e-set-local-xoff-after-fw-update.patch @@ -0,0 +1,50 @@ +From d0049c813edf1f7090ac77f2be2f1367ac0478bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:34 +0300 +Subject: net/mlx5e: Set local Xoff after FW update + +From: Alexei Lazar + +[ Upstream commit aca0c31af61e0d5cf1675a0cbd29460b95ae693c ] + +The local Xoff value is being set before the firmware (FW) update. +In case of a failure where the FW is not updated with the new value, +there is no fallback to the previous value. +Update the local Xoff value after the FW has been successfully set. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Reviewed-by: Dragos Tatulea +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-12-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +index c9d5d8d93994d..7899a7230299d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +@@ -346,7 +346,6 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + if (err) + return err; + } +- priv->dcbx.xoff = xoff; + + /* Apply the settings */ + if (update_buffer) { +@@ -355,6 +354,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + return err; + } + ++ priv->dcbx.xoff = xoff; ++ + if (update_prio2buffer) + err = mlx5e_port_set_priority2buffer(priv->mdev, prio2buffer); + +-- +2.50.1 + diff --git a/queue-5.10/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch b/queue-5.10/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch new file mode 100644 index 0000000000..089f4a6b6d --- /dev/null +++ b/queue-5.10/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch @@ -0,0 +1,100 @@ +From 68c45b5d4899aecf1373f6c532344d8b8818d056 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:32 +0300 +Subject: net/mlx5e: Update and set Xon/Xoff upon MTU set + +From: Alexei Lazar + +[ Upstream commit ceddedc969f0532b7c62ca971ee50d519d2bc0cb ] + +Xon/Xoff sizes are derived from calculation that include the MTU size. +Set Xon/Xoff when MTU is set. +If Xon/Xoff fails, set the previous MTU. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-10-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/en/port_buffer.h | 12 ++++++++++++ + .../net/ethernet/mellanox/mlx5/core/en_main.c | 17 ++++++++++++++++- + 2 files changed, 28 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +index 80af7a5ac6046..a23e3d810f3e4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +@@ -63,11 +63,23 @@ struct mlx5e_port_buffer { + struct mlx5e_bufferx_reg buffer[MLX5E_MAX_BUFFER]; + }; + ++#ifdef CONFIG_MLX5_CORE_EN_DCB + int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + u32 change, unsigned int mtu, + struct ieee_pfc *pfc, + u32 *buffer_size, + u8 *prio2buffer); ++#else ++static inline int ++mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, ++ u32 change, unsigned int mtu, ++ void *pfc, ++ u32 *buffer_size, ++ u8 *prio2buffer) ++{ ++ return 0; ++} ++#endif + + int mlx5e_port_query_buffer(struct mlx5e_priv *priv, + struct mlx5e_port_buffer *port_buffer); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index c3ff1fc577a7c..cef60bc2589cc 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -42,6 +42,7 @@ + #include "eswitch.h" + #include "en.h" + #include "en/txrx.h" ++#include "en/port_buffer.h" + #include "en_tc.h" + #include "en_rep.h" + #include "en_accel/ipsec.h" +@@ -2874,9 +2875,11 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) + struct mlx5e_params *params = &priv->channels.params; + struct net_device *netdev = priv->netdev; + struct mlx5_core_dev *mdev = priv->mdev; +- u16 mtu; ++ u16 mtu, prev_mtu; + int err; + ++ mlx5e_query_mtu(mdev, params, &prev_mtu); ++ + err = mlx5e_set_mtu(mdev, params, params->sw_mtu); + if (err) + return err; +@@ -2886,6 +2889,18 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) + netdev_warn(netdev, "%s: VPort MTU %d is different than netdev mtu %d\n", + __func__, mtu, params->sw_mtu); + ++ if (mtu != prev_mtu && MLX5_BUFFER_SUPPORTED(mdev)) { ++ err = mlx5e_port_manual_buffer_config(priv, 0, mtu, ++ NULL, NULL, NULL); ++ if (err) { ++ netdev_warn(netdev, "%s: Failed to set Xon/Xoff values with MTU %d (err %d), setting back to previous MTU %d\n", ++ __func__, mtu, err, prev_mtu); ++ ++ mlx5e_set_mtu(mdev, params, prev_mtu); ++ return err; ++ } ++ } ++ + params->sw_mtu = mtu; + return 0; + } +-- +2.50.1 + diff --git a/queue-5.10/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch b/queue-5.10/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch new file mode 100644 index 0000000000..e5f76140e5 --- /dev/null +++ b/queue-5.10/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch @@ -0,0 +1,46 @@ +From e771bc39e892fe3eb9efb178f4613876b5e946d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:33 +0300 +Subject: net/mlx5e: Update and set Xon/Xoff upon port speed set + +From: Alexei Lazar + +[ Upstream commit d24341740fe48add8a227a753e68b6eedf4b385a ] + +Xon/Xoff sizes are derived from calculations that include +the port speed. +These settings need to be updated and applied whenever the +port speed is changed. +The port speed is typically set after the physical link goes down +and is negotiated as part of the link-up process between the two +connected interfaces. +Xon/Xoff parameters being updated at the point where the new +negotiated speed is established. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-11-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index cef60bc2589cc..cc93c503984a1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -141,6 +141,8 @@ void mlx5e_update_carrier(struct mlx5e_priv *priv) + if (port_state == VPORT_STATE_UP) { + netdev_info(priv->netdev, "Link up\n"); + netif_carrier_on(priv->netdev); ++ mlx5e_port_manual_buffer_config(priv, 0, priv->netdev->mtu, ++ NULL, NULL, NULL); + } else { + netdev_info(priv->netdev, "Link down\n"); + netif_carrier_off(priv->netdev); +-- +2.50.1 + diff --git a/queue-5.10/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch b/queue-5.10/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch new file mode 100644 index 0000000000..baac294f88 --- /dev/null +++ b/queue-5.10/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch @@ -0,0 +1,49 @@ +From 44900a377bd65e613869bfc5da8caff4955d6a4d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 12:36:52 +0800 +Subject: net: stmmac: xgmac: Do not enable RX FIFO Overflow interrupts + +From: Rohan G Thomas + +[ Upstream commit 4f23382841e67174211271a454811dd17c0ef3c5 ] + +Enabling RX FIFO Overflow interrupts is counterproductive +and causes an interrupt storm when RX FIFO overflows. +Disabling this interrupt has no side effect and eliminates +interrupt storms when the RX FIFO overflows. + +Commit 8a7cb245cf28 ("net: stmmac: Do not enable RX FIFO +overflow interrupts") disables RX FIFO overflow interrupts +for DWMAC4 IP and removes the corresponding handling of +this interrupt. This patch is doing the same thing for +XGMAC IP. + +Fixes: 2142754f8b9c ("net: stmmac: Add MAC related callbacks for XGMAC2") +Signed-off-by: Rohan G Thomas +Reviewed-by: Matthew Gerlach +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250825-xgmac-minor-fixes-v3-1-c225fe4444c0@altera.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +index a5583d706b9f2..e30bbe1933ec8 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +@@ -199,10 +199,6 @@ static void dwxgmac2_dma_rx_mode(void __iomem *ioaddr, int mode, + } + + writel(value, ioaddr + XGMAC_MTL_RXQ_OPMODE(channel)); +- +- /* Enable MTL RX overflow */ +- value = readl(ioaddr + XGMAC_MTL_QINTEN(channel)); +- writel(value | XGMAC_RXOIE, ioaddr + XGMAC_MTL_QINTEN(channel)); + } + + static void dwxgmac2_dma_tx_mode(void __iomem *ioaddr, int mode, +-- +2.50.1 + diff --git a/queue-5.10/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch b/queue-5.10/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch new file mode 100644 index 0000000000..fb6510c5e4 --- /dev/null +++ b/queue-5.10/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch @@ -0,0 +1,68 @@ +From 365ebd7126b79065e7b9416343e990f854237b68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 May 2025 10:11:04 +0530 +Subject: powerpc/kvm: Fix ifdef to remove build warning + +From: Madhavan Srinivasan + +[ Upstream commit 88688a2c8ac6c8036d983ad8b34ce191c46a10aa ] + +When compiling for pseries or powernv defconfig with "make C=1", +these warning were reported bu sparse tool in powerpc/kernel/kvm.c + +arch/powerpc/kernel/kvm.c:635:9: warning: switch with no cases +arch/powerpc/kernel/kvm.c:646:9: warning: switch with no cases + +Currently #ifdef were added after the switch case which are specific +for BOOKE and PPC_BOOK3S_32. These are not enabled in pseries/powernv +defconfig. Fix it by moving the #ifdef before switch(){} + +Fixes: cbe487fac7fc0 ("KVM: PPC: Add mtsrin PV code") +Tested-by: Venkat Rao Bagalkote +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250518044107.39928-1-maddy@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/kvm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c +index d89cf802d9aa7..8067641561a4f 100644 +--- a/arch/powerpc/kernel/kvm.c ++++ b/arch/powerpc/kernel/kvm.c +@@ -632,19 +632,19 @@ static void __init kvm_check_ins(u32 *inst, u32 features) + #endif + } + +- switch (inst_no_rt & ~KVM_MASK_RB) { + #ifdef CONFIG_PPC_BOOK3S_32 ++ switch (inst_no_rt & ~KVM_MASK_RB) { + case KVM_INST_MTSRIN: + if (features & KVM_MAGIC_FEAT_SR) { + u32 inst_rb = _inst & KVM_MASK_RB; + kvm_patch_ins_mtsrin(inst, inst_rt, inst_rb); + } + break; +-#endif + } ++#endif + +- switch (_inst) { + #ifdef CONFIG_BOOKE ++ switch (_inst) { + case KVM_INST_WRTEEI_0: + kvm_patch_ins_wrteei_0(inst); + break; +@@ -652,8 +652,8 @@ static void __init kvm_check_ins(u32 *inst, u32 features) + case KVM_INST_WRTEEI_1: + kvm_patch_ins_wrtee(inst, 0, 1); + break; +-#endif + } ++#endif + } + + extern u32 kvm_template_start[]; +-- +2.50.1 + diff --git a/queue-5.10/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch b/queue-5.10/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch new file mode 100644 index 0000000000..841decd745 --- /dev/null +++ b/queue-5.10/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch @@ -0,0 +1,72 @@ +From 76e8d36a4f53030ffd449407fbcc0fe23253bfa8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Aug 2025 14:13:14 +0000 +Subject: sctp: initialize more fields in sctp_v6_from_sk() + +From: Eric Dumazet + +[ Upstream commit 2e8750469242cad8f01f320131fd5a6f540dbb99 ] + +syzbot found that sin6_scope_id was not properly initialized, +leading to undefined behavior. + +Clear sin6_scope_id and sin6_flowinfo. + +BUG: KMSAN: uninit-value in __sctp_v6_cmp_addr+0x887/0x8c0 net/sctp/ipv6.c:649 + __sctp_v6_cmp_addr+0x887/0x8c0 net/sctp/ipv6.c:649 + sctp_inet6_cmp_addr+0x4f2/0x510 net/sctp/ipv6.c:983 + sctp_bind_addr_conflict+0x22a/0x3b0 net/sctp/bind_addr.c:390 + sctp_get_port_local+0x21eb/0x2440 net/sctp/socket.c:8452 + sctp_get_port net/sctp/socket.c:8523 [inline] + sctp_listen_start net/sctp/socket.c:8567 [inline] + sctp_inet_listen+0x710/0xfd0 net/sctp/socket.c:8636 + __sys_listen_socket net/socket.c:1912 [inline] + __sys_listen net/socket.c:1927 [inline] + __do_sys_listen net/socket.c:1932 [inline] + __se_sys_listen net/socket.c:1930 [inline] + __x64_sys_listen+0x343/0x4c0 net/socket.c:1930 + x64_sys_call+0x271d/0x3e20 arch/x86/include/generated/asm/syscalls_64.h:51 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xd9/0x210 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Local variable addr.i.i created at: + sctp_get_port net/sctp/socket.c:8515 [inline] + sctp_listen_start net/sctp/socket.c:8567 [inline] + sctp_inet_listen+0x650/0xfd0 net/sctp/socket.c:8636 + __sys_listen_socket net/socket.c:1912 [inline] + __sys_listen net/socket.c:1927 [inline] + __do_sys_listen net/socket.c:1932 [inline] + __se_sys_listen net/socket.c:1930 [inline] + __x64_sys_listen+0x343/0x4c0 net/socket.c:1930 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+e69f06a0f30116c68056@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68adc0a2.050a0220.37038e.00c4.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Marcelo Ricardo Leitner +Acked-by: Xin Long +Link: https://patch.msgid.link/20250826141314.1802610-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/ipv6.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c +index d594b949ae82f..a9cfe4d62df83 100644 +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -499,7 +499,9 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) + { + addr->v6.sin6_family = AF_INET6; + addr->v6.sin6_port = 0; ++ addr->v6.sin6_flowinfo = 0; + addr->v6.sin6_addr = sk->sk_v6_rcv_saddr; ++ addr->v6.sin6_scope_id = 0; + } + + /* Initialize sk->sk_rcv_saddr from sctp_addr. */ +-- +2.50.1 + diff --git a/queue-5.10/series b/queue-5.10/series index 45e7ce1e76..afd0baa5df 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -5,3 +5,14 @@ x86-cpu-hygon-add-missing-resctrl_cpu_detect-in-bsp_init-helper.patch nfs-fold-nfs_page_group_lock_subrequests-into-nfs_lock_and_join_requests.patch nfs-fix-a-race-when-updating-an-existing-write.patch vhost-net-protect-ubufs-with-rcu-read-lock-in-vhost_net_ubuf_put.patch +net-ipv4-fix-regression-in-local-broadcast-routes.patch +powerpc-kvm-fix-ifdef-to-remove-build-warning.patch +bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch +atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch +net-dlink-fix-multicast-stats-being-counted-incorrec.patch +net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch +net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch +net-mlx5e-set-local-xoff-after-fw-update.patch +net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch +sctp-initialize-more-fields-in-sctp_v6_from_sk.patch +efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch diff --git a/queue-5.15/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch b/queue-5.15/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch new file mode 100644 index 0000000000..341e2b0d8f --- /dev/null +++ b/queue-5.15/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch @@ -0,0 +1,192 @@ +From 18026b07fcd6b2a9975264ddab50cd935daea54a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Aug 2025 02:18:24 +0000 +Subject: atm: atmtcp: Prevent arbitrary write in atmtcp_recv_control(). + +From: Kuniyuki Iwashima + +[ Upstream commit ec79003c5f9d2c7f9576fc69b8dbda80305cbe3a ] + +syzbot reported the splat below. [0] + +When atmtcp_v_open() or atmtcp_v_close() is called via connect() +or close(), atmtcp_send_control() is called to send an in-kernel +special message. + +The message has ATMTCP_HDR_MAGIC in atmtcp_control.hdr.length. +Also, a pointer of struct atm_vcc is set to atmtcp_control.vcc. + +The notable thing is struct atmtcp_control is uAPI but has a +space for an in-kernel pointer. + + struct atmtcp_control { + struct atmtcp_hdr hdr; /* must be first */ + ... + atm_kptr_t vcc; /* both directions */ + ... + } __ATM_API_ALIGN; + + typedef struct { unsigned char _[8]; } __ATM_API_ALIGN atm_kptr_t; + +The special message is processed in atmtcp_recv_control() called +from atmtcp_c_send(). + +atmtcp_c_send() is vcc->dev->ops->send() and called from 2 paths: + + 1. .ndo_start_xmit() (vcc->send() == atm_send_aal0()) + 2. vcc_sendmsg() + +The problem is sendmsg() does not validate the message length and +userspace can abuse atmtcp_recv_control() to overwrite any kptr +by atmtcp_control. + +Let's add a new ->pre_send() hook to validate messages from sendmsg(). + +[0]: +Oops: general protection fault, probably for non-canonical address 0xdffffc00200000ab: 0000 [#1] SMP KASAN PTI +KASAN: probably user-memory-access in range [0x0000000100000558-0x000000010000055f] +CPU: 0 UID: 0 PID: 5865 Comm: syz-executor331 Not tainted 6.17.0-rc1-syzkaller-00215-gbab3ce404553 #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/12/2025 +RIP: 0010:atmtcp_recv_control drivers/atm/atmtcp.c:93 [inline] +RIP: 0010:atmtcp_c_send+0x1da/0x950 drivers/atm/atmtcp.c:297 +Code: 4d 8d 75 1a 4c 89 f0 48 c1 e8 03 42 0f b6 04 20 84 c0 0f 85 15 06 00 00 41 0f b7 1e 4d 8d b7 60 05 00 00 4c 89 f0 48 c1 e8 03 <42> 0f b6 04 20 84 c0 0f 85 13 06 00 00 66 41 89 1e 4d 8d 75 1c 4c +RSP: 0018:ffffc90003f5f810 EFLAGS: 00010203 +RAX: 00000000200000ab RBX: 0000000000000000 RCX: 0000000000000000 +RDX: ffff88802a510000 RSI: 00000000ffffffff RDI: ffff888030a6068c +RBP: ffff88802699fb40 R08: ffff888030a606eb R09: 1ffff1100614c0dd +R10: dffffc0000000000 R11: ffffffff8718fc40 R12: dffffc0000000000 +R13: ffff888030a60680 R14: 000000010000055f R15: 00000000ffffffff +FS: 00007f8d7e9236c0(0000) GS:ffff888125c1c000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 000000000045ad50 CR3: 0000000075bde000 CR4: 00000000003526f0 +Call Trace: + + vcc_sendmsg+0xa10/0xc60 net/atm/common.c:645 + sock_sendmsg_nosec net/socket.c:714 [inline] + __sock_sendmsg+0x219/0x270 net/socket.c:729 + ____sys_sendmsg+0x505/0x830 net/socket.c:2614 + ___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668 + __sys_sendmsg net/socket.c:2700 [inline] + __do_sys_sendmsg net/socket.c:2705 [inline] + __se_sys_sendmsg net/socket.c:2703 [inline] + __x64_sys_sendmsg+0x19b/0x260 net/socket.c:2703 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +RIP: 0033:0x7f8d7e96a4a9 +Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 51 18 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f8d7e923198 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +RAX: ffffffffffffffda RBX: 00007f8d7e9f4308 RCX: 00007f8d7e96a4a9 +RDX: 0000000000000000 RSI: 0000200000000240 RDI: 0000000000000005 +RBP: 00007f8d7e9f4300 R08: 65732f636f72702f R09: 65732f636f72702f +R10: 65732f636f72702f R11: 0000000000000246 R12: 00007f8d7e9c10ac +R13: 00007f8d7e9231a0 R14: 0000200000000200 R15: 0000200000000250 + +Modules linked in: + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+1741b56d54536f4ec349@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68a6767c.050a0220.3d78fd.0011.GAE@google.com/ +Tested-by: syzbot+1741b56d54536f4ec349@syzkaller.appspotmail.com +Signed-off-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250821021901.2814721-1-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/atm/atmtcp.c | 17 ++++++++++++++--- + include/linux/atmdev.h | 1 + + net/atm/common.c | 15 ++++++++++++--- + 3 files changed, 27 insertions(+), 6 deletions(-) + +diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c +index ff558908897f3..9c83fb29b2f1b 100644 +--- a/drivers/atm/atmtcp.c ++++ b/drivers/atm/atmtcp.c +@@ -279,6 +279,19 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) + return NULL; + } + ++static int atmtcp_c_pre_send(struct atm_vcc *vcc, struct sk_buff *skb) ++{ ++ struct atmtcp_hdr *hdr; ++ ++ if (skb->len < sizeof(struct atmtcp_hdr)) ++ return -EINVAL; ++ ++ hdr = (struct atmtcp_hdr *)skb->data; ++ if (hdr->length == ATMTCP_HDR_MAGIC) ++ return -EINVAL; ++ ++ return 0; ++} + + static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + { +@@ -288,9 +301,6 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + struct sk_buff *new_skb; + int result = 0; + +- if (skb->len < sizeof(struct atmtcp_hdr)) +- goto done; +- + dev = vcc->dev_data; + hdr = (struct atmtcp_hdr *) skb->data; + if (hdr->length == ATMTCP_HDR_MAGIC) { +@@ -347,6 +357,7 @@ static const struct atmdev_ops atmtcp_v_dev_ops = { + + static const struct atmdev_ops atmtcp_c_dev_ops = { + .close = atmtcp_c_close, ++ .pre_send = atmtcp_c_pre_send, + .send = atmtcp_c_send + }; + +diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h +index 45f2f278b50a8..70807c679f1ab 100644 +--- a/include/linux/atmdev.h ++++ b/include/linux/atmdev.h +@@ -185,6 +185,7 @@ struct atmdev_ops { /* only send is required */ + int (*compat_ioctl)(struct atm_dev *dev,unsigned int cmd, + void __user *arg); + #endif ++ int (*pre_send)(struct atm_vcc *vcc, struct sk_buff *skb); + int (*send)(struct atm_vcc *vcc,struct sk_buff *skb); + int (*send_bh)(struct atm_vcc *vcc, struct sk_buff *skb); + int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags); +diff --git a/net/atm/common.c b/net/atm/common.c +index 930eb302cd10f..38ed7b985f655 100644 +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -635,18 +635,27 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size) + + skb->dev = NULL; /* for paths shared with net_device interfaces */ + if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) { +- atm_return_tx(vcc, skb); +- kfree_skb(skb); + error = -EFAULT; +- goto out; ++ goto free_skb; + } + if (eff != size) + memset(skb->data + size, 0, eff-size); ++ ++ if (vcc->dev->ops->pre_send) { ++ error = vcc->dev->ops->pre_send(vcc, skb); ++ if (error) ++ goto free_skb; ++ } ++ + error = vcc->dev->ops->send(vcc, skb); + error = error ? error : size; + out: + release_sock(sk); + return error; ++free_skb: ++ atm_return_tx(vcc, skb); ++ kfree_skb(skb); ++ goto out; + } + + __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait) +-- +2.50.1 + diff --git a/queue-5.15/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch b/queue-5.15/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch new file mode 100644 index 0000000000..d478e4bbb1 --- /dev/null +++ b/queue-5.15/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch @@ -0,0 +1,47 @@ +From c886599c79dfcda729ed09a3aa8a25175ac577f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Aug 2025 17:04:00 -0400 +Subject: Bluetooth: hci_event: Detect if HCI_EV_NUM_COMP_PKTS is unbalanced + +From: Luiz Augusto von Dentz + +[ Upstream commit 15bf2c6391bafb14a3020d06ec0761bce0803463 ] + +This attempts to detect if HCI_EV_NUM_COMP_PKTS contain an unbalanced +(more than currently considered outstanding) number of packets otherwise +it could cause the hcon->sent to underflow and loop around breaking the +tracking of the outstanding packets pending acknowledgment. + +Fixes: f42809185896 ("Bluetooth: Simplify num_comp_pkts_evt function") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 84b07b27b3cf4..cfdaaecf78600 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -3919,7 +3919,17 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) + if (!conn) + continue; + +- conn->sent -= count; ++ /* Check if there is really enough packets outstanding before ++ * attempting to decrease the sent counter otherwise it could ++ * underflow.. ++ */ ++ if (conn->sent >= count) { ++ conn->sent -= count; ++ } else { ++ bt_dev_warn(hdev, "hcon %p sent %u < count %u", ++ conn, conn->sent, count); ++ conn->sent = 0; ++ } + + switch (conn->type) { + case ACL_LINK: +-- +2.50.1 + diff --git a/queue-5.15/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch b/queue-5.15/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch new file mode 100644 index 0000000000..560a082693 --- /dev/null +++ b/queue-5.15/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch @@ -0,0 +1,77 @@ +From 04e740b4dfd074a755299a16dc8394497e284442 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 15:39:54 +0800 +Subject: efivarfs: Fix slab-out-of-bounds in efivarfs_d_compare + +From: Li Nan + +[ Upstream commit a6358f8cf64850f3f27857b8ed8c1b08cfc4685c ] + +Observed on kernel 6.6 (present on master as well): + + BUG: KASAN: slab-out-of-bounds in memcmp+0x98/0xd0 + Call trace: + kasan_check_range+0xe8/0x190 + __asan_loadN+0x1c/0x28 + memcmp+0x98/0xd0 + efivarfs_d_compare+0x68/0xd8 + __d_lookup_rcu_op_compare+0x178/0x218 + __d_lookup_rcu+0x1f8/0x228 + d_alloc_parallel+0x150/0x648 + lookup_open.isra.0+0x5f0/0x8d0 + open_last_lookups+0x264/0x828 + path_openat+0x130/0x3f8 + do_filp_open+0x114/0x248 + do_sys_openat2+0x340/0x3c0 + __arm64_sys_openat+0x120/0x1a0 + +If dentry->d_name.len < EFI_VARIABLE_GUID_LEN , 'guid' can become +negative, leadings to oob. The issue can be triggered by parallel +lookups using invalid filename: + + T1 T2 + lookup_open + ->lookup + simple_lookup + d_add + // invalid dentry is added to hash list + + lookup_open + d_alloc_parallel + __d_lookup_rcu + __d_lookup_rcu_op_compare + hlist_bl_for_each_entry_rcu + // invalid dentry can be retrieved + ->d_compare + efivarfs_d_compare + // oob + +Fix it by checking 'guid' before cmp. + +Fixes: da27a24383b2 ("efivarfs: guid part of filenames are case-insensitive") +Signed-off-by: Li Nan +Signed-off-by: Wu Guanghao +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + fs/efivarfs/super.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c +index 99d002438008b..124db520b2bd6 100644 +--- a/fs/efivarfs/super.c ++++ b/fs/efivarfs/super.c +@@ -47,6 +47,10 @@ static int efivarfs_d_compare(const struct dentry *dentry, + { + int guid = len - EFI_VARIABLE_GUID_LEN; + ++ /* Parallel lookups may produce a temporary invalid filename */ ++ if (guid <= 0) ++ return 1; ++ + if (name->len != len) + return 1; + +-- +2.50.1 + diff --git a/queue-5.15/net-dlink-fix-multicast-stats-being-counted-incorrec.patch b/queue-5.15/net-dlink-fix-multicast-stats-being-counted-incorrec.patch new file mode 100644 index 0000000000..7892b5dadd --- /dev/null +++ b/queue-5.15/net-dlink-fix-multicast-stats-being-counted-incorrec.patch @@ -0,0 +1,46 @@ +From 631de0a7006b7a2bf147157adf4e531c3087fca6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Aug 2025 03:29:24 +0900 +Subject: net: dlink: fix multicast stats being counted incorrectly + +From: Yeounsu Moon + +[ Upstream commit 007a5ffadc4fd51739527f1503b7cf048f31c413 ] + +`McstFramesRcvdOk` counts the number of received multicast packets, and +it reports the value correctly. + +However, reading `McstFramesRcvdOk` clears the register to zero. As a +result, the driver was reporting only the packets since the last read, +instead of the accumulated total. + +Fix this by updating the multicast statistics accumulatively instaed of +instantaneously. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Tested-on: D-Link DGE-550T Rev-A3 +Signed-off-by: Yeounsu Moon +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250823182927.6063-3-yyyynoom@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/dlink/dl2k.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c +index 09a275eb44487..81395852b4d43 100644 +--- a/drivers/net/ethernet/dlink/dl2k.c ++++ b/drivers/net/ethernet/dlink/dl2k.c +@@ -1095,7 +1095,7 @@ get_stats (struct net_device *dev) + dev->stats.rx_bytes += dr32(OctetRcvOk); + dev->stats.tx_bytes += dr32(OctetXmtOk); + +- dev->stats.multicast = dr32(McstFramesRcvdOk); ++ dev->stats.multicast += dr32(McstFramesRcvdOk); + dev->stats.collisions += dr32(SingleColFrames) + + dr32(MultiColFrames); + +-- +2.50.1 + diff --git a/queue-5.15/net-ipv4-fix-regression-in-local-broadcast-routes.patch b/queue-5.15/net-ipv4-fix-regression-in-local-broadcast-routes.patch new file mode 100644 index 0000000000..c342dea31d --- /dev/null +++ b/queue-5.15/net-ipv4-fix-regression-in-local-broadcast-routes.patch @@ -0,0 +1,57 @@ +From 6666f564e6dc3bc10eb0247005b47faff923759a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 08:23:21 +0200 +Subject: net: ipv4: fix regression in local-broadcast routes + +From: Oscar Maes + +[ Upstream commit 5189446ba995556eaa3755a6e875bc06675b88bd ] + +Commit 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") +introduced a regression where local-broadcast packets would have their +gateway set in __mkroute_output, which was caused by fi = NULL being +removed. + +Fix this by resetting the fib_info for local-broadcast packets. This +preserves the intended changes for directed-broadcast packets. + +Cc: stable@vger.kernel.org +Fixes: 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") +Reported-by: Brett A C Sheffield +Closes: https://lore.kernel.org/regressions/20250822165231.4353-4-bacs@librecast.net +Signed-off-by: Oscar Maes +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20250827062322.4807-1-oscmaes92@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/route.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index df4cbf9ba288f..b24de1c67d0c2 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -2552,12 +2552,16 @@ static struct rtable *__mkroute_output(const struct fib_result *res, + !netif_is_l3_master(dev_out)) + return ERR_PTR(-EINVAL); + +- if (ipv4_is_lbcast(fl4->daddr)) ++ if (ipv4_is_lbcast(fl4->daddr)) { + type = RTN_BROADCAST; +- else if (ipv4_is_multicast(fl4->daddr)) ++ ++ /* reset fi to prevent gateway resolution */ ++ fi = NULL; ++ } else if (ipv4_is_multicast(fl4->daddr)) { + type = RTN_MULTICAST; +- else if (ipv4_is_zeronet(fl4->daddr)) ++ } else if (ipv4_is_zeronet(fl4->daddr)) { + return ERR_PTR(-EINVAL); ++ } + + if (dev_out->flags & IFF_LOOPBACK) + flags |= RTCF_LOCAL; +-- +2.50.1 + diff --git a/queue-5.15/net-mlx5e-set-local-xoff-after-fw-update.patch b/queue-5.15/net-mlx5e-set-local-xoff-after-fw-update.patch new file mode 100644 index 0000000000..26899392f7 --- /dev/null +++ b/queue-5.15/net-mlx5e-set-local-xoff-after-fw-update.patch @@ -0,0 +1,50 @@ +From ef84cd46f5974a389e2183063b47367c3de2d8b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:34 +0300 +Subject: net/mlx5e: Set local Xoff after FW update + +From: Alexei Lazar + +[ Upstream commit aca0c31af61e0d5cf1675a0cbd29460b95ae693c ] + +The local Xoff value is being set before the firmware (FW) update. +In case of a failure where the FW is not updated with the new value, +there is no fallback to the previous value. +Update the local Xoff value after the FW has been successfully set. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Reviewed-by: Dragos Tatulea +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-12-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +index c9d5d8d93994d..7899a7230299d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +@@ -346,7 +346,6 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + if (err) + return err; + } +- priv->dcbx.xoff = xoff; + + /* Apply the settings */ + if (update_buffer) { +@@ -355,6 +354,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + return err; + } + ++ priv->dcbx.xoff = xoff; ++ + if (update_prio2buffer) + err = mlx5e_port_set_priority2buffer(priv->mdev, prio2buffer); + +-- +2.50.1 + diff --git a/queue-5.15/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch b/queue-5.15/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch new file mode 100644 index 0000000000..d7e0d0bb6f --- /dev/null +++ b/queue-5.15/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch @@ -0,0 +1,100 @@ +From 7d673e811f13804fda8f0874d49487abf56a521e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:32 +0300 +Subject: net/mlx5e: Update and set Xon/Xoff upon MTU set + +From: Alexei Lazar + +[ Upstream commit ceddedc969f0532b7c62ca971ee50d519d2bc0cb ] + +Xon/Xoff sizes are derived from calculation that include the MTU size. +Set Xon/Xoff when MTU is set. +If Xon/Xoff fails, set the previous MTU. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-10-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/en/port_buffer.h | 12 ++++++++++++ + .../net/ethernet/mellanox/mlx5/core/en_main.c | 17 ++++++++++++++++- + 2 files changed, 28 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +index 80af7a5ac6046..a23e3d810f3e4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +@@ -63,11 +63,23 @@ struct mlx5e_port_buffer { + struct mlx5e_bufferx_reg buffer[MLX5E_MAX_BUFFER]; + }; + ++#ifdef CONFIG_MLX5_CORE_EN_DCB + int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + u32 change, unsigned int mtu, + struct ieee_pfc *pfc, + u32 *buffer_size, + u8 *prio2buffer); ++#else ++static inline int ++mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, ++ u32 change, unsigned int mtu, ++ void *pfc, ++ u32 *buffer_size, ++ u8 *prio2buffer) ++{ ++ return 0; ++} ++#endif + + int mlx5e_port_query_buffer(struct mlx5e_priv *priv, + struct mlx5e_port_buffer *port_buffer); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 321441e6ad328..bb7e3c80ad74e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -42,6 +42,7 @@ + #include "eswitch.h" + #include "en.h" + #include "en/txrx.h" ++#include "en/port_buffer.h" + #include "en_tc.h" + #include "en_rep.h" + #include "en_accel/ipsec.h" +@@ -2242,9 +2243,11 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) + struct mlx5e_params *params = &priv->channels.params; + struct net_device *netdev = priv->netdev; + struct mlx5_core_dev *mdev = priv->mdev; +- u16 mtu; ++ u16 mtu, prev_mtu; + int err; + ++ mlx5e_query_mtu(mdev, params, &prev_mtu); ++ + err = mlx5e_set_mtu(mdev, params, params->sw_mtu); + if (err) + return err; +@@ -2254,6 +2257,18 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) + netdev_warn(netdev, "%s: VPort MTU %d is different than netdev mtu %d\n", + __func__, mtu, params->sw_mtu); + ++ if (mtu != prev_mtu && MLX5_BUFFER_SUPPORTED(mdev)) { ++ err = mlx5e_port_manual_buffer_config(priv, 0, mtu, ++ NULL, NULL, NULL); ++ if (err) { ++ netdev_warn(netdev, "%s: Failed to set Xon/Xoff values with MTU %d (err %d), setting back to previous MTU %d\n", ++ __func__, mtu, err, prev_mtu); ++ ++ mlx5e_set_mtu(mdev, params, prev_mtu); ++ return err; ++ } ++ } ++ + params->sw_mtu = mtu; + return 0; + } +-- +2.50.1 + diff --git a/queue-5.15/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch b/queue-5.15/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch new file mode 100644 index 0000000000..16072d7487 --- /dev/null +++ b/queue-5.15/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch @@ -0,0 +1,46 @@ +From 41ed1b2b238aa0c45ab2d6ca606542ec374a75cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:33 +0300 +Subject: net/mlx5e: Update and set Xon/Xoff upon port speed set + +From: Alexei Lazar + +[ Upstream commit d24341740fe48add8a227a753e68b6eedf4b385a ] + +Xon/Xoff sizes are derived from calculations that include +the port speed. +These settings need to be updated and applied whenever the +port speed is changed. +The port speed is typically set after the physical link goes down +and is negotiated as part of the link-up process between the two +connected interfaces. +Xon/Xoff parameters being updated at the point where the new +negotiated speed is established. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-11-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index bb7e3c80ad74e..cfbc569edfb5f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -104,6 +104,8 @@ void mlx5e_update_carrier(struct mlx5e_priv *priv) + if (up) { + netdev_info(priv->netdev, "Link up\n"); + netif_carrier_on(priv->netdev); ++ mlx5e_port_manual_buffer_config(priv, 0, priv->netdev->mtu, ++ NULL, NULL, NULL); + } else { + netdev_info(priv->netdev, "Link down\n"); + netif_carrier_off(priv->netdev); +-- +2.50.1 + diff --git a/queue-5.15/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch b/queue-5.15/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch new file mode 100644 index 0000000000..2c42711147 --- /dev/null +++ b/queue-5.15/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch @@ -0,0 +1,49 @@ +From 17dcb63450422550503507a8ba929ee9fd226c1c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 12:36:52 +0800 +Subject: net: stmmac: xgmac: Do not enable RX FIFO Overflow interrupts + +From: Rohan G Thomas + +[ Upstream commit 4f23382841e67174211271a454811dd17c0ef3c5 ] + +Enabling RX FIFO Overflow interrupts is counterproductive +and causes an interrupt storm when RX FIFO overflows. +Disabling this interrupt has no side effect and eliminates +interrupt storms when the RX FIFO overflows. + +Commit 8a7cb245cf28 ("net: stmmac: Do not enable RX FIFO +overflow interrupts") disables RX FIFO overflow interrupts +for DWMAC4 IP and removes the corresponding handling of +this interrupt. This patch is doing the same thing for +XGMAC IP. + +Fixes: 2142754f8b9c ("net: stmmac: Add MAC related callbacks for XGMAC2") +Signed-off-by: Rohan G Thomas +Reviewed-by: Matthew Gerlach +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250825-xgmac-minor-fixes-v3-1-c225fe4444c0@altera.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +index 5e98355f422b3..3e4318d5dcdf5 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +@@ -199,10 +199,6 @@ static void dwxgmac2_dma_rx_mode(void __iomem *ioaddr, int mode, + } + + writel(value, ioaddr + XGMAC_MTL_RXQ_OPMODE(channel)); +- +- /* Enable MTL RX overflow */ +- value = readl(ioaddr + XGMAC_MTL_QINTEN(channel)); +- writel(value | XGMAC_RXOIE, ioaddr + XGMAC_MTL_QINTEN(channel)); + } + + static void dwxgmac2_dma_tx_mode(void __iomem *ioaddr, int mode, +-- +2.50.1 + diff --git a/queue-5.15/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch b/queue-5.15/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch new file mode 100644 index 0000000000..dc7764c096 --- /dev/null +++ b/queue-5.15/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch @@ -0,0 +1,135 @@ +From 1ef13ace52d87b240f4952102c94c0173a41e31c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 08:55:43 +0200 +Subject: phy: mscc: Fix when PTP clock is register and unregister + +From: Horatiu Vultur + +[ Upstream commit 882e57cbc7204662f6c5672d5b04336c1d790b03 ] + +It looks like that every time when the interface was set down and up the +driver was creating a new ptp clock. On top of this the function +ptp_clock_unregister was never called. +Therefore fix this by calling ptp_clock_register and initialize the +mii_ts struct inside the probe function and call ptp_clock_unregister when +driver is removed. + +Fixes: 7d272e63e0979d ("net: phy: mscc: timestamping and PHC support") +Signed-off-by: Horatiu Vultur +Reviewed-by: Vadim Fedorenko +Reviewed-by: Vladimir Oltean +Link: https://patch.msgid.link/20250825065543.2916334-1-horatiu.vultur@microchip.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mscc/mscc.h | 4 ++++ + drivers/net/phy/mscc/mscc_main.c | 4 +--- + drivers/net/phy/mscc/mscc_ptp.c | 34 ++++++++++++++++++++------------ + 3 files changed, 26 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h +index 878298304430c..fcfbff691b3c6 100644 +--- a/drivers/net/phy/mscc/mscc.h ++++ b/drivers/net/phy/mscc/mscc.h +@@ -474,6 +474,7 @@ static inline void vsc8584_config_macsec_intr(struct phy_device *phydev) + void vsc85xx_link_change_notify(struct phy_device *phydev); + void vsc8584_config_ts_intr(struct phy_device *phydev); + int vsc8584_ptp_init(struct phy_device *phydev); ++void vsc8584_ptp_deinit(struct phy_device *phydev); + int vsc8584_ptp_probe_once(struct phy_device *phydev); + int vsc8584_ptp_probe(struct phy_device *phydev); + irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev); +@@ -488,6 +489,9 @@ static inline int vsc8584_ptp_init(struct phy_device *phydev) + { + return 0; + } ++static inline void vsc8584_ptp_deinit(struct phy_device *phydev) ++{ ++} + static inline int vsc8584_ptp_probe_once(struct phy_device *phydev) + { + return 0; +diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c +index 03aa85ec60dfc..982e73adf2bcf 100644 +--- a/drivers/net/phy/mscc/mscc_main.c ++++ b/drivers/net/phy/mscc/mscc_main.c +@@ -2326,9 +2326,7 @@ static int vsc85xx_probe(struct phy_device *phydev) + + static void vsc85xx_remove(struct phy_device *phydev) + { +- struct vsc8531_private *priv = phydev->priv; +- +- skb_queue_purge(&priv->rx_skbs_list); ++ vsc8584_ptp_deinit(phydev); + } + + /* Microsemi VSC85xx PHYs */ +diff --git a/drivers/net/phy/mscc/mscc_ptp.c b/drivers/net/phy/mscc/mscc_ptp.c +index f77bfbee5f20b..e30e6ba9da2f4 100644 +--- a/drivers/net/phy/mscc/mscc_ptp.c ++++ b/drivers/net/phy/mscc/mscc_ptp.c +@@ -1294,7 +1294,6 @@ static void vsc8584_set_input_clk_configured(struct phy_device *phydev) + + static int __vsc8584_init_ptp(struct phy_device *phydev) + { +- struct vsc8531_private *vsc8531 = phydev->priv; + static const u32 ltc_seq_e[] = { 0, 400000, 0, 0, 0 }; + static const u8 ltc_seq_a[] = { 8, 6, 5, 4, 2 }; + u32 val; +@@ -1511,17 +1510,7 @@ static int __vsc8584_init_ptp(struct phy_device *phydev) + + vsc85xx_ts_eth_cmp1_sig(phydev); + +- vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; +- vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; +- vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; +- vsc8531->mii_ts.ts_info = vsc85xx_ts_info; +- phydev->mii_ts = &vsc8531->mii_ts; +- +- memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); +- +- vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, +- &phydev->mdio.dev); +- return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); ++ return 0; + } + + void vsc8584_config_ts_intr(struct phy_device *phydev) +@@ -1548,6 +1537,16 @@ int vsc8584_ptp_init(struct phy_device *phydev) + return 0; + } + ++void vsc8584_ptp_deinit(struct phy_device *phydev) ++{ ++ struct vsc8531_private *vsc8531 = phydev->priv; ++ ++ if (vsc8531->ptp->ptp_clock) { ++ ptp_clock_unregister(vsc8531->ptp->ptp_clock); ++ skb_queue_purge(&vsc8531->rx_skbs_list); ++ } ++} ++ + irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev) + { + struct vsc8531_private *priv = phydev->priv; +@@ -1605,7 +1604,16 @@ int vsc8584_ptp_probe(struct phy_device *phydev) + + vsc8531->ptp->phydev = phydev; + +- return 0; ++ vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; ++ vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; ++ vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; ++ vsc8531->mii_ts.ts_info = vsc85xx_ts_info; ++ phydev->mii_ts = &vsc8531->mii_ts; ++ ++ memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); ++ vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, ++ &phydev->mdio.dev); ++ return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); + } + + int vsc8584_ptp_probe_once(struct phy_device *phydev) +-- +2.50.1 + diff --git a/queue-5.15/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch b/queue-5.15/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch new file mode 100644 index 0000000000..33862fe323 --- /dev/null +++ b/queue-5.15/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch @@ -0,0 +1,68 @@ +From bbb8d2abdf55950847e3450f7463eea454664e61 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 May 2025 10:11:04 +0530 +Subject: powerpc/kvm: Fix ifdef to remove build warning + +From: Madhavan Srinivasan + +[ Upstream commit 88688a2c8ac6c8036d983ad8b34ce191c46a10aa ] + +When compiling for pseries or powernv defconfig with "make C=1", +these warning were reported bu sparse tool in powerpc/kernel/kvm.c + +arch/powerpc/kernel/kvm.c:635:9: warning: switch with no cases +arch/powerpc/kernel/kvm.c:646:9: warning: switch with no cases + +Currently #ifdef were added after the switch case which are specific +for BOOKE and PPC_BOOK3S_32. These are not enabled in pseries/powernv +defconfig. Fix it by moving the #ifdef before switch(){} + +Fixes: cbe487fac7fc0 ("KVM: PPC: Add mtsrin PV code") +Tested-by: Venkat Rao Bagalkote +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250518044107.39928-1-maddy@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/kvm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c +index 6568823cf3063..5d9d38834507d 100644 +--- a/arch/powerpc/kernel/kvm.c ++++ b/arch/powerpc/kernel/kvm.c +@@ -632,19 +632,19 @@ static void __init kvm_check_ins(u32 *inst, u32 features) + #endif + } + +- switch (inst_no_rt & ~KVM_MASK_RB) { + #ifdef CONFIG_PPC_BOOK3S_32 ++ switch (inst_no_rt & ~KVM_MASK_RB) { + case KVM_INST_MTSRIN: + if (features & KVM_MAGIC_FEAT_SR) { + u32 inst_rb = _inst & KVM_MASK_RB; + kvm_patch_ins_mtsrin(inst, inst_rt, inst_rb); + } + break; +-#endif + } ++#endif + +- switch (_inst) { + #ifdef CONFIG_BOOKE ++ switch (_inst) { + case KVM_INST_WRTEEI_0: + kvm_patch_ins_wrteei_0(inst); + break; +@@ -652,8 +652,8 @@ static void __init kvm_check_ins(u32 *inst, u32 features) + case KVM_INST_WRTEEI_1: + kvm_patch_ins_wrtee(inst, 0, 1); + break; +-#endif + } ++#endif + } + + extern u32 kvm_template_start[]; +-- +2.50.1 + diff --git a/queue-5.15/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch b/queue-5.15/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch new file mode 100644 index 0000000000..1b14413c0b --- /dev/null +++ b/queue-5.15/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch @@ -0,0 +1,72 @@ +From 7168fc6bd436b474e4170fc54d6a3d426c42399c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Aug 2025 14:13:14 +0000 +Subject: sctp: initialize more fields in sctp_v6_from_sk() + +From: Eric Dumazet + +[ Upstream commit 2e8750469242cad8f01f320131fd5a6f540dbb99 ] + +syzbot found that sin6_scope_id was not properly initialized, +leading to undefined behavior. + +Clear sin6_scope_id and sin6_flowinfo. + +BUG: KMSAN: uninit-value in __sctp_v6_cmp_addr+0x887/0x8c0 net/sctp/ipv6.c:649 + __sctp_v6_cmp_addr+0x887/0x8c0 net/sctp/ipv6.c:649 + sctp_inet6_cmp_addr+0x4f2/0x510 net/sctp/ipv6.c:983 + sctp_bind_addr_conflict+0x22a/0x3b0 net/sctp/bind_addr.c:390 + sctp_get_port_local+0x21eb/0x2440 net/sctp/socket.c:8452 + sctp_get_port net/sctp/socket.c:8523 [inline] + sctp_listen_start net/sctp/socket.c:8567 [inline] + sctp_inet_listen+0x710/0xfd0 net/sctp/socket.c:8636 + __sys_listen_socket net/socket.c:1912 [inline] + __sys_listen net/socket.c:1927 [inline] + __do_sys_listen net/socket.c:1932 [inline] + __se_sys_listen net/socket.c:1930 [inline] + __x64_sys_listen+0x343/0x4c0 net/socket.c:1930 + x64_sys_call+0x271d/0x3e20 arch/x86/include/generated/asm/syscalls_64.h:51 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xd9/0x210 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Local variable addr.i.i created at: + sctp_get_port net/sctp/socket.c:8515 [inline] + sctp_listen_start net/sctp/socket.c:8567 [inline] + sctp_inet_listen+0x650/0xfd0 net/sctp/socket.c:8636 + __sys_listen_socket net/socket.c:1912 [inline] + __sys_listen net/socket.c:1927 [inline] + __do_sys_listen net/socket.c:1932 [inline] + __se_sys_listen net/socket.c:1930 [inline] + __x64_sys_listen+0x343/0x4c0 net/socket.c:1930 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+e69f06a0f30116c68056@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68adc0a2.050a0220.37038e.00c4.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Marcelo Ricardo Leitner +Acked-by: Xin Long +Link: https://patch.msgid.link/20250826141314.1802610-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/ipv6.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c +index 470dbdc27d584..107255d92037f 100644 +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -547,7 +547,9 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) + { + addr->v6.sin6_family = AF_INET6; + addr->v6.sin6_port = 0; ++ addr->v6.sin6_flowinfo = 0; + addr->v6.sin6_addr = sk->sk_v6_rcv_saddr; ++ addr->v6.sin6_scope_id = 0; + } + + /* Initialize sk->sk_rcv_saddr from sctp_addr. */ +-- +2.50.1 + diff --git a/queue-5.15/series b/queue-5.15/series index 54a5b4d148..2f9a025e7c 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -5,3 +5,15 @@ asoc-codecs-tx-macro-correct-tx_macro_component_drv-.patch nfs-fold-nfs_page_group_lock_subrequests-into-nfs_lock_and_join_requests.patch nfs-fix-a-race-when-updating-an-existing-write.patch vhost-net-protect-ubufs-with-rcu-read-lock-in-vhost_net_ubuf_put.patch +net-ipv4-fix-regression-in-local-broadcast-routes.patch +powerpc-kvm-fix-ifdef-to-remove-build-warning.patch +bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch +atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch +net-dlink-fix-multicast-stats-being-counted-incorrec.patch +phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch +net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch +net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch +net-mlx5e-set-local-xoff-after-fw-update.patch +net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch +sctp-initialize-more-fields-in-sctp_v6_from_sk.patch +efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch diff --git a/queue-5.4/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch b/queue-5.4/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch new file mode 100644 index 0000000000..9a52c95ed1 --- /dev/null +++ b/queue-5.4/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch @@ -0,0 +1,192 @@ +From 51d4666edc74dbd1eee81b83126369380eaa2160 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Aug 2025 02:18:24 +0000 +Subject: atm: atmtcp: Prevent arbitrary write in atmtcp_recv_control(). + +From: Kuniyuki Iwashima + +[ Upstream commit ec79003c5f9d2c7f9576fc69b8dbda80305cbe3a ] + +syzbot reported the splat below. [0] + +When atmtcp_v_open() or atmtcp_v_close() is called via connect() +or close(), atmtcp_send_control() is called to send an in-kernel +special message. + +The message has ATMTCP_HDR_MAGIC in atmtcp_control.hdr.length. +Also, a pointer of struct atm_vcc is set to atmtcp_control.vcc. + +The notable thing is struct atmtcp_control is uAPI but has a +space for an in-kernel pointer. + + struct atmtcp_control { + struct atmtcp_hdr hdr; /* must be first */ + ... + atm_kptr_t vcc; /* both directions */ + ... + } __ATM_API_ALIGN; + + typedef struct { unsigned char _[8]; } __ATM_API_ALIGN atm_kptr_t; + +The special message is processed in atmtcp_recv_control() called +from atmtcp_c_send(). + +atmtcp_c_send() is vcc->dev->ops->send() and called from 2 paths: + + 1. .ndo_start_xmit() (vcc->send() == atm_send_aal0()) + 2. vcc_sendmsg() + +The problem is sendmsg() does not validate the message length and +userspace can abuse atmtcp_recv_control() to overwrite any kptr +by atmtcp_control. + +Let's add a new ->pre_send() hook to validate messages from sendmsg(). + +[0]: +Oops: general protection fault, probably for non-canonical address 0xdffffc00200000ab: 0000 [#1] SMP KASAN PTI +KASAN: probably user-memory-access in range [0x0000000100000558-0x000000010000055f] +CPU: 0 UID: 0 PID: 5865 Comm: syz-executor331 Not tainted 6.17.0-rc1-syzkaller-00215-gbab3ce404553 #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/12/2025 +RIP: 0010:atmtcp_recv_control drivers/atm/atmtcp.c:93 [inline] +RIP: 0010:atmtcp_c_send+0x1da/0x950 drivers/atm/atmtcp.c:297 +Code: 4d 8d 75 1a 4c 89 f0 48 c1 e8 03 42 0f b6 04 20 84 c0 0f 85 15 06 00 00 41 0f b7 1e 4d 8d b7 60 05 00 00 4c 89 f0 48 c1 e8 03 <42> 0f b6 04 20 84 c0 0f 85 13 06 00 00 66 41 89 1e 4d 8d 75 1c 4c +RSP: 0018:ffffc90003f5f810 EFLAGS: 00010203 +RAX: 00000000200000ab RBX: 0000000000000000 RCX: 0000000000000000 +RDX: ffff88802a510000 RSI: 00000000ffffffff RDI: ffff888030a6068c +RBP: ffff88802699fb40 R08: ffff888030a606eb R09: 1ffff1100614c0dd +R10: dffffc0000000000 R11: ffffffff8718fc40 R12: dffffc0000000000 +R13: ffff888030a60680 R14: 000000010000055f R15: 00000000ffffffff +FS: 00007f8d7e9236c0(0000) GS:ffff888125c1c000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 000000000045ad50 CR3: 0000000075bde000 CR4: 00000000003526f0 +Call Trace: + + vcc_sendmsg+0xa10/0xc60 net/atm/common.c:645 + sock_sendmsg_nosec net/socket.c:714 [inline] + __sock_sendmsg+0x219/0x270 net/socket.c:729 + ____sys_sendmsg+0x505/0x830 net/socket.c:2614 + ___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668 + __sys_sendmsg net/socket.c:2700 [inline] + __do_sys_sendmsg net/socket.c:2705 [inline] + __se_sys_sendmsg net/socket.c:2703 [inline] + __x64_sys_sendmsg+0x19b/0x260 net/socket.c:2703 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +RIP: 0033:0x7f8d7e96a4a9 +Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 51 18 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f8d7e923198 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +RAX: ffffffffffffffda RBX: 00007f8d7e9f4308 RCX: 00007f8d7e96a4a9 +RDX: 0000000000000000 RSI: 0000200000000240 RDI: 0000000000000005 +RBP: 00007f8d7e9f4300 R08: 65732f636f72702f R09: 65732f636f72702f +R10: 65732f636f72702f R11: 0000000000000246 R12: 00007f8d7e9c10ac +R13: 00007f8d7e9231a0 R14: 0000200000000200 R15: 0000200000000250 + +Modules linked in: + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+1741b56d54536f4ec349@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68a6767c.050a0220.3d78fd.0011.GAE@google.com/ +Tested-by: syzbot+1741b56d54536f4ec349@syzkaller.appspotmail.com +Signed-off-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250821021901.2814721-1-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/atm/atmtcp.c | 17 ++++++++++++++--- + include/linux/atmdev.h | 1 + + net/atm/common.c | 15 ++++++++++++--- + 3 files changed, 27 insertions(+), 6 deletions(-) + +diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c +index afc1af542c3b5..c6915c5effbd7 100644 +--- a/drivers/atm/atmtcp.c ++++ b/drivers/atm/atmtcp.c +@@ -279,6 +279,19 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) + return NULL; + } + ++static int atmtcp_c_pre_send(struct atm_vcc *vcc, struct sk_buff *skb) ++{ ++ struct atmtcp_hdr *hdr; ++ ++ if (skb->len < sizeof(struct atmtcp_hdr)) ++ return -EINVAL; ++ ++ hdr = (struct atmtcp_hdr *)skb->data; ++ if (hdr->length == ATMTCP_HDR_MAGIC) ++ return -EINVAL; ++ ++ return 0; ++} + + static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + { +@@ -288,9 +301,6 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + struct sk_buff *new_skb; + int result = 0; + +- if (skb->len < sizeof(struct atmtcp_hdr)) +- goto done; +- + dev = vcc->dev_data; + hdr = (struct atmtcp_hdr *) skb->data; + if (hdr->length == ATMTCP_HDR_MAGIC) { +@@ -347,6 +357,7 @@ static struct atmdev_ops atmtcp_v_dev_ops = { + + static const struct atmdev_ops atmtcp_c_dev_ops = { + .close = atmtcp_c_close, ++ .pre_send = atmtcp_c_pre_send, + .send = atmtcp_c_send + }; + +diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h +index bc24d19ec2b37..8cbb992f6293c 100644 +--- a/include/linux/atmdev.h ++++ b/include/linux/atmdev.h +@@ -185,6 +185,7 @@ struct atmdev_ops { /* only send is required */ + int (*compat_ioctl)(struct atm_dev *dev,unsigned int cmd, + void __user *arg); + #endif ++ int (*pre_send)(struct atm_vcc *vcc, struct sk_buff *skb); + int (*send)(struct atm_vcc *vcc,struct sk_buff *skb); + int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags); + void (*phy_put)(struct atm_dev *dev,unsigned char value, +diff --git a/net/atm/common.c b/net/atm/common.c +index a51994aba34c4..59b61886629e6 100644 +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -635,18 +635,27 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size) + + skb->dev = NULL; /* for paths shared with net_device interfaces */ + if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) { +- atm_return_tx(vcc, skb); +- kfree_skb(skb); + error = -EFAULT; +- goto out; ++ goto free_skb; + } + if (eff != size) + memset(skb->data + size, 0, eff-size); ++ ++ if (vcc->dev->ops->pre_send) { ++ error = vcc->dev->ops->pre_send(vcc, skb); ++ if (error) ++ goto free_skb; ++ } ++ + error = vcc->dev->ops->send(vcc, skb); + error = error ? error : size; + out: + release_sock(sk); + return error; ++free_skb: ++ atm_return_tx(vcc, skb); ++ kfree_skb(skb); ++ goto out; + } + + __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait) +-- +2.50.1 + diff --git a/queue-5.4/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch b/queue-5.4/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch new file mode 100644 index 0000000000..da24c3ab7a --- /dev/null +++ b/queue-5.4/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch @@ -0,0 +1,47 @@ +From 7a268e98cab1fe76fe4d1519de97acdff4fb12e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Aug 2025 17:04:00 -0400 +Subject: Bluetooth: hci_event: Detect if HCI_EV_NUM_COMP_PKTS is unbalanced + +From: Luiz Augusto von Dentz + +[ Upstream commit 15bf2c6391bafb14a3020d06ec0761bce0803463 ] + +This attempts to detect if HCI_EV_NUM_COMP_PKTS contain an unbalanced +(more than currently considered outstanding) number of packets otherwise +it could cause the hcon->sent to underflow and loop around breaking the +tracking of the outstanding packets pending acknowledgment. + +Fixes: f42809185896 ("Bluetooth: Simplify num_comp_pkts_evt function") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 33b025a52b83a..4e8911501255d 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -3681,7 +3681,17 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) + if (!conn) + continue; + +- conn->sent -= count; ++ /* Check if there is really enough packets outstanding before ++ * attempting to decrease the sent counter otherwise it could ++ * underflow.. ++ */ ++ if (conn->sent >= count) { ++ conn->sent -= count; ++ } else { ++ bt_dev_warn(hdev, "hcon %p sent %u < count %u", ++ conn, conn->sent, count); ++ conn->sent = 0; ++ } + + switch (conn->type) { + case ACL_LINK: +-- +2.50.1 + diff --git a/queue-5.4/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch b/queue-5.4/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch new file mode 100644 index 0000000000..e127926c29 --- /dev/null +++ b/queue-5.4/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch @@ -0,0 +1,77 @@ +From dd55ca1d46c176720dfa0e02a0e3f1961613e275 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 15:39:54 +0800 +Subject: efivarfs: Fix slab-out-of-bounds in efivarfs_d_compare + +From: Li Nan + +[ Upstream commit a6358f8cf64850f3f27857b8ed8c1b08cfc4685c ] + +Observed on kernel 6.6 (present on master as well): + + BUG: KASAN: slab-out-of-bounds in memcmp+0x98/0xd0 + Call trace: + kasan_check_range+0xe8/0x190 + __asan_loadN+0x1c/0x28 + memcmp+0x98/0xd0 + efivarfs_d_compare+0x68/0xd8 + __d_lookup_rcu_op_compare+0x178/0x218 + __d_lookup_rcu+0x1f8/0x228 + d_alloc_parallel+0x150/0x648 + lookup_open.isra.0+0x5f0/0x8d0 + open_last_lookups+0x264/0x828 + path_openat+0x130/0x3f8 + do_filp_open+0x114/0x248 + do_sys_openat2+0x340/0x3c0 + __arm64_sys_openat+0x120/0x1a0 + +If dentry->d_name.len < EFI_VARIABLE_GUID_LEN , 'guid' can become +negative, leadings to oob. The issue can be triggered by parallel +lookups using invalid filename: + + T1 T2 + lookup_open + ->lookup + simple_lookup + d_add + // invalid dentry is added to hash list + + lookup_open + d_alloc_parallel + __d_lookup_rcu + __d_lookup_rcu_op_compare + hlist_bl_for_each_entry_rcu + // invalid dentry can be retrieved + ->d_compare + efivarfs_d_compare + // oob + +Fix it by checking 'guid' before cmp. + +Fixes: da27a24383b2 ("efivarfs: guid part of filenames are case-insensitive") +Signed-off-by: Li Nan +Signed-off-by: Wu Guanghao +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + fs/efivarfs/super.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c +index d12a21b2dd9d0..0f3d3d96599b8 100644 +--- a/fs/efivarfs/super.c ++++ b/fs/efivarfs/super.c +@@ -46,6 +46,10 @@ static int efivarfs_d_compare(const struct dentry *dentry, + { + int guid = len - EFI_VARIABLE_GUID_LEN; + ++ /* Parallel lookups may produce a temporary invalid filename */ ++ if (guid <= 0) ++ return 1; ++ + if (name->len != len) + return 1; + +-- +2.50.1 + diff --git a/queue-5.4/net-atm-remove-the-atmdev_ops-get-set-sockopt-method.patch b/queue-5.4/net-atm-remove-the-atmdev_ops-get-set-sockopt-method.patch new file mode 100644 index 0000000000..a91dca2a1d --- /dev/null +++ b/queue-5.4/net-atm-remove-the-atmdev_ops-get-set-sockopt-method.patch @@ -0,0 +1,331 @@ +From 7461361c85f5aeecb6c604601f57b40cb416c6ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2020 08:23:10 +0200 +Subject: net/atm: remove the atmdev_ops {get, set}sockopt methods + +From: Christoph Hellwig + +[ Upstream commit a06d30ae7af492497ffbca6abf1621d508b8fcaa ] + +All implementations of these two methods are dummies that always +return -EINVAL. + +Signed-off-by: Christoph Hellwig +Signed-off-by: David S. Miller +Stable-dep-of: ec79003c5f9d ("atm: atmtcp: Prevent arbitrary write in atmtcp_recv_control().") +Signed-off-by: Sasha Levin +--- + drivers/atm/eni.c | 17 ----------------- + drivers/atm/firestream.c | 2 -- + drivers/atm/fore200e.c | 27 --------------------------- + drivers/atm/horizon.c | 40 ---------------------------------------- + drivers/atm/iphase.c | 16 ---------------- + drivers/atm/lanai.c | 2 -- + drivers/atm/solos-pci.c | 2 -- + drivers/atm/zatm.c | 16 ---------------- + include/linux/atmdev.h | 9 --------- + net/atm/common.c | 14 ++------------ + 10 files changed, 2 insertions(+), 143 deletions(-) + +diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c +index 4816db0553ef8..0f082bd626543 100644 +--- a/drivers/atm/eni.c ++++ b/drivers/atm/eni.c +@@ -2035,21 +2035,6 @@ static int eni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) + return dev->phy->ioctl(dev,cmd,arg); + } + +- +-static int eni_getsockopt(struct atm_vcc *vcc,int level,int optname, +- void __user *optval,int optlen) +-{ +- return -EINVAL; +-} +- +- +-static int eni_setsockopt(struct atm_vcc *vcc,int level,int optname, +- void __user *optval,unsigned int optlen) +-{ +- return -EINVAL; +-} +- +- + static int eni_send(struct atm_vcc *vcc,struct sk_buff *skb) + { + enum enq_res res; +@@ -2223,8 +2208,6 @@ static const struct atmdev_ops ops = { + .open = eni_open, + .close = eni_close, + .ioctl = eni_ioctl, +- .getsockopt = eni_getsockopt, +- .setsockopt = eni_setsockopt, + .send = eni_send, + .phy_put = eni_phy_put, + .phy_get = eni_phy_get, +diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c +index 8995c39330fac..c7c3aeecd1c61 100644 +--- a/drivers/atm/firestream.c ++++ b/drivers/atm/firestream.c +@@ -1278,8 +1278,6 @@ static const struct atmdev_ops ops = { + .send = fs_send, + .owner = THIS_MODULE, + /* ioctl: fs_ioctl, */ +- /* getsockopt: fs_getsockopt, */ +- /* setsockopt: fs_setsockopt, */ + /* change_qos: fs_change_qos, */ + + /* For now implement these internally here... */ +diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c +index 8fbd36eb89410..a36f555cc0403 100644 +--- a/drivers/atm/fore200e.c ++++ b/drivers/atm/fore200e.c +@@ -1710,31 +1710,6 @@ fore200e_getstats(struct fore200e* fore200e) + return 0; + } + +- +-static int +-fore200e_getsockopt(struct atm_vcc* vcc, int level, int optname, void __user *optval, int optlen) +-{ +- /* struct fore200e* fore200e = FORE200E_DEV(vcc->dev); */ +- +- DPRINTK(2, "getsockopt %d.%d.%d, level = %d, optname = 0x%x, optval = 0x%p, optlen = %d\n", +- vcc->itf, vcc->vpi, vcc->vci, level, optname, optval, optlen); +- +- return -EINVAL; +-} +- +- +-static int +-fore200e_setsockopt(struct atm_vcc* vcc, int level, int optname, void __user *optval, unsigned int optlen) +-{ +- /* struct fore200e* fore200e = FORE200E_DEV(vcc->dev); */ +- +- DPRINTK(2, "setsockopt %d.%d.%d, level = %d, optname = 0x%x, optval = 0x%p, optlen = %d\n", +- vcc->itf, vcc->vpi, vcc->vci, level, optname, optval, optlen); +- +- return -EINVAL; +-} +- +- + #if 0 /* currently unused */ + static int + fore200e_get_oc3(struct fore200e* fore200e, struct oc3_regs* regs) +@@ -3026,8 +3001,6 @@ static const struct atmdev_ops fore200e_ops = { + .open = fore200e_open, + .close = fore200e_close, + .ioctl = fore200e_ioctl, +- .getsockopt = fore200e_getsockopt, +- .setsockopt = fore200e_setsockopt, + .send = fore200e_send, + .change_qos = fore200e_change_qos, + .proc_read = fore200e_proc_read, +diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c +index e5da51f907a25..4f2951cbe69c0 100644 +--- a/drivers/atm/horizon.c ++++ b/drivers/atm/horizon.c +@@ -2527,46 +2527,6 @@ static void hrz_close (struct atm_vcc * atm_vcc) { + clear_bit(ATM_VF_ADDR,&atm_vcc->flags); + } + +-#if 0 +-static int hrz_getsockopt (struct atm_vcc * atm_vcc, int level, int optname, +- void *optval, int optlen) { +- hrz_dev * dev = HRZ_DEV(atm_vcc->dev); +- PRINTD (DBG_FLOW|DBG_VCC, "hrz_getsockopt"); +- switch (level) { +- case SOL_SOCKET: +- switch (optname) { +-// case SO_BCTXOPT: +-// break; +-// case SO_BCRXOPT: +-// break; +- default: +- return -ENOPROTOOPT; +- }; +- break; +- } +- return -EINVAL; +-} +- +-static int hrz_setsockopt (struct atm_vcc * atm_vcc, int level, int optname, +- void *optval, unsigned int optlen) { +- hrz_dev * dev = HRZ_DEV(atm_vcc->dev); +- PRINTD (DBG_FLOW|DBG_VCC, "hrz_setsockopt"); +- switch (level) { +- case SOL_SOCKET: +- switch (optname) { +-// case SO_BCTXOPT: +-// break; +-// case SO_BCRXOPT: +-// break; +- default: +- return -ENOPROTOOPT; +- }; +- break; +- } +- return -EINVAL; +-} +-#endif +- + #if 0 + static int hrz_ioctl (struct atm_dev * atm_dev, unsigned int cmd, void *arg) { + hrz_dev * dev = HRZ_DEV(atm_dev); +diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c +index bfc889367d5e3..cc90f550ab75a 100644 +--- a/drivers/atm/iphase.c ++++ b/drivers/atm/iphase.c +@@ -2882,20 +2882,6 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg) + return 0; + } + +-static int ia_getsockopt(struct atm_vcc *vcc, int level, int optname, +- void __user *optval, int optlen) +-{ +- IF_EVENT(printk(">ia_getsockopt\n");) +- return -EINVAL; +-} +- +-static int ia_setsockopt(struct atm_vcc *vcc, int level, int optname, +- void __user *optval, unsigned int optlen) +-{ +- IF_EVENT(printk(">ia_setsockopt\n");) +- return -EINVAL; +-} +- + static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { + IADEV *iadev; + struct dle *wr_ptr; +@@ -3166,8 +3152,6 @@ static const struct atmdev_ops ops = { + .open = ia_open, + .close = ia_close, + .ioctl = ia_ioctl, +- .getsockopt = ia_getsockopt, +- .setsockopt = ia_setsockopt, + .send = ia_send, + .phy_put = ia_phy_put, + .phy_get = ia_phy_get, +diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c +index c6b38112bcf4f..2ed832e1dafa2 100644 +--- a/drivers/atm/lanai.c ++++ b/drivers/atm/lanai.c +@@ -2540,8 +2540,6 @@ static const struct atmdev_ops ops = { + .dev_close = lanai_dev_close, + .open = lanai_open, + .close = lanai_close, +- .getsockopt = NULL, +- .setsockopt = NULL, + .send = lanai_send, + .phy_put = NULL, + .phy_get = NULL, +diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c +index 9f2148daf8ad1..669466d010efa 100644 +--- a/drivers/atm/solos-pci.c ++++ b/drivers/atm/solos-pci.c +@@ -1179,8 +1179,6 @@ static const struct atmdev_ops fpga_ops = { + .open = popen, + .close = pclose, + .ioctl = NULL, +- .getsockopt = NULL, +- .setsockopt = NULL, + .send = psend, + .send_oam = NULL, + .phy_put = NULL, +diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c +index 165eebe06e39e..ee059c77e3bbc 100644 +--- a/drivers/atm/zatm.c ++++ b/drivers/atm/zatm.c +@@ -1515,20 +1515,6 @@ static int zatm_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) + } + } + +- +-static int zatm_getsockopt(struct atm_vcc *vcc,int level,int optname, +- void __user *optval,int optlen) +-{ +- return -EINVAL; +-} +- +- +-static int zatm_setsockopt(struct atm_vcc *vcc,int level,int optname, +- void __user *optval,unsigned int optlen) +-{ +- return -EINVAL; +-} +- + static int zatm_send(struct atm_vcc *vcc,struct sk_buff *skb) + { + int error; +@@ -1582,8 +1568,6 @@ static const struct atmdev_ops ops = { + .open = zatm_open, + .close = zatm_close, + .ioctl = zatm_ioctl, +- .getsockopt = zatm_getsockopt, +- .setsockopt = zatm_setsockopt, + .send = zatm_send, + .phy_put = zatm_phy_put, + .phy_get = zatm_phy_get, +diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h +index 19c0f91c38bdd..bc24d19ec2b37 100644 +--- a/include/linux/atmdev.h ++++ b/include/linux/atmdev.h +@@ -176,11 +176,6 @@ struct atm_dev { + #define ATM_OF_IMMED 1 /* Attempt immediate delivery */ + #define ATM_OF_INRATE 2 /* Attempt in-rate delivery */ + +- +-/* +- * ioctl, getsockopt, and setsockopt are optional and can be set to NULL. +- */ +- + struct atmdev_ops { /* only send is required */ + void (*dev_close)(struct atm_dev *dev); + int (*open)(struct atm_vcc *vcc); +@@ -190,10 +185,6 @@ struct atmdev_ops { /* only send is required */ + int (*compat_ioctl)(struct atm_dev *dev,unsigned int cmd, + void __user *arg); + #endif +- int (*getsockopt)(struct atm_vcc *vcc,int level,int optname, +- void __user *optval,int optlen); +- int (*setsockopt)(struct atm_vcc *vcc,int level,int optname, +- void __user *optval,unsigned int optlen); + int (*send)(struct atm_vcc *vcc,struct sk_buff *skb); + int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags); + void (*phy_put)(struct atm_dev *dev,unsigned char value, +diff --git a/net/atm/common.c b/net/atm/common.c +index 1e07a5fc53d05..a51994aba34c4 100644 +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -783,13 +783,8 @@ int vcc_setsockopt(struct socket *sock, int level, int optname, + vcc->atm_options &= ~ATM_ATMOPT_CLP; + return 0; + default: +- if (level == SOL_SOCKET) +- return -EINVAL; +- break; +- } +- if (!vcc->dev || !vcc->dev->ops->setsockopt) + return -EINVAL; +- return vcc->dev->ops->setsockopt(vcc, level, optname, optval, optlen); ++ } + } + + int vcc_getsockopt(struct socket *sock, int level, int optname, +@@ -827,13 +822,8 @@ int vcc_getsockopt(struct socket *sock, int level, int optname, + return copy_to_user(optval, &pvc, sizeof(pvc)) ? -EFAULT : 0; + } + default: +- if (level == SOL_SOCKET) +- return -EINVAL; +- break; +- } +- if (!vcc->dev || !vcc->dev->ops->getsockopt) + return -EINVAL; +- return vcc->dev->ops->getsockopt(vcc, level, optname, optval, len); ++ } + } + + int register_atmdevice_notifier(struct notifier_block *nb) +-- +2.50.1 + diff --git a/queue-5.4/net-dlink-fix-multicast-stats-being-counted-incorrec.patch b/queue-5.4/net-dlink-fix-multicast-stats-being-counted-incorrec.patch new file mode 100644 index 0000000000..0a0aef7be5 --- /dev/null +++ b/queue-5.4/net-dlink-fix-multicast-stats-being-counted-incorrec.patch @@ -0,0 +1,46 @@ +From 06520857bf70423ebff4cdebeb35674058ac1fb4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Aug 2025 03:29:24 +0900 +Subject: net: dlink: fix multicast stats being counted incorrectly + +From: Yeounsu Moon + +[ Upstream commit 007a5ffadc4fd51739527f1503b7cf048f31c413 ] + +`McstFramesRcvdOk` counts the number of received multicast packets, and +it reports the value correctly. + +However, reading `McstFramesRcvdOk` clears the register to zero. As a +result, the driver was reporting only the packets since the last read, +instead of the accumulated total. + +Fix this by updating the multicast statistics accumulatively instaed of +instantaneously. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Tested-on: D-Link DGE-550T Rev-A3 +Signed-off-by: Yeounsu Moon +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250823182927.6063-3-yyyynoom@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/dlink/dl2k.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c +index 8d57fb5072054..b4a8d4f12087a 100644 +--- a/drivers/net/ethernet/dlink/dl2k.c ++++ b/drivers/net/ethernet/dlink/dl2k.c +@@ -1102,7 +1102,7 @@ get_stats (struct net_device *dev) + dev->stats.rx_bytes += dr32(OctetRcvOk); + dev->stats.tx_bytes += dr32(OctetXmtOk); + +- dev->stats.multicast = dr32(McstFramesRcvdOk); ++ dev->stats.multicast += dr32(McstFramesRcvdOk); + dev->stats.collisions += dr32(SingleColFrames) + + dr32(MultiColFrames); + +-- +2.50.1 + diff --git a/queue-5.4/net-ipv4-fix-regression-in-local-broadcast-routes.patch b/queue-5.4/net-ipv4-fix-regression-in-local-broadcast-routes.patch new file mode 100644 index 0000000000..c41bc24ec8 --- /dev/null +++ b/queue-5.4/net-ipv4-fix-regression-in-local-broadcast-routes.patch @@ -0,0 +1,57 @@ +From a49d39fa6c97f5a783636b87167f3e41b4de394d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 08:23:21 +0200 +Subject: net: ipv4: fix regression in local-broadcast routes + +From: Oscar Maes + +[ Upstream commit 5189446ba995556eaa3755a6e875bc06675b88bd ] + +Commit 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") +introduced a regression where local-broadcast packets would have their +gateway set in __mkroute_output, which was caused by fi = NULL being +removed. + +Fix this by resetting the fib_info for local-broadcast packets. This +preserves the intended changes for directed-broadcast packets. + +Cc: stable@vger.kernel.org +Fixes: 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") +Reported-by: Brett A C Sheffield +Closes: https://lore.kernel.org/regressions/20250822165231.4353-4-bacs@librecast.net +Signed-off-by: Oscar Maes +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20250827062322.4807-1-oscmaes92@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/route.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 80612f73ff531..eb83ce4b845ab 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -2365,12 +2365,16 @@ static struct rtable *__mkroute_output(const struct fib_result *res, + !netif_is_l3_master(dev_out)) + return ERR_PTR(-EINVAL); + +- if (ipv4_is_lbcast(fl4->daddr)) ++ if (ipv4_is_lbcast(fl4->daddr)) { + type = RTN_BROADCAST; +- else if (ipv4_is_multicast(fl4->daddr)) ++ ++ /* reset fi to prevent gateway resolution */ ++ fi = NULL; ++ } else if (ipv4_is_multicast(fl4->daddr)) { + type = RTN_MULTICAST; +- else if (ipv4_is_zeronet(fl4->daddr)) ++ } else if (ipv4_is_zeronet(fl4->daddr)) { + return ERR_PTR(-EINVAL); ++ } + + if (dev_out->flags & IFF_LOOPBACK) + flags |= RTCF_LOCAL; +-- +2.50.1 + diff --git a/queue-5.4/net-mlx5e-set-local-xoff-after-fw-update.patch b/queue-5.4/net-mlx5e-set-local-xoff-after-fw-update.patch new file mode 100644 index 0000000000..2c505cf337 --- /dev/null +++ b/queue-5.4/net-mlx5e-set-local-xoff-after-fw-update.patch @@ -0,0 +1,50 @@ +From e63cb1028414bc22af506551acb649eb673c6905 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:34 +0300 +Subject: net/mlx5e: Set local Xoff after FW update + +From: Alexei Lazar + +[ Upstream commit aca0c31af61e0d5cf1675a0cbd29460b95ae693c ] + +The local Xoff value is being set before the firmware (FW) update. +In case of a failure where the FW is not updated with the new value, +there is no fallback to the previous value. +Update the local Xoff value after the FW has been successfully set. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Reviewed-by: Dragos Tatulea +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-12-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +index 99c7cdd0404a5..44d3d6826f696 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +@@ -341,7 +341,6 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + if (err) + return err; + } +- priv->dcbx.xoff = xoff; + + /* Apply the settings */ + if (update_buffer) { +@@ -350,6 +349,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + return err; + } + ++ priv->dcbx.xoff = xoff; ++ + if (update_prio2buffer) + err = mlx5e_port_set_priority2buffer(priv->mdev, prio2buffer); + +-- +2.50.1 + diff --git a/queue-5.4/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch b/queue-5.4/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch new file mode 100644 index 0000000000..bc4ecd7685 --- /dev/null +++ b/queue-5.4/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch @@ -0,0 +1,100 @@ +From 65cfd30f453ae6071cfe271ed37a23cd7977e32c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:32 +0300 +Subject: net/mlx5e: Update and set Xon/Xoff upon MTU set + +From: Alexei Lazar + +[ Upstream commit ceddedc969f0532b7c62ca971ee50d519d2bc0cb ] + +Xon/Xoff sizes are derived from calculation that include the MTU size. +Set Xon/Xoff when MTU is set. +If Xon/Xoff fails, set the previous MTU. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-10-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/en/port_buffer.h | 12 ++++++++++++ + .../net/ethernet/mellanox/mlx5/core/en_main.c | 17 ++++++++++++++++- + 2 files changed, 28 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +index 34f55b81a0deb..7b852b87a609f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +@@ -64,11 +64,23 @@ struct mlx5e_port_buffer { + struct mlx5e_bufferx_reg buffer[MLX5E_MAX_BUFFER]; + }; + ++#ifdef CONFIG_MLX5_CORE_EN_DCB + int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + u32 change, unsigned int mtu, + struct ieee_pfc *pfc, + u32 *buffer_size, + u8 *prio2buffer); ++#else ++static inline int ++mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, ++ u32 change, unsigned int mtu, ++ void *pfc, ++ u32 *buffer_size, ++ u8 *prio2buffer) ++{ ++ return 0; ++} ++#endif + + int mlx5e_port_query_buffer(struct mlx5e_priv *priv, + struct mlx5e_port_buffer *port_buffer); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index b3ba996004f1d..41bd16cc9d0f6 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -42,6 +42,7 @@ + #include "eswitch.h" + #include "en.h" + #include "en/txrx.h" ++#include "en/port_buffer.h" + #include "en_tc.h" + #include "en_rep.h" + #include "en_accel/ipsec.h" +@@ -2894,9 +2895,11 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) + struct mlx5e_params *params = &priv->channels.params; + struct net_device *netdev = priv->netdev; + struct mlx5_core_dev *mdev = priv->mdev; +- u16 mtu; ++ u16 mtu, prev_mtu; + int err; + ++ mlx5e_query_mtu(mdev, params, &prev_mtu); ++ + err = mlx5e_set_mtu(mdev, params, params->sw_mtu); + if (err) + return err; +@@ -2906,6 +2909,18 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) + netdev_warn(netdev, "%s: VPort MTU %d is different than netdev mtu %d\n", + __func__, mtu, params->sw_mtu); + ++ if (mtu != prev_mtu && MLX5_BUFFER_SUPPORTED(mdev)) { ++ err = mlx5e_port_manual_buffer_config(priv, 0, mtu, ++ NULL, NULL, NULL); ++ if (err) { ++ netdev_warn(netdev, "%s: Failed to set Xon/Xoff values with MTU %d (err %d), setting back to previous MTU %d\n", ++ __func__, mtu, err, prev_mtu); ++ ++ mlx5e_set_mtu(mdev, params, prev_mtu); ++ return err; ++ } ++ } ++ + params->sw_mtu = mtu; + return 0; + } +-- +2.50.1 + diff --git a/queue-5.4/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch b/queue-5.4/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch new file mode 100644 index 0000000000..349de8c8da --- /dev/null +++ b/queue-5.4/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch @@ -0,0 +1,46 @@ +From 7844bc7fe4896ad0ff5821e80fedee7bcd0283ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:33 +0300 +Subject: net/mlx5e: Update and set Xon/Xoff upon port speed set + +From: Alexei Lazar + +[ Upstream commit d24341740fe48add8a227a753e68b6eedf4b385a ] + +Xon/Xoff sizes are derived from calculations that include +the port speed. +These settings need to be updated and applied whenever the +port speed is changed. +The port speed is typically set after the physical link goes down +and is negotiated as part of the link-up process between the two +connected interfaces. +Xon/Xoff parameters being updated at the point where the new +negotiated speed is established. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-11-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 41bd16cc9d0f6..b8d0b68befcb9 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -141,6 +141,8 @@ void mlx5e_update_carrier(struct mlx5e_priv *priv) + if (port_state == VPORT_STATE_UP) { + netdev_info(priv->netdev, "Link up\n"); + netif_carrier_on(priv->netdev); ++ mlx5e_port_manual_buffer_config(priv, 0, priv->netdev->mtu, ++ NULL, NULL, NULL); + } else { + netdev_info(priv->netdev, "Link down\n"); + netif_carrier_off(priv->netdev); +-- +2.50.1 + diff --git a/queue-5.4/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch b/queue-5.4/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch new file mode 100644 index 0000000000..117b388014 --- /dev/null +++ b/queue-5.4/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch @@ -0,0 +1,49 @@ +From f73fa5730fb89860c7baa5bbce8a80473ce135af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 12:36:52 +0800 +Subject: net: stmmac: xgmac: Do not enable RX FIFO Overflow interrupts + +From: Rohan G Thomas + +[ Upstream commit 4f23382841e67174211271a454811dd17c0ef3c5 ] + +Enabling RX FIFO Overflow interrupts is counterproductive +and causes an interrupt storm when RX FIFO overflows. +Disabling this interrupt has no side effect and eliminates +interrupt storms when the RX FIFO overflows. + +Commit 8a7cb245cf28 ("net: stmmac: Do not enable RX FIFO +overflow interrupts") disables RX FIFO overflow interrupts +for DWMAC4 IP and removes the corresponding handling of +this interrupt. This patch is doing the same thing for +XGMAC IP. + +Fixes: 2142754f8b9c ("net: stmmac: Add MAC related callbacks for XGMAC2") +Signed-off-by: Rohan G Thomas +Reviewed-by: Matthew Gerlach +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250825-xgmac-minor-fixes-v3-1-c225fe4444c0@altera.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +index 07ef0ac725b3e..93d1b78c9d4ec 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +@@ -206,10 +206,6 @@ static void dwxgmac2_dma_rx_mode(void __iomem *ioaddr, int mode, + } + + writel(value, ioaddr + XGMAC_MTL_RXQ_OPMODE(channel)); +- +- /* Enable MTL RX overflow */ +- value = readl(ioaddr + XGMAC_MTL_QINTEN(channel)); +- writel(value | XGMAC_RXOIE, ioaddr + XGMAC_MTL_QINTEN(channel)); + } + + static void dwxgmac2_dma_tx_mode(void __iomem *ioaddr, int mode, +-- +2.50.1 + diff --git a/queue-5.4/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch b/queue-5.4/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch new file mode 100644 index 0000000000..2f5b84b9ab --- /dev/null +++ b/queue-5.4/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch @@ -0,0 +1,68 @@ +From b86acca59e57fb40f6a55f13d567274c0365991d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 May 2025 10:11:04 +0530 +Subject: powerpc/kvm: Fix ifdef to remove build warning + +From: Madhavan Srinivasan + +[ Upstream commit 88688a2c8ac6c8036d983ad8b34ce191c46a10aa ] + +When compiling for pseries or powernv defconfig with "make C=1", +these warning were reported bu sparse tool in powerpc/kernel/kvm.c + +arch/powerpc/kernel/kvm.c:635:9: warning: switch with no cases +arch/powerpc/kernel/kvm.c:646:9: warning: switch with no cases + +Currently #ifdef were added after the switch case which are specific +for BOOKE and PPC_BOOK3S_32. These are not enabled in pseries/powernv +defconfig. Fix it by moving the #ifdef before switch(){} + +Fixes: cbe487fac7fc0 ("KVM: PPC: Add mtsrin PV code") +Tested-by: Venkat Rao Bagalkote +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250518044107.39928-1-maddy@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/kvm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c +index d89cf802d9aa7..8067641561a4f 100644 +--- a/arch/powerpc/kernel/kvm.c ++++ b/arch/powerpc/kernel/kvm.c +@@ -632,19 +632,19 @@ static void __init kvm_check_ins(u32 *inst, u32 features) + #endif + } + +- switch (inst_no_rt & ~KVM_MASK_RB) { + #ifdef CONFIG_PPC_BOOK3S_32 ++ switch (inst_no_rt & ~KVM_MASK_RB) { + case KVM_INST_MTSRIN: + if (features & KVM_MAGIC_FEAT_SR) { + u32 inst_rb = _inst & KVM_MASK_RB; + kvm_patch_ins_mtsrin(inst, inst_rt, inst_rb); + } + break; +-#endif + } ++#endif + +- switch (_inst) { + #ifdef CONFIG_BOOKE ++ switch (_inst) { + case KVM_INST_WRTEEI_0: + kvm_patch_ins_wrteei_0(inst); + break; +@@ -652,8 +652,8 @@ static void __init kvm_check_ins(u32 *inst, u32 features) + case KVM_INST_WRTEEI_1: + kvm_patch_ins_wrtee(inst, 0, 1); + break; +-#endif + } ++#endif + } + + extern u32 kvm_template_start[]; +-- +2.50.1 + diff --git a/queue-5.4/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch b/queue-5.4/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch new file mode 100644 index 0000000000..3946cb57f9 --- /dev/null +++ b/queue-5.4/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch @@ -0,0 +1,72 @@ +From b5a913dcc708835316413c9194bbfde05fb0432b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Aug 2025 14:13:14 +0000 +Subject: sctp: initialize more fields in sctp_v6_from_sk() + +From: Eric Dumazet + +[ Upstream commit 2e8750469242cad8f01f320131fd5a6f540dbb99 ] + +syzbot found that sin6_scope_id was not properly initialized, +leading to undefined behavior. + +Clear sin6_scope_id and sin6_flowinfo. + +BUG: KMSAN: uninit-value in __sctp_v6_cmp_addr+0x887/0x8c0 net/sctp/ipv6.c:649 + __sctp_v6_cmp_addr+0x887/0x8c0 net/sctp/ipv6.c:649 + sctp_inet6_cmp_addr+0x4f2/0x510 net/sctp/ipv6.c:983 + sctp_bind_addr_conflict+0x22a/0x3b0 net/sctp/bind_addr.c:390 + sctp_get_port_local+0x21eb/0x2440 net/sctp/socket.c:8452 + sctp_get_port net/sctp/socket.c:8523 [inline] + sctp_listen_start net/sctp/socket.c:8567 [inline] + sctp_inet_listen+0x710/0xfd0 net/sctp/socket.c:8636 + __sys_listen_socket net/socket.c:1912 [inline] + __sys_listen net/socket.c:1927 [inline] + __do_sys_listen net/socket.c:1932 [inline] + __se_sys_listen net/socket.c:1930 [inline] + __x64_sys_listen+0x343/0x4c0 net/socket.c:1930 + x64_sys_call+0x271d/0x3e20 arch/x86/include/generated/asm/syscalls_64.h:51 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xd9/0x210 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Local variable addr.i.i created at: + sctp_get_port net/sctp/socket.c:8515 [inline] + sctp_listen_start net/sctp/socket.c:8567 [inline] + sctp_inet_listen+0x650/0xfd0 net/sctp/socket.c:8636 + __sys_listen_socket net/socket.c:1912 [inline] + __sys_listen net/socket.c:1927 [inline] + __do_sys_listen net/socket.c:1932 [inline] + __se_sys_listen net/socket.c:1930 [inline] + __x64_sys_listen+0x343/0x4c0 net/socket.c:1930 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+e69f06a0f30116c68056@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68adc0a2.050a0220.37038e.00c4.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Marcelo Ricardo Leitner +Acked-by: Xin Long +Link: https://patch.msgid.link/20250826141314.1802610-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/ipv6.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c +index fae6157e837aa..33981ea102814 100644 +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -499,7 +499,9 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) + { + addr->v6.sin6_family = AF_INET6; + addr->v6.sin6_port = 0; ++ addr->v6.sin6_flowinfo = 0; + addr->v6.sin6_addr = sk->sk_v6_rcv_saddr; ++ addr->v6.sin6_scope_id = 0; + } + + /* Initialize sk->sk_rcv_saddr from sctp_addr. */ +-- +2.50.1 + diff --git a/queue-5.4/series b/queue-5.4/series index 7a5f66f3bc..425cf07ca8 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -2,3 +2,15 @@ pinctrl-stmfx-add-missing-has_iomem-dependency.patch ftrace-fix-potential-warning-in-trace_printk_seq-dur.patch scsi-core-sysfs-correct-sysfs-attributes-access-righ.patch vhost-net-protect-ubufs-with-rcu-read-lock-in-vhost_net_ubuf_put.patch +net-ipv4-fix-regression-in-local-broadcast-routes.patch +powerpc-kvm-fix-ifdef-to-remove-build-warning.patch +bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch +net-atm-remove-the-atmdev_ops-get-set-sockopt-method.patch +atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch +net-dlink-fix-multicast-stats-being-counted-incorrec.patch +net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch +net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch +net-mlx5e-set-local-xoff-after-fw-update.patch +net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch +sctp-initialize-more-fields-in-sctp_v6_from_sk.patch +efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch diff --git a/queue-6.1/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch b/queue-6.1/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch new file mode 100644 index 0000000000..8aaad5fd17 --- /dev/null +++ b/queue-6.1/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch @@ -0,0 +1,192 @@ +From 515045984d0b06fbcb39d0089cf5190e6279f06c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Aug 2025 02:18:24 +0000 +Subject: atm: atmtcp: Prevent arbitrary write in atmtcp_recv_control(). + +From: Kuniyuki Iwashima + +[ Upstream commit ec79003c5f9d2c7f9576fc69b8dbda80305cbe3a ] + +syzbot reported the splat below. [0] + +When atmtcp_v_open() or atmtcp_v_close() is called via connect() +or close(), atmtcp_send_control() is called to send an in-kernel +special message. + +The message has ATMTCP_HDR_MAGIC in atmtcp_control.hdr.length. +Also, a pointer of struct atm_vcc is set to atmtcp_control.vcc. + +The notable thing is struct atmtcp_control is uAPI but has a +space for an in-kernel pointer. + + struct atmtcp_control { + struct atmtcp_hdr hdr; /* must be first */ + ... + atm_kptr_t vcc; /* both directions */ + ... + } __ATM_API_ALIGN; + + typedef struct { unsigned char _[8]; } __ATM_API_ALIGN atm_kptr_t; + +The special message is processed in atmtcp_recv_control() called +from atmtcp_c_send(). + +atmtcp_c_send() is vcc->dev->ops->send() and called from 2 paths: + + 1. .ndo_start_xmit() (vcc->send() == atm_send_aal0()) + 2. vcc_sendmsg() + +The problem is sendmsg() does not validate the message length and +userspace can abuse atmtcp_recv_control() to overwrite any kptr +by atmtcp_control. + +Let's add a new ->pre_send() hook to validate messages from sendmsg(). + +[0]: +Oops: general protection fault, probably for non-canonical address 0xdffffc00200000ab: 0000 [#1] SMP KASAN PTI +KASAN: probably user-memory-access in range [0x0000000100000558-0x000000010000055f] +CPU: 0 UID: 0 PID: 5865 Comm: syz-executor331 Not tainted 6.17.0-rc1-syzkaller-00215-gbab3ce404553 #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/12/2025 +RIP: 0010:atmtcp_recv_control drivers/atm/atmtcp.c:93 [inline] +RIP: 0010:atmtcp_c_send+0x1da/0x950 drivers/atm/atmtcp.c:297 +Code: 4d 8d 75 1a 4c 89 f0 48 c1 e8 03 42 0f b6 04 20 84 c0 0f 85 15 06 00 00 41 0f b7 1e 4d 8d b7 60 05 00 00 4c 89 f0 48 c1 e8 03 <42> 0f b6 04 20 84 c0 0f 85 13 06 00 00 66 41 89 1e 4d 8d 75 1c 4c +RSP: 0018:ffffc90003f5f810 EFLAGS: 00010203 +RAX: 00000000200000ab RBX: 0000000000000000 RCX: 0000000000000000 +RDX: ffff88802a510000 RSI: 00000000ffffffff RDI: ffff888030a6068c +RBP: ffff88802699fb40 R08: ffff888030a606eb R09: 1ffff1100614c0dd +R10: dffffc0000000000 R11: ffffffff8718fc40 R12: dffffc0000000000 +R13: ffff888030a60680 R14: 000000010000055f R15: 00000000ffffffff +FS: 00007f8d7e9236c0(0000) GS:ffff888125c1c000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 000000000045ad50 CR3: 0000000075bde000 CR4: 00000000003526f0 +Call Trace: + + vcc_sendmsg+0xa10/0xc60 net/atm/common.c:645 + sock_sendmsg_nosec net/socket.c:714 [inline] + __sock_sendmsg+0x219/0x270 net/socket.c:729 + ____sys_sendmsg+0x505/0x830 net/socket.c:2614 + ___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668 + __sys_sendmsg net/socket.c:2700 [inline] + __do_sys_sendmsg net/socket.c:2705 [inline] + __se_sys_sendmsg net/socket.c:2703 [inline] + __x64_sys_sendmsg+0x19b/0x260 net/socket.c:2703 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +RIP: 0033:0x7f8d7e96a4a9 +Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 51 18 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f8d7e923198 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +RAX: ffffffffffffffda RBX: 00007f8d7e9f4308 RCX: 00007f8d7e96a4a9 +RDX: 0000000000000000 RSI: 0000200000000240 RDI: 0000000000000005 +RBP: 00007f8d7e9f4300 R08: 65732f636f72702f R09: 65732f636f72702f +R10: 65732f636f72702f R11: 0000000000000246 R12: 00007f8d7e9c10ac +R13: 00007f8d7e9231a0 R14: 0000200000000200 R15: 0000200000000250 + +Modules linked in: + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+1741b56d54536f4ec349@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68a6767c.050a0220.3d78fd.0011.GAE@google.com/ +Tested-by: syzbot+1741b56d54536f4ec349@syzkaller.appspotmail.com +Signed-off-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250821021901.2814721-1-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/atm/atmtcp.c | 17 ++++++++++++++--- + include/linux/atmdev.h | 1 + + net/atm/common.c | 15 ++++++++++++--- + 3 files changed, 27 insertions(+), 6 deletions(-) + +diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c +index ff558908897f3..9c83fb29b2f1b 100644 +--- a/drivers/atm/atmtcp.c ++++ b/drivers/atm/atmtcp.c +@@ -279,6 +279,19 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) + return NULL; + } + ++static int atmtcp_c_pre_send(struct atm_vcc *vcc, struct sk_buff *skb) ++{ ++ struct atmtcp_hdr *hdr; ++ ++ if (skb->len < sizeof(struct atmtcp_hdr)) ++ return -EINVAL; ++ ++ hdr = (struct atmtcp_hdr *)skb->data; ++ if (hdr->length == ATMTCP_HDR_MAGIC) ++ return -EINVAL; ++ ++ return 0; ++} + + static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + { +@@ -288,9 +301,6 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + struct sk_buff *new_skb; + int result = 0; + +- if (skb->len < sizeof(struct atmtcp_hdr)) +- goto done; +- + dev = vcc->dev_data; + hdr = (struct atmtcp_hdr *) skb->data; + if (hdr->length == ATMTCP_HDR_MAGIC) { +@@ -347,6 +357,7 @@ static const struct atmdev_ops atmtcp_v_dev_ops = { + + static const struct atmdev_ops atmtcp_c_dev_ops = { + .close = atmtcp_c_close, ++ .pre_send = atmtcp_c_pre_send, + .send = atmtcp_c_send + }; + +diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h +index 45f2f278b50a8..70807c679f1ab 100644 +--- a/include/linux/atmdev.h ++++ b/include/linux/atmdev.h +@@ -185,6 +185,7 @@ struct atmdev_ops { /* only send is required */ + int (*compat_ioctl)(struct atm_dev *dev,unsigned int cmd, + void __user *arg); + #endif ++ int (*pre_send)(struct atm_vcc *vcc, struct sk_buff *skb); + int (*send)(struct atm_vcc *vcc,struct sk_buff *skb); + int (*send_bh)(struct atm_vcc *vcc, struct sk_buff *skb); + int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags); +diff --git a/net/atm/common.c b/net/atm/common.c +index 9cc82acbc7358..48bb3f66a3f2a 100644 +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -635,18 +635,27 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size) + + skb->dev = NULL; /* for paths shared with net_device interfaces */ + if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) { +- atm_return_tx(vcc, skb); +- kfree_skb(skb); + error = -EFAULT; +- goto out; ++ goto free_skb; + } + if (eff != size) + memset(skb->data + size, 0, eff-size); ++ ++ if (vcc->dev->ops->pre_send) { ++ error = vcc->dev->ops->pre_send(vcc, skb); ++ if (error) ++ goto free_skb; ++ } ++ + error = vcc->dev->ops->send(vcc, skb); + error = error ? error : size; + out: + release_sock(sk); + return error; ++free_skb: ++ atm_return_tx(vcc, skb); ++ kfree_skb(skb); ++ goto out; + } + + __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait) +-- +2.50.1 + diff --git a/queue-6.1/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch b/queue-6.1/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch new file mode 100644 index 0000000000..ea9cc21f57 --- /dev/null +++ b/queue-6.1/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch @@ -0,0 +1,47 @@ +From 49aad117a9b12de69a4f32f21f5202e99a1e52d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Aug 2025 17:04:00 -0400 +Subject: Bluetooth: hci_event: Detect if HCI_EV_NUM_COMP_PKTS is unbalanced + +From: Luiz Augusto von Dentz + +[ Upstream commit 15bf2c6391bafb14a3020d06ec0761bce0803463 ] + +This attempts to detect if HCI_EV_NUM_COMP_PKTS contain an unbalanced +(more than currently considered outstanding) number of packets otherwise +it could cause the hcon->sent to underflow and loop around breaking the +tracking of the outstanding packets pending acknowledgment. + +Fixes: f42809185896 ("Bluetooth: Simplify num_comp_pkts_evt function") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index ff013e1d82a85..3d81afcccff8b 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -4409,7 +4409,17 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, + if (!conn) + continue; + +- conn->sent -= count; ++ /* Check if there is really enough packets outstanding before ++ * attempting to decrease the sent counter otherwise it could ++ * underflow.. ++ */ ++ if (conn->sent >= count) { ++ conn->sent -= count; ++ } else { ++ bt_dev_warn(hdev, "hcon %p sent %u < count %u", ++ conn, conn->sent, count); ++ conn->sent = 0; ++ } + + switch (conn->type) { + case ACL_LINK: +-- +2.50.1 + diff --git a/queue-6.1/bluetooth-hci_event-mark-connection-as-closed-during.patch b/queue-6.1/bluetooth-hci_event-mark-connection-as-closed-during.patch new file mode 100644 index 0000000000..6cd7ca3eee --- /dev/null +++ b/queue-6.1/bluetooth-hci_event-mark-connection-as-closed-during.patch @@ -0,0 +1,80 @@ +From ed821df74519a971266af7d76764f0e17a57c358 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Aug 2025 17:55:27 +0200 +Subject: Bluetooth: hci_event: Mark connection as closed during suspend + disconnect + +From: Ludovico de Nittis + +[ Upstream commit b7fafbc499b5ee164018eb0eefe9027f5a6aaad2 ] + +When suspending, the disconnect command for an active Bluetooth +connection could be issued, but the corresponding +`HCI_EV_DISCONN_COMPLETE` event might not be received before the system +completes the suspend process. This can lead to an inconsistent state. + +On resume, the controller may auto-accept reconnections from the same +device (due to suspend event filters), but these new connections are +rejected by the kernel which still has connection objects from before +suspend. Resulting in errors like: +``` +kernel: Bluetooth: hci0: ACL packet for unknown connection handle 1 +kernel: Bluetooth: hci0: Ignoring HCI_Connection_Complete for existing +connection +``` + +This is a btmon snippet that shows the issue: +``` +< HCI Command: Disconnect (0x01|0x0006) plen 3 + Handle: 1 Address: 78:20:A5:4A:DF:28 (Nintendo Co.,Ltd) + Reason: Remote User Terminated Connection (0x13) +> HCI Event: Command Status (0x0f) plen 4 + Disconnect (0x01|0x0006) ncmd 2 + Status: Success (0x00) +[...] +// Host suspends with the event filter set for the device +// On resume, the device tries to reconnect with a new handle + +> HCI Event: Connect Complete (0x03) plen 11 + Status: Success (0x00) + Handle: 2 + Address: 78:20:A5:4A:DF:28 (Nintendo Co.,Ltd) + +// Kernel ignores this event because there is an existing connection +with +// handle 1 +``` + +By explicitly setting the connection state to BT_CLOSED we can ensure a +consistent state, even if we don't receive the disconnect complete event +in time. + +Link: https://github.com/bluez/bluez/issues/1226 +Fixes: 182ee45da083 ("Bluetooth: hci_sync: Rework hci_suspend_notifier") +Signed-off-by: Ludovico de Nittis +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 3ff428df58a46..ff013e1d82a85 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -2782,6 +2782,12 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) + goto done; + } + ++ /* During suspend, mark connection as closed immediately ++ * since we might not receive HCI_EV_DISCONN_COMPLETE ++ */ ++ if (hdev->suspended) ++ conn->state = BT_CLOSED; ++ + mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); + + if (conn->type == ACL_LINK) { +-- +2.50.1 + diff --git a/queue-6.1/bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch b/queue-6.1/bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch new file mode 100644 index 0000000000..80ba865d43 --- /dev/null +++ b/queue-6.1/bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch @@ -0,0 +1,84 @@ +From 4a12ac6ea3860e8e49c16b8a10b4b550398d5ed4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Aug 2025 17:55:26 +0200 +Subject: Bluetooth: hci_event: Treat UNKNOWN_CONN_ID on disconnect as success + +From: Ludovico de Nittis + +[ Upstream commit 2f050a5392b7a0928bf836d9891df4851463512c ] + +When the host sends an HCI_OP_DISCONNECT command, the controller may +respond with the status HCI_ERROR_UNKNOWN_CONN_ID (0x02). E.g. this can +happen on resume from suspend, if the link was terminated by the remote +device before the event mask was correctly set. + +This is a btmon snippet that shows the issue: +``` +> ACL Data RX: Handle 3 flags 0x02 dlen 12 + L2CAP: Disconnection Request (0x06) ident 5 len 4 + Destination CID: 65 + Source CID: 72 +< ACL Data TX: Handle 3 flags 0x00 dlen 12 + L2CAP: Disconnection Response (0x07) ident 5 len 4 + Destination CID: 65 + Source CID: 72 +> ACL Data RX: Handle 3 flags 0x02 dlen 12 + L2CAP: Disconnection Request (0x06) ident 6 len 4 + Destination CID: 64 + Source CID: 71 +< ACL Data TX: Handle 3 flags 0x00 dlen 12 + L2CAP: Disconnection Response (0x07) ident 6 len 4 + Destination CID: 64 + Source CID: 71 +< HCI Command: Set Event Mask (0x03|0x0001) plen 8 + Mask: 0x3dbff807fffbffff + Inquiry Complete + Inquiry Result + Connection Complete + Connection Request + Disconnection Complete + Authentication Complete +[...] +< HCI Command: Disconnect (0x01|0x0006) plen 3 + Handle: 3 Address: 78:20:A5:4A:DF:28 (Nintendo Co.,Ltd) + Reason: Remote User Terminated Connection (0x13) +> HCI Event: Command Status (0x0f) plen 4 + Disconnect (0x01|0x0006) ncmd 1 + Status: Unknown Connection Identifier (0x02) +``` + +Currently, the hci_cs_disconnect function treats any non-zero status +as a command failure. This can be misleading because the connection is +indeed being terminated and the controller is confirming that is has no +knowledge of that connection handle. Meaning that the initial request of +disconnecting a device should be treated as done. + +With this change we allow the function to proceed, following the success +path, which correctly calls `mgmt_device_disconnected` and ensures a +consistent state. + +Link: https://github.com/bluez/bluez/issues/1226 +Fixes: 182ee45da083 ("Bluetooth: hci_sync: Rework hci_suspend_notifier") +Signed-off-by: Ludovico de Nittis +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 866462c97dbaf..3ff428df58a46 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -2767,7 +2767,7 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) + if (!conn) + goto unlock; + +- if (status) { ++ if (status && status != HCI_ERROR_UNKNOWN_CONN_ID) { + mgmt_disconnect_failed(hdev, &conn->dst, conn->type, + conn->dst_type, status); + +-- +2.50.1 + diff --git a/queue-6.1/bluetooth-hci_sync-fix-set_local_name-race-condition.patch b/queue-6.1/bluetooth-hci_sync-fix-set_local_name-race-condition.patch new file mode 100644 index 0000000000..09834ca746 --- /dev/null +++ b/queue-6.1/bluetooth-hci_sync-fix-set_local_name-race-condition.patch @@ -0,0 +1,90 @@ +From c8647fe81cac13a8586803254ba95ec303a1cda8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Aug 2025 12:20:55 +0300 +Subject: Bluetooth: hci_sync: fix set_local_name race condition + +From: Pavel Shpakovskiy + +[ Upstream commit 6bbd0d3f0c23fc53c17409dd7476f38ae0ff0cd9 ] + +Function set_name_sync() uses hdev->dev_name field to send +HCI_OP_WRITE_LOCAL_NAME command, but copying from data to hdev->dev_name +is called after mgmt cmd was queued, so it is possible that function +set_name_sync() will read old name value. + +This change adds name as a parameter for function hci_update_name_sync() +to avoid race condition. + +Fixes: 6f6ff38a1e14 ("Bluetooth: hci_sync: Convert MGMT_OP_SET_LOCAL_NAME") +Signed-off-by: Pavel Shpakovskiy +Reviewed-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci_sync.h | 2 +- + net/bluetooth/hci_sync.c | 6 +++--- + net/bluetooth/mgmt.c | 5 ++++- + 3 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h +index 3a7658d660224..a8b106d884d41 100644 +--- a/include/net/bluetooth/hci_sync.h ++++ b/include/net/bluetooth/hci_sync.h +@@ -65,7 +65,7 @@ int hci_update_class_sync(struct hci_dev *hdev); + + int hci_update_eir_sync(struct hci_dev *hdev); + int hci_update_class_sync(struct hci_dev *hdev); +-int hci_update_name_sync(struct hci_dev *hdev); ++int hci_update_name_sync(struct hci_dev *hdev, const u8 *name); + int hci_write_ssp_mode_sync(struct hci_dev *hdev, u8 mode); + + int hci_get_random_address(struct hci_dev *hdev, bool require_privacy, +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index acff47da799aa..965b0f2b43a72 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -3424,13 +3424,13 @@ int hci_update_scan_sync(struct hci_dev *hdev) + return hci_write_scan_enable_sync(hdev, scan); + } + +-int hci_update_name_sync(struct hci_dev *hdev) ++int hci_update_name_sync(struct hci_dev *hdev, const u8 *name) + { + struct hci_cp_write_local_name cp; + + memset(&cp, 0, sizeof(cp)); + +- memcpy(cp.name, hdev->dev_name, sizeof(cp.name)); ++ memcpy(cp.name, name, sizeof(cp.name)); + + return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_LOCAL_NAME, + sizeof(cp), &cp, +@@ -3482,7 +3482,7 @@ int hci_powered_update_sync(struct hci_dev *hdev) + hci_write_fast_connectable_sync(hdev, false); + hci_update_scan_sync(hdev); + hci_update_class_sync(hdev); +- hci_update_name_sync(hdev); ++ hci_update_name_sync(hdev, hdev->dev_name); + hci_update_eir_sync(hdev); + } + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 919e1bae2b269..27876512c63a4 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -3897,8 +3897,11 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err) + + static int set_name_sync(struct hci_dev *hdev, void *data) + { ++ struct mgmt_pending_cmd *cmd = data; ++ struct mgmt_cp_set_local_name *cp = cmd->param; ++ + if (lmp_bredr_capable(hdev)) { +- hci_update_name_sync(hdev); ++ hci_update_name_sync(hdev, cp->name); + hci_update_eir_sync(hdev); + } + +-- +2.50.1 + diff --git a/queue-6.1/drm-msm-defer-fd_install-in-submit-ioctl.patch b/queue-6.1/drm-msm-defer-fd_install-in-submit-ioctl.patch new file mode 100644 index 0000000000..a9c0f5ba2f --- /dev/null +++ b/queue-6.1/drm-msm-defer-fd_install-in-submit-ioctl.patch @@ -0,0 +1,59 @@ +From ffd8dad18451b6f59f866ed6630bbf2d3aa890b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Jul 2025 13:28:22 -0700 +Subject: drm/msm: Defer fd_install in SUBMIT ioctl + +From: Rob Clark + +[ Upstream commit f22853435bbd1e9836d0dce7fd99c040b94c2bf1 ] + +Avoid fd_install() until there are no more potential error paths, to +avoid put_unused_fd() after the fd is made visible to userspace. + +Fixes: 68dc6c2d5eec ("drm/msm: Fix submit error-path leaks") +Reported-by: Dan Carpenter +Signed-off-by: Rob Clark +Patchwork: https://patchwork.freedesktop.org/patch/665363/ +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/msm_gem_submit.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c +index 572dd662e8095..6a02f790624a9 100644 +--- a/drivers/gpu/drm/msm/msm_gem_submit.c ++++ b/drivers/gpu/drm/msm/msm_gem_submit.c +@@ -929,12 +929,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, + + if (ret == 0 && args->flags & MSM_SUBMIT_FENCE_FD_OUT) { + sync_file = sync_file_create(submit->user_fence); +- if (!sync_file) { ++ if (!sync_file) + ret = -ENOMEM; +- } else { +- fd_install(out_fence_fd, sync_file->file); +- args->fence_fd = out_fence_fd; +- } + } + + submit_attach_object_fences(submit); +@@ -959,10 +955,14 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, + out_unlock: + mutex_unlock(&queue->lock); + out_post_unlock: +- if (ret && (out_fence_fd >= 0)) { +- put_unused_fd(out_fence_fd); ++ if (ret) { ++ if (out_fence_fd >= 0) ++ put_unused_fd(out_fence_fd); + if (sync_file) + fput(sync_file->file); ++ } else if (sync_file) { ++ fd_install(out_fence_fd, sync_file->file); ++ args->fence_fd = out_fence_fd; + } + + if (!IS_ERR_OR_NULL(submit)) { +-- +2.50.1 + diff --git a/queue-6.1/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch b/queue-6.1/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch new file mode 100644 index 0000000000..94f7ec339a --- /dev/null +++ b/queue-6.1/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch @@ -0,0 +1,77 @@ +From e5b4d67100cfc25f7953ca3f115d0e40a8147495 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 15:39:54 +0800 +Subject: efivarfs: Fix slab-out-of-bounds in efivarfs_d_compare + +From: Li Nan + +[ Upstream commit a6358f8cf64850f3f27857b8ed8c1b08cfc4685c ] + +Observed on kernel 6.6 (present on master as well): + + BUG: KASAN: slab-out-of-bounds in memcmp+0x98/0xd0 + Call trace: + kasan_check_range+0xe8/0x190 + __asan_loadN+0x1c/0x28 + memcmp+0x98/0xd0 + efivarfs_d_compare+0x68/0xd8 + __d_lookup_rcu_op_compare+0x178/0x218 + __d_lookup_rcu+0x1f8/0x228 + d_alloc_parallel+0x150/0x648 + lookup_open.isra.0+0x5f0/0x8d0 + open_last_lookups+0x264/0x828 + path_openat+0x130/0x3f8 + do_filp_open+0x114/0x248 + do_sys_openat2+0x340/0x3c0 + __arm64_sys_openat+0x120/0x1a0 + +If dentry->d_name.len < EFI_VARIABLE_GUID_LEN , 'guid' can become +negative, leadings to oob. The issue can be triggered by parallel +lookups using invalid filename: + + T1 T2 + lookup_open + ->lookup + simple_lookup + d_add + // invalid dentry is added to hash list + + lookup_open + d_alloc_parallel + __d_lookup_rcu + __d_lookup_rcu_op_compare + hlist_bl_for_each_entry_rcu + // invalid dentry can be retrieved + ->d_compare + efivarfs_d_compare + // oob + +Fix it by checking 'guid' before cmp. + +Fixes: da27a24383b2 ("efivarfs: guid part of filenames are case-insensitive") +Signed-off-by: Li Nan +Signed-off-by: Wu Guanghao +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + fs/efivarfs/super.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c +index b8c4641ed152b..9025430cf2ad3 100644 +--- a/fs/efivarfs/super.c ++++ b/fs/efivarfs/super.c +@@ -47,6 +47,10 @@ static int efivarfs_d_compare(const struct dentry *dentry, + { + int guid = len - EFI_VARIABLE_GUID_LEN; + ++ /* Parallel lookups may produce a temporary invalid filename */ ++ if (guid <= 0) ++ return 1; ++ + if (name->len != len) + return 1; + +-- +2.50.1 + diff --git a/queue-6.1/hid-input-rename-hidinput_set_battery_charge_status.patch b/queue-6.1/hid-input-rename-hidinput_set_battery_charge_status.patch new file mode 100644 index 0000000000..6b3ce46f94 --- /dev/null +++ b/queue-6.1/hid-input-rename-hidinput_set_battery_charge_status.patch @@ -0,0 +1,147 @@ +From 0d4293271a70cf23360bfe1b72e5341e9848a65d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Aug 2025 12:39:39 +0200 +Subject: HID: input: rename hidinput_set_battery_charge_status() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit a82231b2a8712d0218fc286a9b0da328d419a3f4 ] + +In preparation for a patch fixing a bug affecting +hidinput_set_battery_charge_status(), rename the function to +hidinput_update_battery_charge_status() and move it up so it can be used +by hidinput_update_battery(). + +Refactor, no functional changes. + +Tested-by: 卢国宏 +Signed-off-by: José Expósito +Signed-off-by: Jiri Kosina +Stable-dep-of: e94536e1d181 ("HID: input: report battery status changes immediately") +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-input-test.c | 10 +++++----- + drivers/hid/hid-input.c | 38 ++++++++++++++++++------------------ + 2 files changed, 24 insertions(+), 24 deletions(-) + +diff --git a/drivers/hid/hid-input-test.c b/drivers/hid/hid-input-test.c +index 77c2d45ac62a7..6f5c71660d823 100644 +--- a/drivers/hid/hid-input-test.c ++++ b/drivers/hid/hid-input-test.c +@@ -7,7 +7,7 @@ + + #include + +-static void hid_test_input_set_battery_charge_status(struct kunit *test) ++static void hid_test_input_update_battery_charge_status(struct kunit *test) + { + struct hid_device *dev; + bool handled; +@@ -15,15 +15,15 @@ static void hid_test_input_set_battery_charge_status(struct kunit *test) + dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + +- handled = hidinput_set_battery_charge_status(dev, HID_DG_HEIGHT, 0); ++ handled = hidinput_update_battery_charge_status(dev, HID_DG_HEIGHT, 0); + KUNIT_EXPECT_FALSE(test, handled); + KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_UNKNOWN); + +- handled = hidinput_set_battery_charge_status(dev, HID_BAT_CHARGING, 0); ++ handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 0); + KUNIT_EXPECT_TRUE(test, handled); + KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_DISCHARGING); + +- handled = hidinput_set_battery_charge_status(dev, HID_BAT_CHARGING, 1); ++ handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 1); + KUNIT_EXPECT_TRUE(test, handled); + KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_CHARGING); + } +@@ -63,7 +63,7 @@ static void hid_test_input_get_battery_property(struct kunit *test) + } + + static struct kunit_case hid_input_tests[] = { +- KUNIT_CASE(hid_test_input_set_battery_charge_status), ++ KUNIT_CASE(hid_test_input_update_battery_charge_status), + KUNIT_CASE(hid_test_input_get_battery_property), + { } + }; +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index b0091819fd58a..51be30b7c1851 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -609,6 +609,20 @@ static void hidinput_cleanup_battery(struct hid_device *dev) + dev->battery = NULL; + } + ++static bool hidinput_update_battery_charge_status(struct hid_device *dev, ++ unsigned int usage, int value) ++{ ++ switch (usage) { ++ case HID_BAT_CHARGING: ++ dev->battery_charge_status = value ? ++ POWER_SUPPLY_STATUS_CHARGING : ++ POWER_SUPPLY_STATUS_DISCHARGING; ++ return true; ++ } ++ ++ return false; ++} ++ + static void hidinput_update_battery(struct hid_device *dev, int value) + { + int capacity; +@@ -631,20 +645,6 @@ static void hidinput_update_battery(struct hid_device *dev, int value) + power_supply_changed(dev->battery); + } + } +- +-static bool hidinput_set_battery_charge_status(struct hid_device *dev, +- unsigned int usage, int value) +-{ +- switch (usage) { +- case HID_BAT_CHARGING: +- dev->battery_charge_status = value ? +- POWER_SUPPLY_STATUS_CHARGING : +- POWER_SUPPLY_STATUS_DISCHARGING; +- return true; +- } +- +- return false; +-} + #else /* !CONFIG_HID_BATTERY_STRENGTH */ + static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, + struct hid_field *field, bool is_percentage) +@@ -656,14 +656,14 @@ static void hidinput_cleanup_battery(struct hid_device *dev) + { + } + +-static void hidinput_update_battery(struct hid_device *dev, int value) ++static bool hidinput_update_battery_charge_status(struct hid_device *dev, ++ unsigned int usage, int value) + { ++ return false; + } + +-static bool hidinput_set_battery_charge_status(struct hid_device *dev, +- unsigned int usage, int value) ++static void hidinput_update_battery(struct hid_device *dev, int value) + { +- return false; + } + #endif /* CONFIG_HID_BATTERY_STRENGTH */ + +@@ -1509,7 +1509,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct + return; + + if (usage->type == EV_PWR) { +- bool handled = hidinput_set_battery_charge_status(hid, usage->hid, value); ++ bool handled = hidinput_update_battery_charge_status(hid, usage->hid, value); + + if (!handled) + hidinput_update_battery(hid, value); +-- +2.50.1 + diff --git a/queue-6.1/hid-input-report-battery-status-changes-immediately.patch b/queue-6.1/hid-input-report-battery-status-changes-immediately.patch new file mode 100644 index 0000000000..9e2bd5d744 --- /dev/null +++ b/queue-6.1/hid-input-report-battery-status-changes-immediately.patch @@ -0,0 +1,97 @@ +From dfa8b47f74e76e1341248105b248a16cbac24cd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Aug 2025 12:39:40 +0200 +Subject: HID: input: report battery status changes immediately +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit e94536e1d1818b0989aa19b443b7089f50133c35 ] + +Previously, the battery status (charging/discharging) was not reported +immediately to user-space.  + +For most input devices, this wasn't problematic because changing their +battery status requires connecting them to a different bus. +For example, a gamepad would report a discharging status while +connected via Bluetooth and a charging status while connected via USB. + +However, certain devices are not connected or disconnected when their +battery status changes. For example, a phone battery changes its status +without connecting or disconnecting it. +In these cases, the battery status was not reported immediately to user +space. + +Report battery status changes immediately to user space to support +these kinds of devices. + +Fixes: a608dc1c0639 ("HID: input: map battery system charging") +Reported-by: 卢国宏 +Closes: https://lore.kernel.org/linux-input/aI49Im0sGb6fpgc8@fedora/T/ +Tested-by: 卢国宏 +Signed-off-by: José Expósito +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-input.c | 23 ++++++++++------------- + 1 file changed, 10 insertions(+), 13 deletions(-) + +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 51be30b7c1851..cd9d031858438 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -623,13 +623,19 @@ static bool hidinput_update_battery_charge_status(struct hid_device *dev, + return false; + } + +-static void hidinput_update_battery(struct hid_device *dev, int value) ++static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, ++ int value) + { + int capacity; + + if (!dev->battery) + return; + ++ if (hidinput_update_battery_charge_status(dev, usage, value)) { ++ power_supply_changed(dev->battery); ++ return; ++ } ++ + if (value == 0 || value < dev->battery_min || value > dev->battery_max) + return; + +@@ -656,13 +662,8 @@ static void hidinput_cleanup_battery(struct hid_device *dev) + { + } + +-static bool hidinput_update_battery_charge_status(struct hid_device *dev, +- unsigned int usage, int value) +-{ +- return false; +-} +- +-static void hidinput_update_battery(struct hid_device *dev, int value) ++static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, ++ int value) + { + } + #endif /* CONFIG_HID_BATTERY_STRENGTH */ +@@ -1509,11 +1510,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct + return; + + if (usage->type == EV_PWR) { +- bool handled = hidinput_update_battery_charge_status(hid, usage->hid, value); +- +- if (!handled) +- hidinput_update_battery(hid, value); +- ++ hidinput_update_battery(hid, usage->hid, value); + return; + } + +-- +2.50.1 + diff --git a/queue-6.1/net-dlink-fix-multicast-stats-being-counted-incorrec.patch b/queue-6.1/net-dlink-fix-multicast-stats-being-counted-incorrec.patch new file mode 100644 index 0000000000..25238a62fc --- /dev/null +++ b/queue-6.1/net-dlink-fix-multicast-stats-being-counted-incorrec.patch @@ -0,0 +1,46 @@ +From ff0fa8ea093748ab38ebcb7f54a9e9bd08e1cf5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Aug 2025 03:29:24 +0900 +Subject: net: dlink: fix multicast stats being counted incorrectly + +From: Yeounsu Moon + +[ Upstream commit 007a5ffadc4fd51739527f1503b7cf048f31c413 ] + +`McstFramesRcvdOk` counts the number of received multicast packets, and +it reports the value correctly. + +However, reading `McstFramesRcvdOk` clears the register to zero. As a +result, the driver was reporting only the packets since the last read, +instead of the accumulated total. + +Fix this by updating the multicast statistics accumulatively instaed of +instantaneously. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Tested-on: D-Link DGE-550T Rev-A3 +Signed-off-by: Yeounsu Moon +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250823182927.6063-3-yyyynoom@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/dlink/dl2k.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c +index dfc23cc173097..2acb63b547c35 100644 +--- a/drivers/net/ethernet/dlink/dl2k.c ++++ b/drivers/net/ethernet/dlink/dl2k.c +@@ -1094,7 +1094,7 @@ get_stats (struct net_device *dev) + dev->stats.rx_bytes += dr32(OctetRcvOk); + dev->stats.tx_bytes += dr32(OctetXmtOk); + +- dev->stats.multicast = dr32(McstFramesRcvdOk); ++ dev->stats.multicast += dr32(McstFramesRcvdOk); + dev->stats.collisions += dr32(SingleColFrames) + + dr32(MultiColFrames); + +-- +2.50.1 + diff --git a/queue-6.1/net-ipv4-fix-regression-in-local-broadcast-routes.patch b/queue-6.1/net-ipv4-fix-regression-in-local-broadcast-routes.patch new file mode 100644 index 0000000000..d78d8d6a5c --- /dev/null +++ b/queue-6.1/net-ipv4-fix-regression-in-local-broadcast-routes.patch @@ -0,0 +1,57 @@ +From 3acb75e4c01db107debd7ea6867cdc8347d95c87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 08:23:21 +0200 +Subject: net: ipv4: fix regression in local-broadcast routes + +From: Oscar Maes + +[ Upstream commit 5189446ba995556eaa3755a6e875bc06675b88bd ] + +Commit 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") +introduced a regression where local-broadcast packets would have their +gateway set in __mkroute_output, which was caused by fi = NULL being +removed. + +Fix this by resetting the fib_info for local-broadcast packets. This +preserves the intended changes for directed-broadcast packets. + +Cc: stable@vger.kernel.org +Fixes: 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") +Reported-by: Brett A C Sheffield +Closes: https://lore.kernel.org/regressions/20250822165231.4353-4-bacs@librecast.net +Signed-off-by: Oscar Maes +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20250827062322.4807-1-oscmaes92@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/route.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index c57a1cee98e2c..395bc567b15d3 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -2549,12 +2549,16 @@ static struct rtable *__mkroute_output(const struct fib_result *res, + !netif_is_l3_master(dev_out)) + return ERR_PTR(-EINVAL); + +- if (ipv4_is_lbcast(fl4->daddr)) ++ if (ipv4_is_lbcast(fl4->daddr)) { + type = RTN_BROADCAST; +- else if (ipv4_is_multicast(fl4->daddr)) ++ ++ /* reset fi to prevent gateway resolution */ ++ fi = NULL; ++ } else if (ipv4_is_multicast(fl4->daddr)) { + type = RTN_MULTICAST; +- else if (ipv4_is_zeronet(fl4->daddr)) ++ } else if (ipv4_is_zeronet(fl4->daddr)) { + return ERR_PTR(-EINVAL); ++ } + + if (dev_out->flags & IFF_LOOPBACK) + flags |= RTCF_LOCAL; +-- +2.50.1 + diff --git a/queue-6.1/net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch b/queue-6.1/net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch new file mode 100644 index 0000000000..9c5f903578 --- /dev/null +++ b/queue-6.1/net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch @@ -0,0 +1,51 @@ +From 831c343133b7497cd786713a7620c835e70ba618 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:28 +0300 +Subject: net/mlx5: Reload auxiliary drivers on fw_activate + +From: Moshe Shemesh + +[ Upstream commit 34cc6a54914f478c93e176450fae6313404f9f74 ] + +The devlink reload fw_activate command performs firmware activation +followed by driver reload, while devlink reload driver_reinit triggers +only driver reload. However, the driver reload logic differs between the +two modes, as on driver_reinit mode mlx5 also reloads auxiliary drivers, +while in fw_activate mode the auxiliary drivers are suspended where +applicable. + +Additionally, following the cited commit, if the device has multiple PFs, +the behavior during fw_activate may vary between PFs: one PF may suspend +auxiliary drivers, while another reloads them. + +Align devlink dev reload fw_activate behavior with devlink dev reload +driver_reinit, to reload all auxiliary drivers. + +Fixes: 72ed5d5624af ("net/mlx5: Suspend auxiliary devices only in case of PCI device suspend") +Signed-off-by: Moshe Shemesh +Reviewed-by: Tariq Toukan +Reviewed-by: Akiva Goldberger +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-6-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +index 3749eb83d9e53..64dcfac9ce724 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +@@ -108,7 +108,7 @@ static int mlx5_devlink_reload_fw_activate(struct devlink *devlink, struct netli + if (err) + return err; + +- mlx5_unload_one_devl_locked(dev, true); ++ mlx5_unload_one_devl_locked(dev, false); + err = mlx5_health_wait_pci_up(dev); + if (err) + NL_SET_ERR_MSG_MOD(extack, "FW activate aborted, PCI reads fail after reset"); +-- +2.50.1 + diff --git a/queue-6.1/net-mlx5e-set-local-xoff-after-fw-update.patch b/queue-6.1/net-mlx5e-set-local-xoff-after-fw-update.patch new file mode 100644 index 0000000000..9196c58cf5 --- /dev/null +++ b/queue-6.1/net-mlx5e-set-local-xoff-after-fw-update.patch @@ -0,0 +1,50 @@ +From 2f9f2ec5cef9ae7ab2205ed3024788126759b0d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:34 +0300 +Subject: net/mlx5e: Set local Xoff after FW update + +From: Alexei Lazar + +[ Upstream commit aca0c31af61e0d5cf1675a0cbd29460b95ae693c ] + +The local Xoff value is being set before the firmware (FW) update. +In case of a failure where the FW is not updated with the new value, +there is no fallback to the previous value. +Update the local Xoff value after the FW has been successfully set. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Reviewed-by: Dragos Tatulea +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-12-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +index c9d5d8d93994d..7899a7230299d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +@@ -346,7 +346,6 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + if (err) + return err; + } +- priv->dcbx.xoff = xoff; + + /* Apply the settings */ + if (update_buffer) { +@@ -355,6 +354,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + return err; + } + ++ priv->dcbx.xoff = xoff; ++ + if (update_prio2buffer) + err = mlx5e_port_set_priority2buffer(priv->mdev, prio2buffer); + +-- +2.50.1 + diff --git a/queue-6.1/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch b/queue-6.1/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch new file mode 100644 index 0000000000..b2ec6f2c8a --- /dev/null +++ b/queue-6.1/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch @@ -0,0 +1,100 @@ +From 08f0d6bce3462cf84ed26cceed7135a084912a20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:32 +0300 +Subject: net/mlx5e: Update and set Xon/Xoff upon MTU set + +From: Alexei Lazar + +[ Upstream commit ceddedc969f0532b7c62ca971ee50d519d2bc0cb ] + +Xon/Xoff sizes are derived from calculation that include the MTU size. +Set Xon/Xoff when MTU is set. +If Xon/Xoff fails, set the previous MTU. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-10-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/en/port_buffer.h | 12 ++++++++++++ + .../net/ethernet/mellanox/mlx5/core/en_main.c | 17 ++++++++++++++++- + 2 files changed, 28 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +index 80af7a5ac6046..a23e3d810f3e4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +@@ -63,11 +63,23 @@ struct mlx5e_port_buffer { + struct mlx5e_bufferx_reg buffer[MLX5E_MAX_BUFFER]; + }; + ++#ifdef CONFIG_MLX5_CORE_EN_DCB + int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + u32 change, unsigned int mtu, + struct ieee_pfc *pfc, + u32 *buffer_size, + u8 *prio2buffer); ++#else ++static inline int ++mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, ++ u32 change, unsigned int mtu, ++ void *pfc, ++ u32 *buffer_size, ++ u8 *prio2buffer) ++{ ++ return 0; ++} ++#endif + + int mlx5e_port_query_buffer(struct mlx5e_priv *priv, + struct mlx5e_port_buffer *port_buffer); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 887d446354006..7612070b66160 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -42,6 +42,7 @@ + #include "eswitch.h" + #include "en.h" + #include "en/txrx.h" ++#include "en/port_buffer.h" + #include "en_tc.h" + #include "en_rep.h" + #include "en_accel/ipsec.h" +@@ -2640,9 +2641,11 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) + struct mlx5e_params *params = &priv->channels.params; + struct net_device *netdev = priv->netdev; + struct mlx5_core_dev *mdev = priv->mdev; +- u16 mtu; ++ u16 mtu, prev_mtu; + int err; + ++ mlx5e_query_mtu(mdev, params, &prev_mtu); ++ + err = mlx5e_set_mtu(mdev, params, params->sw_mtu); + if (err) + return err; +@@ -2652,6 +2655,18 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) + netdev_warn(netdev, "%s: VPort MTU %d is different than netdev mtu %d\n", + __func__, mtu, params->sw_mtu); + ++ if (mtu != prev_mtu && MLX5_BUFFER_SUPPORTED(mdev)) { ++ err = mlx5e_port_manual_buffer_config(priv, 0, mtu, ++ NULL, NULL, NULL); ++ if (err) { ++ netdev_warn(netdev, "%s: Failed to set Xon/Xoff values with MTU %d (err %d), setting back to previous MTU %d\n", ++ __func__, mtu, err, prev_mtu); ++ ++ mlx5e_set_mtu(mdev, params, prev_mtu); ++ return err; ++ } ++ } ++ + params->sw_mtu = mtu; + return 0; + } +-- +2.50.1 + diff --git a/queue-6.1/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch b/queue-6.1/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch new file mode 100644 index 0000000000..100c216b24 --- /dev/null +++ b/queue-6.1/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch @@ -0,0 +1,46 @@ +From b798855a1158684e6262f6096495bc5e99464e14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:33 +0300 +Subject: net/mlx5e: Update and set Xon/Xoff upon port speed set + +From: Alexei Lazar + +[ Upstream commit d24341740fe48add8a227a753e68b6eedf4b385a ] + +Xon/Xoff sizes are derived from calculations that include +the port speed. +These settings need to be updated and applied whenever the +port speed is changed. +The port speed is typically set after the physical link goes down +and is negotiated as part of the link-up process between the two +connected interfaces. +Xon/Xoff parameters being updated at the point where the new +negotiated speed is established. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-11-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 7612070b66160..ae3a7b96f7978 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -107,6 +107,8 @@ void mlx5e_update_carrier(struct mlx5e_priv *priv) + if (up) { + netdev_info(priv->netdev, "Link up\n"); + netif_carrier_on(priv->netdev); ++ mlx5e_port_manual_buffer_config(priv, 0, priv->netdev->mtu, ++ NULL, NULL, NULL); + } else { + netdev_info(priv->netdev, "Link down\n"); + netif_carrier_off(priv->netdev); +-- +2.50.1 + diff --git a/queue-6.1/net-rose-convert-use-field-to-refcount_t.patch b/queue-6.1/net-rose-convert-use-field-to-refcount_t.patch new file mode 100644 index 0000000000..2a59db1c1b --- /dev/null +++ b/queue-6.1/net-rose-convert-use-field-to-refcount_t.patch @@ -0,0 +1,370 @@ +From 9666ef8acc9799c4e776bfe40ead3ee83f50da46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Aug 2025 17:58:56 +0900 +Subject: net: rose: convert 'use' field to refcount_t + +From: Takamitsu Iwai + +[ Upstream commit d860d1faa6b2ce3becfdb8b0c2b048ad31800061 ] + +The 'use' field in struct rose_neigh is used as a reference counter but +lacks atomicity. This can lead to race conditions where a rose_neigh +structure is freed while still being referenced by other code paths. + +For example, when rose_neigh->use becomes zero during an ioctl operation +via rose_rt_ioctl(), the structure may be removed while its timer is +still active, potentially causing use-after-free issues. + +This patch changes the type of 'use' from unsigned short to refcount_t and +updates all code paths to use rose_neigh_hold() and rose_neigh_put() which +operate reference counts atomically. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Takamitsu Iwai +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250823085857.47674-3-takamitz@amazon.co.jp +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/rose.h | 18 +++++++++++++----- + net/rose/af_rose.c | 13 +++++++------ + net/rose/rose_in.c | 12 ++++++------ + net/rose/rose_route.c | 33 ++++++++++++++++++--------------- + net/rose/rose_timer.c | 2 +- + 5 files changed, 45 insertions(+), 33 deletions(-) + +diff --git a/include/net/rose.h b/include/net/rose.h +index 174b4f605d849..2b5491bbf39ab 100644 +--- a/include/net/rose.h ++++ b/include/net/rose.h +@@ -8,6 +8,7 @@ + #ifndef _ROSE_H + #define _ROSE_H + ++#include + #include + #include + #include +@@ -96,7 +97,7 @@ struct rose_neigh { + ax25_cb *ax25; + struct net_device *dev; + unsigned short count; +- unsigned short use; ++ refcount_t use; + unsigned int number; + char restarted; + char dce_mode; +@@ -151,12 +152,19 @@ struct rose_sock { + + #define rose_sk(sk) ((struct rose_sock *)(sk)) + ++static inline void rose_neigh_hold(struct rose_neigh *rose_neigh) ++{ ++ refcount_inc(&rose_neigh->use); ++} ++ + static inline void rose_neigh_put(struct rose_neigh *rose_neigh) + { +- if (rose_neigh->ax25) +- ax25_cb_put(rose_neigh->ax25); +- kfree(rose_neigh->digipeat); +- kfree(rose_neigh); ++ if (refcount_dec_and_test(&rose_neigh->use)) { ++ if (rose_neigh->ax25) ++ ax25_cb_put(rose_neigh->ax25); ++ kfree(rose_neigh->digipeat); ++ kfree(rose_neigh); ++ } + } + + /* af_rose.c */ +diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c +index b21c2ce401928..5a0bf022a84be 100644 +--- a/net/rose/af_rose.c ++++ b/net/rose/af_rose.c +@@ -170,7 +170,7 @@ void rose_kill_by_neigh(struct rose_neigh *neigh) + + if (rose->neighbour == neigh) { + rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + rose->neighbour = NULL; + } + } +@@ -212,7 +212,7 @@ static void rose_kill_by_device(struct net_device *dev) + if (rose->device == dev) { + rose_disconnect(sk, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); + if (rose->neighbour) +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + netdev_put(rose->device, &rose->dev_tracker); + rose->device = NULL; + } +@@ -655,7 +655,7 @@ static int rose_release(struct socket *sock) + break; + + case ROSE_STATE_2: +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + release_sock(sk); + rose_disconnect(sk, 0, -1, -1); + lock_sock(sk); +@@ -823,6 +823,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + rose->lci = rose_new_lci(rose->neighbour); + if (!rose->lci) { + err = -ENETUNREACH; ++ rose_neigh_put(rose->neighbour); + goto out_release; + } + +@@ -834,12 +835,14 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + dev = rose_dev_first(); + if (!dev) { + err = -ENETUNREACH; ++ rose_neigh_put(rose->neighbour); + goto out_release; + } + + user = ax25_findbyuid(current_euid()); + if (!user) { + err = -EINVAL; ++ rose_neigh_put(rose->neighbour); + dev_put(dev); + goto out_release; + } +@@ -874,8 +877,6 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + + rose->state = ROSE_STATE_1; + +- rose->neighbour->use++; +- + rose_write_internal(sk, ROSE_CALL_REQUEST); + rose_start_heartbeat(sk); + rose_start_t1timer(sk); +@@ -1077,7 +1078,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros + GFP_ATOMIC); + make_rose->facilities = facilities; + +- make_rose->neighbour->use++; ++ rose_neigh_hold(make_rose->neighbour); + + if (rose_sk(sk)->defer) { + make_rose->state = ROSE_STATE_5; +diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c +index 4d67f36dce1b4..7caae93937ee9 100644 +--- a/net/rose/rose_in.c ++++ b/net/rose/rose_in.c +@@ -56,7 +56,7 @@ static int rose_state1_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + default: +@@ -79,12 +79,12 @@ static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + case ROSE_CLEAR_CONFIRMATION: + rose_disconnect(sk, 0, -1, -1); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + default: +@@ -120,7 +120,7 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + case ROSE_RR: +@@ -233,7 +233,7 @@ static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + default: +@@ -253,7 +253,7 @@ static int rose_state5_machine(struct sock *sk, struct sk_buff *skb, int framety + if (frametype == ROSE_CLEAR_REQUEST) { + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose_sk(sk)->neighbour->use--; ++ rose_neigh_put(rose_sk(sk)->neighbour); + } + + return 0; +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index b406b1e0fb1e7..42460da0854d5 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -93,11 +93,11 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, + rose_neigh->ax25 = NULL; + rose_neigh->dev = dev; + rose_neigh->count = 0; +- rose_neigh->use = 0; + rose_neigh->dce_mode = 0; + rose_neigh->loopback = 0; + rose_neigh->number = rose_neigh_no++; + rose_neigh->restarted = 0; ++ refcount_set(&rose_neigh->use, 1); + + skb_queue_head_init(&rose_neigh->queue); + +@@ -255,10 +255,10 @@ static void rose_remove_route(struct rose_route *rose_route) + struct rose_route *s; + + if (rose_route->neigh1 != NULL) +- rose_route->neigh1->use--; ++ rose_neigh_put(rose_route->neigh1); + + if (rose_route->neigh2 != NULL) +- rose_route->neigh2->use--; ++ rose_neigh_put(rose_route->neigh2); + + if ((s = rose_route_list) == rose_route) { + rose_route_list = rose_route->next; +@@ -323,7 +323,7 @@ static int rose_del_node(struct rose_route_struct *rose_route, + if (rose_node->neighbour[i] == rose_neigh) { + rose_neigh->count--; + +- if (rose_neigh->count == 0 && rose_neigh->use == 0) { ++ if (rose_neigh->count == 0) { + rose_remove_neigh(rose_neigh); + rose_neigh_put(rose_neigh); + } +@@ -375,11 +375,11 @@ void rose_add_loopback_neigh(void) + sn->ax25 = NULL; + sn->dev = NULL; + sn->count = 0; +- sn->use = 0; + sn->dce_mode = 1; + sn->loopback = 1; + sn->number = rose_neigh_no++; + sn->restarted = 1; ++ refcount_set(&sn->use, 1); + + skb_queue_head_init(&sn->queue); + +@@ -561,8 +561,7 @@ static int rose_clear_routes(void) + s = rose_neigh; + rose_neigh = rose_neigh->next; + +- if (s->use == 0 && !s->loopback) { +- s->count = 0; ++ if (!s->loopback) { + rose_remove_neigh(s); + rose_neigh_put(s); + } +@@ -680,6 +679,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, + for (i = 0; i < node->count; i++) { + if (node->neighbour[i]->restarted) { + res = node->neighbour[i]; ++ rose_neigh_hold(node->neighbour[i]); + goto out; + } + } +@@ -691,6 +691,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, + for (i = 0; i < node->count; i++) { + if (!rose_ftimer_running(node->neighbour[i])) { + res = node->neighbour[i]; ++ rose_neigh_hold(node->neighbour[i]); + goto out; + } + failed = 1; +@@ -780,13 +781,13 @@ static void rose_del_route_by_neigh(struct rose_neigh *rose_neigh) + } + + if (rose_route->neigh1 == rose_neigh) { +- rose_route->neigh1->use--; ++ rose_neigh_put(rose_route->neigh1); + rose_route->neigh1 = NULL; + rose_transmit_clear_request(rose_route->neigh2, rose_route->lci2, ROSE_OUT_OF_ORDER, 0); + } + + if (rose_route->neigh2 == rose_neigh) { +- rose_route->neigh2->use--; ++ rose_neigh_put(rose_route->neigh2); + rose_route->neigh2 = NULL; + rose_transmit_clear_request(rose_route->neigh1, rose_route->lci1, ROSE_OUT_OF_ORDER, 0); + } +@@ -915,7 +916,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + rose_clear_queues(sk); + rose->cause = ROSE_NETWORK_CONGESTION; + rose->diagnostic = 0; +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + rose->neighbour = NULL; + rose->lci = 0; + rose->state = ROSE_STATE_0; +@@ -1040,12 +1041,12 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + + if ((new_lci = rose_new_lci(new_neigh)) == 0) { + rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 71); +- goto out; ++ goto put_neigh; + } + + if ((rose_route = kmalloc(sizeof(*rose_route), GFP_ATOMIC)) == NULL) { + rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 120); +- goto out; ++ goto put_neigh; + } + + rose_route->lci1 = lci; +@@ -1058,8 +1059,8 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + rose_route->lci2 = new_lci; + rose_route->neigh2 = new_neigh; + +- rose_route->neigh1->use++; +- rose_route->neigh2->use++; ++ rose_neigh_hold(rose_route->neigh1); ++ rose_neigh_hold(rose_route->neigh2); + + rose_route->next = rose_route_list; + rose_route_list = rose_route; +@@ -1071,6 +1072,8 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + rose_transmit_link(skb, rose_route->neigh2); + res = 1; + ++put_neigh: ++ rose_neigh_put(new_neigh); + out: + spin_unlock_bh(&rose_route_list_lock); + spin_unlock_bh(&rose_neigh_list_lock); +@@ -1186,7 +1189,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v) + (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign), + rose_neigh->dev ? rose_neigh->dev->name : "???", + rose_neigh->count, +- rose_neigh->use, ++ refcount_read(&rose_neigh->use) - 1, + (rose_neigh->dce_mode) ? "DCE" : "DTE", + (rose_neigh->restarted) ? "yes" : "no", + ax25_display_timer(&rose_neigh->t0timer) / HZ, +diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c +index 1525773e94aa1..c52d7d20c5199 100644 +--- a/net/rose/rose_timer.c ++++ b/net/rose/rose_timer.c +@@ -180,7 +180,7 @@ static void rose_timer_expiry(struct timer_list *t) + break; + + case ROSE_STATE_2: /* T3 */ +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + rose_disconnect(sk, ETIMEDOUT, -1, -1); + break; + +-- +2.50.1 + diff --git a/queue-6.1/net-rose-include-node-references-in-rose_neigh-refco.patch b/queue-6.1/net-rose-include-node-references-in-rose_neigh-refco.patch new file mode 100644 index 0000000000..f84a51f987 --- /dev/null +++ b/queue-6.1/net-rose-include-node-references-in-rose_neigh-refco.patch @@ -0,0 +1,142 @@ +From 9d5f8b18b47e19d73d093926dfd2aedc48c01c5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Aug 2025 17:58:57 +0900 +Subject: net: rose: include node references in rose_neigh refcount + +From: Takamitsu Iwai + +[ Upstream commit da9c9c877597170b929a6121a68dcd3dd9a80f45 ] + +Current implementation maintains two separate reference counting +mechanisms: the 'count' field in struct rose_neigh tracks references from +rose_node structures, while the 'use' field (now refcount_t) tracks +references from rose_sock. + +This patch merges these two reference counting systems using 'use' field +for proper reference management. Specifically, this patch adds incrementing +and decrementing of rose_neigh->use when rose_neigh->count is incremented +or decremented. + +This patch also modifies rose_rt_free(), rose_rt_device_down() and +rose_clear_route() to properly release references to rose_neigh objects +before freeing a rose_node through rose_remove_node(). + +These changes ensure rose_neigh structures are properly freed only when +all references, including those from rose_node structures, are released. +As a result, this resolves a slab-use-after-free issue reported by Syzbot. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+942297eecf7d2d61d1f1@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=942297eecf7d2d61d1f1 +Signed-off-by: Takamitsu Iwai +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250823085857.47674-4-takamitz@amazon.co.jp +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/rose/rose_route.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index 42460da0854d5..6acbb795c506d 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -178,6 +178,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, + } + } + rose_neigh->count++; ++ rose_neigh_hold(rose_neigh); + + goto out; + } +@@ -187,6 +188,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, + rose_node->neighbour[rose_node->count] = rose_neigh; + rose_node->count++; + rose_neigh->count++; ++ rose_neigh_hold(rose_neigh); + } + + out: +@@ -322,6 +324,7 @@ static int rose_del_node(struct rose_route_struct *rose_route, + for (i = 0; i < rose_node->count; i++) { + if (rose_node->neighbour[i] == rose_neigh) { + rose_neigh->count--; ++ rose_neigh_put(rose_neigh); + + if (rose_neigh->count == 0) { + rose_remove_neigh(rose_neigh); +@@ -430,6 +433,7 @@ int rose_add_loopback_node(const rose_address *address) + rose_node_list = rose_node; + + rose_loopback_neigh->count++; ++ rose_neigh_hold(rose_loopback_neigh); + + out: + spin_unlock_bh(&rose_node_list_lock); +@@ -461,6 +465,7 @@ void rose_del_loopback_node(const rose_address *address) + rose_remove_node(rose_node); + + rose_loopback_neigh->count--; ++ rose_neigh_put(rose_loopback_neigh); + + out: + spin_unlock_bh(&rose_node_list_lock); +@@ -500,6 +505,7 @@ void rose_rt_device_down(struct net_device *dev) + memmove(&t->neighbour[i], &t->neighbour[i + 1], + sizeof(t->neighbour[0]) * + (t->count - i)); ++ rose_neigh_put(s); + } + + if (t->count <= 0) +@@ -543,6 +549,7 @@ static int rose_clear_routes(void) + { + struct rose_neigh *s, *rose_neigh; + struct rose_node *t, *rose_node; ++ int i; + + spin_lock_bh(&rose_node_list_lock); + spin_lock_bh(&rose_neigh_list_lock); +@@ -553,8 +560,12 @@ static int rose_clear_routes(void) + while (rose_node != NULL) { + t = rose_node; + rose_node = rose_node->next; +- if (!t->loopback) ++ ++ if (!t->loopback) { ++ for (i = 0; i < rose_node->count; i++) ++ rose_neigh_put(t->neighbour[i]); + rose_remove_node(t); ++ } + } + + while (rose_neigh != NULL) { +@@ -1189,7 +1200,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v) + (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign), + rose_neigh->dev ? rose_neigh->dev->name : "???", + rose_neigh->count, +- refcount_read(&rose_neigh->use) - 1, ++ refcount_read(&rose_neigh->use) - rose_neigh->count - 1, + (rose_neigh->dce_mode) ? "DCE" : "DTE", + (rose_neigh->restarted) ? "yes" : "no", + ax25_display_timer(&rose_neigh->t0timer) / HZ, +@@ -1294,6 +1305,7 @@ void __exit rose_rt_free(void) + struct rose_neigh *s, *rose_neigh = rose_neigh_list; + struct rose_node *t, *rose_node = rose_node_list; + struct rose_route *u, *rose_route = rose_route_list; ++ int i; + + while (rose_neigh != NULL) { + s = rose_neigh; +@@ -1307,6 +1319,8 @@ void __exit rose_rt_free(void) + t = rose_node; + rose_node = rose_node->next; + ++ for (i = 0; i < t->count; i++) ++ rose_neigh_put(t->neighbour[i]); + rose_remove_node(t); + } + +-- +2.50.1 + diff --git a/queue-6.1/net-rose-split-remove-and-free-operations-in-rose_re.patch b/queue-6.1/net-rose-split-remove-and-free-operations-in-rose_re.patch new file mode 100644 index 0000000000..07dfe5c679 --- /dev/null +++ b/queue-6.1/net-rose-split-remove-and-free-operations-in-rose_re.patch @@ -0,0 +1,115 @@ +From 3c8bbd7d9ec2674b5e4dd6ed3fb22c2486bb1b4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Aug 2025 17:58:55 +0900 +Subject: net: rose: split remove and free operations in rose_remove_neigh() + +From: Takamitsu Iwai + +[ Upstream commit dcb34659028f856c423a29ef9b4e2571d203444d ] + +The current rose_remove_neigh() performs two distinct operations: +1. Removes rose_neigh from rose_neigh_list +2. Frees the rose_neigh structure + +Split these operations into separate functions to improve maintainability +and prepare for upcoming refcount_t conversion. The timer cleanup remains +in rose_remove_neigh() because free operations can be called from timer +itself. + +This patch introduce rose_neigh_put() to handle the freeing of rose_neigh +structures and modify rose_remove_neigh() to handle removal only. + +Signed-off-by: Takamitsu Iwai +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250823085857.47674-2-takamitz@amazon.co.jp +Signed-off-by: Jakub Kicinski +Stable-dep-of: d860d1faa6b2 ("net: rose: convert 'use' field to refcount_t") +Signed-off-by: Sasha Levin +--- + include/net/rose.h | 8 ++++++++ + net/rose/rose_route.c | 15 ++++++--------- + 2 files changed, 14 insertions(+), 9 deletions(-) + +diff --git a/include/net/rose.h b/include/net/rose.h +index 23267b4efcfa3..174b4f605d849 100644 +--- a/include/net/rose.h ++++ b/include/net/rose.h +@@ -151,6 +151,14 @@ struct rose_sock { + + #define rose_sk(sk) ((struct rose_sock *)(sk)) + ++static inline void rose_neigh_put(struct rose_neigh *rose_neigh) ++{ ++ if (rose_neigh->ax25) ++ ax25_cb_put(rose_neigh->ax25); ++ kfree(rose_neigh->digipeat); ++ kfree(rose_neigh); ++} ++ + /* af_rose.c */ + extern ax25_address rose_callsign; + extern int sysctl_rose_restart_request_timeout; +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index a7054546f52df..b406b1e0fb1e7 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -234,20 +234,12 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) + + if ((s = rose_neigh_list) == rose_neigh) { + rose_neigh_list = rose_neigh->next; +- if (rose_neigh->ax25) +- ax25_cb_put(rose_neigh->ax25); +- kfree(rose_neigh->digipeat); +- kfree(rose_neigh); + return; + } + + while (s != NULL && s->next != NULL) { + if (s->next == rose_neigh) { + s->next = rose_neigh->next; +- if (rose_neigh->ax25) +- ax25_cb_put(rose_neigh->ax25); +- kfree(rose_neigh->digipeat); +- kfree(rose_neigh); + return; + } + +@@ -331,8 +323,10 @@ static int rose_del_node(struct rose_route_struct *rose_route, + if (rose_node->neighbour[i] == rose_neigh) { + rose_neigh->count--; + +- if (rose_neigh->count == 0 && rose_neigh->use == 0) ++ if (rose_neigh->count == 0 && rose_neigh->use == 0) { + rose_remove_neigh(rose_neigh); ++ rose_neigh_put(rose_neigh); ++ } + + rose_node->count--; + +@@ -513,6 +507,7 @@ void rose_rt_device_down(struct net_device *dev) + } + + rose_remove_neigh(s); ++ rose_neigh_put(s); + } + spin_unlock_bh(&rose_neigh_list_lock); + spin_unlock_bh(&rose_node_list_lock); +@@ -569,6 +564,7 @@ static int rose_clear_routes(void) + if (s->use == 0 && !s->loopback) { + s->count = 0; + rose_remove_neigh(s); ++ rose_neigh_put(s); + } + } + +@@ -1301,6 +1297,7 @@ void __exit rose_rt_free(void) + rose_neigh = rose_neigh->next; + + rose_remove_neigh(s); ++ rose_neigh_put(s); + } + + while (rose_node != NULL) { +-- +2.50.1 + diff --git a/queue-6.1/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch b/queue-6.1/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch new file mode 100644 index 0000000000..c83d96d684 --- /dev/null +++ b/queue-6.1/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch @@ -0,0 +1,49 @@ +From e4d3b2f3c42ea950f76ef8f986c6084ee0b23228 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 12:36:52 +0800 +Subject: net: stmmac: xgmac: Do not enable RX FIFO Overflow interrupts + +From: Rohan G Thomas + +[ Upstream commit 4f23382841e67174211271a454811dd17c0ef3c5 ] + +Enabling RX FIFO Overflow interrupts is counterproductive +and causes an interrupt storm when RX FIFO overflows. +Disabling this interrupt has no side effect and eliminates +interrupt storms when the RX FIFO overflows. + +Commit 8a7cb245cf28 ("net: stmmac: Do not enable RX FIFO +overflow interrupts") disables RX FIFO overflow interrupts +for DWMAC4 IP and removes the corresponding handling of +this interrupt. This patch is doing the same thing for +XGMAC IP. + +Fixes: 2142754f8b9c ("net: stmmac: Add MAC related callbacks for XGMAC2") +Signed-off-by: Rohan G Thomas +Reviewed-by: Matthew Gerlach +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250825-xgmac-minor-fixes-v3-1-c225fe4444c0@altera.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +index 5e98355f422b3..3e4318d5dcdf5 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +@@ -199,10 +199,6 @@ static void dwxgmac2_dma_rx_mode(void __iomem *ioaddr, int mode, + } + + writel(value, ioaddr + XGMAC_MTL_RXQ_OPMODE(channel)); +- +- /* Enable MTL RX overflow */ +- value = readl(ioaddr + XGMAC_MTL_QINTEN(channel)); +- writel(value | XGMAC_RXOIE, ioaddr + XGMAC_MTL_QINTEN(channel)); + } + + static void dwxgmac2_dma_tx_mode(void __iomem *ioaddr, int mode, +-- +2.50.1 + diff --git a/queue-6.1/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch b/queue-6.1/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch new file mode 100644 index 0000000000..2fbee29a6d --- /dev/null +++ b/queue-6.1/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch @@ -0,0 +1,135 @@ +From 9da465f24262fd3c9e37cca7ad2144a4c8ef0eaa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 08:55:43 +0200 +Subject: phy: mscc: Fix when PTP clock is register and unregister + +From: Horatiu Vultur + +[ Upstream commit 882e57cbc7204662f6c5672d5b04336c1d790b03 ] + +It looks like that every time when the interface was set down and up the +driver was creating a new ptp clock. On top of this the function +ptp_clock_unregister was never called. +Therefore fix this by calling ptp_clock_register and initialize the +mii_ts struct inside the probe function and call ptp_clock_unregister when +driver is removed. + +Fixes: 7d272e63e0979d ("net: phy: mscc: timestamping and PHC support") +Signed-off-by: Horatiu Vultur +Reviewed-by: Vadim Fedorenko +Reviewed-by: Vladimir Oltean +Link: https://patch.msgid.link/20250825065543.2916334-1-horatiu.vultur@microchip.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mscc/mscc.h | 4 ++++ + drivers/net/phy/mscc/mscc_main.c | 4 +--- + drivers/net/phy/mscc/mscc_ptp.c | 34 ++++++++++++++++++++------------ + 3 files changed, 26 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h +index 878298304430c..fcfbff691b3c6 100644 +--- a/drivers/net/phy/mscc/mscc.h ++++ b/drivers/net/phy/mscc/mscc.h +@@ -474,6 +474,7 @@ static inline void vsc8584_config_macsec_intr(struct phy_device *phydev) + void vsc85xx_link_change_notify(struct phy_device *phydev); + void vsc8584_config_ts_intr(struct phy_device *phydev); + int vsc8584_ptp_init(struct phy_device *phydev); ++void vsc8584_ptp_deinit(struct phy_device *phydev); + int vsc8584_ptp_probe_once(struct phy_device *phydev); + int vsc8584_ptp_probe(struct phy_device *phydev); + irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev); +@@ -488,6 +489,9 @@ static inline int vsc8584_ptp_init(struct phy_device *phydev) + { + return 0; + } ++static inline void vsc8584_ptp_deinit(struct phy_device *phydev) ++{ ++} + static inline int vsc8584_ptp_probe_once(struct phy_device *phydev) + { + return 0; +diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c +index 36734bb217e42..2fabb6a7d2415 100644 +--- a/drivers/net/phy/mscc/mscc_main.c ++++ b/drivers/net/phy/mscc/mscc_main.c +@@ -2326,9 +2326,7 @@ static int vsc85xx_probe(struct phy_device *phydev) + + static void vsc85xx_remove(struct phy_device *phydev) + { +- struct vsc8531_private *priv = phydev->priv; +- +- skb_queue_purge(&priv->rx_skbs_list); ++ vsc8584_ptp_deinit(phydev); + } + + /* Microsemi VSC85xx PHYs */ +diff --git a/drivers/net/phy/mscc/mscc_ptp.c b/drivers/net/phy/mscc/mscc_ptp.c +index add1a9ee721af..1f6237705b44b 100644 +--- a/drivers/net/phy/mscc/mscc_ptp.c ++++ b/drivers/net/phy/mscc/mscc_ptp.c +@@ -1297,7 +1297,6 @@ static void vsc8584_set_input_clk_configured(struct phy_device *phydev) + + static int __vsc8584_init_ptp(struct phy_device *phydev) + { +- struct vsc8531_private *vsc8531 = phydev->priv; + static const u32 ltc_seq_e[] = { 0, 400000, 0, 0, 0 }; + static const u8 ltc_seq_a[] = { 8, 6, 5, 4, 2 }; + u32 val; +@@ -1514,17 +1513,7 @@ static int __vsc8584_init_ptp(struct phy_device *phydev) + + vsc85xx_ts_eth_cmp1_sig(phydev); + +- vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; +- vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; +- vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; +- vsc8531->mii_ts.ts_info = vsc85xx_ts_info; +- phydev->mii_ts = &vsc8531->mii_ts; +- +- memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); +- +- vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, +- &phydev->mdio.dev); +- return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); ++ return 0; + } + + void vsc8584_config_ts_intr(struct phy_device *phydev) +@@ -1551,6 +1540,16 @@ int vsc8584_ptp_init(struct phy_device *phydev) + return 0; + } + ++void vsc8584_ptp_deinit(struct phy_device *phydev) ++{ ++ struct vsc8531_private *vsc8531 = phydev->priv; ++ ++ if (vsc8531->ptp->ptp_clock) { ++ ptp_clock_unregister(vsc8531->ptp->ptp_clock); ++ skb_queue_purge(&vsc8531->rx_skbs_list); ++ } ++} ++ + irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev) + { + struct vsc8531_private *priv = phydev->priv; +@@ -1608,7 +1607,16 @@ int vsc8584_ptp_probe(struct phy_device *phydev) + + vsc8531->ptp->phydev = phydev; + +- return 0; ++ vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; ++ vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; ++ vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; ++ vsc8531->mii_ts.ts_info = vsc85xx_ts_info; ++ phydev->mii_ts = &vsc8531->mii_ts; ++ ++ memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); ++ vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, ++ &phydev->mdio.dev); ++ return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); + } + + int vsc8584_ptp_probe_once(struct phy_device *phydev) +-- +2.50.1 + diff --git a/queue-6.1/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch b/queue-6.1/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch new file mode 100644 index 0000000000..7201bcbd38 --- /dev/null +++ b/queue-6.1/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch @@ -0,0 +1,68 @@ +From fea42020e1cc8cf9cd2d6c512325306a8903b262 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 May 2025 10:11:04 +0530 +Subject: powerpc/kvm: Fix ifdef to remove build warning + +From: Madhavan Srinivasan + +[ Upstream commit 88688a2c8ac6c8036d983ad8b34ce191c46a10aa ] + +When compiling for pseries or powernv defconfig with "make C=1", +these warning were reported bu sparse tool in powerpc/kernel/kvm.c + +arch/powerpc/kernel/kvm.c:635:9: warning: switch with no cases +arch/powerpc/kernel/kvm.c:646:9: warning: switch with no cases + +Currently #ifdef were added after the switch case which are specific +for BOOKE and PPC_BOOK3S_32. These are not enabled in pseries/powernv +defconfig. Fix it by moving the #ifdef before switch(){} + +Fixes: cbe487fac7fc0 ("KVM: PPC: Add mtsrin PV code") +Tested-by: Venkat Rao Bagalkote +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250518044107.39928-1-maddy@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/kvm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c +index 5b3c093611baf..7209d00a9c257 100644 +--- a/arch/powerpc/kernel/kvm.c ++++ b/arch/powerpc/kernel/kvm.c +@@ -632,19 +632,19 @@ static void __init kvm_check_ins(u32 *inst, u32 features) + #endif + } + +- switch (inst_no_rt & ~KVM_MASK_RB) { + #ifdef CONFIG_PPC_BOOK3S_32 ++ switch (inst_no_rt & ~KVM_MASK_RB) { + case KVM_INST_MTSRIN: + if (features & KVM_MAGIC_FEAT_SR) { + u32 inst_rb = _inst & KVM_MASK_RB; + kvm_patch_ins_mtsrin(inst, inst_rt, inst_rb); + } + break; +-#endif + } ++#endif + +- switch (_inst) { + #ifdef CONFIG_BOOKE ++ switch (_inst) { + case KVM_INST_WRTEEI_0: + kvm_patch_ins_wrteei_0(inst); + break; +@@ -652,8 +652,8 @@ static void __init kvm_check_ins(u32 *inst, u32 features) + case KVM_INST_WRTEEI_1: + kvm_patch_ins_wrtee(inst, 0, 1); + break; +-#endif + } ++#endif + } + + extern u32 kvm_template_start[]; +-- +2.50.1 + diff --git a/queue-6.1/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch b/queue-6.1/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch new file mode 100644 index 0000000000..a0828d6f69 --- /dev/null +++ b/queue-6.1/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch @@ -0,0 +1,72 @@ +From 192861fb3fee49d6282d4a56c7068160ef4216f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Aug 2025 14:13:14 +0000 +Subject: sctp: initialize more fields in sctp_v6_from_sk() + +From: Eric Dumazet + +[ Upstream commit 2e8750469242cad8f01f320131fd5a6f540dbb99 ] + +syzbot found that sin6_scope_id was not properly initialized, +leading to undefined behavior. + +Clear sin6_scope_id and sin6_flowinfo. + +BUG: KMSAN: uninit-value in __sctp_v6_cmp_addr+0x887/0x8c0 net/sctp/ipv6.c:649 + __sctp_v6_cmp_addr+0x887/0x8c0 net/sctp/ipv6.c:649 + sctp_inet6_cmp_addr+0x4f2/0x510 net/sctp/ipv6.c:983 + sctp_bind_addr_conflict+0x22a/0x3b0 net/sctp/bind_addr.c:390 + sctp_get_port_local+0x21eb/0x2440 net/sctp/socket.c:8452 + sctp_get_port net/sctp/socket.c:8523 [inline] + sctp_listen_start net/sctp/socket.c:8567 [inline] + sctp_inet_listen+0x710/0xfd0 net/sctp/socket.c:8636 + __sys_listen_socket net/socket.c:1912 [inline] + __sys_listen net/socket.c:1927 [inline] + __do_sys_listen net/socket.c:1932 [inline] + __se_sys_listen net/socket.c:1930 [inline] + __x64_sys_listen+0x343/0x4c0 net/socket.c:1930 + x64_sys_call+0x271d/0x3e20 arch/x86/include/generated/asm/syscalls_64.h:51 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xd9/0x210 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Local variable addr.i.i created at: + sctp_get_port net/sctp/socket.c:8515 [inline] + sctp_listen_start net/sctp/socket.c:8567 [inline] + sctp_inet_listen+0x650/0xfd0 net/sctp/socket.c:8636 + __sys_listen_socket net/socket.c:1912 [inline] + __sys_listen net/socket.c:1927 [inline] + __do_sys_listen net/socket.c:1932 [inline] + __se_sys_listen net/socket.c:1930 [inline] + __x64_sys_listen+0x343/0x4c0 net/socket.c:1930 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+e69f06a0f30116c68056@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68adc0a2.050a0220.37038e.00c4.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Marcelo Ricardo Leitner +Acked-by: Xin Long +Link: https://patch.msgid.link/20250826141314.1802610-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/ipv6.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c +index d081858c2d073..a1cb8ac0408af 100644 +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -547,7 +547,9 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) + { + addr->v6.sin6_family = AF_INET6; + addr->v6.sin6_port = 0; ++ addr->v6.sin6_flowinfo = 0; + addr->v6.sin6_addr = sk->sk_v6_rcv_saddr; ++ addr->v6.sin6_scope_id = 0; + } + + /* Initialize sk->sk_rcv_saddr from sctp_addr. */ +-- +2.50.1 + diff --git a/queue-6.1/series b/queue-6.1/series index 522cbe2ac5..39e2b81d22 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -10,3 +10,25 @@ acpi-ec-add-device-to-acpi_ec_no_wakeup-qurik-list.patch nfs-fold-nfs_page_group_lock_subrequests-into-nfs_lock_and_join_requests.patch nfs-fix-a-race-when-updating-an-existing-write.patch vhost-net-protect-ubufs-with-rcu-read-lock-in-vhost_net_ubuf_put.patch +net-ipv4-fix-regression-in-local-broadcast-routes.patch +drm-msm-defer-fd_install-in-submit-ioctl.patch +powerpc-kvm-fix-ifdef-to-remove-build-warning.patch +hid-input-rename-hidinput_set_battery_charge_status.patch +hid-input-report-battery-status-changes-immediately.patch +bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch +bluetooth-hci_event-mark-connection-as-closed-during.patch +bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch +bluetooth-hci_sync-fix-set_local_name-race-condition.patch +atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch +net-dlink-fix-multicast-stats-being-counted-incorrec.patch +phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch +net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch +net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch +net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch +net-mlx5e-set-local-xoff-after-fw-update.patch +net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch +net-rose-split-remove-and-free-operations-in-rose_re.patch +net-rose-convert-use-field-to-refcount_t.patch +net-rose-include-node-references-in-rose_neigh-refco.patch +sctp-initialize-more-fields-in-sctp_v6_from_sk.patch +efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch diff --git a/queue-6.12/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch b/queue-6.12/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch new file mode 100644 index 0000000000..c63eae2dae --- /dev/null +++ b/queue-6.12/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch @@ -0,0 +1,192 @@ +From 687aceb7b0d9af513b48098f317fcb30bf1e67bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Aug 2025 02:18:24 +0000 +Subject: atm: atmtcp: Prevent arbitrary write in atmtcp_recv_control(). + +From: Kuniyuki Iwashima + +[ Upstream commit ec79003c5f9d2c7f9576fc69b8dbda80305cbe3a ] + +syzbot reported the splat below. [0] + +When atmtcp_v_open() or atmtcp_v_close() is called via connect() +or close(), atmtcp_send_control() is called to send an in-kernel +special message. + +The message has ATMTCP_HDR_MAGIC in atmtcp_control.hdr.length. +Also, a pointer of struct atm_vcc is set to atmtcp_control.vcc. + +The notable thing is struct atmtcp_control is uAPI but has a +space for an in-kernel pointer. + + struct atmtcp_control { + struct atmtcp_hdr hdr; /* must be first */ + ... + atm_kptr_t vcc; /* both directions */ + ... + } __ATM_API_ALIGN; + + typedef struct { unsigned char _[8]; } __ATM_API_ALIGN atm_kptr_t; + +The special message is processed in atmtcp_recv_control() called +from atmtcp_c_send(). + +atmtcp_c_send() is vcc->dev->ops->send() and called from 2 paths: + + 1. .ndo_start_xmit() (vcc->send() == atm_send_aal0()) + 2. vcc_sendmsg() + +The problem is sendmsg() does not validate the message length and +userspace can abuse atmtcp_recv_control() to overwrite any kptr +by atmtcp_control. + +Let's add a new ->pre_send() hook to validate messages from sendmsg(). + +[0]: +Oops: general protection fault, probably for non-canonical address 0xdffffc00200000ab: 0000 [#1] SMP KASAN PTI +KASAN: probably user-memory-access in range [0x0000000100000558-0x000000010000055f] +CPU: 0 UID: 0 PID: 5865 Comm: syz-executor331 Not tainted 6.17.0-rc1-syzkaller-00215-gbab3ce404553 #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/12/2025 +RIP: 0010:atmtcp_recv_control drivers/atm/atmtcp.c:93 [inline] +RIP: 0010:atmtcp_c_send+0x1da/0x950 drivers/atm/atmtcp.c:297 +Code: 4d 8d 75 1a 4c 89 f0 48 c1 e8 03 42 0f b6 04 20 84 c0 0f 85 15 06 00 00 41 0f b7 1e 4d 8d b7 60 05 00 00 4c 89 f0 48 c1 e8 03 <42> 0f b6 04 20 84 c0 0f 85 13 06 00 00 66 41 89 1e 4d 8d 75 1c 4c +RSP: 0018:ffffc90003f5f810 EFLAGS: 00010203 +RAX: 00000000200000ab RBX: 0000000000000000 RCX: 0000000000000000 +RDX: ffff88802a510000 RSI: 00000000ffffffff RDI: ffff888030a6068c +RBP: ffff88802699fb40 R08: ffff888030a606eb R09: 1ffff1100614c0dd +R10: dffffc0000000000 R11: ffffffff8718fc40 R12: dffffc0000000000 +R13: ffff888030a60680 R14: 000000010000055f R15: 00000000ffffffff +FS: 00007f8d7e9236c0(0000) GS:ffff888125c1c000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 000000000045ad50 CR3: 0000000075bde000 CR4: 00000000003526f0 +Call Trace: + + vcc_sendmsg+0xa10/0xc60 net/atm/common.c:645 + sock_sendmsg_nosec net/socket.c:714 [inline] + __sock_sendmsg+0x219/0x270 net/socket.c:729 + ____sys_sendmsg+0x505/0x830 net/socket.c:2614 + ___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668 + __sys_sendmsg net/socket.c:2700 [inline] + __do_sys_sendmsg net/socket.c:2705 [inline] + __se_sys_sendmsg net/socket.c:2703 [inline] + __x64_sys_sendmsg+0x19b/0x260 net/socket.c:2703 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +RIP: 0033:0x7f8d7e96a4a9 +Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 51 18 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f8d7e923198 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +RAX: ffffffffffffffda RBX: 00007f8d7e9f4308 RCX: 00007f8d7e96a4a9 +RDX: 0000000000000000 RSI: 0000200000000240 RDI: 0000000000000005 +RBP: 00007f8d7e9f4300 R08: 65732f636f72702f R09: 65732f636f72702f +R10: 65732f636f72702f R11: 0000000000000246 R12: 00007f8d7e9c10ac +R13: 00007f8d7e9231a0 R14: 0000200000000200 R15: 0000200000000250 + +Modules linked in: + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+1741b56d54536f4ec349@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68a6767c.050a0220.3d78fd.0011.GAE@google.com/ +Tested-by: syzbot+1741b56d54536f4ec349@syzkaller.appspotmail.com +Signed-off-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250821021901.2814721-1-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/atm/atmtcp.c | 17 ++++++++++++++--- + include/linux/atmdev.h | 1 + + net/atm/common.c | 15 ++++++++++++--- + 3 files changed, 27 insertions(+), 6 deletions(-) + +diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c +index eeae160c898d3..fa3c76a2b49d1 100644 +--- a/drivers/atm/atmtcp.c ++++ b/drivers/atm/atmtcp.c +@@ -279,6 +279,19 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) + return NULL; + } + ++static int atmtcp_c_pre_send(struct atm_vcc *vcc, struct sk_buff *skb) ++{ ++ struct atmtcp_hdr *hdr; ++ ++ if (skb->len < sizeof(struct atmtcp_hdr)) ++ return -EINVAL; ++ ++ hdr = (struct atmtcp_hdr *)skb->data; ++ if (hdr->length == ATMTCP_HDR_MAGIC) ++ return -EINVAL; ++ ++ return 0; ++} + + static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + { +@@ -288,9 +301,6 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + struct sk_buff *new_skb; + int result = 0; + +- if (skb->len < sizeof(struct atmtcp_hdr)) +- goto done; +- + dev = vcc->dev_data; + hdr = (struct atmtcp_hdr *) skb->data; + if (hdr->length == ATMTCP_HDR_MAGIC) { +@@ -347,6 +357,7 @@ static const struct atmdev_ops atmtcp_v_dev_ops = { + + static const struct atmdev_ops atmtcp_c_dev_ops = { + .close = atmtcp_c_close, ++ .pre_send = atmtcp_c_pre_send, + .send = atmtcp_c_send + }; + +diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h +index 45f2f278b50a8..70807c679f1ab 100644 +--- a/include/linux/atmdev.h ++++ b/include/linux/atmdev.h +@@ -185,6 +185,7 @@ struct atmdev_ops { /* only send is required */ + int (*compat_ioctl)(struct atm_dev *dev,unsigned int cmd, + void __user *arg); + #endif ++ int (*pre_send)(struct atm_vcc *vcc, struct sk_buff *skb); + int (*send)(struct atm_vcc *vcc,struct sk_buff *skb); + int (*send_bh)(struct atm_vcc *vcc, struct sk_buff *skb); + int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags); +diff --git a/net/atm/common.c b/net/atm/common.c +index d7f7976ea13ac..881c7f259dbd4 100644 +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -635,18 +635,27 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size) + + skb->dev = NULL; /* for paths shared with net_device interfaces */ + if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) { +- atm_return_tx(vcc, skb); +- kfree_skb(skb); + error = -EFAULT; +- goto out; ++ goto free_skb; + } + if (eff != size) + memset(skb->data + size, 0, eff-size); ++ ++ if (vcc->dev->ops->pre_send) { ++ error = vcc->dev->ops->pre_send(vcc, skb); ++ if (error) ++ goto free_skb; ++ } ++ + error = vcc->dev->ops->send(vcc, skb); + error = error ? error : size; + out: + release_sock(sk); + return error; ++free_skb: ++ atm_return_tx(vcc, skb); ++ kfree_skb(skb); ++ goto out; + } + + __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait) +-- +2.50.1 + diff --git a/queue-6.12/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch b/queue-6.12/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch new file mode 100644 index 0000000000..2ebb56f891 --- /dev/null +++ b/queue-6.12/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch @@ -0,0 +1,47 @@ +From 8742d460d4ff9605984e6f4221b08411b078b60f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Aug 2025 17:04:00 -0400 +Subject: Bluetooth: hci_event: Detect if HCI_EV_NUM_COMP_PKTS is unbalanced + +From: Luiz Augusto von Dentz + +[ Upstream commit 15bf2c6391bafb14a3020d06ec0761bce0803463 ] + +This attempts to detect if HCI_EV_NUM_COMP_PKTS contain an unbalanced +(more than currently considered outstanding) number of packets otherwise +it could cause the hcon->sent to underflow and loop around breaking the +tracking of the outstanding packets pending acknowledgment. + +Fixes: f42809185896 ("Bluetooth: Simplify num_comp_pkts_evt function") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index b8213bfa0a674..262ff30261d67 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -4395,7 +4395,17 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, + if (!conn) + continue; + +- conn->sent -= count; ++ /* Check if there is really enough packets outstanding before ++ * attempting to decrease the sent counter otherwise it could ++ * underflow.. ++ */ ++ if (conn->sent >= count) { ++ conn->sent -= count; ++ } else { ++ bt_dev_warn(hdev, "hcon %p sent %u < count %u", ++ conn, conn->sent, count); ++ conn->sent = 0; ++ } + + switch (conn->type) { + case ACL_LINK: +-- +2.50.1 + diff --git a/queue-6.12/bluetooth-hci_event-mark-connection-as-closed-during.patch b/queue-6.12/bluetooth-hci_event-mark-connection-as-closed-during.patch new file mode 100644 index 0000000000..5a0b9f0087 --- /dev/null +++ b/queue-6.12/bluetooth-hci_event-mark-connection-as-closed-during.patch @@ -0,0 +1,80 @@ +From a38f9aa0ee062b0243b10165b8a71996ed90c694 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Aug 2025 17:55:27 +0200 +Subject: Bluetooth: hci_event: Mark connection as closed during suspend + disconnect + +From: Ludovico de Nittis + +[ Upstream commit b7fafbc499b5ee164018eb0eefe9027f5a6aaad2 ] + +When suspending, the disconnect command for an active Bluetooth +connection could be issued, but the corresponding +`HCI_EV_DISCONN_COMPLETE` event might not be received before the system +completes the suspend process. This can lead to an inconsistent state. + +On resume, the controller may auto-accept reconnections from the same +device (due to suspend event filters), but these new connections are +rejected by the kernel which still has connection objects from before +suspend. Resulting in errors like: +``` +kernel: Bluetooth: hci0: ACL packet for unknown connection handle 1 +kernel: Bluetooth: hci0: Ignoring HCI_Connection_Complete for existing +connection +``` + +This is a btmon snippet that shows the issue: +``` +< HCI Command: Disconnect (0x01|0x0006) plen 3 + Handle: 1 Address: 78:20:A5:4A:DF:28 (Nintendo Co.,Ltd) + Reason: Remote User Terminated Connection (0x13) +> HCI Event: Command Status (0x0f) plen 4 + Disconnect (0x01|0x0006) ncmd 2 + Status: Success (0x00) +[...] +// Host suspends with the event filter set for the device +// On resume, the device tries to reconnect with a new handle + +> HCI Event: Connect Complete (0x03) plen 11 + Status: Success (0x00) + Handle: 2 + Address: 78:20:A5:4A:DF:28 (Nintendo Co.,Ltd) + +// Kernel ignores this event because there is an existing connection +with +// handle 1 +``` + +By explicitly setting the connection state to BT_CLOSED we can ensure a +consistent state, even if we don't receive the disconnect complete event +in time. + +Link: https://github.com/bluez/bluez/issues/1226 +Fixes: 182ee45da083 ("Bluetooth: hci_sync: Rework hci_suspend_notifier") +Signed-off-by: Ludovico de Nittis +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 428aba38a3654..b8213bfa0a674 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -2709,6 +2709,12 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) + goto done; + } + ++ /* During suspend, mark connection as closed immediately ++ * since we might not receive HCI_EV_DISCONN_COMPLETE ++ */ ++ if (hdev->suspended) ++ conn->state = BT_CLOSED; ++ + mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); + + if (conn->type == ACL_LINK) { +-- +2.50.1 + diff --git a/queue-6.12/bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch b/queue-6.12/bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch new file mode 100644 index 0000000000..74f8c4ac5f --- /dev/null +++ b/queue-6.12/bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch @@ -0,0 +1,84 @@ +From eacf8dc08de40aae74d47b0f4990737307871633 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Aug 2025 17:55:26 +0200 +Subject: Bluetooth: hci_event: Treat UNKNOWN_CONN_ID on disconnect as success + +From: Ludovico de Nittis + +[ Upstream commit 2f050a5392b7a0928bf836d9891df4851463512c ] + +When the host sends an HCI_OP_DISCONNECT command, the controller may +respond with the status HCI_ERROR_UNKNOWN_CONN_ID (0x02). E.g. this can +happen on resume from suspend, if the link was terminated by the remote +device before the event mask was correctly set. + +This is a btmon snippet that shows the issue: +``` +> ACL Data RX: Handle 3 flags 0x02 dlen 12 + L2CAP: Disconnection Request (0x06) ident 5 len 4 + Destination CID: 65 + Source CID: 72 +< ACL Data TX: Handle 3 flags 0x00 dlen 12 + L2CAP: Disconnection Response (0x07) ident 5 len 4 + Destination CID: 65 + Source CID: 72 +> ACL Data RX: Handle 3 flags 0x02 dlen 12 + L2CAP: Disconnection Request (0x06) ident 6 len 4 + Destination CID: 64 + Source CID: 71 +< ACL Data TX: Handle 3 flags 0x00 dlen 12 + L2CAP: Disconnection Response (0x07) ident 6 len 4 + Destination CID: 64 + Source CID: 71 +< HCI Command: Set Event Mask (0x03|0x0001) plen 8 + Mask: 0x3dbff807fffbffff + Inquiry Complete + Inquiry Result + Connection Complete + Connection Request + Disconnection Complete + Authentication Complete +[...] +< HCI Command: Disconnect (0x01|0x0006) plen 3 + Handle: 3 Address: 78:20:A5:4A:DF:28 (Nintendo Co.,Ltd) + Reason: Remote User Terminated Connection (0x13) +> HCI Event: Command Status (0x0f) plen 4 + Disconnect (0x01|0x0006) ncmd 1 + Status: Unknown Connection Identifier (0x02) +``` + +Currently, the hci_cs_disconnect function treats any non-zero status +as a command failure. This can be misleading because the connection is +indeed being terminated and the controller is confirming that is has no +knowledge of that connection handle. Meaning that the initial request of +disconnecting a device should be treated as done. + +With this change we allow the function to proceed, following the success +path, which correctly calls `mgmt_device_disconnected` and ensures a +consistent state. + +Link: https://github.com/bluez/bluez/issues/1226 +Fixes: 182ee45da083 ("Bluetooth: hci_sync: Rework hci_suspend_notifier") +Signed-off-by: Ludovico de Nittis +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 768bd5fd808f2..428aba38a3654 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -2694,7 +2694,7 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) + if (!conn) + goto unlock; + +- if (status) { ++ if (status && status != HCI_ERROR_UNKNOWN_CONN_ID) { + mgmt_disconnect_failed(hdev, &conn->dst, conn->type, + conn->dst_type, status); + +-- +2.50.1 + diff --git a/queue-6.12/bluetooth-hci_sync-fix-set_local_name-race-condition.patch b/queue-6.12/bluetooth-hci_sync-fix-set_local_name-race-condition.patch new file mode 100644 index 0000000000..e180c08055 --- /dev/null +++ b/queue-6.12/bluetooth-hci_sync-fix-set_local_name-race-condition.patch @@ -0,0 +1,90 @@ +From 1efa42f26b69b7a61f88a8c52cb27c12632a334a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Aug 2025 12:20:55 +0300 +Subject: Bluetooth: hci_sync: fix set_local_name race condition + +From: Pavel Shpakovskiy + +[ Upstream commit 6bbd0d3f0c23fc53c17409dd7476f38ae0ff0cd9 ] + +Function set_name_sync() uses hdev->dev_name field to send +HCI_OP_WRITE_LOCAL_NAME command, but copying from data to hdev->dev_name +is called after mgmt cmd was queued, so it is possible that function +set_name_sync() will read old name value. + +This change adds name as a parameter for function hci_update_name_sync() +to avoid race condition. + +Fixes: 6f6ff38a1e14 ("Bluetooth: hci_sync: Convert MGMT_OP_SET_LOCAL_NAME") +Signed-off-by: Pavel Shpakovskiy +Reviewed-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci_sync.h | 2 +- + net/bluetooth/hci_sync.c | 6 +++--- + net/bluetooth/mgmt.c | 5 ++++- + 3 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h +index dbabc17b30cdf..17e5112f7840e 100644 +--- a/include/net/bluetooth/hci_sync.h ++++ b/include/net/bluetooth/hci_sync.h +@@ -93,7 +93,7 @@ int hci_update_class_sync(struct hci_dev *hdev); + + int hci_update_eir_sync(struct hci_dev *hdev); + int hci_update_class_sync(struct hci_dev *hdev); +-int hci_update_name_sync(struct hci_dev *hdev); ++int hci_update_name_sync(struct hci_dev *hdev, const u8 *name); + int hci_write_ssp_mode_sync(struct hci_dev *hdev, u8 mode); + + int hci_get_random_address(struct hci_dev *hdev, bool require_privacy, +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index af86df9de941d..bc2aa514b8c5d 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -3491,13 +3491,13 @@ int hci_update_scan_sync(struct hci_dev *hdev) + return hci_write_scan_enable_sync(hdev, scan); + } + +-int hci_update_name_sync(struct hci_dev *hdev) ++int hci_update_name_sync(struct hci_dev *hdev, const u8 *name) + { + struct hci_cp_write_local_name cp; + + memset(&cp, 0, sizeof(cp)); + +- memcpy(cp.name, hdev->dev_name, sizeof(cp.name)); ++ memcpy(cp.name, name, sizeof(cp.name)); + + return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_LOCAL_NAME, + sizeof(cp), &cp, +@@ -3550,7 +3550,7 @@ int hci_powered_update_sync(struct hci_dev *hdev) + hci_write_fast_connectable_sync(hdev, false); + hci_update_scan_sync(hdev); + hci_update_class_sync(hdev); +- hci_update_name_sync(hdev); ++ hci_update_name_sync(hdev, hdev->dev_name); + hci_update_eir_sync(hdev); + } + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index ade93532db34b..8b75647076bae 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -3826,8 +3826,11 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err) + + static int set_name_sync(struct hci_dev *hdev, void *data) + { ++ struct mgmt_pending_cmd *cmd = data; ++ struct mgmt_cp_set_local_name *cp = cmd->param; ++ + if (lmp_bredr_capable(hdev)) { +- hci_update_name_sync(hdev); ++ hci_update_name_sync(hdev, cp->name); + hci_update_eir_sync(hdev); + } + +-- +2.50.1 + diff --git a/queue-6.12/bnxt_en-adjust-tx-rings-if-reservation-is-less-than-.patch b/queue-6.12/bnxt_en-adjust-tx-rings-if-reservation-is-less-than-.patch new file mode 100644 index 0000000000..a1807e5a93 --- /dev/null +++ b/queue-6.12/bnxt_en-adjust-tx-rings-if-reservation-is-less-than-.patch @@ -0,0 +1,64 @@ +From 8a59728704077d2ebdbcded760bcf3b467776186 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 10:59:26 -0700 +Subject: bnxt_en: Adjust TX rings if reservation is less than requested + +From: Michael Chan + +[ Upstream commit 1ee581c24dfdcbc6de25aac95a48c1f08e9a542c ] + +Before we accept an ethtool request to increase a resource (such as +rings), we call the FW to check that the requested resource is likely +available first before we commit. But it is still possible that +the actual reservation or allocation can fail. The existing code +is missing the logic to adjust the TX rings in case the reserved +TX rings are less than requested. Add a warning message (a similar +message for RX rings already exists) and add the logic to adjust +the TX rings. Without this fix, the number of TX rings reported +to the stack can exceed the actual TX rings and ethtool -l will +report more than the actual TX rings. + +Fixes: 674f50a5b026 ("bnxt_en: Implement new method to reserve rings.") +Reviewed-by: Kalesh AP +Reviewed-by: Somnath Kotur +Signed-off-by: Michael Chan +Link: https://patch.msgid.link/20250825175927.459987-3-michael.chan@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index dc123822771b6..b8c6087a5c31e 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -7788,6 +7788,11 @@ static int __bnxt_reserve_rings(struct bnxt *bp) + hwr.rx = rx_rings << 1; + tx_cp = bnxt_num_tx_to_cp(bp, hwr.tx); + hwr.cp = sh ? max_t(int, tx_cp, rx_rings) : tx_cp + rx_rings; ++ if (hwr.tx != bp->tx_nr_rings) { ++ netdev_warn(bp->dev, ++ "Able to reserve only %d out of %d requested TX rings\n", ++ hwr.tx, bp->tx_nr_rings); ++ } + bp->tx_nr_rings = hwr.tx; + + /* If we cannot reserve all the RX rings, reset the RSS map only +@@ -12269,6 +12274,13 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) + if (rc) + return rc; + ++ /* Make adjustments if reserved TX rings are less than requested */ ++ bp->tx_nr_rings -= bp->tx_nr_rings_xdp; ++ bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); ++ if (bp->tx_nr_rings_xdp) { ++ bp->tx_nr_rings_xdp = bp->tx_nr_rings_per_tc; ++ bp->tx_nr_rings += bp->tx_nr_rings_xdp; ++ } + rc = bnxt_alloc_mem(bp, irq_re_init); + if (rc) { + netdev_err(bp->dev, "bnxt_alloc_mem err: %x\n", rc); +-- +2.50.1 + diff --git a/queue-6.12/bnxt_en-fix-memory-corruption-when-fw-resources-chan.patch b/queue-6.12/bnxt_en-fix-memory-corruption-when-fw-resources-chan.patch new file mode 100644 index 0000000000..4a46304be8 --- /dev/null +++ b/queue-6.12/bnxt_en-fix-memory-corruption-when-fw-resources-chan.patch @@ -0,0 +1,106 @@ +From a7e3730820faf6b43ca08e0dc86d3b5f3d26e2ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 10:59:25 -0700 +Subject: bnxt_en: Fix memory corruption when FW resources change during ifdown + +From: Sreekanth Reddy + +[ Upstream commit 2747328ba2714f1a7454208dbbc1dc0631990b4a ] + +bnxt_set_dflt_rings() assumes that it is always called before any TC has +been created. So it doesn't take bp->num_tc into account and assumes +that it is always 0 or 1. + +In the FW resource or capability change scenario, the FW will return +flags in bnxt_hwrm_if_change() that will cause the driver to +reinitialize and call bnxt_cancel_reservations(). This will lead to +bnxt_init_dflt_ring_mode() calling bnxt_set_dflt_rings() and bp->num_tc +may be greater than 1. This will cause bp->tx_ring[] to be sized too +small and cause memory corruption in bnxt_alloc_cp_rings(). + +Fix it by properly scaling the TX rings by bp->num_tc in the code +paths mentioned above. Add 2 helper functions to determine +bp->tx_nr_rings and bp->tx_nr_rings_per_tc. + +Fixes: ec5d31e3c15d ("bnxt_en: Handle firmware reset status during IF_UP.") +Reviewed-by: Kalesh AP +Reviewed-by: Andy Gospodarek +Signed-off-by: Sreekanth Reddy +Signed-off-by: Michael Chan +Link: https://patch.msgid.link/20250825175927.459987-2-michael.chan@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index f4bafc71a7399..dc123822771b6 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -12241,6 +12241,17 @@ static int bnxt_set_xps_mapping(struct bnxt *bp) + return rc; + } + ++static int bnxt_tx_nr_rings(struct bnxt *bp) ++{ ++ return bp->num_tc ? bp->tx_nr_rings_per_tc * bp->num_tc : ++ bp->tx_nr_rings_per_tc; ++} ++ ++static int bnxt_tx_nr_rings_per_tc(struct bnxt *bp) ++{ ++ return bp->num_tc ? bp->tx_nr_rings / bp->num_tc : bp->tx_nr_rings; ++} ++ + static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) + { + int rc = 0; +@@ -15676,7 +15687,7 @@ static void bnxt_trim_dflt_sh_rings(struct bnxt *bp) + bp->cp_nr_rings = min_t(int, bp->tx_nr_rings_per_tc, bp->rx_nr_rings); + bp->rx_nr_rings = bp->cp_nr_rings; + bp->tx_nr_rings_per_tc = bp->cp_nr_rings; +- bp->tx_nr_rings = bp->tx_nr_rings_per_tc; ++ bp->tx_nr_rings = bnxt_tx_nr_rings(bp); + } + + static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) +@@ -15708,7 +15719,7 @@ static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) + bnxt_trim_dflt_sh_rings(bp); + else + bp->cp_nr_rings = bp->tx_nr_rings_per_tc + bp->rx_nr_rings; +- bp->tx_nr_rings = bp->tx_nr_rings_per_tc; ++ bp->tx_nr_rings = bnxt_tx_nr_rings(bp); + + avail_msix = bnxt_get_max_func_irqs(bp) - bp->cp_nr_rings; + if (avail_msix >= BNXT_MIN_ROCE_CP_RINGS) { +@@ -15721,7 +15732,7 @@ static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) + rc = __bnxt_reserve_rings(bp); + if (rc && rc != -ENODEV) + netdev_warn(bp->dev, "Unable to reserve tx rings\n"); +- bp->tx_nr_rings_per_tc = bp->tx_nr_rings; ++ bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); + if (sh) + bnxt_trim_dflt_sh_rings(bp); + +@@ -15730,7 +15741,7 @@ static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) + rc = __bnxt_reserve_rings(bp); + if (rc && rc != -ENODEV) + netdev_warn(bp->dev, "2nd rings reservation failed.\n"); +- bp->tx_nr_rings_per_tc = bp->tx_nr_rings; ++ bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); + } + if (BNXT_CHIP_TYPE_NITRO_A0(bp)) { + bp->rx_nr_rings++; +@@ -15764,7 +15775,7 @@ static int bnxt_init_dflt_ring_mode(struct bnxt *bp) + if (rc) + goto init_dflt_ring_err; + +- bp->tx_nr_rings_per_tc = bp->tx_nr_rings; ++ bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); + + bnxt_set_dflt_rfs(bp); + +-- +2.50.1 + diff --git a/queue-6.12/bnxt_en-fix-stats-context-reservation-logic.patch b/queue-6.12/bnxt_en-fix-stats-context-reservation-logic.patch new file mode 100644 index 0000000000..8906e01ef9 --- /dev/null +++ b/queue-6.12/bnxt_en-fix-stats-context-reservation-logic.patch @@ -0,0 +1,44 @@ +From 2ffd938d0b3fe90bd0cdbda7e7e124825add1978 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 10:59:27 -0700 +Subject: bnxt_en: Fix stats context reservation logic + +From: Michael Chan + +[ Upstream commit b4fc8faacfea2538184a1dbd616ae9447a361f3d ] + +The HW resource reservation logic allows the L2 driver to use the +RoCE resources if the RoCE driver is not registered. When calculating +the stats contexts available for L2, we should not blindly subtract +the stats contexts reserved for RoCE unless the RoCE driver is +registered. This bug may cause the L2 rings to be less than the +number requested when we are close to running out of stats contexts. + +Fixes: 2e4592dc9bee ("bnxt_en: Change MSIX/NQs allocation policy") +Reviewed-by: Kalesh AP +Reviewed-by: Somnath Kotur +Signed-off-by: Michael Chan +Link: https://patch.msgid.link/20250825175927.459987-4-michael.chan@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index b8c6087a5c31e..08886c3a28c61 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -7780,7 +7780,8 @@ static int __bnxt_reserve_rings(struct bnxt *bp) + } + rx_rings = min_t(int, rx_rings, hwr.grp); + hwr.cp = min_t(int, hwr.cp, bp->cp_nr_rings); +- if (hwr.stat > bnxt_get_ulp_stat_ctxs(bp)) ++ if (bnxt_ulp_registered(bp->edev) && ++ hwr.stat > bnxt_get_ulp_stat_ctxs(bp)) + hwr.stat -= bnxt_get_ulp_stat_ctxs(bp); + hwr.cp = min_t(int, hwr.cp, hwr.stat); + rc = bnxt_trim_rings(bp, &rx_rings, &hwr.tx, hwr.cp, sh); +-- +2.50.1 + diff --git a/queue-6.12/drm-mediatek-add-error-handling-for-old-state-crtc-i.patch b/queue-6.12/drm-mediatek-add-error-handling-for-old-state-crtc-i.patch new file mode 100644 index 0000000000..40ca4f9822 --- /dev/null +++ b/queue-6.12/drm-mediatek-add-error-handling-for-old-state-crtc-i.patch @@ -0,0 +1,66 @@ +From 23bb2edbf20032947f7a47761276665fe714ce36 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Jul 2025 10:48:50 +0800 +Subject: drm/mediatek: Add error handling for old state CRTC in atomic_disable + +From: Jason-JH Lin + +[ Upstream commit 0c6b24d70da21201ed009a2aca740d2dfddc7ab5 ] + +Introduce error handling to address an issue where, after a hotplug +event, the cursor continues to update. This situation can lead to a +kernel panic due to accessing the NULL `old_state->crtc`. + +E,g. +Unable to handle kernel NULL pointer dereference at virtual address +Call trace: + mtk_crtc_plane_disable+0x24/0x140 + mtk_plane_atomic_update+0x8c/0xa8 + drm_atomic_helper_commit_planes+0x114/0x2c8 + drm_atomic_helper_commit_tail_rpm+0x4c/0x158 + commit_tail+0xa0/0x168 + drm_atomic_helper_commit+0x110/0x120 + drm_atomic_commit+0x8c/0xe0 + drm_atomic_helper_update_plane+0xd4/0x128 + __setplane_atomic+0xcc/0x110 + drm_mode_cursor_common+0x250/0x440 + drm_mode_cursor_ioctl+0x44/0x70 + drm_ioctl+0x264/0x5d8 + __arm64_sys_ioctl+0xd8/0x510 + invoke_syscall+0x6c/0xe0 + do_el0_svc+0x68/0xe8 + el0_svc+0x34/0x60 + el0t_64_sync_handler+0x1c/0xf8 + el0t_64_sync+0x180/0x188 + +Adding NULL pointer checks to ensure stability by preventing operations +on an invalid CRTC state. + +Fixes: d208261e9f7c ("drm/mediatek: Add wait_event_timeout when disabling plane") +Signed-off-by: Jason-JH Lin +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: CK Hu +Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20250728025036.24953-1-jason-jh.lin@mediatek.com/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/mediatek/mtk_plane.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/mediatek/mtk_plane.c b/drivers/gpu/drm/mediatek/mtk_plane.c +index 74c2704efb664..6e20f7037b5bb 100644 +--- a/drivers/gpu/drm/mediatek/mtk_plane.c ++++ b/drivers/gpu/drm/mediatek/mtk_plane.c +@@ -292,7 +292,8 @@ static void mtk_plane_atomic_disable(struct drm_plane *plane, + wmb(); /* Make sure the above parameter is set before update */ + mtk_plane_state->pending.dirty = true; + +- mtk_crtc_plane_disable(old_state->crtc, plane); ++ if (old_state && old_state->crtc) ++ mtk_crtc_plane_disable(old_state->crtc, plane); + } + + static void mtk_plane_atomic_update(struct drm_plane *plane, +-- +2.50.1 + diff --git a/queue-6.12/drm-msm-defer-fd_install-in-submit-ioctl.patch b/queue-6.12/drm-msm-defer-fd_install-in-submit-ioctl.patch new file mode 100644 index 0000000000..ce9c052cef --- /dev/null +++ b/queue-6.12/drm-msm-defer-fd_install-in-submit-ioctl.patch @@ -0,0 +1,59 @@ +From 93316df3cf5624b86066b09d9e48489023825a58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Jul 2025 13:28:22 -0700 +Subject: drm/msm: Defer fd_install in SUBMIT ioctl + +From: Rob Clark + +[ Upstream commit f22853435bbd1e9836d0dce7fd99c040b94c2bf1 ] + +Avoid fd_install() until there are no more potential error paths, to +avoid put_unused_fd() after the fd is made visible to userspace. + +Fixes: 68dc6c2d5eec ("drm/msm: Fix submit error-path leaks") +Reported-by: Dan Carpenter +Signed-off-by: Rob Clark +Patchwork: https://patchwork.freedesktop.org/patch/665363/ +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/msm_gem_submit.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c +index 4b3a8ee8e278f..3eee6517541e3 100644 +--- a/drivers/gpu/drm/msm/msm_gem_submit.c ++++ b/drivers/gpu/drm/msm/msm_gem_submit.c +@@ -879,12 +879,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, + + if (ret == 0 && args->flags & MSM_SUBMIT_FENCE_FD_OUT) { + sync_file = sync_file_create(submit->user_fence); +- if (!sync_file) { ++ if (!sync_file) + ret = -ENOMEM; +- } else { +- fd_install(out_fence_fd, sync_file->file); +- args->fence_fd = out_fence_fd; +- } + } + + if (ret) +@@ -912,10 +908,14 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, + out_unlock: + mutex_unlock(&queue->lock); + out_post_unlock: +- if (ret && (out_fence_fd >= 0)) { +- put_unused_fd(out_fence_fd); ++ if (ret) { ++ if (out_fence_fd >= 0) ++ put_unused_fd(out_fence_fd); + if (sync_file) + fput(sync_file->file); ++ } else if (sync_file) { ++ fd_install(out_fence_fd, sync_file->file); ++ args->fence_fd = out_fence_fd; + } + + if (!IS_ERR_OR_NULL(submit)) { +-- +2.50.1 + diff --git a/queue-6.12/drm-msm-kms-move-snapshot-init-earlier-in-kms-init.patch b/queue-6.12/drm-msm-kms-move-snapshot-init-earlier-in-kms-init.patch new file mode 100644 index 0000000000..14a063fa9f --- /dev/null +++ b/queue-6.12/drm-msm-kms-move-snapshot-init-earlier-in-kms-init.patch @@ -0,0 +1,118 @@ +From a57a0e8e68d8d2fbf0fab60ef8f37dca9d5aecd6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Jul 2025 18:50:37 +0300 +Subject: drm/msm/kms: move snapshot init earlier in KMS init + +From: Dmitry Baryshkov + +[ Upstream commit 553666f839b86545300773954df7426a45c169c4 ] + +Various parts of the display driver can be triggering the display +snapshot (including the IOMMU fault handlers). Move the call to +msm_disp_snapshot_init() before KMS initialization, otherwise it is +possible to ocassionally trigger the kernel fault during init: + + __lock_acquire+0x44/0x2798 (P) + lock_acquire+0x114/0x25c + _raw_spin_lock_irqsave+0x6c/0x90 + kthread_queue_work+0x2c/0xac + msm_disp_snapshot_state+0x2c/0x4c + msm_kms_fault_handler+0x2c/0x74 + msm_disp_fault_handler+0x30/0x48 + report_iommu_fault+0x54/0x128 + arm_smmu_context_fault+0x74/0x184 + __handle_irq_event_percpu+0xa4/0x24c + handle_irq_event_percpu+0x20/0x5c + handle_irq_event+0x48/0x84 + handle_fasteoi_irq+0xcc/0x170 + generic_handle_domain_irq+0x48/0x70 + gic_handle_irq+0x54/0x11c + call_on_irq_stack+0x3c/0x50 + do_interrupt_handler+0x54/0x78 + el1_interrupt+0x3c/0x5c + el1h_64_irq_handler+0x20/0x30 + el1h_64_irq+0x6c/0x70 + _raw_spin_unlock_irqrestore+0x44/0x68 (P) + klist_next+0xc4/0x124 + bus_for_each_drv+0x9c/0xe8 + __device_attach+0xfc/0x190 + device_initial_probe+0x1c/0x2c + bus_probe_device+0x44/0xa0 + device_add+0x204/0x3e4 + platform_device_add+0x170/0x244 + platform_device_register_full+0x130/0x138 + drm_connector_hdmi_audio_init+0xc0/0x108 + drm_bridge_connector_init+0x318/0x394 + msm_dsi_manager_connector_init+0xac/0xdc + msm_dsi_modeset_init+0x78/0xc0 + _dpu_kms_drm_obj_init+0x198/0x75c + dpu_kms_hw_init+0x2f8/0x494 + msm_drm_kms_init+0xb0/0x230 + msm_drm_init+0x218/0x250 + msm_drm_bind+0x3c/0x4c + try_to_bring_up_aggregate_device+0x208/0x2a4 + __component_add+0xa8/0x188 + component_add+0x1c/0x2c + dsi_dev_attach+0x24/0x34 + dsi_host_attach+0x68/0xa0 + devm_mipi_dsi_attach+0x40/0xcc + lt9611_attach_dsi+0x94/0x118 + lt9611_probe+0x368/0x3c8 + i2c_device_probe+0x2d0/0x3d8 + really_probe+0x130/0x354 + __driver_probe_device+0xac/0x110 + driver_probe_device+0x44/0x110 + __device_attach_driver+0xb0/0x138 + bus_for_each_drv+0x90/0xe8 + __device_attach+0xfc/0x190 + device_initial_probe+0x1c/0x2c + bus_probe_device+0x44/0xa0 + deferred_probe_work_func+0xac/0x110 + process_one_work+0x20c/0x51c + process_scheduled_works+0x58/0x88 + worker_thread+0x1ec/0x304 + kthread+0x194/0x1d4 + ret_from_fork+0x10/0x20 + +Reported-by: Konrad Dybcio +Fixes: 98659487b845 ("drm/msm: add support to take dpu snapshot") +Signed-off-by: Dmitry Baryshkov +Reviewed-by: Konrad Dybcio +Patchwork: https://patchwork.freedesktop.org/patch/664149/ +Link: https://lore.kernel.org/r/20250715-msm-move-snapshot-init-v1-1-f39c396192ab@oss.qualcomm.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/msm_kms.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c +index 6749f0fbca96d..52464a1346f81 100644 +--- a/drivers/gpu/drm/msm/msm_kms.c ++++ b/drivers/gpu/drm/msm/msm_kms.c +@@ -241,6 +241,12 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) + if (ret) + return ret; + ++ ret = msm_disp_snapshot_init(ddev); ++ if (ret) { ++ DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret); ++ return ret; ++ } ++ + ret = priv->kms_init(ddev); + if (ret) { + DRM_DEV_ERROR(dev, "failed to load kms\n"); +@@ -293,10 +299,6 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) + goto err_msm_uninit; + } + +- ret = msm_disp_snapshot_init(ddev); +- if (ret) +- DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret); +- + drm_mode_config_reset(ddev); + + return 0; +-- +2.50.1 + diff --git a/queue-6.12/drm-msm-update-the-high-bitfield-of-certain-dsi-regi.patch b/queue-6.12/drm-msm-update-the-high-bitfield-of-certain-dsi-regi.patch new file mode 100644 index 0000000000..78c080a7c0 --- /dev/null +++ b/queue-6.12/drm-msm-update-the-high-bitfield-of-certain-dsi-regi.patch @@ -0,0 +1,89 @@ +From 3644bfe38ef67e87834d43291a213eec2e79cc48 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Jul 2025 18:09:38 +0530 +Subject: drm/msm: update the high bitfield of certain DSI registers + +From: Ayushi Makhija + +[ Upstream commit 494045c561e68945b1183ff416b8db8e37a122d6 ] + +Currently, the high bitfield of certain DSI registers +do not align with the configuration of the SWI registers +description. This can lead to wrong programming these DSI +registers, for example for 4k resloution where H_TOTAL is +taking 13 bits but software is programming only 12 bits +because of the incorrect bitmask for H_TOTAL bitfeild, +this is causing DSI FIFO errors. To resolve this issue, +increase the high bitfield of the DSI registers from 12 bits +to 16 bits in dsi.xml to match the SWI register configuration. + +Signed-off-by: Ayushi Makhija +Fixes: 4f52f5e63b62 ("drm/msm: import XML display registers database") +Reviewed-by: Dmitry Baryshkov +Patchwork: https://patchwork.freedesktop.org/patch/666229/ +Link: https://lore.kernel.org/r/20250730123938.1038640-1-quic_amakhija@quicinc.com +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/registers/display/dsi.xml | 28 +++++++++---------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/drivers/gpu/drm/msm/registers/display/dsi.xml b/drivers/gpu/drm/msm/registers/display/dsi.xml +index 501ffc585a9f6..c7a7b633d747b 100644 +--- a/drivers/gpu/drm/msm/registers/display/dsi.xml ++++ b/drivers/gpu/drm/msm/registers/display/dsi.xml +@@ -159,28 +159,28 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> + + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + + +@@ -209,8 +209,8 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> + + + +- +- ++ ++ + + + +-- +2.50.1 + diff --git a/queue-6.12/drm-nouveau-remove-unused-increment-in-gm200_flcn_pi.patch b/queue-6.12/drm-nouveau-remove-unused-increment-in-gm200_flcn_pi.patch new file mode 100644 index 0000000000..6e9f0501f4 --- /dev/null +++ b/queue-6.12/drm-nouveau-remove-unused-increment-in-gm200_flcn_pi.patch @@ -0,0 +1,39 @@ +From 9f1639b83ddb706015a8fa3e576957489ed4a49f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Aug 2025 19:10:03 -0500 +Subject: drm/nouveau: remove unused increment in gm200_flcn_pio_imem_wr + +From: Timur Tabi + +[ Upstream commit f529b8915543fb9ceb732cec5571f7fe12bc9530 ] + +The 'tag' parameter is passed by value and is not actually used after +being incremented, so remove the increment. It's the function that calls +gm200_flcn_pio_imem_wr that is supposed to (and does) increment 'tag'. + +Fixes: 0e44c2170876 ("drm/nouveau/flcn: new code to load+boot simple HS FWs (VPR scrubber)") +Reviewed-by: Philipp Stanner +Signed-off-by: Timur Tabi +Link: https://lore.kernel.org/r/20250813001004.2986092-2-ttabi@nvidia.com +Signed-off-by: Danilo Krummrich +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +index b7da3ab44c277..6a004c6e67425 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c ++++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +@@ -103,7 +103,7 @@ gm200_flcn_pio_imem_wr_init(struct nvkm_falcon *falcon, u8 port, bool sec, u32 i + static void + gm200_flcn_pio_imem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len, u16 tag) + { +- nvkm_falcon_wr32(falcon, 0x188 + (port * 0x10), tag++); ++ nvkm_falcon_wr32(falcon, 0x188 + (port * 0x10), tag); + while (len >= 4) { + nvkm_falcon_wr32(falcon, 0x184 + (port * 0x10), *(u32 *)img); + img += 4; +-- +2.50.1 + diff --git a/queue-6.12/drm-nouveau-remove-unused-memory-target-test.patch b/queue-6.12/drm-nouveau-remove-unused-memory-target-test.patch new file mode 100644 index 0000000000..0b56ba7746 --- /dev/null +++ b/queue-6.12/drm-nouveau-remove-unused-memory-target-test.patch @@ -0,0 +1,57 @@ +From 768c07fc37905da64c3caa744c8051260da4965b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Aug 2025 19:10:04 -0500 +Subject: drm/nouveau: remove unused memory target test + +From: Timur Tabi + +[ Upstream commit 64c722b5e7f6b909b0e448e580f64628a0d76208 ] + +The memory target check is a hold-over from a refactor. It's harmless +but distracting, so just remove it. + +Fixes: 2541626cfb79 ("drm/nouveau/acr: use common falcon HS FW code for ACR FWs") +Signed-off-by: Timur Tabi +Link: https://lore.kernel.org/r/20250813001004.2986092-3-ttabi@nvidia.com +Signed-off-by: Danilo Krummrich +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c | 13 +++---------- + 1 file changed, 3 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +index 6a004c6e67425..7c43397c19e61 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c ++++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +@@ -249,9 +249,11 @@ int + gm200_flcn_fw_load(struct nvkm_falcon_fw *fw) + { + struct nvkm_falcon *falcon = fw->falcon; +- int target, ret; ++ int ret; + + if (fw->inst) { ++ int target; ++ + nvkm_falcon_mask(falcon, 0x048, 0x00000001, 0x00000001); + + switch (nvkm_memory_target(fw->inst)) { +@@ -285,15 +287,6 @@ gm200_flcn_fw_load(struct nvkm_falcon_fw *fw) + } + + if (fw->boot) { +- switch (nvkm_memory_target(&fw->fw.mem.memory)) { +- case NVKM_MEM_TARGET_VRAM: target = 4; break; +- case NVKM_MEM_TARGET_HOST: target = 5; break; +- case NVKM_MEM_TARGET_NCOH: target = 6; break; +- default: +- WARN_ON(1); +- return -EINVAL; +- } +- + ret = nvkm_falcon_pio_wr(falcon, fw->boot, 0, 0, + IMEM, falcon->code.limit - fw->boot_size, fw->boot_size, + fw->boot_addr >> 8, false); +-- +2.50.1 + diff --git a/queue-6.12/drm-xe-don-t-trigger-rebind-on-initial-dma-buf-valid.patch b/queue-6.12/drm-xe-don-t-trigger-rebind-on-initial-dma-buf-valid.patch new file mode 100644 index 0000000000..37f05d08a1 --- /dev/null +++ b/queue-6.12/drm-xe-don-t-trigger-rebind-on-initial-dma-buf-valid.patch @@ -0,0 +1,48 @@ +From 60f50f33cd54966008a221b09a9f682a0127dcff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 08:28:41 -0700 +Subject: drm/xe: Don't trigger rebind on initial dma-buf validation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Matthew Brost + +[ Upstream commit 16ca06aa2c2218cb21907c0c45a746958c944def ] + +On the first validate of an imported dma-buf (initial bind), the device +has no GPU mappings, so a rebind is unnecessary. Rebinding here is +harmful in multi-GPU setups and for VMs using preempt-fence mode, as it +would evict in-flight GPU work. + +v2: + - Drop dma_buf_validated, check for XE_PL_SYSTEM (Thomas) + +Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs") +Signed-off-by: Matthew Brost +Reviewed-by: Thomas Hellström +Link: https://lore.kernel.org/r/20250825152841.3837378-1-matthew.brost@intel.com +(cherry picked from commit ffdf968762e4fb3cdae54e811ec3525e67440a60) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_bo.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c +index 5f745d9ed6cc2..445bbe0299b08 100644 +--- a/drivers/gpu/drm/xe/xe_bo.c ++++ b/drivers/gpu/drm/xe/xe_bo.c +@@ -671,7 +671,8 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict, + } + + if (ttm_bo->type == ttm_bo_type_sg) { +- ret = xe_bo_move_notify(bo, ctx); ++ if (new_mem->mem_type == XE_PL_SYSTEM) ++ ret = xe_bo_move_notify(bo, ctx); + if (!ret) + ret = xe_bo_move_dmabuf(ttm_bo, new_mem); + return ret; +-- +2.50.1 + diff --git a/queue-6.12/drm-xe-xe_sync-avoid-race-during-ufence-signaling.patch b/queue-6.12/drm-xe-xe_sync-avoid-race-during-ufence-signaling.patch new file mode 100644 index 0000000000..05f60b1d8a --- /dev/null +++ b/queue-6.12/drm-xe-xe_sync-avoid-race-during-ufence-signaling.patch @@ -0,0 +1,56 @@ +From b324dc7789028df9286c46bfd4fc6fda30707fe7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Aug 2025 10:39:04 +0200 +Subject: drm/xe/xe_sync: avoid race during ufence signaling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Zbigniew Kempczyński + +[ Upstream commit 04e1f683cd28dc9407b238543871a6e09a570dc0 ] + +Marking ufence as signalled after copy_to_user() is too late. +Worker thread which signals ufence by memory write might be raced +with another userspace vm-bind call. In map/unmap scenario unmap +may still see ufence is not signalled causing -EBUSY. Change the +order of marking / write to user-fence fixes this issue. + +Fixes: 977e5b82e090 ("drm/xe: Expose user fence from xe_sync_entry") +Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/5536 +Signed-off-by: Zbigniew Kempczyński +Cc: Matthew Brost +Cc: Matthew Auld +Reviewed-by: Matthew Brost +Signed-off-by: Matthew Brost +Link: https://lore.kernel.org/r/20250820083903.2109891-2-zbigniew.kempczynski@intel.com +(cherry picked from commit 8ae04fe9ffc93d6bc3bc63ac08375427d69cee06) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_sync.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_sync.c b/drivers/gpu/drm/xe/xe_sync.c +index b0684e6d2047b..dd7bd766ae184 100644 +--- a/drivers/gpu/drm/xe/xe_sync.c ++++ b/drivers/gpu/drm/xe/xe_sync.c +@@ -77,6 +77,7 @@ static void user_fence_worker(struct work_struct *w) + { + struct xe_user_fence *ufence = container_of(w, struct xe_user_fence, worker); + ++ WRITE_ONCE(ufence->signalled, 1); + if (mmget_not_zero(ufence->mm)) { + kthread_use_mm(ufence->mm); + if (copy_to_user(ufence->addr, &ufence->value, sizeof(ufence->value))) +@@ -89,7 +90,6 @@ static void user_fence_worker(struct work_struct *w) + * Wake up waiters only after updating the ufence state, allowing the UMD + * to safely reuse the same ufence without encountering -EBUSY errors. + */ +- WRITE_ONCE(ufence->signalled, 1); + wake_up_all(&ufence->xe->ufence_wq); + user_fence_put(ufence); + } +-- +2.50.1 + diff --git a/queue-6.12/dt-bindings-display-msm-qcom-mdp5-drop-lut-clock.patch b/queue-6.12/dt-bindings-display-msm-qcom-mdp5-drop-lut-clock.patch new file mode 100644 index 0000000000..10fbf71f2d --- /dev/null +++ b/queue-6.12/dt-bindings-display-msm-qcom-mdp5-drop-lut-clock.patch @@ -0,0 +1,39 @@ +From 3c58e54ef9ec24d58a23ea32aa2373306d37a0e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 9 Aug 2025 11:36:54 +0300 +Subject: dt-bindings: display/msm: qcom,mdp5: drop lut clock + +From: Dmitry Baryshkov + +[ Upstream commit 7ab3b7579a6d2660a3425b9ea93b9a140b07f49c ] + +None of MDP5 platforms have a LUT clock on the display-controller, it +was added by the mistake. Drop it, fixing DT warnings on MSM8976 / +MSM8956 platforms. Technically it's an ABI break, but no other platforms +are affected. + +Fixes: 385c8ac763b3 ("dt-bindings: display/msm: convert MDP5 schema to YAML format") +Signed-off-by: Dmitry Baryshkov +Acked-by: Rob Herring (Arm) +Patchwork: https://patchwork.freedesktop.org/patch/667822/ +Signed-off-by: Rob Clark +Signed-off-by: Sasha Levin +--- + Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml b/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml +index e153f8d26e7aa..2735c78b0b67a 100644 +--- a/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml ++++ b/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml +@@ -60,7 +60,6 @@ properties: + - const: bus + - const: core + - const: vsync +- - const: lut + - const: tbu + - const: tbu_rt + # MSM8996 has additional iommu clock +-- +2.50.1 + diff --git a/queue-6.12/efi-stmm-fix-incorrect-buffer-allocation-method.patch b/queue-6.12/efi-stmm-fix-incorrect-buffer-allocation-method.patch new file mode 100644 index 0000000000..0db518858f --- /dev/null +++ b/queue-6.12/efi-stmm-fix-incorrect-buffer-allocation-method.patch @@ -0,0 +1,111 @@ +From 1329715063cc21aa07b52f39911d96b406c76254 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 18:07:10 +0200 +Subject: efi: stmm: Fix incorrect buffer allocation method + +From: Jan Kiszka + +[ Upstream commit c5e81e672699e0c5557b2b755cc8f7a69aa92bff ] + +The communication buffer allocated by setup_mm_hdr() is later on passed +to tee_shm_register_kernel_buf(). The latter expects those buffers to be +contiguous pages, but setup_mm_hdr() just uses kmalloc(). That can cause +various corruptions or BUGs, specifically since commit 9aec2fb0fd5e +("slab: allocate frozen pages"), though it was broken before as well. + +Fix this by using alloc_pages_exact() instead of kmalloc(). + +Fixes: c44b6be62e8d ("efi: Add tee-based EFI variable driver") +Signed-off-by: Jan Kiszka +Acked-by: Ilias Apalodimas +Acked-by: Sumit Garg +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + drivers/firmware/efi/stmm/tee_stmm_efi.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/drivers/firmware/efi/stmm/tee_stmm_efi.c b/drivers/firmware/efi/stmm/tee_stmm_efi.c +index f741ca279052b..e15d11ed165ee 100644 +--- a/drivers/firmware/efi/stmm/tee_stmm_efi.c ++++ b/drivers/firmware/efi/stmm/tee_stmm_efi.c +@@ -143,6 +143,10 @@ static efi_status_t mm_communicate(u8 *comm_buf, size_t payload_size) + return var_hdr->ret_status; + } + ++#define COMM_BUF_SIZE(__payload_size) (MM_COMMUNICATE_HEADER_SIZE + \ ++ MM_VARIABLE_COMMUNICATE_SIZE + \ ++ (__payload_size)) ++ + /** + * setup_mm_hdr() - Allocate a buffer for StandAloneMM and initialize the + * header data. +@@ -173,9 +177,8 @@ static void *setup_mm_hdr(u8 **dptr, size_t payload_size, size_t func, + return NULL; + } + +- comm_buf = kzalloc(MM_COMMUNICATE_HEADER_SIZE + +- MM_VARIABLE_COMMUNICATE_SIZE + payload_size, +- GFP_KERNEL); ++ comm_buf = alloc_pages_exact(COMM_BUF_SIZE(payload_size), ++ GFP_KERNEL | __GFP_ZERO); + if (!comm_buf) { + *ret = EFI_OUT_OF_RESOURCES; + return NULL; +@@ -239,7 +242,7 @@ static efi_status_t get_max_payload(size_t *size) + */ + *size -= 2; + out: +- kfree(comm_buf); ++ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); + return ret; + } + +@@ -282,7 +285,7 @@ static efi_status_t get_property_int(u16 *name, size_t name_size, + memcpy(var_property, &smm_property->property, sizeof(*var_property)); + + out: +- kfree(comm_buf); ++ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); + return ret; + } + +@@ -347,7 +350,7 @@ static efi_status_t tee_get_variable(u16 *name, efi_guid_t *vendor, + memcpy(data, (u8 *)var_acc->name + var_acc->name_size, + var_acc->data_size); + out: +- kfree(comm_buf); ++ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); + return ret; + } + +@@ -404,7 +407,7 @@ static efi_status_t tee_get_next_variable(unsigned long *name_size, + memcpy(name, var_getnext->name, var_getnext->name_size); + + out: +- kfree(comm_buf); ++ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); + return ret; + } + +@@ -467,7 +470,7 @@ static efi_status_t tee_set_variable(efi_char16_t *name, efi_guid_t *vendor, + ret = mm_communicate(comm_buf, payload_size); + dev_dbg(pvt_data.dev, "Set Variable %s %d %lx\n", __FILE__, __LINE__, ret); + out: +- kfree(comm_buf); ++ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); + return ret; + } + +@@ -507,7 +510,7 @@ static efi_status_t tee_query_variable_info(u32 attributes, + *max_variable_size = mm_query_info->max_variable_size; + + out: +- kfree(comm_buf); ++ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); + return ret; + } + +-- +2.50.1 + diff --git a/queue-6.12/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch b/queue-6.12/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch new file mode 100644 index 0000000000..6a819f9d4b --- /dev/null +++ b/queue-6.12/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch @@ -0,0 +1,77 @@ +From 3ac5c874579749a79dd928cbafa4115d9757d66a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 15:39:54 +0800 +Subject: efivarfs: Fix slab-out-of-bounds in efivarfs_d_compare + +From: Li Nan + +[ Upstream commit a6358f8cf64850f3f27857b8ed8c1b08cfc4685c ] + +Observed on kernel 6.6 (present on master as well): + + BUG: KASAN: slab-out-of-bounds in memcmp+0x98/0xd0 + Call trace: + kasan_check_range+0xe8/0x190 + __asan_loadN+0x1c/0x28 + memcmp+0x98/0xd0 + efivarfs_d_compare+0x68/0xd8 + __d_lookup_rcu_op_compare+0x178/0x218 + __d_lookup_rcu+0x1f8/0x228 + d_alloc_parallel+0x150/0x648 + lookup_open.isra.0+0x5f0/0x8d0 + open_last_lookups+0x264/0x828 + path_openat+0x130/0x3f8 + do_filp_open+0x114/0x248 + do_sys_openat2+0x340/0x3c0 + __arm64_sys_openat+0x120/0x1a0 + +If dentry->d_name.len < EFI_VARIABLE_GUID_LEN , 'guid' can become +negative, leadings to oob. The issue can be triggered by parallel +lookups using invalid filename: + + T1 T2 + lookup_open + ->lookup + simple_lookup + d_add + // invalid dentry is added to hash list + + lookup_open + d_alloc_parallel + __d_lookup_rcu + __d_lookup_rcu_op_compare + hlist_bl_for_each_entry_rcu + // invalid dentry can be retrieved + ->d_compare + efivarfs_d_compare + // oob + +Fix it by checking 'guid' before cmp. + +Fixes: da27a24383b2 ("efivarfs: guid part of filenames are case-insensitive") +Signed-off-by: Li Nan +Signed-off-by: Wu Guanghao +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + fs/efivarfs/super.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c +index 11ebddc57bc73..1831e015b2f26 100644 +--- a/fs/efivarfs/super.c ++++ b/fs/efivarfs/super.c +@@ -127,6 +127,10 @@ static int efivarfs_d_compare(const struct dentry *dentry, + { + int guid = len - EFI_VARIABLE_GUID_LEN; + ++ /* Parallel lookups may produce a temporary invalid filename */ ++ if (guid <= 0) ++ return 1; ++ + if (name->len != len) + return 1; + +-- +2.50.1 + diff --git a/queue-6.12/fbnic-move-phylink-resume-out-of-service_task-and-in.patch b/queue-6.12/fbnic-move-phylink-resume-out-of-service_task-and-in.patch new file mode 100644 index 0000000000..ddd9785db9 --- /dev/null +++ b/queue-6.12/fbnic-move-phylink-resume-out-of-service_task-and-in.patch @@ -0,0 +1,120 @@ +From 0ab0a25913e4111285f05def02dcd646101a15c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 15:56:13 -0700 +Subject: fbnic: Move phylink resume out of service_task and into open/close + +From: Alexander Duyck + +[ Upstream commit 6ede14a2c6365e7e5d855643c7c8390b5268c467 ] + +The fbnic driver was presenting with the following locking assert coming +out of a PM resume: +[ 42.208116][ T164] RTNL: assertion failed at drivers/net/phy/phylink.c (2611) +[ 42.208492][ T164] WARNING: CPU: 1 PID: 164 at drivers/net/phy/phylink.c:2611 phylink_resume+0x190/0x1e0 +[ 42.208872][ T164] Modules linked in: +[ 42.209140][ T164] CPU: 1 UID: 0 PID: 164 Comm: bash Not tainted 6.17.0-rc2-virtme #134 PREEMPT(full) +[ 42.209496][ T164] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.17.0-5.fc42 04/01/2014 +[ 42.209861][ T164] RIP: 0010:phylink_resume+0x190/0x1e0 +[ 42.210057][ T164] Code: 83 e5 01 0f 85 b0 fe ff ff c6 05 1c cd 3e 02 01 90 ba 33 0a 00 00 48 c7 c6 20 3a 1d a5 48 c7 c7 e0 3e 1d a5 e8 21 b8 90 fe 90 <0f> 0b 90 90 e9 86 fe ff ff e8 42 ea 1f ff e9 e2 fe ff ff 48 89 ef +[ 42.210708][ T164] RSP: 0018:ffffc90000affbd8 EFLAGS: 00010296 +[ 42.210983][ T164] RAX: 0000000000000000 RBX: ffff8880078d8400 RCX: 0000000000000000 +[ 42.211235][ T164] RDX: 0000000000000000 RSI: 1ffffffff4f10938 RDI: 0000000000000001 +[ 42.211466][ T164] RBP: 0000000000000000 R08: ffffffffa2ae79ea R09: fffffbfff4b3eb84 +[ 42.211707][ T164] R10: 0000000000000003 R11: 0000000000000000 R12: ffff888007ad8000 +[ 42.211997][ T164] R13: 0000000000000002 R14: ffff888006a18800 R15: ffffffffa34c59e0 +[ 42.212234][ T164] FS: 00007f0dc8e39740(0000) GS:ffff88808f51f000(0000) knlGS:0000000000000000 +[ 42.212505][ T164] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 42.212704][ T164] CR2: 00007f0dc8e9fe10 CR3: 000000000b56d003 CR4: 0000000000772ef0 +[ 42.213227][ T164] PKRU: 55555554 +[ 42.213366][ T164] Call Trace: +[ 42.213483][ T164] +[ 42.213565][ T164] __fbnic_pm_attach.isra.0+0x8e/0xa0 +[ 42.213725][ T164] pci_reset_function+0x116/0x1d0 +[ 42.213895][ T164] reset_store+0xa0/0x100 +[ 42.214025][ T164] ? pci_dev_reset_attr_is_visible+0x50/0x50 +[ 42.214221][ T164] ? sysfs_file_kobj+0xc1/0x1e0 +[ 42.214374][ T164] ? sysfs_kf_write+0x65/0x160 +[ 42.214526][ T164] kernfs_fop_write_iter+0x2f8/0x4c0 +[ 42.214677][ T164] ? kernfs_vma_page_mkwrite+0x1f0/0x1f0 +[ 42.214836][ T164] new_sync_write+0x308/0x6f0 +[ 42.214987][ T164] ? __lock_acquire+0x34c/0x740 +[ 42.215135][ T164] ? new_sync_read+0x6f0/0x6f0 +[ 42.215288][ T164] ? lock_acquire.part.0+0xbc/0x260 +[ 42.215440][ T164] ? ksys_write+0xff/0x200 +[ 42.215590][ T164] ? perf_trace_sched_switch+0x6d0/0x6d0 +[ 42.215742][ T164] vfs_write+0x65e/0xbb0 +[ 42.215876][ T164] ksys_write+0xff/0x200 +[ 42.215994][ T164] ? __ia32_sys_read+0xc0/0xc0 +[ 42.216141][ T164] ? do_user_addr_fault+0x269/0x9f0 +[ 42.216292][ T164] ? rcu_is_watching+0x15/0xd0 +[ 42.216442][ T164] do_syscall_64+0xbb/0x360 +[ 42.216591][ T164] entry_SYSCALL_64_after_hwframe+0x4b/0x53 +[ 42.216784][ T164] RIP: 0033:0x7f0dc8ea9986 + +A bit of digging showed that we were invoking the phylink_resume as a part +of the fbnic_up path when we were enabling the service task while not +holding the RTNL lock. We should be enabling this sooner as a part of the +ndo_open path and then just letting the service task come online later. +This will help to enforce the correct locking and brings the phylink +interface online at the same time as the network interface, instead of at a +later time. + +I tested this on QEMU to verify this was working by putting the system to +sleep using "echo mem > /sys/power/state" to put the system to sleep in the +guest and then using the command "system_wakeup" in the QEMU monitor. + +Fixes: 69684376eed5 ("eth: fbnic: Add link detection") +Signed-off-by: Alexander Duyck +Reviewed-by: Przemek Kitszel +Link: https://patch.msgid.link/175616257316.1963577.12238158800417771119.stgit@ahduyck-xeon-server.home.arpa +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/meta/fbnic/fbnic_netdev.c | 4 ++++ + drivers/net/ethernet/meta/fbnic/fbnic_pci.c | 2 -- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +index 79e94632533c8..a8c95b1732f4d 100644 +--- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c ++++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +@@ -53,6 +53,8 @@ int __fbnic_open(struct fbnic_net *fbn) + fbnic_bmc_rpc_init(fbd); + fbnic_rss_reinit(fbd, fbn); + ++ phylink_resume(fbn->phylink); ++ + return 0; + release_ownership: + fbnic_fw_xmit_ownership_msg(fbn->fbd, false); +@@ -79,6 +81,8 @@ static int fbnic_stop(struct net_device *netdev) + { + struct fbnic_net *fbn = netdev_priv(netdev); + ++ phylink_suspend(fbn->phylink, fbnic_bmc_present(fbn->fbd)); ++ + fbnic_down(fbn); + fbnic_pcs_irq_disable(fbn->fbd); + +diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c +index 268489b15616f..72bdc6c76c0c5 100644 +--- a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c ++++ b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c +@@ -116,14 +116,12 @@ static void fbnic_service_task_start(struct fbnic_net *fbn) + struct fbnic_dev *fbd = fbn->fbd; + + schedule_delayed_work(&fbd->service_task, HZ); +- phylink_resume(fbn->phylink); + } + + static void fbnic_service_task_stop(struct fbnic_net *fbn) + { + struct fbnic_dev *fbd = fbn->fbd; + +- phylink_suspend(fbn->phylink, fbnic_bmc_present(fbd)); + cancel_delayed_work(&fbd->service_task); + } + +-- +2.50.1 + diff --git a/queue-6.12/hid-input-rename-hidinput_set_battery_charge_status.patch b/queue-6.12/hid-input-rename-hidinput_set_battery_charge_status.patch new file mode 100644 index 0000000000..666950d387 --- /dev/null +++ b/queue-6.12/hid-input-rename-hidinput_set_battery_charge_status.patch @@ -0,0 +1,147 @@ +From 6ed7183eeaccdf5f881b37501585d73357b3fe81 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Aug 2025 12:39:39 +0200 +Subject: HID: input: rename hidinput_set_battery_charge_status() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit a82231b2a8712d0218fc286a9b0da328d419a3f4 ] + +In preparation for a patch fixing a bug affecting +hidinput_set_battery_charge_status(), rename the function to +hidinput_update_battery_charge_status() and move it up so it can be used +by hidinput_update_battery(). + +Refactor, no functional changes. + +Tested-by: 卢国宏 +Signed-off-by: José Expósito +Signed-off-by: Jiri Kosina +Stable-dep-of: e94536e1d181 ("HID: input: report battery status changes immediately") +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-input-test.c | 10 +++++----- + drivers/hid/hid-input.c | 38 ++++++++++++++++++------------------ + 2 files changed, 24 insertions(+), 24 deletions(-) + +diff --git a/drivers/hid/hid-input-test.c b/drivers/hid/hid-input-test.c +index 77c2d45ac62a7..6f5c71660d823 100644 +--- a/drivers/hid/hid-input-test.c ++++ b/drivers/hid/hid-input-test.c +@@ -7,7 +7,7 @@ + + #include + +-static void hid_test_input_set_battery_charge_status(struct kunit *test) ++static void hid_test_input_update_battery_charge_status(struct kunit *test) + { + struct hid_device *dev; + bool handled; +@@ -15,15 +15,15 @@ static void hid_test_input_set_battery_charge_status(struct kunit *test) + dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + +- handled = hidinput_set_battery_charge_status(dev, HID_DG_HEIGHT, 0); ++ handled = hidinput_update_battery_charge_status(dev, HID_DG_HEIGHT, 0); + KUNIT_EXPECT_FALSE(test, handled); + KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_UNKNOWN); + +- handled = hidinput_set_battery_charge_status(dev, HID_BAT_CHARGING, 0); ++ handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 0); + KUNIT_EXPECT_TRUE(test, handled); + KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_DISCHARGING); + +- handled = hidinput_set_battery_charge_status(dev, HID_BAT_CHARGING, 1); ++ handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 1); + KUNIT_EXPECT_TRUE(test, handled); + KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_CHARGING); + } +@@ -63,7 +63,7 @@ static void hid_test_input_get_battery_property(struct kunit *test) + } + + static struct kunit_case hid_input_tests[] = { +- KUNIT_CASE(hid_test_input_set_battery_charge_status), ++ KUNIT_CASE(hid_test_input_update_battery_charge_status), + KUNIT_CASE(hid_test_input_get_battery_property), + { } + }; +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 9d80635a91ebd..b372b74f3e24b 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -595,6 +595,20 @@ static void hidinput_cleanup_battery(struct hid_device *dev) + dev->battery = NULL; + } + ++static bool hidinput_update_battery_charge_status(struct hid_device *dev, ++ unsigned int usage, int value) ++{ ++ switch (usage) { ++ case HID_BAT_CHARGING: ++ dev->battery_charge_status = value ? ++ POWER_SUPPLY_STATUS_CHARGING : ++ POWER_SUPPLY_STATUS_DISCHARGING; ++ return true; ++ } ++ ++ return false; ++} ++ + static void hidinput_update_battery(struct hid_device *dev, int value) + { + int capacity; +@@ -617,20 +631,6 @@ static void hidinput_update_battery(struct hid_device *dev, int value) + power_supply_changed(dev->battery); + } + } +- +-static bool hidinput_set_battery_charge_status(struct hid_device *dev, +- unsigned int usage, int value) +-{ +- switch (usage) { +- case HID_BAT_CHARGING: +- dev->battery_charge_status = value ? +- POWER_SUPPLY_STATUS_CHARGING : +- POWER_SUPPLY_STATUS_DISCHARGING; +- return true; +- } +- +- return false; +-} + #else /* !CONFIG_HID_BATTERY_STRENGTH */ + static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, + struct hid_field *field, bool is_percentage) +@@ -642,14 +642,14 @@ static void hidinput_cleanup_battery(struct hid_device *dev) + { + } + +-static void hidinput_update_battery(struct hid_device *dev, int value) ++static bool hidinput_update_battery_charge_status(struct hid_device *dev, ++ unsigned int usage, int value) + { ++ return false; + } + +-static bool hidinput_set_battery_charge_status(struct hid_device *dev, +- unsigned int usage, int value) ++static void hidinput_update_battery(struct hid_device *dev, int value) + { +- return false; + } + #endif /* CONFIG_HID_BATTERY_STRENGTH */ + +@@ -1515,7 +1515,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct + return; + + if (usage->type == EV_PWR) { +- bool handled = hidinput_set_battery_charge_status(hid, usage->hid, value); ++ bool handled = hidinput_update_battery_charge_status(hid, usage->hid, value); + + if (!handled) + hidinput_update_battery(hid, value); +-- +2.50.1 + diff --git a/queue-6.12/hid-input-report-battery-status-changes-immediately.patch b/queue-6.12/hid-input-report-battery-status-changes-immediately.patch new file mode 100644 index 0000000000..12ef707465 --- /dev/null +++ b/queue-6.12/hid-input-report-battery-status-changes-immediately.patch @@ -0,0 +1,97 @@ +From 83093093b438e989a01804dd51939eca14ee3f84 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Aug 2025 12:39:40 +0200 +Subject: HID: input: report battery status changes immediately +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit e94536e1d1818b0989aa19b443b7089f50133c35 ] + +Previously, the battery status (charging/discharging) was not reported +immediately to user-space.  + +For most input devices, this wasn't problematic because changing their +battery status requires connecting them to a different bus. +For example, a gamepad would report a discharging status while +connected via Bluetooth and a charging status while connected via USB. + +However, certain devices are not connected or disconnected when their +battery status changes. For example, a phone battery changes its status +without connecting or disconnecting it. +In these cases, the battery status was not reported immediately to user +space. + +Report battery status changes immediately to user space to support +these kinds of devices. + +Fixes: a608dc1c0639 ("HID: input: map battery system charging") +Reported-by: 卢国宏 +Closes: https://lore.kernel.org/linux-input/aI49Im0sGb6fpgc8@fedora/T/ +Tested-by: 卢国宏 +Signed-off-by: José Expósito +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-input.c | 23 ++++++++++------------- + 1 file changed, 10 insertions(+), 13 deletions(-) + +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index b372b74f3e24b..f5c217ac4bfaa 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -609,13 +609,19 @@ static bool hidinput_update_battery_charge_status(struct hid_device *dev, + return false; + } + +-static void hidinput_update_battery(struct hid_device *dev, int value) ++static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, ++ int value) + { + int capacity; + + if (!dev->battery) + return; + ++ if (hidinput_update_battery_charge_status(dev, usage, value)) { ++ power_supply_changed(dev->battery); ++ return; ++ } ++ + if (value == 0 || value < dev->battery_min || value > dev->battery_max) + return; + +@@ -642,13 +648,8 @@ static void hidinput_cleanup_battery(struct hid_device *dev) + { + } + +-static bool hidinput_update_battery_charge_status(struct hid_device *dev, +- unsigned int usage, int value) +-{ +- return false; +-} +- +-static void hidinput_update_battery(struct hid_device *dev, int value) ++static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, ++ int value) + { + } + #endif /* CONFIG_HID_BATTERY_STRENGTH */ +@@ -1515,11 +1516,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct + return; + + if (usage->type == EV_PWR) { +- bool handled = hidinput_update_battery_charge_status(hid, usage->hid, value); +- +- if (!handled) +- hidinput_update_battery(hid, value); +- ++ hidinput_update_battery(hid, usage->hid, value); + return; + } + +-- +2.50.1 + diff --git a/queue-6.12/hv_netvsc-link-queues-to-napis.patch b/queue-6.12/hv_netvsc-link-queues-to-napis.patch new file mode 100644 index 0000000000..e56fe96afc --- /dev/null +++ b/queue-6.12/hv_netvsc-link-queues-to-napis.patch @@ -0,0 +1,110 @@ +From 47b18549e5d8bd0cf953155c44834f4bfc3e496d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 30 Sep 2024 17:27:09 +0000 +Subject: hv_netvsc: Link queues to NAPIs + +From: Joe Damato + +[ Upstream commit 8b641b5e4c782464c8818a71b443eeef8984bf34 ] + +Use netif_queue_set_napi to link queues to NAPI instances so that they +can be queried with netlink. + +Shradha Gupta tested the patch and reported that the results are +as expected: + +$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml \ + --dump queue-get --json='{"ifindex": 2}' + + [{'id': 0, 'ifindex': 2, 'napi-id': 8193, 'type': 'rx'}, + {'id': 1, 'ifindex': 2, 'napi-id': 8194, 'type': 'rx'}, + {'id': 2, 'ifindex': 2, 'napi-id': 8195, 'type': 'rx'}, + {'id': 3, 'ifindex': 2, 'napi-id': 8196, 'type': 'rx'}, + {'id': 4, 'ifindex': 2, 'napi-id': 8197, 'type': 'rx'}, + {'id': 5, 'ifindex': 2, 'napi-id': 8198, 'type': 'rx'}, + {'id': 6, 'ifindex': 2, 'napi-id': 8199, 'type': 'rx'}, + {'id': 7, 'ifindex': 2, 'napi-id': 8200, 'type': 'rx'}, + {'id': 0, 'ifindex': 2, 'napi-id': 8193, 'type': 'tx'}, + {'id': 1, 'ifindex': 2, 'napi-id': 8194, 'type': 'tx'}, + {'id': 2, 'ifindex': 2, 'napi-id': 8195, 'type': 'tx'}, + {'id': 3, 'ifindex': 2, 'napi-id': 8196, 'type': 'tx'}, + {'id': 4, 'ifindex': 2, 'napi-id': 8197, 'type': 'tx'}, + {'id': 5, 'ifindex': 2, 'napi-id': 8198, 'type': 'tx'}, + {'id': 6, 'ifindex': 2, 'napi-id': 8199, 'type': 'tx'}, + {'id': 7, 'ifindex': 2, 'napi-id': 8200, 'type': 'tx'}] + +Signed-off-by: Joe Damato +Reviewed-by: Haiyang Zhang +Tested-by: Shradha Gupta +Signed-off-by: David S. Miller +Stable-dep-of: 9448ccd85336 ("net: hv_netvsc: fix loss of early receive events from host during channel open.") +Signed-off-by: Sasha Levin +--- + drivers/net/hyperv/netvsc.c | 13 ++++++++++++- + drivers/net/hyperv/rndis_filter.c | 9 +++++++-- + 2 files changed, 19 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +index 807465dd4c8e3..87ac2a5f18091 100644 +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -712,8 +712,13 @@ void netvsc_device_remove(struct hv_device *device) + for (i = 0; i < net_device->num_chn; i++) { + /* See also vmbus_reset_channel_cb(). */ + /* only disable enabled NAPI channel */ +- if (i < ndev->real_num_rx_queues) ++ if (i < ndev->real_num_rx_queues) { ++ netif_queue_set_napi(ndev, i, NETDEV_QUEUE_TYPE_TX, ++ NULL); ++ netif_queue_set_napi(ndev, i, NETDEV_QUEUE_TYPE_RX, ++ NULL); + napi_disable(&net_device->chan_table[i].napi); ++ } + + netif_napi_del(&net_device->chan_table[i].napi); + } +@@ -1826,6 +1831,10 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, + netdev_dbg(ndev, "hv_netvsc channel opened successfully\n"); + + napi_enable(&net_device->chan_table[0].napi); ++ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, ++ &net_device->chan_table[0].napi); ++ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, ++ &net_device->chan_table[0].napi); + + /* Connect with the NetVsp */ + ret = netvsc_connect_vsp(device, net_device, device_info); +@@ -1844,6 +1853,8 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, + + close: + RCU_INIT_POINTER(net_device_ctx->nvdev, NULL); ++ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, NULL); ++ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, NULL); + napi_disable(&net_device->chan_table[0].napi); + + /* Now, we can close the channel safely */ +diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c +index e457f809fe311..9b8769a8b77a1 100644 +--- a/drivers/net/hyperv/rndis_filter.c ++++ b/drivers/net/hyperv/rndis_filter.c +@@ -1255,10 +1255,15 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc) + ret = vmbus_open(new_sc, netvsc_ring_bytes, + netvsc_ring_bytes, NULL, 0, + netvsc_channel_cb, nvchan); +- if (ret == 0) ++ if (ret == 0) { + napi_enable(&nvchan->napi); +- else ++ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_RX, ++ &nvchan->napi); ++ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_TX, ++ &nvchan->napi); ++ } else { + netdev_notice(ndev, "sub channel open failed: %d\n", ret); ++ } + + if (atomic_inc_return(&nvscdev->open_chn) == nvscdev->num_chn) + wake_up(&nvscdev->subchan_open); +-- +2.50.1 + diff --git a/queue-6.12/ice-don-t-leave-device-non-functional-if-tx-schedule.patch b/queue-6.12/ice-don-t-leave-device-non-functional-if-tx-schedule.patch new file mode 100644 index 0000000000..8256177cdb --- /dev/null +++ b/queue-6.12/ice-don-t-leave-device-non-functional-if-tx-schedule.patch @@ -0,0 +1,238 @@ +From 13b10e4ac93c7b81a58b661ff2004d05ab52d197 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Jul 2025 09:57:09 -0700 +Subject: ice: don't leave device non-functional if Tx scheduler config fails + +From: Jacob Keller + +[ Upstream commit 86aae43f21cf784c1d7f6a9af93e5116b0f232ab ] + +The ice_cfg_tx_topo function attempts to apply Tx scheduler topology +configuration based on NVM parameters, selecting either a 5 or 9 layer +topology. + +As part of this flow, the driver acquires the "Global Configuration Lock", +which is a hardware resource associated with programming the DDP package +to the device. This "lock" is implemented by firmware as a way to +guarantee that only one PF can program the DDP for a device. Unlike a +traditional lock, once a PF has acquired this lock, no other PF will be +able to acquire it again (including that PF) until a CORER of the device. +Future requests to acquire the lock report that global configuration has +already completed. + +The following flow is used to program the Tx topology: + + * Read the DDP package for scheduler configuration data + * Acquire the global configuration lock + * Program Tx scheduler topology according to DDP package data + * Trigger a CORER which clears the global configuration lock + +This is followed by the flow for programming the DDP package: + + * Acquire the global configuration lock (again) + * Download the DDP package to the device + * Release the global configuration lock. + +However, if configuration of the Tx topology fails, (i.e. +ice_get_set_tx_topo returns an error code), the driver exits +ice_cfg_tx_topo() immediately, and fails to trigger CORER. + +While the global configuration lock is held, the firmware rejects most +AdminQ commands, as it is waiting for the DDP package download (or Tx +scheduler topology programming) to occur. + +The current driver flows assume that the global configuration lock has been +reset by CORER after programming the Tx topology. Thus, the same PF +attempts to acquire the global lock again, and fails. This results in the +driver reporting "an unknown error occurred when loading the DDP package". +It then attempts to enter safe mode, but ultimately fails to finish +ice_probe() since nearly all AdminQ command report error codes, and the +driver stops loading the device at some point during its initialization. + +The only currently known way that ice_get_set_tx_topo() can fail is with +certain older DDP packages which contain invalid topology configuration, on +firmware versions which strictly validate this data. The most recent +releases of the DDP have resolved the invalid data. However, it is still +poor practice to essentially brick the device, and prevent access to the +device even through safe mode or recovery mode. It is also plausible that +this command could fail for some other reason in the future. + +We cannot simply release the global lock after a failed call to +ice_get_set_tx_topo(). Releasing the lock indicates to firmware that global +configuration (downloading of the DDP) has completed. Future attempts by +this or other PFs to load the DDP will fail with a report that the DDP +package has already been downloaded. Then, PFs will enter safe mode as they +realize that the package on the device does not meet the minimum version +requirement to load. The reported error messages are confusing, as they +indicate the version of the default "safe mode" package in the NVM, rather +than the version of the file loaded from /lib/firmware. + +Instead, we need to trigger CORER to clear global configuration. This is +the lowest level of hardware reset which clears the global configuration +lock and related state. It also clears any already downloaded DDP. +Crucially, it does *not* clear the Tx scheduler topology configuration. + +Refactor ice_cfg_tx_topo() to always trigger a CORER after acquiring the +global lock, regardless of success or failure of the topology +configuration. + +We need to re-initialize the HW structure when we trigger the CORER. Thus, +it makes sense for this to be the responsibility of ice_cfg_tx_topo() +rather than its caller, ice_init_tx_topology(). This avoids needless +re-initialization in cases where we don't attempt to update the Tx +scheduler topology, such as if it has already been programmed. + +There is one catch: failure to re-initialize the HW struct should stop +ice_probe(). If this function fails, we won't have a valid HW structure and +cannot ensure the device is functioning properly. To handle this, ensure +ice_cfg_tx_topo() returns a limited set of error codes. Set aside one +specifically, -ENODEV, to indicate that the ice_init_tx_topology() should +fail and stop probe. + +Other error codes indicate failure to apply the Tx scheduler topology. This +is treated as a non-fatal error, with an informational message informing +the system administrator that the updated Tx topology did not apply. This +allows the device to load and function with the default Tx scheduler +topology, rather than failing to load entirely. + +Note that this use of CORER will not result in loops with future PFs +attempting to also load the invalid Tx topology configuration. The first PF +will acquire the global configuration lock as part of programming the DDP. +Each PF after this will attempt to acquire the global lock as part of +programming the Tx topology, and will fail with the indication from +firmware that global configuration is already complete. Tx scheduler +topology configuration is only performed during driver init (probe or +devlink reload) and not during cleanup for a CORER that happens after probe +completes. + +Fixes: 91427e6d9030 ("ice: Support 5 layer topology") +Signed-off-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_ddp.c | 44 ++++++++++++++++------- + drivers/net/ethernet/intel/ice/ice_main.c | 16 ++++++--- + 2 files changed, 43 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ddp.c b/drivers/net/ethernet/intel/ice/ice_ddp.c +index e4c8cd12a41d1..04bec5d8e7084 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ddp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ddp.c +@@ -2352,7 +2352,13 @@ ice_get_set_tx_topo(struct ice_hw *hw, u8 *buf, u16 buf_size, + * The function will apply the new Tx topology from the package buffer + * if available. + * +- * Return: zero when update was successful, negative values otherwise. ++ * Return: ++ * * 0 - Successfully applied topology configuration. ++ * * -EBUSY - Failed to acquire global configuration lock. ++ * * -EEXIST - Topology configuration has already been applied. ++ * * -EIO - Unable to apply topology configuration. ++ * * -ENODEV - Failed to re-initialize device after applying configuration. ++ * * Other negative error codes indicate unexpected failures. + */ + int ice_cfg_tx_topo(struct ice_hw *hw, const void *buf, u32 len) + { +@@ -2385,7 +2391,7 @@ int ice_cfg_tx_topo(struct ice_hw *hw, const void *buf, u32 len) + + if (status) { + ice_debug(hw, ICE_DBG_INIT, "Get current topology is failed\n"); +- return status; ++ return -EIO; + } + + /* Is default topology already applied ? */ +@@ -2472,31 +2478,45 @@ int ice_cfg_tx_topo(struct ice_hw *hw, const void *buf, u32 len) + ICE_GLOBAL_CFG_LOCK_TIMEOUT); + if (status) { + ice_debug(hw, ICE_DBG_INIT, "Failed to acquire global lock\n"); +- return status; ++ return -EBUSY; + } + + /* Check if reset was triggered already. */ + reg = rd32(hw, GLGEN_RSTAT); + if (reg & GLGEN_RSTAT_DEVSTATE_M) { +- /* Reset is in progress, re-init the HW again */ + ice_debug(hw, ICE_DBG_INIT, "Reset is in progress. Layer topology might be applied already\n"); + ice_check_reset(hw); +- return 0; ++ /* Reset is in progress, re-init the HW again */ ++ goto reinit_hw; + } + + /* Set new topology */ + status = ice_get_set_tx_topo(hw, new_topo, size, NULL, NULL, true); + if (status) { +- ice_debug(hw, ICE_DBG_INIT, "Failed setting Tx topology\n"); +- return status; ++ ice_debug(hw, ICE_DBG_INIT, "Failed to set Tx topology, status %pe\n", ++ ERR_PTR(status)); ++ /* only report -EIO here as the caller checks the error value ++ * and reports an informational error message informing that ++ * the driver failed to program Tx topology. ++ */ ++ status = -EIO; + } + +- /* New topology is updated, delay 1 second before issuing the CORER */ ++ /* Even if Tx topology config failed, we need to CORE reset here to ++ * clear the global configuration lock. Delay 1 second to allow ++ * hardware to settle then issue a CORER ++ */ + msleep(1000); + ice_reset(hw, ICE_RESET_CORER); +- /* CORER will clear the global lock, so no explicit call +- * required for release. +- */ ++ ice_check_reset(hw); ++ ++reinit_hw: ++ /* Since we triggered a CORER, re-initialize hardware */ ++ ice_deinit_hw(hw); ++ if (ice_init_hw(hw)) { ++ ice_debug(hw, ICE_DBG_INIT, "Failed to re-init hardware after setting Tx topology\n"); ++ return -ENODEV; ++ } + +- return 0; ++ return status; + } +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index d1abd21cfc647..74d4f2fde3e0f 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -4559,17 +4559,23 @@ ice_init_tx_topology(struct ice_hw *hw, const struct firmware *firmware) + dev_info(dev, "Tx scheduling layers switching feature disabled\n"); + else + dev_info(dev, "Tx scheduling layers switching feature enabled\n"); +- /* if there was a change in topology ice_cfg_tx_topo triggered +- * a CORER and we need to re-init hw ++ return 0; ++ } else if (err == -ENODEV) { ++ /* If we failed to re-initialize the device, we can no longer ++ * continue loading. + */ +- ice_deinit_hw(hw); +- err = ice_init_hw(hw); +- ++ dev_warn(dev, "Failed to initialize hardware after applying Tx scheduling configuration.\n"); + return err; + } else if (err == -EIO) { + dev_info(dev, "DDP package does not support Tx scheduling layers switching feature - please update to the latest DDP package and try again\n"); ++ return 0; ++ } else if (err == -EEXIST) { ++ return 0; + } + ++ /* Do not treat this as a fatal error. */ ++ dev_info(dev, "Failed to apply Tx scheduling configuration, err %pe\n", ++ ERR_PTR(err)); + return 0; + } + +-- +2.50.1 + diff --git a/queue-6.12/ice-fix-incorrect-counter-for-buffer-allocation-fail.patch b/queue-6.12/ice-fix-incorrect-counter-for-buffer-allocation-fail.patch new file mode 100644 index 0000000000..4ed3ebb595 --- /dev/null +++ b/queue-6.12/ice-fix-incorrect-counter-for-buffer-allocation-fail.patch @@ -0,0 +1,46 @@ +From 84791f14f20b44015822f6ca5791d1c0bd24585b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Aug 2025 17:53:10 +0200 +Subject: ice: fix incorrect counter for buffer allocation failures + +From: Michal Kubiak + +[ Upstream commit b1a0c977c6f1130f7dd125ee3db8c2435d7e3d41 ] + +Currently, the driver increments `alloc_page_failed` when buffer allocation fails +in `ice_clean_rx_irq()`. However, this counter is intended for page allocation +failures, not buffer allocation issues. + +This patch corrects the counter by incrementing `alloc_buf_failed` instead, +ensuring accurate statistics reporting for buffer allocation failures. + +Fixes: 2fba7dc5157b ("ice: Add support for XDP multi-buffer on Rx side") +Reported-by: Jacob Keller +Suggested-by: Paul Menzel +Signed-off-by: Michal Kubiak +Reviewed-by: Paul Menzel +Reviewed-by: Jason Xing +Reviewed-by: Aleksandr Loktionov +Tested-by: Priya Singh +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_txrx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c +index f522dd42093a9..cde69f5686656 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.c ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c +@@ -1295,7 +1295,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) + skb = ice_construct_skb(rx_ring, xdp); + /* exit if we failed to retrieve a buffer */ + if (!skb) { +- rx_ring->ring_stats->rx_stats.alloc_page_failed++; ++ rx_ring->ring_stats->rx_stats.alloc_buf_failed++; + xdp_verdict = ICE_XDP_CONSUMED; + } + ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict); +-- +2.50.1 + diff --git a/queue-6.12/ice-use-fixed-adapter-index-for-e825c-embedded-devic.patch b/queue-6.12/ice-use-fixed-adapter-index-for-e825c-embedded-devic.patch new file mode 100644 index 0000000000..910e02c5a6 --- /dev/null +++ b/queue-6.12/ice-use-fixed-adapter-index-for-e825c-embedded-devic.patch @@ -0,0 +1,202 @@ +From ec18b0f742f2f8c03c0d6c975059403927507bb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Aug 2025 15:27:12 -0700 +Subject: ice: use fixed adapter index for E825C embedded devices + +From: Jacob Keller + +[ Upstream commit 5c5e5b52bf05c7fe88768318c041052c5fac36b8 ] + +The ice_adapter structure is used by the ice driver to connect multiple +physical functions of a device in software. It was introduced by +commit 0e2bddf9e5f9 ("ice: add ice_adapter for shared data across PFs on +the same NIC") and is primarily used for PTP support, as well as for +handling certain cross-PF synchronization. + +The original design of ice_adapter used PCI address information to +determine which devices should be connected. This was extended to support +E825C devices by commit fdb7f54700b1 ("ice: Initial support for E825C +hardware in ice_adapter"), which used the device ID for E825C devices +instead of the PCI address. + +Later, commit 0093cb194a75 ("ice: use DSN instead of PCI BDF for +ice_adapter index") replaced the use of Bus/Device/Function addressing with +use of the device serial number. + +E825C devices may appear in "Dual NAC" configuration which has multiple +physical devices tied to the same clock source and which need to use the +same ice_adapter. Unfortunately, each "NAC" has its own NVM which has its +own unique Device Serial Number. Thus, use of the DSN for connecting +ice_adapter does not work properly. It "worked" in the pre-production +systems because the DSN was not initialized on the test NVMs and all the +NACs had the same zero'd serial number. + +Since we cannot rely on the DSN, lets fall back to the logic in the +original E825C support which used the device ID. This is safe for E825C +only because of the embedded nature of the device. It isn't a discreet +adapter that can be plugged into an arbitrary system. All E825C devices on +a given system are connected to the same clock source and need to be +configured through the same PTP clock. + +To make this separation clear, reserve bit 63 of the 64-bit index values as +a "fixed index" indicator. Always clear this bit when using the device +serial number as an index. + +For E825C, use a fixed value defined as the 0x579C E825C backplane device +ID bitwise ORed with the fixed index indicator. This is slightly different +than the original logic of just using the device ID directly. Doing so +prevents a potential issue with systems where only one of the NACs is +connected with an external PHY over SGMII. In that case, one NAC would +have the E825C_SGMII device ID, but the other would not. + +Separate the determination of the full 64-bit index from the 32-bit +reduction logic. Provide both ice_adapter_index() and a wrapping +ice_adapter_xa_index() which handles reducing the index to a long on 32-bit +systems. As before, cache the full index value in the adapter structure to +warn about collisions. + +This fixes issues with E825C not initializing PTP on both NACs, due to +failure to connect the appropriate devices to the same ice_adapter. + +Fixes: 0093cb194a75 ("ice: use DSN instead of PCI BDF for ice_adapter index") +Signed-off-by: Jacob Keller +Reviewed-by: Grzegorz Nitka +Reviewed-by: Aleksandr Loktionov +Reviewed-by: Przemek Kitszel +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_adapter.c | 49 +++++++++++++++----- + drivers/net/ethernet/intel/ice/ice_adapter.h | 4 +- + 2 files changed, 40 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.c b/drivers/net/ethernet/intel/ice/ice_adapter.c +index 66e070095d1bb..10285995c9edd 100644 +--- a/drivers/net/ethernet/intel/ice/ice_adapter.c ++++ b/drivers/net/ethernet/intel/ice/ice_adapter.c +@@ -13,16 +13,45 @@ + static DEFINE_XARRAY(ice_adapters); + static DEFINE_MUTEX(ice_adapters_mutex); + +-static unsigned long ice_adapter_index(u64 dsn) ++#define ICE_ADAPTER_FIXED_INDEX BIT_ULL(63) ++ ++#define ICE_ADAPTER_INDEX_E825C \ ++ (ICE_DEV_ID_E825C_BACKPLANE | ICE_ADAPTER_FIXED_INDEX) ++ ++static u64 ice_adapter_index(struct pci_dev *pdev) + { ++ switch (pdev->device) { ++ case ICE_DEV_ID_E825C_BACKPLANE: ++ case ICE_DEV_ID_E825C_QSFP: ++ case ICE_DEV_ID_E825C_SFP: ++ case ICE_DEV_ID_E825C_SGMII: ++ /* E825C devices have multiple NACs which are connected to the ++ * same clock source, and which must share the same ++ * ice_adapter structure. We can't use the serial number since ++ * each NAC has its own NVM generated with its own unique ++ * Device Serial Number. Instead, rely on the embedded nature ++ * of the E825C devices, and use a fixed index. This relies on ++ * the fact that all E825C physical functions in a given ++ * system are part of the same overall device. ++ */ ++ return ICE_ADAPTER_INDEX_E825C; ++ default: ++ return pci_get_dsn(pdev) & ~ICE_ADAPTER_FIXED_INDEX; ++ } ++} ++ ++static unsigned long ice_adapter_xa_index(struct pci_dev *pdev) ++{ ++ u64 index = ice_adapter_index(pdev); ++ + #if BITS_PER_LONG == 64 +- return dsn; ++ return index; + #else +- return (u32)dsn ^ (u32)(dsn >> 32); ++ return (u32)index ^ (u32)(index >> 32); + #endif + } + +-static struct ice_adapter *ice_adapter_new(u64 dsn) ++static struct ice_adapter *ice_adapter_new(struct pci_dev *pdev) + { + struct ice_adapter *adapter; + +@@ -30,7 +59,7 @@ static struct ice_adapter *ice_adapter_new(u64 dsn) + if (!adapter) + return NULL; + +- adapter->device_serial_number = dsn; ++ adapter->index = ice_adapter_index(pdev); + spin_lock_init(&adapter->ptp_gltsyn_time_lock); + refcount_set(&adapter->refcount, 1); + +@@ -63,24 +92,23 @@ static void ice_adapter_free(struct ice_adapter *adapter) + */ + struct ice_adapter *ice_adapter_get(struct pci_dev *pdev) + { +- u64 dsn = pci_get_dsn(pdev); + struct ice_adapter *adapter; + unsigned long index; + int err; + +- index = ice_adapter_index(dsn); ++ index = ice_adapter_xa_index(pdev); + scoped_guard(mutex, &ice_adapters_mutex) { + err = xa_insert(&ice_adapters, index, NULL, GFP_KERNEL); + if (err == -EBUSY) { + adapter = xa_load(&ice_adapters, index); + refcount_inc(&adapter->refcount); +- WARN_ON_ONCE(adapter->device_serial_number != dsn); ++ WARN_ON_ONCE(adapter->index != ice_adapter_index(pdev)); + return adapter; + } + if (err) + return ERR_PTR(err); + +- adapter = ice_adapter_new(dsn); ++ adapter = ice_adapter_new(pdev); + if (!adapter) + return ERR_PTR(-ENOMEM); + xa_store(&ice_adapters, index, adapter, GFP_KERNEL); +@@ -99,11 +127,10 @@ struct ice_adapter *ice_adapter_get(struct pci_dev *pdev) + */ + void ice_adapter_put(struct pci_dev *pdev) + { +- u64 dsn = pci_get_dsn(pdev); + struct ice_adapter *adapter; + unsigned long index; + +- index = ice_adapter_index(dsn); ++ index = ice_adapter_xa_index(pdev); + scoped_guard(mutex, &ice_adapters_mutex) { + adapter = xa_load(&ice_adapters, index); + if (WARN_ON(!adapter)) +diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.h b/drivers/net/ethernet/intel/ice/ice_adapter.h +index ac15c0d2bc1a4..409467847c753 100644 +--- a/drivers/net/ethernet/intel/ice/ice_adapter.h ++++ b/drivers/net/ethernet/intel/ice/ice_adapter.h +@@ -32,7 +32,7 @@ struct ice_port_list { + * @refcount: Reference count. struct ice_pf objects hold the references. + * @ctrl_pf: Control PF of the adapter + * @ports: Ports list +- * @device_serial_number: DSN cached for collision detection on 32bit systems ++ * @index: 64-bit index cached for collision detection on 32bit systems + */ + struct ice_adapter { + refcount_t refcount; +@@ -41,7 +41,7 @@ struct ice_adapter { + + struct ice_pf *ctrl_pf; + struct ice_port_list ports; +- u64 device_serial_number; ++ u64 index; + }; + + struct ice_adapter *ice_adapter_get(struct pci_dev *pdev); +-- +2.50.1 + diff --git a/queue-6.12/l2tp-do-not-use-sock_hold-in-pppol2tp_session_get_so.patch b/queue-6.12/l2tp-do-not-use-sock_hold-in-pppol2tp_session_get_so.patch new file mode 100644 index 0000000000..0c6fc504b0 --- /dev/null +++ b/queue-6.12/l2tp-do-not-use-sock_hold-in-pppol2tp_session_get_so.patch @@ -0,0 +1,112 @@ +From a8e2d0e7edd1d9a33531482f397fb8c24195a72c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Aug 2025 13:44:35 +0000 +Subject: l2tp: do not use sock_hold() in pppol2tp_session_get_sock() + +From: Eric Dumazet + +[ Upstream commit 9b8c88f875c04d4cb9111bd5dd9291c7e9691bf5 ] + +pppol2tp_session_get_sock() is using RCU, it must be ready +for sk_refcnt being zero. + +Commit ee40fb2e1eb5 ("l2tp: protect sock pointer of +struct pppol2tp_session with RCU") was correct because it +had a call_rcu(..., pppol2tp_put_sk) which was later removed in blamed commit. + +pppol2tp_recv() can use pppol2tp_session_get_sock() as well. + +Fixes: c5cbaef992d6 ("l2tp: refactor ppp socket/session relationship") +Signed-off-by: Eric Dumazet +Cc: James Chapman +Reviewed-by: Guillaume Nault +Link: https://patch.msgid.link/20250826134435.1683435-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/l2tp/l2tp_ppp.c | 25 ++++++++----------------- + 1 file changed, 8 insertions(+), 17 deletions(-) + +diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c +index 53baf2dd5d5da..16c514f628eac 100644 +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -129,22 +129,12 @@ static const struct ppp_channel_ops pppol2tp_chan_ops = { + + static const struct proto_ops pppol2tp_ops; + +-/* Retrieves the pppol2tp socket associated to a session. +- * A reference is held on the returned socket, so this function must be paired +- * with sock_put(). +- */ ++/* Retrieves the pppol2tp socket associated to a session. */ + static struct sock *pppol2tp_session_get_sock(struct l2tp_session *session) + { + struct pppol2tp_session *ps = l2tp_session_priv(session); +- struct sock *sk; +- +- rcu_read_lock(); +- sk = rcu_dereference(ps->sk); +- if (sk) +- sock_hold(sk); +- rcu_read_unlock(); + +- return sk; ++ return rcu_dereference(ps->sk); + } + + /* Helpers to obtain tunnel/session contexts from sockets. +@@ -206,14 +196,13 @@ static int pppol2tp_recvmsg(struct socket *sock, struct msghdr *msg, + + static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int data_len) + { +- struct pppol2tp_session *ps = l2tp_session_priv(session); +- struct sock *sk = NULL; ++ struct sock *sk; + + /* If the socket is bound, send it in to PPP's input queue. Otherwise + * queue it on the session socket. + */ + rcu_read_lock(); +- sk = rcu_dereference(ps->sk); ++ sk = pppol2tp_session_get_sock(session); + if (!sk) + goto no_sock; + +@@ -510,13 +499,14 @@ static void pppol2tp_show(struct seq_file *m, void *arg) + struct l2tp_session *session = arg; + struct sock *sk; + ++ rcu_read_lock(); + sk = pppol2tp_session_get_sock(session); + if (sk) { + struct pppox_sock *po = pppox_sk(sk); + + seq_printf(m, " interface %s\n", ppp_dev_name(&po->chan)); +- sock_put(sk); + } ++ rcu_read_unlock(); + } + + static void pppol2tp_session_init(struct l2tp_session *session) +@@ -1529,6 +1519,7 @@ static void pppol2tp_seq_session_show(struct seq_file *m, void *v) + port = ntohs(inet->inet_sport); + } + ++ rcu_read_lock(); + sk = pppol2tp_session_get_sock(session); + if (sk) { + state = sk->sk_state; +@@ -1564,8 +1555,8 @@ static void pppol2tp_seq_session_show(struct seq_file *m, void *v) + struct pppox_sock *po = pppox_sk(sk); + + seq_printf(m, " interface %s\n", ppp_dev_name(&po->chan)); +- sock_put(sk); + } ++ rcu_read_unlock(); + } + + static int pppol2tp_seq_show(struct seq_file *m, void *v) +-- +2.50.1 + diff --git a/queue-6.12/net-dlink-fix-multicast-stats-being-counted-incorrec.patch b/queue-6.12/net-dlink-fix-multicast-stats-being-counted-incorrec.patch new file mode 100644 index 0000000000..0dbf078b6b --- /dev/null +++ b/queue-6.12/net-dlink-fix-multicast-stats-being-counted-incorrec.patch @@ -0,0 +1,46 @@ +From c9f00cf87102c00aa4da68a43d324fb233ae7947 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Aug 2025 03:29:24 +0900 +Subject: net: dlink: fix multicast stats being counted incorrectly + +From: Yeounsu Moon + +[ Upstream commit 007a5ffadc4fd51739527f1503b7cf048f31c413 ] + +`McstFramesRcvdOk` counts the number of received multicast packets, and +it reports the value correctly. + +However, reading `McstFramesRcvdOk` clears the register to zero. As a +result, the driver was reporting only the packets since the last read, +instead of the accumulated total. + +Fix this by updating the multicast statistics accumulatively instaed of +instantaneously. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Tested-on: D-Link DGE-550T Rev-A3 +Signed-off-by: Yeounsu Moon +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250823182927.6063-3-yyyynoom@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/dlink/dl2k.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c +index 787218d60c6b1..2c1b551e14423 100644 +--- a/drivers/net/ethernet/dlink/dl2k.c ++++ b/drivers/net/ethernet/dlink/dl2k.c +@@ -1091,7 +1091,7 @@ get_stats (struct net_device *dev) + dev->stats.rx_bytes += dr32(OctetRcvOk); + dev->stats.tx_bytes += dr32(OctetXmtOk); + +- dev->stats.multicast = dr32(McstFramesRcvdOk); ++ dev->stats.multicast += dr32(McstFramesRcvdOk); + dev->stats.collisions += dr32(SingleColFrames) + + dr32(MultiColFrames); + +-- +2.50.1 + diff --git a/queue-6.12/net-hv_netvsc-fix-loss-of-early-receive-events-from-.patch b/queue-6.12/net-hv_netvsc-fix-loss-of-early-receive-events-from-.patch new file mode 100644 index 0000000000..2d46b772e5 --- /dev/null +++ b/queue-6.12/net-hv_netvsc-fix-loss-of-early-receive-events-from-.patch @@ -0,0 +1,122 @@ +From 3a60e772658803e5a200c03d353f7b78750ac313 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 04:56:27 -0700 +Subject: net: hv_netvsc: fix loss of early receive events from host during + channel open. + +From: Dipayaan Roy + +[ Upstream commit 9448ccd853368582efa9db05db344f8bb9dffe0f ] + +The hv_netvsc driver currently enables NAPI after opening the primary and +subchannels. This ordering creates a race: if the Hyper-V host places data +in the host -> guest ring buffer and signals the channel before +napi_enable() has been called, the channel callback will run but +napi_schedule_prep() will return false. As a result, the NAPI poller never +gets scheduled, the data in the ring buffer is not consumed, and the +receive queue may remain permanently stuck until another interrupt happens +to arrive. + +Fix this by enabling NAPI and registering it with the RX/TX queues before +vmbus channel is opened. This guarantees that any early host signal after +open will correctly trigger NAPI scheduling and the ring buffer will be +drained. + +Fixes: 76bb5db5c749d ("netvsc: fix use after free on module removal") +Signed-off-by: Dipayaan Roy +Link: https://patch.msgid.link/20250825115627.GA32189@linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/hyperv/netvsc.c | 17 ++++++++--------- + drivers/net/hyperv/rndis_filter.c | 23 ++++++++++++++++------- + 2 files changed, 24 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +index 87ac2a5f18091..5f14799b68c53 100644 +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -1811,6 +1811,11 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, + + /* Enable NAPI handler before init callbacks */ + netif_napi_add(ndev, &net_device->chan_table[0].napi, netvsc_poll); ++ napi_enable(&net_device->chan_table[0].napi); ++ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, ++ &net_device->chan_table[0].napi); ++ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, ++ &net_device->chan_table[0].napi); + + /* Open the channel */ + device->channel->next_request_id_callback = vmbus_next_request_id; +@@ -1830,12 +1835,6 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, + /* Channel is opened */ + netdev_dbg(ndev, "hv_netvsc channel opened successfully\n"); + +- napi_enable(&net_device->chan_table[0].napi); +- netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, +- &net_device->chan_table[0].napi); +- netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, +- &net_device->chan_table[0].napi); +- + /* Connect with the NetVsp */ + ret = netvsc_connect_vsp(device, net_device, device_info); + if (ret != 0) { +@@ -1853,14 +1852,14 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, + + close: + RCU_INIT_POINTER(net_device_ctx->nvdev, NULL); +- netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, NULL); +- netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, NULL); +- napi_disable(&net_device->chan_table[0].napi); + + /* Now, we can close the channel safely */ + vmbus_close(device->channel); + + cleanup: ++ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, NULL); ++ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, NULL); ++ napi_disable(&net_device->chan_table[0].napi); + netif_napi_del(&net_device->chan_table[0].napi); + + cleanup2: +diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c +index 9b8769a8b77a1..9a92552ee35c2 100644 +--- a/drivers/net/hyperv/rndis_filter.c ++++ b/drivers/net/hyperv/rndis_filter.c +@@ -1252,17 +1252,26 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc) + new_sc->rqstor_size = netvsc_rqstor_size(netvsc_ring_bytes); + new_sc->max_pkt_size = NETVSC_MAX_PKT_SIZE; + ++ /* Enable napi before opening the vmbus channel to avoid races ++ * as the host placing data on the host->guest ring may be left ++ * out if napi was not enabled. ++ */ ++ napi_enable(&nvchan->napi); ++ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_RX, ++ &nvchan->napi); ++ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_TX, ++ &nvchan->napi); ++ + ret = vmbus_open(new_sc, netvsc_ring_bytes, + netvsc_ring_bytes, NULL, 0, + netvsc_channel_cb, nvchan); +- if (ret == 0) { +- napi_enable(&nvchan->napi); +- netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_RX, +- &nvchan->napi); +- netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_TX, +- &nvchan->napi); +- } else { ++ if (ret != 0) { + netdev_notice(ndev, "sub channel open failed: %d\n", ret); ++ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_TX, ++ NULL); ++ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_RX, ++ NULL); ++ napi_disable(&nvchan->napi); + } + + if (atomic_inc_return(&nvscdev->open_chn) == nvscdev->num_chn) +-- +2.50.1 + diff --git a/queue-6.12/net-ipv4-fix-regression-in-local-broadcast-routes.patch b/queue-6.12/net-ipv4-fix-regression-in-local-broadcast-routes.patch new file mode 100644 index 0000000000..250dbd0bc9 --- /dev/null +++ b/queue-6.12/net-ipv4-fix-regression-in-local-broadcast-routes.patch @@ -0,0 +1,57 @@ +From 2053842dfbc405f44eb671b366bcb3f68e00f445 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 08:23:21 +0200 +Subject: net: ipv4: fix regression in local-broadcast routes + +From: Oscar Maes + +[ Upstream commit 5189446ba995556eaa3755a6e875bc06675b88bd ] + +Commit 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") +introduced a regression where local-broadcast packets would have their +gateway set in __mkroute_output, which was caused by fi = NULL being +removed. + +Fix this by resetting the fib_info for local-broadcast packets. This +preserves the intended changes for directed-broadcast packets. + +Cc: stable@vger.kernel.org +Fixes: 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") +Reported-by: Brett A C Sheffield +Closes: https://lore.kernel.org/regressions/20250822165231.4353-4-bacs@librecast.net +Signed-off-by: Oscar Maes +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20250827062322.4807-1-oscmaes92@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/route.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 9a5c9497b3931..261ddb6542a40 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -2532,12 +2532,16 @@ static struct rtable *__mkroute_output(const struct fib_result *res, + !netif_is_l3_master(dev_out)) + return ERR_PTR(-EINVAL); + +- if (ipv4_is_lbcast(fl4->daddr)) ++ if (ipv4_is_lbcast(fl4->daddr)) { + type = RTN_BROADCAST; +- else if (ipv4_is_multicast(fl4->daddr)) ++ ++ /* reset fi to prevent gateway resolution */ ++ fi = NULL; ++ } else if (ipv4_is_multicast(fl4->daddr)) { + type = RTN_MULTICAST; +- else if (ipv4_is_zeronet(fl4->daddr)) ++ } else if (ipv4_is_zeronet(fl4->daddr)) { + return ERR_PTR(-EINVAL); ++ } + + if (dev_out->flags & IFF_LOOPBACK) + flags |= RTCF_LOCAL; +-- +2.50.1 + diff --git a/queue-6.12/net-macb-disable-clocks-once.patch b/queue-6.12/net-macb-disable-clocks-once.patch new file mode 100644 index 0000000000..56274c22af --- /dev/null +++ b/queue-6.12/net-macb-disable-clocks-once.patch @@ -0,0 +1,49 @@ +From d50a0061fa6e2e36188ec60bb5f3c0201b9effe3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Aug 2025 10:30:22 -0400 +Subject: net: macb: Disable clocks once + +From: Neil Mandir + +[ Upstream commit dac978e51cce0c1f00a14c4a82f81d387f79b2d4 ] + +When the driver is removed the clocks are disabled twice: once in +macb_remove and a second time by runtime pm. Disable wakeup in remove so +all the clocks are disabled and skip the second call to macb_clks_disable. +Always suspend the device as we always set it active in probe. + +Fixes: d54f89af6cc4 ("net: macb: Add pm runtime support") +Signed-off-by: Neil Mandir +Co-developed-by: Sean Anderson +Signed-off-by: Sean Anderson +Link: https://patch.msgid.link/20250826143022.935521-1-sean.anderson@linux.dev +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cadence/macb_main.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index 2421a7bcd221e..6c2d69ef1a8db 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -5230,14 +5230,11 @@ static void macb_remove(struct platform_device *pdev) + mdiobus_unregister(bp->mii_bus); + mdiobus_free(bp->mii_bus); + ++ device_set_wakeup_enable(&bp->pdev->dev, 0); + cancel_work_sync(&bp->hresp_err_bh_work); + pm_runtime_disable(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); +- if (!pm_runtime_suspended(&pdev->dev)) { +- macb_clks_disable(bp->pclk, bp->hclk, bp->tx_clk, +- bp->rx_clk, bp->tsu_clk); +- pm_runtime_set_suspended(&pdev->dev); +- } ++ pm_runtime_set_suspended(&pdev->dev); + phylink_destroy(bp->phylink); + free_netdev(dev); + } +-- +2.50.1 + diff --git a/queue-6.12/net-macb-fix-unregister_netdev-call-order-in-macb_re.patch b/queue-6.12/net-macb-fix-unregister_netdev-call-order-in-macb_re.patch new file mode 100644 index 0000000000..cd8d66cffa --- /dev/null +++ b/queue-6.12/net-macb-fix-unregister_netdev-call-order-in-macb_re.patch @@ -0,0 +1,63 @@ +From 4682769487e10126710667542f30f606416557a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Aug 2025 07:25:27 +0800 +Subject: net: macb: fix unregister_netdev call order in macb_remove() + +From: luoguangfei <15388634752@163.com> + +[ Upstream commit 01b9128c5db1b470575d07b05b67ffa3cb02ebf1 ] + +When removing a macb device, the driver calls phy_exit() before +unregister_netdev(). This leads to a WARN from kernfs: + + ------------[ cut here ]------------ + kernfs: can not remove 'attached_dev', no directory + WARNING: CPU: 1 PID: 27146 at fs/kernfs/dir.c:1683 + Call trace: + kernfs_remove_by_name_ns+0xd8/0xf0 + sysfs_remove_link+0x24/0x58 + phy_detach+0x5c/0x168 + phy_disconnect+0x4c/0x70 + phylink_disconnect_phy+0x6c/0xc0 [phylink] + macb_close+0x6c/0x170 [macb] + ... + macb_remove+0x60/0x168 [macb] + platform_remove+0x5c/0x80 + ... + +The warning happens because the PHY is being exited while the netdev +is still registered. The correct order is to unregister the netdev +before shutting down the PHY and cleaning up the MDIO bus. + +Fix this by moving unregister_netdev() ahead of phy_exit() in +macb_remove(). + +Fixes: 8b73fa3ae02b ("net: macb: Added ZynqMP-specific initialization") +Signed-off-by: luoguangfei <15388634752@163.com> +Link: https://patch.msgid.link/20250818232527.1316-1-15388634752@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cadence/macb_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index 3c2a7919b1289..2421a7bcd221e 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -5225,11 +5225,11 @@ static void macb_remove(struct platform_device *pdev) + + if (dev) { + bp = netdev_priv(dev); ++ unregister_netdev(dev); + phy_exit(bp->sgmii_phy); + mdiobus_unregister(bp->mii_bus); + mdiobus_free(bp->mii_bus); + +- unregister_netdev(dev); + cancel_work_sync(&bp->hresp_err_bh_work); + pm_runtime_disable(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); +-- +2.50.1 + diff --git a/queue-6.12/net-mlx5-fix-lockdep-assertion-on-sync-reset-unload-.patch b/queue-6.12/net-mlx5-fix-lockdep-assertion-on-sync-reset-unload-.patch new file mode 100644 index 0000000000..ee1fd81757 --- /dev/null +++ b/queue-6.12/net-mlx5-fix-lockdep-assertion-on-sync-reset-unload-.patch @@ -0,0 +1,247 @@ +From 4ae30f329aee5fe1c57434e23ad9ae6cfc1fb216 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:29 +0300 +Subject: net/mlx5: Fix lockdep assertion on sync reset unload event + +From: Moshe Shemesh + +[ Upstream commit 902a8bc23a24882200f57cadc270e15a2cfaf2bb ] + +Fix lockdep assertion triggered during sync reset unload event. When the +sync reset flow is initiated using the devlink reload fw_activate +option, the PF already holds the devlink lock while handling unload +event. In this case, delegate sync reset unload event handling back to +the devlink callback process to avoid double-locking and resolve the +lockdep warning. + +Kernel log: +WARNING: CPU: 9 PID: 1578 at devl_assert_locked+0x31/0x40 +[...] +Call Trace: + + mlx5_unload_one_devl_locked+0x2c/0xc0 [mlx5_core] + mlx5_sync_reset_unload_event+0xaf/0x2f0 [mlx5_core] + process_one_work+0x222/0x640 + worker_thread+0x199/0x350 + kthread+0x10b/0x230 + ? __pfx_worker_thread+0x10/0x10 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x8e/0x100 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + +Fixes: 7a9770f1bfea ("net/mlx5: Handle sync reset unload event") +Signed-off-by: Moshe Shemesh +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-7-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mellanox/mlx5/core/devlink.c | 2 +- + .../ethernet/mellanox/mlx5/core/fw_reset.c | 108 ++++++++++-------- + .../ethernet/mellanox/mlx5/core/fw_reset.h | 1 + + 3 files changed, 63 insertions(+), 48 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +index 7211e65ad2dcc..511b3ba245420 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +@@ -107,7 +107,7 @@ static int mlx5_devlink_reload_fw_activate(struct devlink *devlink, struct netli + if (err) + return err; + +- mlx5_unload_one_devl_locked(dev, false); ++ mlx5_sync_reset_unload_flow(dev, true); + err = mlx5_health_wait_pci_up(dev); + if (err) + NL_SET_ERR_MSG_MOD(extack, "FW activate aborted, PCI reads fail after reset"); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index 4f55e55ecb551..0829912157c97 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -12,7 +12,8 @@ enum { + MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, + MLX5_FW_RESET_FLAGS_PENDING_COMP, + MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, +- MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED ++ MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED, ++ MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, + }; + + struct mlx5_fw_reset { +@@ -218,7 +219,7 @@ int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev) + return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL0, 0, 0, false); + } + +-static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unloaded) ++static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev) + { + struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; + struct devlink *devlink = priv_to_devlink(dev); +@@ -227,8 +228,7 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unload + if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) { + complete(&fw_reset->done); + } else { +- if (!unloaded) +- mlx5_unload_one(dev, false); ++ mlx5_sync_reset_unload_flow(dev, false); + if (mlx5_health_wait_pci_up(dev)) + mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n"); + else +@@ -271,7 +271,7 @@ static void mlx5_sync_reset_reload_work(struct work_struct *work) + + mlx5_sync_reset_clear_reset_requested(dev, false); + mlx5_enter_error_state(dev, true); +- mlx5_fw_reset_complete_reload(dev, false); ++ mlx5_fw_reset_complete_reload(dev); + } + + #define MLX5_RESET_POLL_INTERVAL (HZ / 10) +@@ -581,6 +581,59 @@ static int mlx5_sync_pci_reset(struct mlx5_core_dev *dev, u8 reset_method) + return err; + } + ++void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked) ++{ ++ struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; ++ unsigned long timeout; ++ bool reset_action; ++ u8 rst_state; ++ int err; ++ ++ if (locked) ++ mlx5_unload_one_devl_locked(dev, false); ++ else ++ mlx5_unload_one(dev, false); ++ ++ if (!test_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags)) ++ return; ++ ++ mlx5_set_fw_rst_ack(dev); ++ mlx5_core_warn(dev, "Sync Reset Unload done, device reset expected\n"); ++ ++ reset_action = false; ++ timeout = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, RESET_UNLOAD)); ++ do { ++ rst_state = mlx5_get_fw_rst_state(dev); ++ if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ || ++ rst_state == MLX5_FW_RST_STATE_IDLE) { ++ reset_action = true; ++ break; ++ } ++ msleep(20); ++ } while (!time_after(jiffies, timeout)); ++ ++ if (!reset_action) { ++ mlx5_core_err(dev, "Got timeout waiting for sync reset action, state = %u\n", ++ rst_state); ++ fw_reset->ret = -ETIMEDOUT; ++ goto done; ++ } ++ ++ mlx5_core_warn(dev, "Sync Reset, got reset action. rst_state = %u\n", ++ rst_state); ++ if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ) { ++ err = mlx5_sync_pci_reset(dev, fw_reset->reset_method); ++ if (err) { ++ mlx5_core_warn(dev, "mlx5_sync_pci_reset failed, err %d\n", ++ err); ++ fw_reset->ret = err; ++ } ++ } ++ ++done: ++ clear_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags); ++} ++ + static void mlx5_sync_reset_now_event(struct work_struct *work) + { + struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, +@@ -608,16 +661,13 @@ static void mlx5_sync_reset_now_event(struct work_struct *work) + mlx5_enter_error_state(dev, true); + done: + fw_reset->ret = err; +- mlx5_fw_reset_complete_reload(dev, false); ++ mlx5_fw_reset_complete_reload(dev); + } + + static void mlx5_sync_reset_unload_event(struct work_struct *work) + { + struct mlx5_fw_reset *fw_reset; + struct mlx5_core_dev *dev; +- unsigned long timeout; +- bool reset_action; +- u8 rst_state; + int err; + + fw_reset = container_of(work, struct mlx5_fw_reset, reset_unload_work); +@@ -626,6 +676,7 @@ static void mlx5_sync_reset_unload_event(struct work_struct *work) + if (mlx5_sync_reset_clear_reset_requested(dev, false)) + return; + ++ set_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags); + mlx5_core_warn(dev, "Sync Reset Unload. Function is forced down.\n"); + + err = mlx5_cmd_fast_teardown_hca(dev); +@@ -634,44 +685,7 @@ static void mlx5_sync_reset_unload_event(struct work_struct *work) + else + mlx5_enter_error_state(dev, true); + +- if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) +- mlx5_unload_one_devl_locked(dev, false); +- else +- mlx5_unload_one(dev, false); +- +- mlx5_set_fw_rst_ack(dev); +- mlx5_core_warn(dev, "Sync Reset Unload done, device reset expected\n"); +- +- reset_action = false; +- timeout = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, RESET_UNLOAD)); +- do { +- rst_state = mlx5_get_fw_rst_state(dev); +- if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ || +- rst_state == MLX5_FW_RST_STATE_IDLE) { +- reset_action = true; +- break; +- } +- msleep(20); +- } while (!time_after(jiffies, timeout)); +- +- if (!reset_action) { +- mlx5_core_err(dev, "Got timeout waiting for sync reset action, state = %u\n", +- rst_state); +- fw_reset->ret = -ETIMEDOUT; +- goto done; +- } +- +- mlx5_core_warn(dev, "Sync Reset, got reset action. rst_state = %u\n", rst_state); +- if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ) { +- err = mlx5_sync_pci_reset(dev, fw_reset->reset_method); +- if (err) { +- mlx5_core_warn(dev, "mlx5_sync_pci_reset failed, err %d\n", err); +- fw_reset->ret = err; +- } +- } +- +-done: +- mlx5_fw_reset_complete_reload(dev, true); ++ mlx5_fw_reset_complete_reload(dev); + } + + static void mlx5_sync_reset_abort_event(struct work_struct *work) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h +index ea527d06a85f0..d5b28525c960d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h +@@ -12,6 +12,7 @@ int mlx5_fw_reset_set_reset_sync(struct mlx5_core_dev *dev, u8 reset_type_sel, + int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev); + + int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev); ++void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked); + int mlx5_fw_reset_verify_fw_complete(struct mlx5_core_dev *dev, + struct netlink_ext_ack *extack); + void mlx5_fw_reset_events_start(struct mlx5_core_dev *dev); +-- +2.50.1 + diff --git a/queue-6.12/net-mlx5-nack-sync-reset-when-sfs-are-present.patch b/queue-6.12/net-mlx5-nack-sync-reset-when-sfs-are-present.patch new file mode 100644 index 0000000000..ef5e00ccd3 --- /dev/null +++ b/queue-6.12/net-mlx5-nack-sync-reset-when-sfs-are-present.patch @@ -0,0 +1,100 @@ +From 0305d98a7569aa2db9f851517fd3bf6d6209cc08 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:30 +0300 +Subject: net/mlx5: Nack sync reset when SFs are present + +From: Moshe Shemesh + +[ Upstream commit 26e42ec7712d392d561964514b1f253b1a96f42d ] + +If PF (Physical Function) has SFs (Sub-Functions), since the SFs are not +taking part in the synchronization flow, sync reset can lead to fatal +error on the SFs, as the function will be closed unexpectedly from the +SF point of view. + +Add a check to prevent sync reset when there are SFs on a PF device +which is not ECPF, as ECPF is teardowned gracefully before reset. + +Fixes: 92501fa6e421 ("net/mlx5: Ack on sync_reset_request only if PF can do reset_now") +Signed-off-by: Moshe Shemesh +Reviewed-by: Parav Pandit +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-8-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 6 ++++++ + drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c | 10 ++++++++++ + drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h | 6 ++++++ + 3 files changed, 22 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index 0829912157c97..516df7f1997eb 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -6,6 +6,7 @@ + #include "fw_reset.h" + #include "diag/fw_tracer.h" + #include "lib/tout.h" ++#include "sf/sf.h" + + enum { + MLX5_FW_RESET_FLAGS_RESET_REQUESTED, +@@ -423,6 +424,11 @@ static bool mlx5_is_reset_now_capable(struct mlx5_core_dev *dev, + return false; + } + ++ if (!mlx5_core_is_ecpf(dev) && !mlx5_sf_table_empty(dev)) { ++ mlx5_core_warn(dev, "SFs should be removed before reset\n"); ++ return false; ++ } ++ + #if IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE) + if (reset_method != MLX5_MFRL_REG_PCI_RESET_METHOD_HOT_RESET) { + err = mlx5_check_hotplug_interrupt(dev); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +index b96909fbeb12d..bdac3db1bd61d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +@@ -518,3 +518,13 @@ void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev) + WARN_ON(!xa_empty(&table->function_ids)); + kfree(table); + } ++ ++bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev) ++{ ++ struct mlx5_sf_table *table = dev->priv.sf_table; ++ ++ if (!table) ++ return true; ++ ++ return xa_empty(&table->function_ids); ++} +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h +index 860f9ddb7107b..89559a37997ad 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h +@@ -17,6 +17,7 @@ void mlx5_sf_hw_table_destroy(struct mlx5_core_dev *dev); + + int mlx5_sf_table_init(struct mlx5_core_dev *dev); + void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev); ++bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev); + + int mlx5_devlink_sf_port_new(struct devlink *devlink, + const struct devlink_port_new_attrs *add_attr, +@@ -61,6 +62,11 @@ static inline void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev) + { + } + ++static inline bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev) ++{ ++ return true; ++} ++ + #endif + + #endif +-- +2.50.1 + diff --git a/queue-6.12/net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch b/queue-6.12/net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch new file mode 100644 index 0000000000..416832fa21 --- /dev/null +++ b/queue-6.12/net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch @@ -0,0 +1,51 @@ +From 80660628a803bd3aacc006ba6403cfc16e627fd4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:28 +0300 +Subject: net/mlx5: Reload auxiliary drivers on fw_activate + +From: Moshe Shemesh + +[ Upstream commit 34cc6a54914f478c93e176450fae6313404f9f74 ] + +The devlink reload fw_activate command performs firmware activation +followed by driver reload, while devlink reload driver_reinit triggers +only driver reload. However, the driver reload logic differs between the +two modes, as on driver_reinit mode mlx5 also reloads auxiliary drivers, +while in fw_activate mode the auxiliary drivers are suspended where +applicable. + +Additionally, following the cited commit, if the device has multiple PFs, +the behavior during fw_activate may vary between PFs: one PF may suspend +auxiliary drivers, while another reloads them. + +Align devlink dev reload fw_activate behavior with devlink dev reload +driver_reinit, to reload all auxiliary drivers. + +Fixes: 72ed5d5624af ("net/mlx5: Suspend auxiliary devices only in case of PCI device suspend") +Signed-off-by: Moshe Shemesh +Reviewed-by: Tariq Toukan +Reviewed-by: Akiva Goldberger +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-6-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +index a2cf3e79693dd..7211e65ad2dcc 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +@@ -107,7 +107,7 @@ static int mlx5_devlink_reload_fw_activate(struct devlink *devlink, struct netli + if (err) + return err; + +- mlx5_unload_one_devl_locked(dev, true); ++ mlx5_unload_one_devl_locked(dev, false); + err = mlx5_health_wait_pci_up(dev); + if (err) + NL_SET_ERR_MSG_MOD(extack, "FW activate aborted, PCI reads fail after reset"); +-- +2.50.1 + diff --git a/queue-6.12/net-mlx5e-set-local-xoff-after-fw-update.patch b/queue-6.12/net-mlx5e-set-local-xoff-after-fw-update.patch new file mode 100644 index 0000000000..1af4407702 --- /dev/null +++ b/queue-6.12/net-mlx5e-set-local-xoff-after-fw-update.patch @@ -0,0 +1,50 @@ +From b11f28dc3d930781e666b59b5287b57ec75144c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:34 +0300 +Subject: net/mlx5e: Set local Xoff after FW update + +From: Alexei Lazar + +[ Upstream commit aca0c31af61e0d5cf1675a0cbd29460b95ae693c ] + +The local Xoff value is being set before the firmware (FW) update. +In case of a failure where the FW is not updated with the new value, +there is no fallback to the previous value. +Update the local Xoff value after the FW has been successfully set. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Reviewed-by: Dragos Tatulea +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-12-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +index 3efa8bf1d14ef..4720523813b97 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +@@ -575,7 +575,6 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + if (err) + return err; + } +- priv->dcbx.xoff = xoff; + + /* Apply the settings */ + if (update_buffer) { +@@ -584,6 +583,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + return err; + } + ++ priv->dcbx.xoff = xoff; ++ + if (update_prio2buffer) + err = mlx5e_port_set_priority2buffer(priv->mdev, prio2buffer); + +-- +2.50.1 + diff --git a/queue-6.12/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch b/queue-6.12/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch new file mode 100644 index 0000000000..b509f9f2d1 --- /dev/null +++ b/queue-6.12/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch @@ -0,0 +1,100 @@ +From 66bef2beb2be1701962f54c355755376b35f1c32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:32 +0300 +Subject: net/mlx5e: Update and set Xon/Xoff upon MTU set + +From: Alexei Lazar + +[ Upstream commit ceddedc969f0532b7c62ca971ee50d519d2bc0cb ] + +Xon/Xoff sizes are derived from calculation that include the MTU size. +Set Xon/Xoff when MTU is set. +If Xon/Xoff fails, set the previous MTU. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-10-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/en/port_buffer.h | 12 ++++++++++++ + .../net/ethernet/mellanox/mlx5/core/en_main.c | 17 ++++++++++++++++- + 2 files changed, 28 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +index f4a19ffbb641c..66d276a1be836 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +@@ -66,11 +66,23 @@ struct mlx5e_port_buffer { + struct mlx5e_bufferx_reg buffer[MLX5E_MAX_NETWORK_BUFFER]; + }; + ++#ifdef CONFIG_MLX5_CORE_EN_DCB + int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + u32 change, unsigned int mtu, + struct ieee_pfc *pfc, + u32 *buffer_size, + u8 *prio2buffer); ++#else ++static inline int ++mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, ++ u32 change, unsigned int mtu, ++ void *pfc, ++ u32 *buffer_size, ++ u8 *prio2buffer) ++{ ++ return 0; ++} ++#endif + + int mlx5e_port_query_buffer(struct mlx5e_priv *priv, + struct mlx5e_port_buffer *port_buffer); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 4a2f58a9d7066..de2327ffb0f78 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -47,6 +47,7 @@ + #include "en.h" + #include "en/dim.h" + #include "en/txrx.h" ++#include "en/port_buffer.h" + #include "en_tc.h" + #include "en_rep.h" + #include "en_accel/ipsec.h" +@@ -2917,9 +2918,11 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) + struct mlx5e_params *params = &priv->channels.params; + struct net_device *netdev = priv->netdev; + struct mlx5_core_dev *mdev = priv->mdev; +- u16 mtu; ++ u16 mtu, prev_mtu; + int err; + ++ mlx5e_query_mtu(mdev, params, &prev_mtu); ++ + err = mlx5e_set_mtu(mdev, params, params->sw_mtu); + if (err) + return err; +@@ -2929,6 +2932,18 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) + netdev_warn(netdev, "%s: VPort MTU %d is different than netdev mtu %d\n", + __func__, mtu, params->sw_mtu); + ++ if (mtu != prev_mtu && MLX5_BUFFER_SUPPORTED(mdev)) { ++ err = mlx5e_port_manual_buffer_config(priv, 0, mtu, ++ NULL, NULL, NULL); ++ if (err) { ++ netdev_warn(netdev, "%s: Failed to set Xon/Xoff values with MTU %d (err %d), setting back to previous MTU %d\n", ++ __func__, mtu, err, prev_mtu); ++ ++ mlx5e_set_mtu(mdev, params, prev_mtu); ++ return err; ++ } ++ } ++ + params->sw_mtu = mtu; + return 0; + } +-- +2.50.1 + diff --git a/queue-6.12/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch b/queue-6.12/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch new file mode 100644 index 0000000000..5bfb35e802 --- /dev/null +++ b/queue-6.12/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch @@ -0,0 +1,46 @@ +From ad7d85c7665145322f6cc2c6d3169d00eb152099 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:33 +0300 +Subject: net/mlx5e: Update and set Xon/Xoff upon port speed set + +From: Alexei Lazar + +[ Upstream commit d24341740fe48add8a227a753e68b6eedf4b385a ] + +Xon/Xoff sizes are derived from calculations that include +the port speed. +These settings need to be updated and applied whenever the +port speed is changed. +The port speed is typically set after the physical link goes down +and is negotiated as part of the link-up process between the two +connected interfaces. +Xon/Xoff parameters being updated at the point where the new +negotiated speed is established. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-11-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index de2327ffb0f78..6176457b846bc 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -135,6 +135,8 @@ void mlx5e_update_carrier(struct mlx5e_priv *priv) + if (up) { + netdev_info(priv->netdev, "Link up\n"); + netif_carrier_on(priv->netdev); ++ mlx5e_port_manual_buffer_config(priv, 0, priv->netdev->mtu, ++ NULL, NULL, NULL); + } else { + netdev_info(priv->netdev, "Link down\n"); + netif_carrier_off(priv->netdev); +-- +2.50.1 + diff --git a/queue-6.12/net-rose-convert-use-field-to-refcount_t.patch b/queue-6.12/net-rose-convert-use-field-to-refcount_t.patch new file mode 100644 index 0000000000..bfe4960308 --- /dev/null +++ b/queue-6.12/net-rose-convert-use-field-to-refcount_t.patch @@ -0,0 +1,370 @@ +From af3b1f96a4b1ec39e8ae59d453e7c3db06736ec4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Aug 2025 17:58:56 +0900 +Subject: net: rose: convert 'use' field to refcount_t + +From: Takamitsu Iwai + +[ Upstream commit d860d1faa6b2ce3becfdb8b0c2b048ad31800061 ] + +The 'use' field in struct rose_neigh is used as a reference counter but +lacks atomicity. This can lead to race conditions where a rose_neigh +structure is freed while still being referenced by other code paths. + +For example, when rose_neigh->use becomes zero during an ioctl operation +via rose_rt_ioctl(), the structure may be removed while its timer is +still active, potentially causing use-after-free issues. + +This patch changes the type of 'use' from unsigned short to refcount_t and +updates all code paths to use rose_neigh_hold() and rose_neigh_put() which +operate reference counts atomically. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Takamitsu Iwai +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250823085857.47674-3-takamitz@amazon.co.jp +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/rose.h | 18 +++++++++++++----- + net/rose/af_rose.c | 13 +++++++------ + net/rose/rose_in.c | 12 ++++++------ + net/rose/rose_route.c | 33 ++++++++++++++++++--------------- + net/rose/rose_timer.c | 2 +- + 5 files changed, 45 insertions(+), 33 deletions(-) + +diff --git a/include/net/rose.h b/include/net/rose.h +index 174b4f605d849..2b5491bbf39ab 100644 +--- a/include/net/rose.h ++++ b/include/net/rose.h +@@ -8,6 +8,7 @@ + #ifndef _ROSE_H + #define _ROSE_H + ++#include + #include + #include + #include +@@ -96,7 +97,7 @@ struct rose_neigh { + ax25_cb *ax25; + struct net_device *dev; + unsigned short count; +- unsigned short use; ++ refcount_t use; + unsigned int number; + char restarted; + char dce_mode; +@@ -151,12 +152,19 @@ struct rose_sock { + + #define rose_sk(sk) ((struct rose_sock *)(sk)) + ++static inline void rose_neigh_hold(struct rose_neigh *rose_neigh) ++{ ++ refcount_inc(&rose_neigh->use); ++} ++ + static inline void rose_neigh_put(struct rose_neigh *rose_neigh) + { +- if (rose_neigh->ax25) +- ax25_cb_put(rose_neigh->ax25); +- kfree(rose_neigh->digipeat); +- kfree(rose_neigh); ++ if (refcount_dec_and_test(&rose_neigh->use)) { ++ if (rose_neigh->ax25) ++ ax25_cb_put(rose_neigh->ax25); ++ kfree(rose_neigh->digipeat); ++ kfree(rose_neigh); ++ } + } + + /* af_rose.c */ +diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c +index a4a668b88a8f2..b8078b42f5de6 100644 +--- a/net/rose/af_rose.c ++++ b/net/rose/af_rose.c +@@ -170,7 +170,7 @@ void rose_kill_by_neigh(struct rose_neigh *neigh) + + if (rose->neighbour == neigh) { + rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + rose->neighbour = NULL; + } + } +@@ -212,7 +212,7 @@ static void rose_kill_by_device(struct net_device *dev) + if (rose->device == dev) { + rose_disconnect(sk, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); + if (rose->neighbour) +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + netdev_put(rose->device, &rose->dev_tracker); + rose->device = NULL; + } +@@ -655,7 +655,7 @@ static int rose_release(struct socket *sock) + break; + + case ROSE_STATE_2: +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + release_sock(sk); + rose_disconnect(sk, 0, -1, -1); + lock_sock(sk); +@@ -823,6 +823,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + rose->lci = rose_new_lci(rose->neighbour); + if (!rose->lci) { + err = -ENETUNREACH; ++ rose_neigh_put(rose->neighbour); + goto out_release; + } + +@@ -834,12 +835,14 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + dev = rose_dev_first(); + if (!dev) { + err = -ENETUNREACH; ++ rose_neigh_put(rose->neighbour); + goto out_release; + } + + user = ax25_findbyuid(current_euid()); + if (!user) { + err = -EINVAL; ++ rose_neigh_put(rose->neighbour); + dev_put(dev); + goto out_release; + } +@@ -874,8 +877,6 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + + rose->state = ROSE_STATE_1; + +- rose->neighbour->use++; +- + rose_write_internal(sk, ROSE_CALL_REQUEST); + rose_start_heartbeat(sk); + rose_start_t1timer(sk); +@@ -1077,7 +1078,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros + GFP_ATOMIC); + make_rose->facilities = facilities; + +- make_rose->neighbour->use++; ++ rose_neigh_hold(make_rose->neighbour); + + if (rose_sk(sk)->defer) { + make_rose->state = ROSE_STATE_5; +diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c +index 4d67f36dce1b4..7caae93937ee9 100644 +--- a/net/rose/rose_in.c ++++ b/net/rose/rose_in.c +@@ -56,7 +56,7 @@ static int rose_state1_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + default: +@@ -79,12 +79,12 @@ static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + case ROSE_CLEAR_CONFIRMATION: + rose_disconnect(sk, 0, -1, -1); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + default: +@@ -120,7 +120,7 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + case ROSE_RR: +@@ -233,7 +233,7 @@ static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + default: +@@ -253,7 +253,7 @@ static int rose_state5_machine(struct sock *sk, struct sk_buff *skb, int framety + if (frametype == ROSE_CLEAR_REQUEST) { + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose_sk(sk)->neighbour->use--; ++ rose_neigh_put(rose_sk(sk)->neighbour); + } + + return 0; +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index b406b1e0fb1e7..42460da0854d5 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -93,11 +93,11 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, + rose_neigh->ax25 = NULL; + rose_neigh->dev = dev; + rose_neigh->count = 0; +- rose_neigh->use = 0; + rose_neigh->dce_mode = 0; + rose_neigh->loopback = 0; + rose_neigh->number = rose_neigh_no++; + rose_neigh->restarted = 0; ++ refcount_set(&rose_neigh->use, 1); + + skb_queue_head_init(&rose_neigh->queue); + +@@ -255,10 +255,10 @@ static void rose_remove_route(struct rose_route *rose_route) + struct rose_route *s; + + if (rose_route->neigh1 != NULL) +- rose_route->neigh1->use--; ++ rose_neigh_put(rose_route->neigh1); + + if (rose_route->neigh2 != NULL) +- rose_route->neigh2->use--; ++ rose_neigh_put(rose_route->neigh2); + + if ((s = rose_route_list) == rose_route) { + rose_route_list = rose_route->next; +@@ -323,7 +323,7 @@ static int rose_del_node(struct rose_route_struct *rose_route, + if (rose_node->neighbour[i] == rose_neigh) { + rose_neigh->count--; + +- if (rose_neigh->count == 0 && rose_neigh->use == 0) { ++ if (rose_neigh->count == 0) { + rose_remove_neigh(rose_neigh); + rose_neigh_put(rose_neigh); + } +@@ -375,11 +375,11 @@ void rose_add_loopback_neigh(void) + sn->ax25 = NULL; + sn->dev = NULL; + sn->count = 0; +- sn->use = 0; + sn->dce_mode = 1; + sn->loopback = 1; + sn->number = rose_neigh_no++; + sn->restarted = 1; ++ refcount_set(&sn->use, 1); + + skb_queue_head_init(&sn->queue); + +@@ -561,8 +561,7 @@ static int rose_clear_routes(void) + s = rose_neigh; + rose_neigh = rose_neigh->next; + +- if (s->use == 0 && !s->loopback) { +- s->count = 0; ++ if (!s->loopback) { + rose_remove_neigh(s); + rose_neigh_put(s); + } +@@ -680,6 +679,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, + for (i = 0; i < node->count; i++) { + if (node->neighbour[i]->restarted) { + res = node->neighbour[i]; ++ rose_neigh_hold(node->neighbour[i]); + goto out; + } + } +@@ -691,6 +691,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, + for (i = 0; i < node->count; i++) { + if (!rose_ftimer_running(node->neighbour[i])) { + res = node->neighbour[i]; ++ rose_neigh_hold(node->neighbour[i]); + goto out; + } + failed = 1; +@@ -780,13 +781,13 @@ static void rose_del_route_by_neigh(struct rose_neigh *rose_neigh) + } + + if (rose_route->neigh1 == rose_neigh) { +- rose_route->neigh1->use--; ++ rose_neigh_put(rose_route->neigh1); + rose_route->neigh1 = NULL; + rose_transmit_clear_request(rose_route->neigh2, rose_route->lci2, ROSE_OUT_OF_ORDER, 0); + } + + if (rose_route->neigh2 == rose_neigh) { +- rose_route->neigh2->use--; ++ rose_neigh_put(rose_route->neigh2); + rose_route->neigh2 = NULL; + rose_transmit_clear_request(rose_route->neigh1, rose_route->lci1, ROSE_OUT_OF_ORDER, 0); + } +@@ -915,7 +916,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + rose_clear_queues(sk); + rose->cause = ROSE_NETWORK_CONGESTION; + rose->diagnostic = 0; +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + rose->neighbour = NULL; + rose->lci = 0; + rose->state = ROSE_STATE_0; +@@ -1040,12 +1041,12 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + + if ((new_lci = rose_new_lci(new_neigh)) == 0) { + rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 71); +- goto out; ++ goto put_neigh; + } + + if ((rose_route = kmalloc(sizeof(*rose_route), GFP_ATOMIC)) == NULL) { + rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 120); +- goto out; ++ goto put_neigh; + } + + rose_route->lci1 = lci; +@@ -1058,8 +1059,8 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + rose_route->lci2 = new_lci; + rose_route->neigh2 = new_neigh; + +- rose_route->neigh1->use++; +- rose_route->neigh2->use++; ++ rose_neigh_hold(rose_route->neigh1); ++ rose_neigh_hold(rose_route->neigh2); + + rose_route->next = rose_route_list; + rose_route_list = rose_route; +@@ -1071,6 +1072,8 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + rose_transmit_link(skb, rose_route->neigh2); + res = 1; + ++put_neigh: ++ rose_neigh_put(new_neigh); + out: + spin_unlock_bh(&rose_route_list_lock); + spin_unlock_bh(&rose_neigh_list_lock); +@@ -1186,7 +1189,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v) + (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign), + rose_neigh->dev ? rose_neigh->dev->name : "???", + rose_neigh->count, +- rose_neigh->use, ++ refcount_read(&rose_neigh->use) - 1, + (rose_neigh->dce_mode) ? "DCE" : "DTE", + (rose_neigh->restarted) ? "yes" : "no", + ax25_display_timer(&rose_neigh->t0timer) / HZ, +diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c +index 1525773e94aa1..c52d7d20c5199 100644 +--- a/net/rose/rose_timer.c ++++ b/net/rose/rose_timer.c +@@ -180,7 +180,7 @@ static void rose_timer_expiry(struct timer_list *t) + break; + + case ROSE_STATE_2: /* T3 */ +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + rose_disconnect(sk, ETIMEDOUT, -1, -1); + break; + +-- +2.50.1 + diff --git a/queue-6.12/net-rose-include-node-references-in-rose_neigh-refco.patch b/queue-6.12/net-rose-include-node-references-in-rose_neigh-refco.patch new file mode 100644 index 0000000000..7791916f25 --- /dev/null +++ b/queue-6.12/net-rose-include-node-references-in-rose_neigh-refco.patch @@ -0,0 +1,142 @@ +From 93c95d20d183797f279f77a77bcda21d14739ed3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Aug 2025 17:58:57 +0900 +Subject: net: rose: include node references in rose_neigh refcount + +From: Takamitsu Iwai + +[ Upstream commit da9c9c877597170b929a6121a68dcd3dd9a80f45 ] + +Current implementation maintains two separate reference counting +mechanisms: the 'count' field in struct rose_neigh tracks references from +rose_node structures, while the 'use' field (now refcount_t) tracks +references from rose_sock. + +This patch merges these two reference counting systems using 'use' field +for proper reference management. Specifically, this patch adds incrementing +and decrementing of rose_neigh->use when rose_neigh->count is incremented +or decremented. + +This patch also modifies rose_rt_free(), rose_rt_device_down() and +rose_clear_route() to properly release references to rose_neigh objects +before freeing a rose_node through rose_remove_node(). + +These changes ensure rose_neigh structures are properly freed only when +all references, including those from rose_node structures, are released. +As a result, this resolves a slab-use-after-free issue reported by Syzbot. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+942297eecf7d2d61d1f1@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=942297eecf7d2d61d1f1 +Signed-off-by: Takamitsu Iwai +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250823085857.47674-4-takamitz@amazon.co.jp +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/rose/rose_route.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index 42460da0854d5..6acbb795c506d 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -178,6 +178,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, + } + } + rose_neigh->count++; ++ rose_neigh_hold(rose_neigh); + + goto out; + } +@@ -187,6 +188,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, + rose_node->neighbour[rose_node->count] = rose_neigh; + rose_node->count++; + rose_neigh->count++; ++ rose_neigh_hold(rose_neigh); + } + + out: +@@ -322,6 +324,7 @@ static int rose_del_node(struct rose_route_struct *rose_route, + for (i = 0; i < rose_node->count; i++) { + if (rose_node->neighbour[i] == rose_neigh) { + rose_neigh->count--; ++ rose_neigh_put(rose_neigh); + + if (rose_neigh->count == 0) { + rose_remove_neigh(rose_neigh); +@@ -430,6 +433,7 @@ int rose_add_loopback_node(const rose_address *address) + rose_node_list = rose_node; + + rose_loopback_neigh->count++; ++ rose_neigh_hold(rose_loopback_neigh); + + out: + spin_unlock_bh(&rose_node_list_lock); +@@ -461,6 +465,7 @@ void rose_del_loopback_node(const rose_address *address) + rose_remove_node(rose_node); + + rose_loopback_neigh->count--; ++ rose_neigh_put(rose_loopback_neigh); + + out: + spin_unlock_bh(&rose_node_list_lock); +@@ -500,6 +505,7 @@ void rose_rt_device_down(struct net_device *dev) + memmove(&t->neighbour[i], &t->neighbour[i + 1], + sizeof(t->neighbour[0]) * + (t->count - i)); ++ rose_neigh_put(s); + } + + if (t->count <= 0) +@@ -543,6 +549,7 @@ static int rose_clear_routes(void) + { + struct rose_neigh *s, *rose_neigh; + struct rose_node *t, *rose_node; ++ int i; + + spin_lock_bh(&rose_node_list_lock); + spin_lock_bh(&rose_neigh_list_lock); +@@ -553,8 +560,12 @@ static int rose_clear_routes(void) + while (rose_node != NULL) { + t = rose_node; + rose_node = rose_node->next; +- if (!t->loopback) ++ ++ if (!t->loopback) { ++ for (i = 0; i < rose_node->count; i++) ++ rose_neigh_put(t->neighbour[i]); + rose_remove_node(t); ++ } + } + + while (rose_neigh != NULL) { +@@ -1189,7 +1200,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v) + (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign), + rose_neigh->dev ? rose_neigh->dev->name : "???", + rose_neigh->count, +- refcount_read(&rose_neigh->use) - 1, ++ refcount_read(&rose_neigh->use) - rose_neigh->count - 1, + (rose_neigh->dce_mode) ? "DCE" : "DTE", + (rose_neigh->restarted) ? "yes" : "no", + ax25_display_timer(&rose_neigh->t0timer) / HZ, +@@ -1294,6 +1305,7 @@ void __exit rose_rt_free(void) + struct rose_neigh *s, *rose_neigh = rose_neigh_list; + struct rose_node *t, *rose_node = rose_node_list; + struct rose_route *u, *rose_route = rose_route_list; ++ int i; + + while (rose_neigh != NULL) { + s = rose_neigh; +@@ -1307,6 +1319,8 @@ void __exit rose_rt_free(void) + t = rose_node; + rose_node = rose_node->next; + ++ for (i = 0; i < t->count; i++) ++ rose_neigh_put(t->neighbour[i]); + rose_remove_node(t); + } + +-- +2.50.1 + diff --git a/queue-6.12/net-rose-split-remove-and-free-operations-in-rose_re.patch b/queue-6.12/net-rose-split-remove-and-free-operations-in-rose_re.patch new file mode 100644 index 0000000000..2c45d3fd03 --- /dev/null +++ b/queue-6.12/net-rose-split-remove-and-free-operations-in-rose_re.patch @@ -0,0 +1,115 @@ +From a2748e21b13e2c0c770b77e13d842cb1edc831e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Aug 2025 17:58:55 +0900 +Subject: net: rose: split remove and free operations in rose_remove_neigh() + +From: Takamitsu Iwai + +[ Upstream commit dcb34659028f856c423a29ef9b4e2571d203444d ] + +The current rose_remove_neigh() performs two distinct operations: +1. Removes rose_neigh from rose_neigh_list +2. Frees the rose_neigh structure + +Split these operations into separate functions to improve maintainability +and prepare for upcoming refcount_t conversion. The timer cleanup remains +in rose_remove_neigh() because free operations can be called from timer +itself. + +This patch introduce rose_neigh_put() to handle the freeing of rose_neigh +structures and modify rose_remove_neigh() to handle removal only. + +Signed-off-by: Takamitsu Iwai +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250823085857.47674-2-takamitz@amazon.co.jp +Signed-off-by: Jakub Kicinski +Stable-dep-of: d860d1faa6b2 ("net: rose: convert 'use' field to refcount_t") +Signed-off-by: Sasha Levin +--- + include/net/rose.h | 8 ++++++++ + net/rose/rose_route.c | 15 ++++++--------- + 2 files changed, 14 insertions(+), 9 deletions(-) + +diff --git a/include/net/rose.h b/include/net/rose.h +index 23267b4efcfa3..174b4f605d849 100644 +--- a/include/net/rose.h ++++ b/include/net/rose.h +@@ -151,6 +151,14 @@ struct rose_sock { + + #define rose_sk(sk) ((struct rose_sock *)(sk)) + ++static inline void rose_neigh_put(struct rose_neigh *rose_neigh) ++{ ++ if (rose_neigh->ax25) ++ ax25_cb_put(rose_neigh->ax25); ++ kfree(rose_neigh->digipeat); ++ kfree(rose_neigh); ++} ++ + /* af_rose.c */ + extern ax25_address rose_callsign; + extern int sysctl_rose_restart_request_timeout; +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index a7054546f52df..b406b1e0fb1e7 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -234,20 +234,12 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) + + if ((s = rose_neigh_list) == rose_neigh) { + rose_neigh_list = rose_neigh->next; +- if (rose_neigh->ax25) +- ax25_cb_put(rose_neigh->ax25); +- kfree(rose_neigh->digipeat); +- kfree(rose_neigh); + return; + } + + while (s != NULL && s->next != NULL) { + if (s->next == rose_neigh) { + s->next = rose_neigh->next; +- if (rose_neigh->ax25) +- ax25_cb_put(rose_neigh->ax25); +- kfree(rose_neigh->digipeat); +- kfree(rose_neigh); + return; + } + +@@ -331,8 +323,10 @@ static int rose_del_node(struct rose_route_struct *rose_route, + if (rose_node->neighbour[i] == rose_neigh) { + rose_neigh->count--; + +- if (rose_neigh->count == 0 && rose_neigh->use == 0) ++ if (rose_neigh->count == 0 && rose_neigh->use == 0) { + rose_remove_neigh(rose_neigh); ++ rose_neigh_put(rose_neigh); ++ } + + rose_node->count--; + +@@ -513,6 +507,7 @@ void rose_rt_device_down(struct net_device *dev) + } + + rose_remove_neigh(s); ++ rose_neigh_put(s); + } + spin_unlock_bh(&rose_neigh_list_lock); + spin_unlock_bh(&rose_node_list_lock); +@@ -569,6 +564,7 @@ static int rose_clear_routes(void) + if (s->use == 0 && !s->loopback) { + s->count = 0; + rose_remove_neigh(s); ++ rose_neigh_put(s); + } + } + +@@ -1301,6 +1297,7 @@ void __exit rose_rt_free(void) + rose_neigh = rose_neigh->next; + + rose_remove_neigh(s); ++ rose_neigh_put(s); + } + + while (rose_node != NULL) { +-- +2.50.1 + diff --git a/queue-6.12/net-stmmac-set-cic-bit-only-for-tx-queues-with-coe.patch b/queue-6.12/net-stmmac-set-cic-bit-only-for-tx-queues-with-coe.patch new file mode 100644 index 0000000000..75e60e664a --- /dev/null +++ b/queue-6.12/net-stmmac-set-cic-bit-only-for-tx-queues-with-coe.patch @@ -0,0 +1,68 @@ +From ae8d420d7e128b9a02396d38cd542c9b890c81dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 12:36:54 +0800 +Subject: net: stmmac: Set CIC bit only for TX queues with COE + +From: Rohan G Thomas + +[ Upstream commit b1eded580ab28119de0b0f21efe37ee2b4419144 ] + +Currently, in the AF_XDP transmit paths, the CIC bit of +TX Desc3 is set for all packets. Setting this bit for +packets transmitting through queues that don't support +checksum offloading causes the TX DMA to get stuck after +transmitting some packets. This patch ensures the CIC bit +of TX Desc3 is set only if the TX queue supports checksum +offloading. + +Fixes: 132c32ee5bc0 ("net: stmmac: Add TX via XDP zero-copy socket") +Signed-off-by: Rohan G Thomas +Reviewed-by: Matthew Gerlach +Link: https://patch.msgid.link/20250825-xgmac-minor-fixes-v3-3-c225fe4444c0@altera.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 058cd9e9fd71d..40d56ff66b6a8 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -2488,6 +2488,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) + struct netdev_queue *nq = netdev_get_tx_queue(priv->dev, queue); + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; + struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[queue]; ++ bool csum = !priv->plat->tx_queues_cfg[queue].coe_unsupported; + struct xsk_buff_pool *pool = tx_q->xsk_pool; + unsigned int entry = tx_q->cur_tx; + struct dma_desc *tx_desc = NULL; +@@ -2573,7 +2574,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) + } + + stmmac_prepare_tx_desc(priv, tx_desc, 1, xdp_desc.len, +- true, priv->mode, true, true, ++ csum, priv->mode, true, true, + xdp_desc.len); + + stmmac_enable_dma_transmission(priv, priv->ioaddr, queue); +@@ -4902,6 +4903,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue, + { + struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[queue]; + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; ++ bool csum = !priv->plat->tx_queues_cfg[queue].coe_unsupported; + unsigned int entry = tx_q->cur_tx; + struct dma_desc *tx_desc; + dma_addr_t dma_addr; +@@ -4953,7 +4955,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue, + stmmac_set_desc_addr(priv, tx_desc, dma_addr); + + stmmac_prepare_tx_desc(priv, tx_desc, 1, xdpf->len, +- true, priv->mode, true, true, ++ csum, priv->mode, true, true, + xdpf->len); + + tx_q->tx_count_frames++; +-- +2.50.1 + diff --git a/queue-6.12/net-stmmac-xgmac-correct-supported-speed-modes.patch b/queue-6.12/net-stmmac-xgmac-correct-supported-speed-modes.patch new file mode 100644 index 0000000000..8d71078933 --- /dev/null +++ b/queue-6.12/net-stmmac-xgmac-correct-supported-speed-modes.patch @@ -0,0 +1,96 @@ +From 1a4d2517f1d21daef0a273d2adbfac5da7ae5030 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 12:36:53 +0800 +Subject: net: stmmac: xgmac: Correct supported speed modes + +From: Rohan G Thomas + +[ Upstream commit 42ef11b2bff5b6a2910c28d2ea47cc00e0fbcaec ] + +Correct supported speed modes as per the XGMAC databook. +Commit 9cb54af214a7 ("net: stmmac: Fix IP-cores specific +MAC capabilities") removes support for 10M, 100M and +1000HD. 1000HD is not supported by XGMAC IP, but it does +support 10M and 100M FD mode for XGMAC version >= 2_20, +and it also supports 10M and 100M HD mode if the HDSEL bit +is set in the MAC_HW_FEATURE0 reg. This commit enables support +for 10M and 100M speed modes for XGMAC IP based on XGMAC +version and MAC capabilities. + +Fixes: 9cb54af214a7 ("net: stmmac: Fix IP-cores specific MAC capabilities") +Signed-off-by: Rohan G Thomas +Reviewed-by: Matthew Gerlach +Link: https://patch.msgid.link/20250825-xgmac-minor-fixes-v3-2-c225fe4444c0@altera.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 13 +++++++++++-- + drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 5 +++++ + 2 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +index f519d43738b08..445259f2ee935 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +@@ -47,6 +47,14 @@ static void dwxgmac2_core_init(struct mac_device_info *hw, + writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN); + } + ++static void dwxgmac2_update_caps(struct stmmac_priv *priv) ++{ ++ if (!priv->dma_cap.mbps_10_100) ++ priv->hw->link.caps &= ~(MAC_10 | MAC_100); ++ else if (!priv->dma_cap.half_duplex) ++ priv->hw->link.caps &= ~(MAC_10HD | MAC_100HD); ++} ++ + static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable) + { + u32 tx = readl(ioaddr + XGMAC_TX_CONFIG); +@@ -1532,6 +1540,7 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, + + const struct stmmac_ops dwxgmac210_ops = { + .core_init = dwxgmac2_core_init, ++ .update_caps = dwxgmac2_update_caps, + .set_mac = dwxgmac2_set_mac, + .rx_ipc = dwxgmac2_rx_ipc, + .rx_queue_enable = dwxgmac2_rx_queue_enable, +@@ -1646,8 +1655,8 @@ int dwxgmac2_setup(struct stmmac_priv *priv) + mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); + + mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | +- MAC_1000FD | MAC_2500FD | MAC_5000FD | +- MAC_10000FD; ++ MAC_10 | MAC_100 | MAC_1000FD | ++ MAC_2500FD | MAC_5000FD | MAC_10000FD; + mac->link.duplex = 0; + mac->link.speed10 = XGMAC_CONFIG_SS_10_MII; + mac->link.speed100 = XGMAC_CONFIG_SS_100_MII; +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +index 7201a38842651..4d6bb995d8d84 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +@@ -382,8 +382,11 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, + static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, + struct dma_features *dma_cap) + { ++ struct stmmac_priv *priv; + u32 hw_cap; + ++ priv = container_of(dma_cap, struct stmmac_priv, dma_cap); ++ + /* MAC HW feature 0 */ + hw_cap = readl(ioaddr + XGMAC_HW_FEATURE0); + dma_cap->edma = (hw_cap & XGMAC_HWFEAT_EDMA) >> 31; +@@ -406,6 +409,8 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, + dma_cap->vlhash = (hw_cap & XGMAC_HWFEAT_VLHASH) >> 4; + dma_cap->half_duplex = (hw_cap & XGMAC_HWFEAT_HDSEL) >> 3; + dma_cap->mbps_1000 = (hw_cap & XGMAC_HWFEAT_GMIISEL) >> 1; ++ if (dma_cap->mbps_1000 && priv->synopsys_id >= DWXGMAC_CORE_2_20) ++ dma_cap->mbps_10_100 = 1; + + /* MAC HW feature 1 */ + hw_cap = readl(ioaddr + XGMAC_HW_FEATURE1); +-- +2.50.1 + diff --git a/queue-6.12/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch b/queue-6.12/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch new file mode 100644 index 0000000000..ad52ecd3fd --- /dev/null +++ b/queue-6.12/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch @@ -0,0 +1,49 @@ +From 21d8fd933800cb4019e17798b522eca54b67be1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 12:36:52 +0800 +Subject: net: stmmac: xgmac: Do not enable RX FIFO Overflow interrupts + +From: Rohan G Thomas + +[ Upstream commit 4f23382841e67174211271a454811dd17c0ef3c5 ] + +Enabling RX FIFO Overflow interrupts is counterproductive +and causes an interrupt storm when RX FIFO overflows. +Disabling this interrupt has no side effect and eliminates +interrupt storms when the RX FIFO overflows. + +Commit 8a7cb245cf28 ("net: stmmac: Do not enable RX FIFO +overflow interrupts") disables RX FIFO overflow interrupts +for DWMAC4 IP and removes the corresponding handling of +this interrupt. This patch is doing the same thing for +XGMAC IP. + +Fixes: 2142754f8b9c ("net: stmmac: Add MAC related callbacks for XGMAC2") +Signed-off-by: Rohan G Thomas +Reviewed-by: Matthew Gerlach +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250825-xgmac-minor-fixes-v3-1-c225fe4444c0@altera.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +index 5dcc95bc0ad28..7201a38842651 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +@@ -203,10 +203,6 @@ static void dwxgmac2_dma_rx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, + } + + writel(value, ioaddr + XGMAC_MTL_RXQ_OPMODE(channel)); +- +- /* Enable MTL RX overflow */ +- value = readl(ioaddr + XGMAC_MTL_QINTEN(channel)); +- writel(value | XGMAC_RXOIE, ioaddr + XGMAC_MTL_QINTEN(channel)); + } + + static void dwxgmac2_dma_tx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, +-- +2.50.1 + diff --git a/queue-6.12/of-reserved_mem-restructure-call-site-for-dma_contig.patch b/queue-6.12/of-reserved_mem-restructure-call-site-for-dma_contig.patch new file mode 100644 index 0000000000..a1db2b0780 --- /dev/null +++ b/queue-6.12/of-reserved_mem-restructure-call-site-for-dma_contig.patch @@ -0,0 +1,101 @@ +From 2c88ee76ee491dd224dfb5c628dfd172dd4ea8a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Aug 2025 10:24:21 -0700 +Subject: of: reserved_mem: Restructure call site for + dma_contiguous_early_fixup() + +From: Oreoluwa Babatunde + +[ Upstream commit 2c223f7239f376a90d71903ec474ba887cf21d94 ] + +Restructure the call site for dma_contiguous_early_fixup() to +where the reserved_mem nodes are being parsed from the DT so that +dma_mmu_remap[] is populated before dma_contiguous_remap() is called. + +Fixes: 8a6e02d0c00e ("of: reserved_mem: Restructure how the reserved memory regions are processed") +Signed-off-by: Oreoluwa Babatunde +Tested-by: William Zhang +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20250806172421.2748302-1-oreoluwa.babatunde@oss.qualcomm.com +Signed-off-by: Sasha Levin +--- + drivers/of/of_reserved_mem.c | 16 ++++++++++++---- + include/linux/dma-map-ops.h | 3 +++ + kernel/dma/contiguous.c | 2 -- + 3 files changed, 15 insertions(+), 6 deletions(-) + +diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c +index 45445a1600a96..7b5d6562fe4a0 100644 +--- a/drivers/of/of_reserved_mem.c ++++ b/drivers/of/of_reserved_mem.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #include "of_private.h" + +@@ -128,13 +129,17 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, + base = dt_mem_next_cell(dt_root_addr_cells, &prop); + size = dt_mem_next_cell(dt_root_size_cells, &prop); + +- if (size && +- early_init_dt_reserve_memory(base, size, nomap) == 0) ++ if (size && early_init_dt_reserve_memory(base, size, nomap) == 0) { ++ /* Architecture specific contiguous memory fixup. */ ++ if (of_flat_dt_is_compatible(node, "shared-dma-pool") && ++ of_get_flat_dt_prop(node, "reusable", NULL)) ++ dma_contiguous_early_fixup(base, size); + pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n", + uname, &base, (unsigned long)(size / SZ_1M)); +- else ++ } else { + pr_err("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n", + uname, &base, (unsigned long)(size / SZ_1M)); ++ } + + len -= t_len; + } +@@ -417,7 +422,10 @@ static int __init __reserved_mem_alloc_size(unsigned long node, const char *unam + uname, (unsigned long)(size / SZ_1M)); + return -ENOMEM; + } +- ++ /* Architecture specific contiguous memory fixup. */ ++ if (of_flat_dt_is_compatible(node, "shared-dma-pool") && ++ of_get_flat_dt_prop(node, "reusable", NULL)) ++ dma_contiguous_early_fixup(base, size); + /* Save region in the reserved_mem array */ + fdt_reserved_mem_save_node(node, uname, base, size); + return 0; +diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h +index b7773201414c2..b42408a24ad13 100644 +--- a/include/linux/dma-map-ops.h ++++ b/include/linux/dma-map-ops.h +@@ -153,6 +153,9 @@ static inline void dma_free_contiguous(struct device *dev, struct page *page, + { + __free_pages(page, get_order(size)); + } ++static inline void dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) ++{ ++} + #endif /* CONFIG_DMA_CMA*/ + + #ifdef CONFIG_DMA_DECLARE_COHERENT +diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c +index 8df0dfaaca18e..9e5d63efe7c57 100644 +--- a/kernel/dma/contiguous.c ++++ b/kernel/dma/contiguous.c +@@ -480,8 +480,6 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem) + pr_err("Reserved memory: unable to setup CMA region\n"); + return err; + } +- /* Architecture specific contiguous memory fixup. */ +- dma_contiguous_early_fixup(rmem->base, rmem->size); + + if (default_cma) + dma_contiguous_default_area = cma; +-- +2.50.1 + diff --git a/queue-6.12/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch b/queue-6.12/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch new file mode 100644 index 0000000000..adf196c29d --- /dev/null +++ b/queue-6.12/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch @@ -0,0 +1,135 @@ +From 136619f1311981f6639f4ce9ef7d3c5800678d66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 08:55:43 +0200 +Subject: phy: mscc: Fix when PTP clock is register and unregister + +From: Horatiu Vultur + +[ Upstream commit 882e57cbc7204662f6c5672d5b04336c1d790b03 ] + +It looks like that every time when the interface was set down and up the +driver was creating a new ptp clock. On top of this the function +ptp_clock_unregister was never called. +Therefore fix this by calling ptp_clock_register and initialize the +mii_ts struct inside the probe function and call ptp_clock_unregister when +driver is removed. + +Fixes: 7d272e63e0979d ("net: phy: mscc: timestamping and PHC support") +Signed-off-by: Horatiu Vultur +Reviewed-by: Vadim Fedorenko +Reviewed-by: Vladimir Oltean +Link: https://patch.msgid.link/20250825065543.2916334-1-horatiu.vultur@microchip.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mscc/mscc.h | 4 ++++ + drivers/net/phy/mscc/mscc_main.c | 4 +--- + drivers/net/phy/mscc/mscc_ptp.c | 34 ++++++++++++++++++++------------ + 3 files changed, 26 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h +index 58c6d47fbe046..2bfe314ef881c 100644 +--- a/drivers/net/phy/mscc/mscc.h ++++ b/drivers/net/phy/mscc/mscc.h +@@ -481,6 +481,7 @@ static inline void vsc8584_config_macsec_intr(struct phy_device *phydev) + void vsc85xx_link_change_notify(struct phy_device *phydev); + void vsc8584_config_ts_intr(struct phy_device *phydev); + int vsc8584_ptp_init(struct phy_device *phydev); ++void vsc8584_ptp_deinit(struct phy_device *phydev); + int vsc8584_ptp_probe_once(struct phy_device *phydev); + int vsc8584_ptp_probe(struct phy_device *phydev); + irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev); +@@ -495,6 +496,9 @@ static inline int vsc8584_ptp_init(struct phy_device *phydev) + { + return 0; + } ++static inline void vsc8584_ptp_deinit(struct phy_device *phydev) ++{ ++} + static inline int vsc8584_ptp_probe_once(struct phy_device *phydev) + { + return 0; +diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c +index 42cafa68c4009..19983b206405c 100644 +--- a/drivers/net/phy/mscc/mscc_main.c ++++ b/drivers/net/phy/mscc/mscc_main.c +@@ -2337,9 +2337,7 @@ static int vsc85xx_probe(struct phy_device *phydev) + + static void vsc85xx_remove(struct phy_device *phydev) + { +- struct vsc8531_private *priv = phydev->priv; +- +- skb_queue_purge(&priv->rx_skbs_list); ++ vsc8584_ptp_deinit(phydev); + } + + /* Microsemi VSC85xx PHYs */ +diff --git a/drivers/net/phy/mscc/mscc_ptp.c b/drivers/net/phy/mscc/mscc_ptp.c +index 80992827a3bdd..920f35f8f84e7 100644 +--- a/drivers/net/phy/mscc/mscc_ptp.c ++++ b/drivers/net/phy/mscc/mscc_ptp.c +@@ -1295,7 +1295,6 @@ static void vsc8584_set_input_clk_configured(struct phy_device *phydev) + + static int __vsc8584_init_ptp(struct phy_device *phydev) + { +- struct vsc8531_private *vsc8531 = phydev->priv; + static const u32 ltc_seq_e[] = { 0, 400000, 0, 0, 0 }; + static const u8 ltc_seq_a[] = { 8, 6, 5, 4, 2 }; + u32 val; +@@ -1512,17 +1511,7 @@ static int __vsc8584_init_ptp(struct phy_device *phydev) + + vsc85xx_ts_eth_cmp1_sig(phydev); + +- vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; +- vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; +- vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; +- vsc8531->mii_ts.ts_info = vsc85xx_ts_info; +- phydev->mii_ts = &vsc8531->mii_ts; +- +- memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); +- +- vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, +- &phydev->mdio.dev); +- return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); ++ return 0; + } + + void vsc8584_config_ts_intr(struct phy_device *phydev) +@@ -1549,6 +1538,16 @@ int vsc8584_ptp_init(struct phy_device *phydev) + return 0; + } + ++void vsc8584_ptp_deinit(struct phy_device *phydev) ++{ ++ struct vsc8531_private *vsc8531 = phydev->priv; ++ ++ if (vsc8531->ptp->ptp_clock) { ++ ptp_clock_unregister(vsc8531->ptp->ptp_clock); ++ skb_queue_purge(&vsc8531->rx_skbs_list); ++ } ++} ++ + irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev) + { + struct vsc8531_private *priv = phydev->priv; +@@ -1609,7 +1608,16 @@ int vsc8584_ptp_probe(struct phy_device *phydev) + + vsc8531->ptp->phydev = phydev; + +- return 0; ++ vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; ++ vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; ++ vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; ++ vsc8531->mii_ts.ts_info = vsc85xx_ts_info; ++ phydev->mii_ts = &vsc8531->mii_ts; ++ ++ memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); ++ vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, ++ &phydev->mdio.dev); ++ return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); + } + + int vsc8584_ptp_probe_once(struct phy_device *phydev) +-- +2.50.1 + diff --git a/queue-6.12/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch b/queue-6.12/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch new file mode 100644 index 0000000000..b8ffdf603c --- /dev/null +++ b/queue-6.12/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch @@ -0,0 +1,68 @@ +From b55c17db53adb9617ed394336f77e7e15147127c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 May 2025 10:11:04 +0530 +Subject: powerpc/kvm: Fix ifdef to remove build warning + +From: Madhavan Srinivasan + +[ Upstream commit 88688a2c8ac6c8036d983ad8b34ce191c46a10aa ] + +When compiling for pseries or powernv defconfig with "make C=1", +these warning were reported bu sparse tool in powerpc/kernel/kvm.c + +arch/powerpc/kernel/kvm.c:635:9: warning: switch with no cases +arch/powerpc/kernel/kvm.c:646:9: warning: switch with no cases + +Currently #ifdef were added after the switch case which are specific +for BOOKE and PPC_BOOK3S_32. These are not enabled in pseries/powernv +defconfig. Fix it by moving the #ifdef before switch(){} + +Fixes: cbe487fac7fc0 ("KVM: PPC: Add mtsrin PV code") +Tested-by: Venkat Rao Bagalkote +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250518044107.39928-1-maddy@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/kvm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c +index 5b3c093611baf..7209d00a9c257 100644 +--- a/arch/powerpc/kernel/kvm.c ++++ b/arch/powerpc/kernel/kvm.c +@@ -632,19 +632,19 @@ static void __init kvm_check_ins(u32 *inst, u32 features) + #endif + } + +- switch (inst_no_rt & ~KVM_MASK_RB) { + #ifdef CONFIG_PPC_BOOK3S_32 ++ switch (inst_no_rt & ~KVM_MASK_RB) { + case KVM_INST_MTSRIN: + if (features & KVM_MAGIC_FEAT_SR) { + u32 inst_rb = _inst & KVM_MASK_RB; + kvm_patch_ins_mtsrin(inst, inst_rt, inst_rb); + } + break; +-#endif + } ++#endif + +- switch (_inst) { + #ifdef CONFIG_BOOKE ++ switch (_inst) { + case KVM_INST_WRTEEI_0: + kvm_patch_ins_wrteei_0(inst); + break; +@@ -652,8 +652,8 @@ static void __init kvm_check_ins(u32 *inst, u32 features) + case KVM_INST_WRTEEI_1: + kvm_patch_ins_wrtee(inst, 0, 1); + break; +-#endif + } ++#endif + } + + extern u32 kvm_template_start[]; +-- +2.50.1 + diff --git a/queue-6.12/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch b/queue-6.12/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch new file mode 100644 index 0000000000..53ece61a6b --- /dev/null +++ b/queue-6.12/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch @@ -0,0 +1,72 @@ +From a8034c1d5c73cced6548531d13f4c797523ded0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Aug 2025 14:13:14 +0000 +Subject: sctp: initialize more fields in sctp_v6_from_sk() + +From: Eric Dumazet + +[ Upstream commit 2e8750469242cad8f01f320131fd5a6f540dbb99 ] + +syzbot found that sin6_scope_id was not properly initialized, +leading to undefined behavior. + +Clear sin6_scope_id and sin6_flowinfo. + +BUG: KMSAN: uninit-value in __sctp_v6_cmp_addr+0x887/0x8c0 net/sctp/ipv6.c:649 + __sctp_v6_cmp_addr+0x887/0x8c0 net/sctp/ipv6.c:649 + sctp_inet6_cmp_addr+0x4f2/0x510 net/sctp/ipv6.c:983 + sctp_bind_addr_conflict+0x22a/0x3b0 net/sctp/bind_addr.c:390 + sctp_get_port_local+0x21eb/0x2440 net/sctp/socket.c:8452 + sctp_get_port net/sctp/socket.c:8523 [inline] + sctp_listen_start net/sctp/socket.c:8567 [inline] + sctp_inet_listen+0x710/0xfd0 net/sctp/socket.c:8636 + __sys_listen_socket net/socket.c:1912 [inline] + __sys_listen net/socket.c:1927 [inline] + __do_sys_listen net/socket.c:1932 [inline] + __se_sys_listen net/socket.c:1930 [inline] + __x64_sys_listen+0x343/0x4c0 net/socket.c:1930 + x64_sys_call+0x271d/0x3e20 arch/x86/include/generated/asm/syscalls_64.h:51 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xd9/0x210 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Local variable addr.i.i created at: + sctp_get_port net/sctp/socket.c:8515 [inline] + sctp_listen_start net/sctp/socket.c:8567 [inline] + sctp_inet_listen+0x650/0xfd0 net/sctp/socket.c:8636 + __sys_listen_socket net/socket.c:1912 [inline] + __sys_listen net/socket.c:1927 [inline] + __do_sys_listen net/socket.c:1932 [inline] + __se_sys_listen net/socket.c:1930 [inline] + __x64_sys_listen+0x343/0x4c0 net/socket.c:1930 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+e69f06a0f30116c68056@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68adc0a2.050a0220.37038e.00c4.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Marcelo Ricardo Leitner +Acked-by: Xin Long +Link: https://patch.msgid.link/20250826141314.1802610-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/ipv6.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c +index 38e2fbdcbeac4..9f835e674c599 100644 +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -546,7 +546,9 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) + { + addr->v6.sin6_family = AF_INET6; + addr->v6.sin6_port = 0; ++ addr->v6.sin6_flowinfo = 0; + addr->v6.sin6_addr = sk->sk_v6_rcv_saddr; ++ addr->v6.sin6_scope_id = 0; + } + + /* Initialize sk->sk_rcv_saddr from sctp_addr. */ +-- +2.50.1 + diff --git a/queue-6.12/series b/queue-6.12/series index e260a49596..7f624fbcaa 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -16,3 +16,51 @@ asoc-codecs-tx-macro-correct-tx_macro_component_drv-.patch erofs-fix-atomic-context-detection-when-config_debug.patch acpi-ec-add-device-to-acpi_ec_no_wakeup-qurik-list.patch vhost-net-protect-ubufs-with-rcu-read-lock-in-vhost_net_ubuf_put.patch +net-ipv4-fix-regression-in-local-broadcast-routes.patch +drm-msm-defer-fd_install-in-submit-ioctl.patch +of-reserved_mem-restructure-call-site-for-dma_contig.patch +drm-msm-kms-move-snapshot-init-earlier-in-kms-init.patch +drm-msm-update-the-high-bitfield-of-certain-dsi-regi.patch +drm-mediatek-add-error-handling-for-old-state-crtc-i.patch +powerpc-kvm-fix-ifdef-to-remove-build-warning.patch +hid-input-rename-hidinput_set_battery_charge_status.patch +hid-input-report-battery-status-changes-immediately.patch +net-macb-fix-unregister_netdev-call-order-in-macb_re.patch +bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch +bluetooth-hci_event-mark-connection-as-closed-during.patch +bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch +bluetooth-hci_sync-fix-set_local_name-race-condition.patch +atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch +drm-nouveau-remove-unused-increment-in-gm200_flcn_pi.patch +drm-nouveau-remove-unused-memory-target-test.patch +ice-don-t-leave-device-non-functional-if-tx-schedule.patch +ice-use-fixed-adapter-index-for-e825c-embedded-devic.patch +ice-fix-incorrect-counter-for-buffer-allocation-fail.patch +dt-bindings-display-msm-qcom-mdp5-drop-lut-clock.patch +net-dlink-fix-multicast-stats-being-counted-incorrec.patch +efi-stmm-fix-incorrect-buffer-allocation-method.patch +drm-xe-xe_sync-avoid-race-during-ufence-signaling.patch +drm-xe-don-t-trigger-rebind-on-initial-dma-buf-valid.patch +phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch +bnxt_en-fix-memory-corruption-when-fw-resources-chan.patch +bnxt_en-adjust-tx-rings-if-reservation-is-less-than-.patch +bnxt_en-fix-stats-context-reservation-logic.patch +net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch +net-mlx5-fix-lockdep-assertion-on-sync-reset-unload-.patch +net-mlx5-nack-sync-reset-when-sfs-are-present.patch +net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch +net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch +net-mlx5e-set-local-xoff-after-fw-update.patch +net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch +net-stmmac-xgmac-correct-supported-speed-modes.patch +net-stmmac-set-cic-bit-only-for-tx-queues-with-coe.patch +hv_netvsc-link-queues-to-napis.patch +net-hv_netvsc-fix-loss-of-early-receive-events-from-.patch +net-rose-split-remove-and-free-operations-in-rose_re.patch +net-rose-convert-use-field-to-refcount_t.patch +net-rose-include-node-references-in-rose_neigh-refco.patch +sctp-initialize-more-fields-in-sctp_v6_from_sk.patch +l2tp-do-not-use-sock_hold-in-pppol2tp_session_get_so.patch +fbnic-move-phylink-resume-out-of-service_task-and-in.patch +efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch +net-macb-disable-clocks-once.patch diff --git a/queue-6.16/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch b/queue-6.16/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch new file mode 100644 index 0000000000..7011de7949 --- /dev/null +++ b/queue-6.16/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch @@ -0,0 +1,192 @@ +From f9253d2466a57b581daa54dbfd40320a109d165f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Aug 2025 02:18:24 +0000 +Subject: atm: atmtcp: Prevent arbitrary write in atmtcp_recv_control(). + +From: Kuniyuki Iwashima + +[ Upstream commit ec79003c5f9d2c7f9576fc69b8dbda80305cbe3a ] + +syzbot reported the splat below. [0] + +When atmtcp_v_open() or atmtcp_v_close() is called via connect() +or close(), atmtcp_send_control() is called to send an in-kernel +special message. + +The message has ATMTCP_HDR_MAGIC in atmtcp_control.hdr.length. +Also, a pointer of struct atm_vcc is set to atmtcp_control.vcc. + +The notable thing is struct atmtcp_control is uAPI but has a +space for an in-kernel pointer. + + struct atmtcp_control { + struct atmtcp_hdr hdr; /* must be first */ + ... + atm_kptr_t vcc; /* both directions */ + ... + } __ATM_API_ALIGN; + + typedef struct { unsigned char _[8]; } __ATM_API_ALIGN atm_kptr_t; + +The special message is processed in atmtcp_recv_control() called +from atmtcp_c_send(). + +atmtcp_c_send() is vcc->dev->ops->send() and called from 2 paths: + + 1. .ndo_start_xmit() (vcc->send() == atm_send_aal0()) + 2. vcc_sendmsg() + +The problem is sendmsg() does not validate the message length and +userspace can abuse atmtcp_recv_control() to overwrite any kptr +by atmtcp_control. + +Let's add a new ->pre_send() hook to validate messages from sendmsg(). + +[0]: +Oops: general protection fault, probably for non-canonical address 0xdffffc00200000ab: 0000 [#1] SMP KASAN PTI +KASAN: probably user-memory-access in range [0x0000000100000558-0x000000010000055f] +CPU: 0 UID: 0 PID: 5865 Comm: syz-executor331 Not tainted 6.17.0-rc1-syzkaller-00215-gbab3ce404553 #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/12/2025 +RIP: 0010:atmtcp_recv_control drivers/atm/atmtcp.c:93 [inline] +RIP: 0010:atmtcp_c_send+0x1da/0x950 drivers/atm/atmtcp.c:297 +Code: 4d 8d 75 1a 4c 89 f0 48 c1 e8 03 42 0f b6 04 20 84 c0 0f 85 15 06 00 00 41 0f b7 1e 4d 8d b7 60 05 00 00 4c 89 f0 48 c1 e8 03 <42> 0f b6 04 20 84 c0 0f 85 13 06 00 00 66 41 89 1e 4d 8d 75 1c 4c +RSP: 0018:ffffc90003f5f810 EFLAGS: 00010203 +RAX: 00000000200000ab RBX: 0000000000000000 RCX: 0000000000000000 +RDX: ffff88802a510000 RSI: 00000000ffffffff RDI: ffff888030a6068c +RBP: ffff88802699fb40 R08: ffff888030a606eb R09: 1ffff1100614c0dd +R10: dffffc0000000000 R11: ffffffff8718fc40 R12: dffffc0000000000 +R13: ffff888030a60680 R14: 000000010000055f R15: 00000000ffffffff +FS: 00007f8d7e9236c0(0000) GS:ffff888125c1c000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 000000000045ad50 CR3: 0000000075bde000 CR4: 00000000003526f0 +Call Trace: + + vcc_sendmsg+0xa10/0xc60 net/atm/common.c:645 + sock_sendmsg_nosec net/socket.c:714 [inline] + __sock_sendmsg+0x219/0x270 net/socket.c:729 + ____sys_sendmsg+0x505/0x830 net/socket.c:2614 + ___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668 + __sys_sendmsg net/socket.c:2700 [inline] + __do_sys_sendmsg net/socket.c:2705 [inline] + __se_sys_sendmsg net/socket.c:2703 [inline] + __x64_sys_sendmsg+0x19b/0x260 net/socket.c:2703 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +RIP: 0033:0x7f8d7e96a4a9 +Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 51 18 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f8d7e923198 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +RAX: ffffffffffffffda RBX: 00007f8d7e9f4308 RCX: 00007f8d7e96a4a9 +RDX: 0000000000000000 RSI: 0000200000000240 RDI: 0000000000000005 +RBP: 00007f8d7e9f4300 R08: 65732f636f72702f R09: 65732f636f72702f +R10: 65732f636f72702f R11: 0000000000000246 R12: 00007f8d7e9c10ac +R13: 00007f8d7e9231a0 R14: 0000200000000200 R15: 0000200000000250 + +Modules linked in: + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+1741b56d54536f4ec349@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68a6767c.050a0220.3d78fd.0011.GAE@google.com/ +Tested-by: syzbot+1741b56d54536f4ec349@syzkaller.appspotmail.com +Signed-off-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250821021901.2814721-1-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/atm/atmtcp.c | 17 ++++++++++++++--- + include/linux/atmdev.h | 1 + + net/atm/common.c | 15 ++++++++++++--- + 3 files changed, 27 insertions(+), 6 deletions(-) + +diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c +index eeae160c898d3..fa3c76a2b49d1 100644 +--- a/drivers/atm/atmtcp.c ++++ b/drivers/atm/atmtcp.c +@@ -279,6 +279,19 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) + return NULL; + } + ++static int atmtcp_c_pre_send(struct atm_vcc *vcc, struct sk_buff *skb) ++{ ++ struct atmtcp_hdr *hdr; ++ ++ if (skb->len < sizeof(struct atmtcp_hdr)) ++ return -EINVAL; ++ ++ hdr = (struct atmtcp_hdr *)skb->data; ++ if (hdr->length == ATMTCP_HDR_MAGIC) ++ return -EINVAL; ++ ++ return 0; ++} + + static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + { +@@ -288,9 +301,6 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + struct sk_buff *new_skb; + int result = 0; + +- if (skb->len < sizeof(struct atmtcp_hdr)) +- goto done; +- + dev = vcc->dev_data; + hdr = (struct atmtcp_hdr *) skb->data; + if (hdr->length == ATMTCP_HDR_MAGIC) { +@@ -347,6 +357,7 @@ static const struct atmdev_ops atmtcp_v_dev_ops = { + + static const struct atmdev_ops atmtcp_c_dev_ops = { + .close = atmtcp_c_close, ++ .pre_send = atmtcp_c_pre_send, + .send = atmtcp_c_send + }; + +diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h +index 45f2f278b50a8..70807c679f1ab 100644 +--- a/include/linux/atmdev.h ++++ b/include/linux/atmdev.h +@@ -185,6 +185,7 @@ struct atmdev_ops { /* only send is required */ + int (*compat_ioctl)(struct atm_dev *dev,unsigned int cmd, + void __user *arg); + #endif ++ int (*pre_send)(struct atm_vcc *vcc, struct sk_buff *skb); + int (*send)(struct atm_vcc *vcc,struct sk_buff *skb); + int (*send_bh)(struct atm_vcc *vcc, struct sk_buff *skb); + int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags); +diff --git a/net/atm/common.c b/net/atm/common.c +index d7f7976ea13ac..881c7f259dbd4 100644 +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -635,18 +635,27 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size) + + skb->dev = NULL; /* for paths shared with net_device interfaces */ + if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) { +- atm_return_tx(vcc, skb); +- kfree_skb(skb); + error = -EFAULT; +- goto out; ++ goto free_skb; + } + if (eff != size) + memset(skb->data + size, 0, eff-size); ++ ++ if (vcc->dev->ops->pre_send) { ++ error = vcc->dev->ops->pre_send(vcc, skb); ++ if (error) ++ goto free_skb; ++ } ++ + error = vcc->dev->ops->send(vcc, skb); + error = error ? error : size; + out: + release_sock(sk); + return error; ++free_skb: ++ atm_return_tx(vcc, skb); ++ kfree_skb(skb); ++ goto out; + } + + __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait) +-- +2.50.1 + diff --git a/queue-6.16/block-validate-qos-before-calling-__rq_qos_done_bio.patch b/queue-6.16/block-validate-qos-before-calling-__rq_qos_done_bio.patch new file mode 100644 index 0000000000..314f96d12b --- /dev/null +++ b/queue-6.16/block-validate-qos-before-calling-__rq_qos_done_bio.patch @@ -0,0 +1,54 @@ +From 71ee7d6d8a5e362507936a311f858e1885a745db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Aug 2025 22:00:32 +0530 +Subject: block: validate QoS before calling __rq_qos_done_bio() + +From: Nilay Shroff + +[ Upstream commit e3ef9445cd9d90e43de0bd3cd55d437773dfd139 ] + +If a bio has BIO_QOS_xxx set, it doesn't guarantee that q->rq_qos is +also present at-least for stacked block devices. For instance, in case +of NVMe when multipath is enabled, the bottom device may have QoS +enabled but top device doesn't. So always validate QoS is enabled and +q->rq_qos is present before calling __rq_qos_done_bio(). + +Fixes: 370ac285f23a ("block: avoid cpu_hotplug_lock depedency on freeze_lock") +Reported-by: Venkat Rao Bagalkote +Closes: https://lore.kernel.org/all/3a07b752-06a4-4eee-b302-f4669feb859d@linux.ibm.com/ +Signed-off-by: Nilay Shroff +Link: https://lore.kernel.org/r/20250826163128.1952394-1-nilay@linux.ibm.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-rq-qos.h | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/block/blk-rq-qos.h b/block/blk-rq-qos.h +index 1fe22000a3790..b538f2c0febc2 100644 +--- a/block/blk-rq-qos.h ++++ b/block/blk-rq-qos.h +@@ -149,12 +149,15 @@ static inline void rq_qos_done_bio(struct bio *bio) + q = bdev_get_queue(bio->bi_bdev); + + /* +- * If a bio has BIO_QOS_xxx set, it implicitly implies that +- * q->rq_qos is present. So, we skip re-checking q->rq_qos +- * here as an extra optimization and directly call +- * __rq_qos_done_bio(). ++ * A BIO may carry BIO_QOS_* flags even if the associated request_queue ++ * does not have rq_qos enabled. This can happen with stacked block ++ * devices — for example, NVMe multipath, where it's possible that the ++ * bottom device has QoS enabled but the top device does not. Therefore, ++ * always verify that q->rq_qos is present and QoS is enabled before ++ * calling __rq_qos_done_bio(). + */ +- __rq_qos_done_bio(q->rq_qos, bio); ++ if (test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags) && q->rq_qos) ++ __rq_qos_done_bio(q->rq_qos, bio); + } + + static inline void rq_qos_throttle(struct request_queue *q, struct bio *bio) +-- +2.50.1 + diff --git a/queue-6.16/bluetooth-hci_conn-make-unacked-packet-handling-more.patch b/queue-6.16/bluetooth-hci_conn-make-unacked-packet-handling-more.patch new file mode 100644 index 0000000000..89d513afdc --- /dev/null +++ b/queue-6.16/bluetooth-hci_conn-make-unacked-packet-handling-more.patch @@ -0,0 +1,106 @@ +From dd7c40fab01a5e41e822b0b35d0d9fcb075a7e10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Aug 2025 13:40:18 -0400 +Subject: Bluetooth: hci_conn: Make unacked packet handling more robust + +From: Luiz Augusto von Dentz + +[ Upstream commit 5d7eba62e5eb68347de59b31b347b24f304cf21c ] + +This attempts to make unacked packet handling more robust by detecting +if there are no connections left then restore all buffers of the +respective pool. + +Fixes: 5638d9ea9c01 ("Bluetooth: hci_conn: Fix not restoring ISO buffer count on disconnect") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_conn.c | 58 ++++++++++++++++++++++++++++------------ + 1 file changed, 41 insertions(+), 17 deletions(-) + +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index 6a064a6b0e431..ad5574e9a93ee 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -149,8 +149,6 @@ static void hci_conn_cleanup(struct hci_conn *conn) + + hci_chan_list_flush(conn); + +- hci_conn_hash_del(hdev, conn); +- + if (HCI_CONN_HANDLE_UNSET(conn->handle)) + ida_free(&hdev->unset_handle_ida, conn->handle); + +@@ -1142,28 +1140,54 @@ void hci_conn_del(struct hci_conn *conn) + disable_delayed_work_sync(&conn->auto_accept_work); + disable_delayed_work_sync(&conn->idle_work); + +- if (conn->type == ACL_LINK) { +- /* Unacked frames */ +- hdev->acl_cnt += conn->sent; +- } else if (conn->type == LE_LINK) { +- cancel_delayed_work(&conn->le_conn_timeout); ++ /* Remove the connection from the list so unacked logic can detect when ++ * a certain pool is not being utilized. ++ */ ++ hci_conn_hash_del(hdev, conn); + +- if (hdev->le_pkts) +- hdev->le_cnt += conn->sent; ++ /* Handle unacked frames: ++ * ++ * - In case there are no connection, or if restoring the buffers ++ * considered in transist would overflow, restore all buffers to the ++ * pool. ++ * - Otherwise restore just the buffers considered in transit for the ++ * hci_conn ++ */ ++ switch (conn->type) { ++ case ACL_LINK: ++ if (!hci_conn_num(hdev, ACL_LINK) || ++ hdev->acl_cnt + conn->sent > hdev->acl_pkts) ++ hdev->acl_cnt = hdev->acl_pkts; + else + hdev->acl_cnt += conn->sent; +- } else { +- /* Unacked ISO frames */ +- if (conn->type == CIS_LINK || +- conn->type == BIS_LINK || +- conn->type == PA_LINK) { +- if (hdev->iso_pkts) +- hdev->iso_cnt += conn->sent; +- else if (hdev->le_pkts) ++ break; ++ case LE_LINK: ++ cancel_delayed_work(&conn->le_conn_timeout); ++ ++ if (hdev->le_pkts) { ++ if (!hci_conn_num(hdev, LE_LINK) || ++ hdev->le_cnt + conn->sent > hdev->le_pkts) ++ hdev->le_cnt = hdev->le_pkts; ++ else + hdev->le_cnt += conn->sent; ++ } else { ++ if ((!hci_conn_num(hdev, LE_LINK) && ++ !hci_conn_num(hdev, ACL_LINK)) || ++ hdev->acl_cnt + conn->sent > hdev->acl_pkts) ++ hdev->acl_cnt = hdev->acl_pkts; + else + hdev->acl_cnt += conn->sent; + } ++ break; ++ case CIS_LINK: ++ case BIS_LINK: ++ case PA_LINK: ++ if (!hci_iso_count(hdev) || ++ hdev->iso_cnt + conn->sent > hdev->iso_pkts) ++ hdev->iso_cnt = hdev->iso_pkts; ++ else ++ hdev->iso_cnt += conn->sent; ++ break; + } + + skb_queue_purge(&conn->data_q); +-- +2.50.1 + diff --git a/queue-6.16/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch b/queue-6.16/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch new file mode 100644 index 0000000000..d3be6fee1e --- /dev/null +++ b/queue-6.16/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch @@ -0,0 +1,47 @@ +From d392fd1d430b4afc49bb5cca6b24d1c56ea4f18e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Aug 2025 17:04:00 -0400 +Subject: Bluetooth: hci_event: Detect if HCI_EV_NUM_COMP_PKTS is unbalanced + +From: Luiz Augusto von Dentz + +[ Upstream commit 15bf2c6391bafb14a3020d06ec0761bce0803463 ] + +This attempts to detect if HCI_EV_NUM_COMP_PKTS contain an unbalanced +(more than currently considered outstanding) number of packets otherwise +it could cause the hcon->sent to underflow and loop around breaking the +tracking of the outstanding packets pending acknowledgment. + +Fixes: f42809185896 ("Bluetooth: Simplify num_comp_pkts_evt function") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index cadb53e21c0ef..02b2ef9a75746 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -4404,7 +4404,17 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, + if (!conn) + continue; + +- conn->sent -= count; ++ /* Check if there is really enough packets outstanding before ++ * attempting to decrease the sent counter otherwise it could ++ * underflow.. ++ */ ++ if (conn->sent >= count) { ++ conn->sent -= count; ++ } else { ++ bt_dev_warn(hdev, "hcon %p sent %u < count %u", ++ conn, conn->sent, count); ++ conn->sent = 0; ++ } + + for (i = 0; i < count; ++i) + hci_conn_tx_dequeue(conn); +-- +2.50.1 + diff --git a/queue-6.16/bluetooth-hci_event-disconnect-device-when-big-sync-.patch b/queue-6.16/bluetooth-hci_event-disconnect-device-when-big-sync-.patch new file mode 100644 index 0000000000..6991021a1a --- /dev/null +++ b/queue-6.16/bluetooth-hci_event-disconnect-device-when-big-sync-.patch @@ -0,0 +1,65 @@ +From 4c447d1ff9b38451ca7fb1ec5f1f08e3364c0bb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Aug 2025 10:16:17 +0800 +Subject: Bluetooth: hci_event: Disconnect device when BIG sync is lost + +From: Yang Li + +[ Upstream commit 55b9551fcdf6a2fe7f3422918d5697b56794da72 ] + +When a BIG sync is lost, the device should be set to "disconnected". +This ensures symmetry with the ISO path setup, where the device is +marked as "connected" once the path is established. Without this +change, the device state remains inconsistent and may lead to a +memory leak. + +Fixes: b2a5f2e1c127 ("Bluetooth: hci_event: Add support for handling LE BIG Sync Lost event") +Signed-off-by: Yang Li +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 5 +++++ + net/bluetooth/mgmt.c | 4 +++- + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 02b2ef9a75746..0ffdbe249f5d3 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -7019,6 +7019,7 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data, + { + struct hci_evt_le_big_sync_lost *ev = data; + struct hci_conn *bis, *conn; ++ bool mgmt_conn; + + bt_dev_dbg(hdev, "big handle 0x%2.2x", ev->handle); + +@@ -7037,6 +7038,10 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data, + while ((bis = hci_conn_hash_lookup_big_state(hdev, ev->handle, + BT_CONNECTED, + HCI_ROLE_SLAVE))) { ++ mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &bis->flags); ++ mgmt_device_disconnected(hdev, &bis->dst, bis->type, bis->dst_type, ++ ev->reason, mgmt_conn); ++ + clear_bit(HCI_CONN_BIG_SYNC, &bis->flags); + hci_disconn_cfm(bis, ev->reason); + hci_conn_del(bis); +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 3166f5fb876b1..90e37ff2c85db 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -9705,7 +9705,9 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, + if (!mgmt_connected) + return; + +- if (link_type != ACL_LINK && link_type != LE_LINK) ++ if (link_type != ACL_LINK && ++ link_type != LE_LINK && ++ link_type != BIS_LINK) + return; + + bacpy(&ev.addr.bdaddr, bdaddr); +-- +2.50.1 + diff --git a/queue-6.16/bluetooth-hci_event-mark-connection-as-closed-during.patch b/queue-6.16/bluetooth-hci_event-mark-connection-as-closed-during.patch new file mode 100644 index 0000000000..2dd89a116e --- /dev/null +++ b/queue-6.16/bluetooth-hci_event-mark-connection-as-closed-during.patch @@ -0,0 +1,80 @@ +From 674fe564ad11835bd72555e6e077103673811942 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Aug 2025 17:55:27 +0200 +Subject: Bluetooth: hci_event: Mark connection as closed during suspend + disconnect + +From: Ludovico de Nittis + +[ Upstream commit b7fafbc499b5ee164018eb0eefe9027f5a6aaad2 ] + +When suspending, the disconnect command for an active Bluetooth +connection could be issued, but the corresponding +`HCI_EV_DISCONN_COMPLETE` event might not be received before the system +completes the suspend process. This can lead to an inconsistent state. + +On resume, the controller may auto-accept reconnections from the same +device (due to suspend event filters), but these new connections are +rejected by the kernel which still has connection objects from before +suspend. Resulting in errors like: +``` +kernel: Bluetooth: hci0: ACL packet for unknown connection handle 1 +kernel: Bluetooth: hci0: Ignoring HCI_Connection_Complete for existing +connection +``` + +This is a btmon snippet that shows the issue: +``` +< HCI Command: Disconnect (0x01|0x0006) plen 3 + Handle: 1 Address: 78:20:A5:4A:DF:28 (Nintendo Co.,Ltd) + Reason: Remote User Terminated Connection (0x13) +> HCI Event: Command Status (0x0f) plen 4 + Disconnect (0x01|0x0006) ncmd 2 + Status: Success (0x00) +[...] +// Host suspends with the event filter set for the device +// On resume, the device tries to reconnect with a new handle + +> HCI Event: Connect Complete (0x03) plen 11 + Status: Success (0x00) + Handle: 2 + Address: 78:20:A5:4A:DF:28 (Nintendo Co.,Ltd) + +// Kernel ignores this event because there is an existing connection +with +// handle 1 +``` + +By explicitly setting the connection state to BT_CLOSED we can ensure a +consistent state, even if we don't receive the disconnect complete event +in time. + +Link: https://github.com/bluez/bluez/issues/1226 +Fixes: 182ee45da083 ("Bluetooth: hci_sync: Rework hci_suspend_notifier") +Signed-off-by: Ludovico de Nittis +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 1902982538da7..cadb53e21c0ef 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -2718,6 +2718,12 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) + goto done; + } + ++ /* During suspend, mark connection as closed immediately ++ * since we might not receive HCI_EV_DISCONN_COMPLETE ++ */ ++ if (hdev->suspended) ++ conn->state = BT_CLOSED; ++ + mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); + + if (conn->type == ACL_LINK) { +-- +2.50.1 + diff --git a/queue-6.16/bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch b/queue-6.16/bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch new file mode 100644 index 0000000000..d05617db0b --- /dev/null +++ b/queue-6.16/bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch @@ -0,0 +1,84 @@ +From 57880a80e476d8e932ceadfa7d8a452562019ee0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Aug 2025 17:55:26 +0200 +Subject: Bluetooth: hci_event: Treat UNKNOWN_CONN_ID on disconnect as success + +From: Ludovico de Nittis + +[ Upstream commit 2f050a5392b7a0928bf836d9891df4851463512c ] + +When the host sends an HCI_OP_DISCONNECT command, the controller may +respond with the status HCI_ERROR_UNKNOWN_CONN_ID (0x02). E.g. this can +happen on resume from suspend, if the link was terminated by the remote +device before the event mask was correctly set. + +This is a btmon snippet that shows the issue: +``` +> ACL Data RX: Handle 3 flags 0x02 dlen 12 + L2CAP: Disconnection Request (0x06) ident 5 len 4 + Destination CID: 65 + Source CID: 72 +< ACL Data TX: Handle 3 flags 0x00 dlen 12 + L2CAP: Disconnection Response (0x07) ident 5 len 4 + Destination CID: 65 + Source CID: 72 +> ACL Data RX: Handle 3 flags 0x02 dlen 12 + L2CAP: Disconnection Request (0x06) ident 6 len 4 + Destination CID: 64 + Source CID: 71 +< ACL Data TX: Handle 3 flags 0x00 dlen 12 + L2CAP: Disconnection Response (0x07) ident 6 len 4 + Destination CID: 64 + Source CID: 71 +< HCI Command: Set Event Mask (0x03|0x0001) plen 8 + Mask: 0x3dbff807fffbffff + Inquiry Complete + Inquiry Result + Connection Complete + Connection Request + Disconnection Complete + Authentication Complete +[...] +< HCI Command: Disconnect (0x01|0x0006) plen 3 + Handle: 3 Address: 78:20:A5:4A:DF:28 (Nintendo Co.,Ltd) + Reason: Remote User Terminated Connection (0x13) +> HCI Event: Command Status (0x0f) plen 4 + Disconnect (0x01|0x0006) ncmd 1 + Status: Unknown Connection Identifier (0x02) +``` + +Currently, the hci_cs_disconnect function treats any non-zero status +as a command failure. This can be misleading because the connection is +indeed being terminated and the controller is confirming that is has no +knowledge of that connection handle. Meaning that the initial request of +disconnecting a device should be treated as done. + +With this change we allow the function to proceed, following the success +path, which correctly calls `mgmt_device_disconnected` and ensures a +consistent state. + +Link: https://github.com/bluez/bluez/issues/1226 +Fixes: 182ee45da083 ("Bluetooth: hci_sync: Rework hci_suspend_notifier") +Signed-off-by: Ludovico de Nittis +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 5ef54853bc5eb..1902982538da7 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -2703,7 +2703,7 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) + if (!conn) + goto unlock; + +- if (status) { ++ if (status && status != HCI_ERROR_UNKNOWN_CONN_ID) { + mgmt_disconnect_failed(hdev, &conn->dst, conn->type, + conn->dst_type, status); + +-- +2.50.1 + diff --git a/queue-6.16/bluetooth-hci_sync-fix-set_local_name-race-condition.patch b/queue-6.16/bluetooth-hci_sync-fix-set_local_name-race-condition.patch new file mode 100644 index 0000000000..2d93da1cd5 --- /dev/null +++ b/queue-6.16/bluetooth-hci_sync-fix-set_local_name-race-condition.patch @@ -0,0 +1,90 @@ +From 7dbac4e2175ef7cdeab9b544e8fab30b66f50759 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Aug 2025 12:20:55 +0300 +Subject: Bluetooth: hci_sync: fix set_local_name race condition + +From: Pavel Shpakovskiy + +[ Upstream commit 6bbd0d3f0c23fc53c17409dd7476f38ae0ff0cd9 ] + +Function set_name_sync() uses hdev->dev_name field to send +HCI_OP_WRITE_LOCAL_NAME command, but copying from data to hdev->dev_name +is called after mgmt cmd was queued, so it is possible that function +set_name_sync() will read old name value. + +This change adds name as a parameter for function hci_update_name_sync() +to avoid race condition. + +Fixes: 6f6ff38a1e14 ("Bluetooth: hci_sync: Convert MGMT_OP_SET_LOCAL_NAME") +Signed-off-by: Pavel Shpakovskiy +Reviewed-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci_sync.h | 2 +- + net/bluetooth/hci_sync.c | 6 +++--- + net/bluetooth/mgmt.c | 5 ++++- + 3 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h +index 5224f57f6af2c..e352a4e0ef8d7 100644 +--- a/include/net/bluetooth/hci_sync.h ++++ b/include/net/bluetooth/hci_sync.h +@@ -93,7 +93,7 @@ int hci_update_class_sync(struct hci_dev *hdev); + + int hci_update_eir_sync(struct hci_dev *hdev); + int hci_update_class_sync(struct hci_dev *hdev); +-int hci_update_name_sync(struct hci_dev *hdev); ++int hci_update_name_sync(struct hci_dev *hdev, const u8 *name); + int hci_write_ssp_mode_sync(struct hci_dev *hdev, u8 mode); + + int hci_get_random_address(struct hci_dev *hdev, bool require_privacy, +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index 115dc1cd99ce4..749bba1512eb1 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -3481,13 +3481,13 @@ int hci_update_scan_sync(struct hci_dev *hdev) + return hci_write_scan_enable_sync(hdev, scan); + } + +-int hci_update_name_sync(struct hci_dev *hdev) ++int hci_update_name_sync(struct hci_dev *hdev, const u8 *name) + { + struct hci_cp_write_local_name cp; + + memset(&cp, 0, sizeof(cp)); + +- memcpy(cp.name, hdev->dev_name, sizeof(cp.name)); ++ memcpy(cp.name, name, sizeof(cp.name)); + + return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_LOCAL_NAME, + sizeof(cp), &cp, +@@ -3540,7 +3540,7 @@ int hci_powered_update_sync(struct hci_dev *hdev) + hci_write_fast_connectable_sync(hdev, false); + hci_update_scan_sync(hdev); + hci_update_class_sync(hdev); +- hci_update_name_sync(hdev); ++ hci_update_name_sync(hdev, hdev->dev_name); + hci_update_eir_sync(hdev); + } + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 90e37ff2c85db..50634ef5c8b70 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -3892,8 +3892,11 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err) + + static int set_name_sync(struct hci_dev *hdev, void *data) + { ++ struct mgmt_pending_cmd *cmd = data; ++ struct mgmt_cp_set_local_name *cp = cmd->param; ++ + if (lmp_bredr_capable(hdev)) { +- hci_update_name_sync(hdev); ++ hci_update_name_sync(hdev, cp->name); + hci_update_eir_sync(hdev); + } + +-- +2.50.1 + diff --git a/queue-6.16/bnxt_en-adjust-tx-rings-if-reservation-is-less-than-.patch b/queue-6.16/bnxt_en-adjust-tx-rings-if-reservation-is-less-than-.patch new file mode 100644 index 0000000000..e4c1d68395 --- /dev/null +++ b/queue-6.16/bnxt_en-adjust-tx-rings-if-reservation-is-less-than-.patch @@ -0,0 +1,64 @@ +From bd11dca44cf30511d4c2417c82320e9ef5ed8492 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 10:59:26 -0700 +Subject: bnxt_en: Adjust TX rings if reservation is less than requested + +From: Michael Chan + +[ Upstream commit 1ee581c24dfdcbc6de25aac95a48c1f08e9a542c ] + +Before we accept an ethtool request to increase a resource (such as +rings), we call the FW to check that the requested resource is likely +available first before we commit. But it is still possible that +the actual reservation or allocation can fail. The existing code +is missing the logic to adjust the TX rings in case the reserved +TX rings are less than requested. Add a warning message (a similar +message for RX rings already exists) and add the logic to adjust +the TX rings. Without this fix, the number of TX rings reported +to the stack can exceed the actual TX rings and ethtool -l will +report more than the actual TX rings. + +Fixes: 674f50a5b026 ("bnxt_en: Implement new method to reserve rings.") +Reviewed-by: Kalesh AP +Reviewed-by: Somnath Kotur +Signed-off-by: Michael Chan +Link: https://patch.msgid.link/20250825175927.459987-3-michael.chan@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index a4f4d90caf5e9..5360c42ad409c 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -8017,6 +8017,11 @@ static int __bnxt_reserve_rings(struct bnxt *bp) + hwr.rx = rx_rings << 1; + tx_cp = bnxt_num_tx_to_cp(bp, hwr.tx); + hwr.cp = sh ? max_t(int, tx_cp, rx_rings) : tx_cp + rx_rings; ++ if (hwr.tx != bp->tx_nr_rings) { ++ netdev_warn(bp->dev, ++ "Able to reserve only %d out of %d requested TX rings\n", ++ hwr.tx, bp->tx_nr_rings); ++ } + bp->tx_nr_rings = hwr.tx; + + /* If we cannot reserve all the RX rings, reset the RSS map only +@@ -12872,6 +12877,13 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) + if (rc) + return rc; + ++ /* Make adjustments if reserved TX rings are less than requested */ ++ bp->tx_nr_rings -= bp->tx_nr_rings_xdp; ++ bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); ++ if (bp->tx_nr_rings_xdp) { ++ bp->tx_nr_rings_xdp = bp->tx_nr_rings_per_tc; ++ bp->tx_nr_rings += bp->tx_nr_rings_xdp; ++ } + rc = bnxt_alloc_mem(bp, irq_re_init); + if (rc) { + netdev_err(bp->dev, "bnxt_alloc_mem err: %x\n", rc); +-- +2.50.1 + diff --git a/queue-6.16/bnxt_en-fix-memory-corruption-when-fw-resources-chan.patch b/queue-6.16/bnxt_en-fix-memory-corruption-when-fw-resources-chan.patch new file mode 100644 index 0000000000..2ee699aad0 --- /dev/null +++ b/queue-6.16/bnxt_en-fix-memory-corruption-when-fw-resources-chan.patch @@ -0,0 +1,106 @@ +From 1028d4f3c65673898e39224f25372b8ca0f1eb55 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 10:59:25 -0700 +Subject: bnxt_en: Fix memory corruption when FW resources change during ifdown + +From: Sreekanth Reddy + +[ Upstream commit 2747328ba2714f1a7454208dbbc1dc0631990b4a ] + +bnxt_set_dflt_rings() assumes that it is always called before any TC has +been created. So it doesn't take bp->num_tc into account and assumes +that it is always 0 or 1. + +In the FW resource or capability change scenario, the FW will return +flags in bnxt_hwrm_if_change() that will cause the driver to +reinitialize and call bnxt_cancel_reservations(). This will lead to +bnxt_init_dflt_ring_mode() calling bnxt_set_dflt_rings() and bp->num_tc +may be greater than 1. This will cause bp->tx_ring[] to be sized too +small and cause memory corruption in bnxt_alloc_cp_rings(). + +Fix it by properly scaling the TX rings by bp->num_tc in the code +paths mentioned above. Add 2 helper functions to determine +bp->tx_nr_rings and bp->tx_nr_rings_per_tc. + +Fixes: ec5d31e3c15d ("bnxt_en: Handle firmware reset status during IF_UP.") +Reviewed-by: Kalesh AP +Reviewed-by: Andy Gospodarek +Signed-off-by: Sreekanth Reddy +Signed-off-by: Michael Chan +Link: https://patch.msgid.link/20250825175927.459987-2-michael.chan@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index ec8752c298e69..a4f4d90caf5e9 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -12844,6 +12844,17 @@ static int bnxt_set_xps_mapping(struct bnxt *bp) + return rc; + } + ++static int bnxt_tx_nr_rings(struct bnxt *bp) ++{ ++ return bp->num_tc ? bp->tx_nr_rings_per_tc * bp->num_tc : ++ bp->tx_nr_rings_per_tc; ++} ++ ++static int bnxt_tx_nr_rings_per_tc(struct bnxt *bp) ++{ ++ return bp->num_tc ? bp->tx_nr_rings / bp->num_tc : bp->tx_nr_rings; ++} ++ + static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) + { + int rc = 0; +@@ -16338,7 +16349,7 @@ static void bnxt_trim_dflt_sh_rings(struct bnxt *bp) + bp->cp_nr_rings = min_t(int, bp->tx_nr_rings_per_tc, bp->rx_nr_rings); + bp->rx_nr_rings = bp->cp_nr_rings; + bp->tx_nr_rings_per_tc = bp->cp_nr_rings; +- bp->tx_nr_rings = bp->tx_nr_rings_per_tc; ++ bp->tx_nr_rings = bnxt_tx_nr_rings(bp); + } + + static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) +@@ -16370,7 +16381,7 @@ static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) + bnxt_trim_dflt_sh_rings(bp); + else + bp->cp_nr_rings = bp->tx_nr_rings_per_tc + bp->rx_nr_rings; +- bp->tx_nr_rings = bp->tx_nr_rings_per_tc; ++ bp->tx_nr_rings = bnxt_tx_nr_rings(bp); + + avail_msix = bnxt_get_max_func_irqs(bp) - bp->cp_nr_rings; + if (avail_msix >= BNXT_MIN_ROCE_CP_RINGS) { +@@ -16383,7 +16394,7 @@ static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) + rc = __bnxt_reserve_rings(bp); + if (rc && rc != -ENODEV) + netdev_warn(bp->dev, "Unable to reserve tx rings\n"); +- bp->tx_nr_rings_per_tc = bp->tx_nr_rings; ++ bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); + if (sh) + bnxt_trim_dflt_sh_rings(bp); + +@@ -16392,7 +16403,7 @@ static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) + rc = __bnxt_reserve_rings(bp); + if (rc && rc != -ENODEV) + netdev_warn(bp->dev, "2nd rings reservation failed.\n"); +- bp->tx_nr_rings_per_tc = bp->tx_nr_rings; ++ bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); + } + if (BNXT_CHIP_TYPE_NITRO_A0(bp)) { + bp->rx_nr_rings++; +@@ -16426,7 +16437,7 @@ static int bnxt_init_dflt_ring_mode(struct bnxt *bp) + if (rc) + goto init_dflt_ring_err; + +- bp->tx_nr_rings_per_tc = bp->tx_nr_rings; ++ bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); + + bnxt_set_dflt_rfs(bp); + +-- +2.50.1 + diff --git a/queue-6.16/bnxt_en-fix-stats-context-reservation-logic.patch b/queue-6.16/bnxt_en-fix-stats-context-reservation-logic.patch new file mode 100644 index 0000000000..53e9b7d3d9 --- /dev/null +++ b/queue-6.16/bnxt_en-fix-stats-context-reservation-logic.patch @@ -0,0 +1,44 @@ +From daf38dbb8f1bfb0d57daa254b01b7f9912f79ac5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 10:59:27 -0700 +Subject: bnxt_en: Fix stats context reservation logic + +From: Michael Chan + +[ Upstream commit b4fc8faacfea2538184a1dbd616ae9447a361f3d ] + +The HW resource reservation logic allows the L2 driver to use the +RoCE resources if the RoCE driver is not registered. When calculating +the stats contexts available for L2, we should not blindly subtract +the stats contexts reserved for RoCE unless the RoCE driver is +registered. This bug may cause the L2 rings to be less than the +number requested when we are close to running out of stats contexts. + +Fixes: 2e4592dc9bee ("bnxt_en: Change MSIX/NQs allocation policy") +Reviewed-by: Kalesh AP +Reviewed-by: Somnath Kotur +Signed-off-by: Michael Chan +Link: https://patch.msgid.link/20250825175927.459987-4-michael.chan@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 5360c42ad409c..cb76ab78904fc 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -8009,7 +8009,8 @@ static int __bnxt_reserve_rings(struct bnxt *bp) + } + rx_rings = min_t(int, rx_rings, hwr.grp); + hwr.cp = min_t(int, hwr.cp, bp->cp_nr_rings); +- if (hwr.stat > bnxt_get_ulp_stat_ctxs(bp)) ++ if (bnxt_ulp_registered(bp->edev) && ++ hwr.stat > bnxt_get_ulp_stat_ctxs(bp)) + hwr.stat -= bnxt_get_ulp_stat_ctxs(bp); + hwr.cp = min_t(int, hwr.cp, hwr.stat); + rc = bnxt_trim_rings(bp, &rx_rings, &hwr.tx, hwr.cp, sh); +-- +2.50.1 + diff --git a/queue-6.16/drm-mediatek-add-error-handling-for-old-state-crtc-i.patch b/queue-6.16/drm-mediatek-add-error-handling-for-old-state-crtc-i.patch new file mode 100644 index 0000000000..30356cc758 --- /dev/null +++ b/queue-6.16/drm-mediatek-add-error-handling-for-old-state-crtc-i.patch @@ -0,0 +1,66 @@ +From 643e0d64586d376b5871131c616949c76383bf5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Jul 2025 10:48:50 +0800 +Subject: drm/mediatek: Add error handling for old state CRTC in atomic_disable + +From: Jason-JH Lin + +[ Upstream commit 0c6b24d70da21201ed009a2aca740d2dfddc7ab5 ] + +Introduce error handling to address an issue where, after a hotplug +event, the cursor continues to update. This situation can lead to a +kernel panic due to accessing the NULL `old_state->crtc`. + +E,g. +Unable to handle kernel NULL pointer dereference at virtual address +Call trace: + mtk_crtc_plane_disable+0x24/0x140 + mtk_plane_atomic_update+0x8c/0xa8 + drm_atomic_helper_commit_planes+0x114/0x2c8 + drm_atomic_helper_commit_tail_rpm+0x4c/0x158 + commit_tail+0xa0/0x168 + drm_atomic_helper_commit+0x110/0x120 + drm_atomic_commit+0x8c/0xe0 + drm_atomic_helper_update_plane+0xd4/0x128 + __setplane_atomic+0xcc/0x110 + drm_mode_cursor_common+0x250/0x440 + drm_mode_cursor_ioctl+0x44/0x70 + drm_ioctl+0x264/0x5d8 + __arm64_sys_ioctl+0xd8/0x510 + invoke_syscall+0x6c/0xe0 + do_el0_svc+0x68/0xe8 + el0_svc+0x34/0x60 + el0t_64_sync_handler+0x1c/0xf8 + el0t_64_sync+0x180/0x188 + +Adding NULL pointer checks to ensure stability by preventing operations +on an invalid CRTC state. + +Fixes: d208261e9f7c ("drm/mediatek: Add wait_event_timeout when disabling plane") +Signed-off-by: Jason-JH Lin +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: CK Hu +Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20250728025036.24953-1-jason-jh.lin@mediatek.com/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/mediatek/mtk_plane.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/mediatek/mtk_plane.c b/drivers/gpu/drm/mediatek/mtk_plane.c +index cbc4f37da8ba8..02349bd440017 100644 +--- a/drivers/gpu/drm/mediatek/mtk_plane.c ++++ b/drivers/gpu/drm/mediatek/mtk_plane.c +@@ -292,7 +292,8 @@ static void mtk_plane_atomic_disable(struct drm_plane *plane, + wmb(); /* Make sure the above parameter is set before update */ + mtk_plane_state->pending.dirty = true; + +- mtk_crtc_plane_disable(old_state->crtc, plane); ++ if (old_state && old_state->crtc) ++ mtk_crtc_plane_disable(old_state->crtc, plane); + } + + static void mtk_plane_atomic_update(struct drm_plane *plane, +-- +2.50.1 + diff --git a/queue-6.16/drm-mediatek-mtk_hdmi-fix-inverted-parameters-in-som.patch b/queue-6.16/drm-mediatek-mtk_hdmi-fix-inverted-parameters-in-som.patch new file mode 100644 index 0000000000..6bedadd0e8 --- /dev/null +++ b/queue-6.16/drm-mediatek-mtk_hdmi-fix-inverted-parameters-in-som.patch @@ -0,0 +1,54 @@ +From 721777d3e398883c79ada0e27257f6787719fc62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Aug 2025 16:17:52 +0200 +Subject: drm/mediatek: mtk_hdmi: Fix inverted parameters in some + regmap_update_bits calls + +From: Louis-Alexis Eyraud + +[ Upstream commit c34414883f773412964404d77cd2fea04c6f7d60 ] + +In mtk_hdmi driver, a recent change replaced custom register access +function calls by regmap ones, but two replacements by regmap_update_bits +were done incorrectly, because original offset and mask parameters were +inverted, so fix them. + +Fixes: d6e25b3590a0 ("drm/mediatek: hdmi: Use regmap instead of iomem for main registers") +Signed-off-by: Louis-Alexis Eyraud +Reviewed-by: CK Hu +Link: https://patchwork.kernel.org/project/dri-devel/patch/20250818-mt8173-fix-hdmi-issue-v1-1-55aff9b0295d@collabora.com/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/mediatek/mtk_hdmi.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c +index 8803cd4a8bc9b..4404e1b527b52 100644 +--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c ++++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c +@@ -182,8 +182,8 @@ static inline struct mtk_hdmi *hdmi_ctx_from_bridge(struct drm_bridge *b) + + static void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, bool black) + { +- regmap_update_bits(hdmi->regs, VIDEO_SOURCE_SEL, +- VIDEO_CFG_4, black ? GEN_RGB : NORMAL_PATH); ++ regmap_update_bits(hdmi->regs, VIDEO_CFG_4, ++ VIDEO_SOURCE_SEL, black ? GEN_RGB : NORMAL_PATH); + } + + static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable) +@@ -310,8 +310,8 @@ static void mtk_hdmi_hw_send_info_frame(struct mtk_hdmi *hdmi, u8 *buffer, + + static void mtk_hdmi_hw_send_aud_packet(struct mtk_hdmi *hdmi, bool enable) + { +- regmap_update_bits(hdmi->regs, AUDIO_PACKET_OFF, +- GRL_SHIFT_R2, enable ? 0 : AUDIO_PACKET_OFF); ++ regmap_update_bits(hdmi->regs, GRL_SHIFT_R2, ++ AUDIO_PACKET_OFF, enable ? 0 : AUDIO_PACKET_OFF); + } + + static void mtk_hdmi_hw_config_sys(struct mtk_hdmi *hdmi) +-- +2.50.1 + diff --git a/queue-6.16/drm-msm-defer-fd_install-in-submit-ioctl.patch b/queue-6.16/drm-msm-defer-fd_install-in-submit-ioctl.patch new file mode 100644 index 0000000000..1e2e60b548 --- /dev/null +++ b/queue-6.16/drm-msm-defer-fd_install-in-submit-ioctl.patch @@ -0,0 +1,59 @@ +From cedc6de13668f5088bfc92adb4ff52aa728211bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Jul 2025 13:28:22 -0700 +Subject: drm/msm: Defer fd_install in SUBMIT ioctl + +From: Rob Clark + +[ Upstream commit f22853435bbd1e9836d0dce7fd99c040b94c2bf1 ] + +Avoid fd_install() until there are no more potential error paths, to +avoid put_unused_fd() after the fd is made visible to userspace. + +Fixes: 68dc6c2d5eec ("drm/msm: Fix submit error-path leaks") +Reported-by: Dan Carpenter +Signed-off-by: Rob Clark +Patchwork: https://patchwork.freedesktop.org/patch/665363/ +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/msm_gem_submit.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c +index d4f71bb54e84c..081d59979e31d 100644 +--- a/drivers/gpu/drm/msm/msm_gem_submit.c ++++ b/drivers/gpu/drm/msm/msm_gem_submit.c +@@ -869,12 +869,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, + + if (ret == 0 && args->flags & MSM_SUBMIT_FENCE_FD_OUT) { + sync_file = sync_file_create(submit->user_fence); +- if (!sync_file) { ++ if (!sync_file) + ret = -ENOMEM; +- } else { +- fd_install(out_fence_fd, sync_file->file); +- args->fence_fd = out_fence_fd; +- } + } + + if (ret) +@@ -902,10 +898,14 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, + out_unlock: + mutex_unlock(&queue->lock); + out_post_unlock: +- if (ret && (out_fence_fd >= 0)) { +- put_unused_fd(out_fence_fd); ++ if (ret) { ++ if (out_fence_fd >= 0) ++ put_unused_fd(out_fence_fd); + if (sync_file) + fput(sync_file->file); ++ } else if (sync_file) { ++ fd_install(out_fence_fd, sync_file->file); ++ args->fence_fd = out_fence_fd; + } + + if (!IS_ERR_OR_NULL(submit)) { +-- +2.50.1 + diff --git a/queue-6.16/drm-msm-dpu-add-a-null-ptr-check-for-dpu_encoder_nee.patch b/queue-6.16/drm-msm-dpu-add-a-null-ptr-check-for-dpu_encoder_nee.patch new file mode 100644 index 0000000000..b4ca14dd3f --- /dev/null +++ b/queue-6.16/drm-msm-dpu-add-a-null-ptr-check-for-dpu_encoder_nee.patch @@ -0,0 +1,42 @@ +From 1085747a2621ee739c2b1840e757e3d381da2601 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Jul 2025 16:17:40 -0500 +Subject: drm/msm/dpu: Add a null ptr check for dpu_encoder_needs_modeset + +From: Chenyuan Yang + +[ Upstream commit abebfed208515726760d79cf4f9f1a76b9a10a84 ] + +The drm_atomic_get_new_connector_state() can return NULL if the +connector is not part of the atomic state. Add a check to prevent +a NULL pointer dereference. + +This follows the same pattern used in dpu_encoder_update_topology() +within the same file, which checks for NULL before using conn_state. + +Signed-off-by: Chenyuan Yang +Fixes: 1ce69c265a53 ("drm/msm/dpu: move resource allocation to CRTC") +Reviewed-by: Dmitry Baryshkov +Patchwork: https://patchwork.freedesktop.org/patch/665188/ +Signed-off-by: Rob Clark +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +index c0ed110a7d30f..4bddb9504796b 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +@@ -729,6 +729,8 @@ bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_st + return false; + + conn_state = drm_atomic_get_new_connector_state(state, connector); ++ if (!conn_state) ++ return false; + + /** + * These checks are duplicated from dpu_encoder_update_topology() since +-- +2.50.1 + diff --git a/queue-6.16/drm-msm-dpu-correct-dpu_plane_virtual_atomic_check.patch b/queue-6.16/drm-msm-dpu-correct-dpu_plane_virtual_atomic_check.patch new file mode 100644 index 0000000000..089c1e41ac --- /dev/null +++ b/queue-6.16/drm-msm-dpu-correct-dpu_plane_virtual_atomic_check.patch @@ -0,0 +1,41 @@ +From b6dd18ad11593feb8e60fdc32a51ede696151b3e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Jul 2025 20:28:18 +0300 +Subject: drm/msm/dpu: correct dpu_plane_virtual_atomic_check() + +From: Dmitry Baryshkov + +[ Upstream commit 1a76b255eceb9c570c6228f6393e1d63d97a22ba ] + +Fix c&p error in dpu_plane_virtual_atomic_check(), compare CRTC width +too, in addition to CRTC height. + +Fixes: 8c62a31607f6 ("drm/msm/dpu: allow using two SSPP blocks for a single plane") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202507150432.U0cALR6W-lkp@intel.com/ +Signed-off-by: Dmitry Baryshkov +Reviewed-by: Jessica Zhang +Reviewed-by: Konrad Dybcio +Patchwork: https://patchwork.freedesktop.org/patch/664170/ +Link: https://lore.kernel.org/r/20250715-msm-fix-virt-atomic-check-v1-1-9bab02c9f952@oss.qualcomm.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +index 421138bc3cb77..28d42eade5ccb 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +@@ -1169,7 +1169,7 @@ static int dpu_plane_virtual_atomic_check(struct drm_plane *plane, + if (!old_plane_state || !old_plane_state->fb || + old_plane_state->src_w != plane_state->src_w || + old_plane_state->src_h != plane_state->src_h || +- old_plane_state->src_w != plane_state->src_w || ++ old_plane_state->crtc_w != plane_state->crtc_w || + old_plane_state->crtc_h != plane_state->crtc_h || + msm_framebuffer_format(old_plane_state->fb) != + msm_framebuffer_format(plane_state->fb)) +-- +2.50.1 + diff --git a/queue-6.16/drm-msm-kms-move-snapshot-init-earlier-in-kms-init.patch b/queue-6.16/drm-msm-kms-move-snapshot-init-earlier-in-kms-init.patch new file mode 100644 index 0000000000..d07348c64f --- /dev/null +++ b/queue-6.16/drm-msm-kms-move-snapshot-init-earlier-in-kms-init.patch @@ -0,0 +1,118 @@ +From 2cdaed6725c591a52bd5dede850f6d78049c647e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Jul 2025 18:50:37 +0300 +Subject: drm/msm/kms: move snapshot init earlier in KMS init + +From: Dmitry Baryshkov + +[ Upstream commit 553666f839b86545300773954df7426a45c169c4 ] + +Various parts of the display driver can be triggering the display +snapshot (including the IOMMU fault handlers). Move the call to +msm_disp_snapshot_init() before KMS initialization, otherwise it is +possible to ocassionally trigger the kernel fault during init: + + __lock_acquire+0x44/0x2798 (P) + lock_acquire+0x114/0x25c + _raw_spin_lock_irqsave+0x6c/0x90 + kthread_queue_work+0x2c/0xac + msm_disp_snapshot_state+0x2c/0x4c + msm_kms_fault_handler+0x2c/0x74 + msm_disp_fault_handler+0x30/0x48 + report_iommu_fault+0x54/0x128 + arm_smmu_context_fault+0x74/0x184 + __handle_irq_event_percpu+0xa4/0x24c + handle_irq_event_percpu+0x20/0x5c + handle_irq_event+0x48/0x84 + handle_fasteoi_irq+0xcc/0x170 + generic_handle_domain_irq+0x48/0x70 + gic_handle_irq+0x54/0x11c + call_on_irq_stack+0x3c/0x50 + do_interrupt_handler+0x54/0x78 + el1_interrupt+0x3c/0x5c + el1h_64_irq_handler+0x20/0x30 + el1h_64_irq+0x6c/0x70 + _raw_spin_unlock_irqrestore+0x44/0x68 (P) + klist_next+0xc4/0x124 + bus_for_each_drv+0x9c/0xe8 + __device_attach+0xfc/0x190 + device_initial_probe+0x1c/0x2c + bus_probe_device+0x44/0xa0 + device_add+0x204/0x3e4 + platform_device_add+0x170/0x244 + platform_device_register_full+0x130/0x138 + drm_connector_hdmi_audio_init+0xc0/0x108 + drm_bridge_connector_init+0x318/0x394 + msm_dsi_manager_connector_init+0xac/0xdc + msm_dsi_modeset_init+0x78/0xc0 + _dpu_kms_drm_obj_init+0x198/0x75c + dpu_kms_hw_init+0x2f8/0x494 + msm_drm_kms_init+0xb0/0x230 + msm_drm_init+0x218/0x250 + msm_drm_bind+0x3c/0x4c + try_to_bring_up_aggregate_device+0x208/0x2a4 + __component_add+0xa8/0x188 + component_add+0x1c/0x2c + dsi_dev_attach+0x24/0x34 + dsi_host_attach+0x68/0xa0 + devm_mipi_dsi_attach+0x40/0xcc + lt9611_attach_dsi+0x94/0x118 + lt9611_probe+0x368/0x3c8 + i2c_device_probe+0x2d0/0x3d8 + really_probe+0x130/0x354 + __driver_probe_device+0xac/0x110 + driver_probe_device+0x44/0x110 + __device_attach_driver+0xb0/0x138 + bus_for_each_drv+0x90/0xe8 + __device_attach+0xfc/0x190 + device_initial_probe+0x1c/0x2c + bus_probe_device+0x44/0xa0 + deferred_probe_work_func+0xac/0x110 + process_one_work+0x20c/0x51c + process_scheduled_works+0x58/0x88 + worker_thread+0x1ec/0x304 + kthread+0x194/0x1d4 + ret_from_fork+0x10/0x20 + +Reported-by: Konrad Dybcio +Fixes: 98659487b845 ("drm/msm: add support to take dpu snapshot") +Signed-off-by: Dmitry Baryshkov +Reviewed-by: Konrad Dybcio +Patchwork: https://patchwork.freedesktop.org/patch/664149/ +Link: https://lore.kernel.org/r/20250715-msm-move-snapshot-init-v1-1-f39c396192ab@oss.qualcomm.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/msm_kms.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c +index 35d5397e73b4c..f2c00716f9d1a 100644 +--- a/drivers/gpu/drm/msm/msm_kms.c ++++ b/drivers/gpu/drm/msm/msm_kms.c +@@ -258,6 +258,12 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) + if (ret) + return ret; + ++ ret = msm_disp_snapshot_init(ddev); ++ if (ret) { ++ DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret); ++ return ret; ++ } ++ + ret = priv->kms_init(ddev); + if (ret) { + DRM_DEV_ERROR(dev, "failed to load kms\n"); +@@ -310,10 +316,6 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) + goto err_msm_uninit; + } + +- ret = msm_disp_snapshot_init(ddev); +- if (ret) +- DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret); +- + drm_mode_config_reset(ddev); + + return 0; +-- +2.50.1 + diff --git a/queue-6.16/drm-msm-update-the-high-bitfield-of-certain-dsi-regi.patch b/queue-6.16/drm-msm-update-the-high-bitfield-of-certain-dsi-regi.patch new file mode 100644 index 0000000000..35d78889d5 --- /dev/null +++ b/queue-6.16/drm-msm-update-the-high-bitfield-of-certain-dsi-regi.patch @@ -0,0 +1,89 @@ +From 79e96c1c52a349e29f628a54916a9dd796141faa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Jul 2025 18:09:38 +0530 +Subject: drm/msm: update the high bitfield of certain DSI registers + +From: Ayushi Makhija + +[ Upstream commit 494045c561e68945b1183ff416b8db8e37a122d6 ] + +Currently, the high bitfield of certain DSI registers +do not align with the configuration of the SWI registers +description. This can lead to wrong programming these DSI +registers, for example for 4k resloution where H_TOTAL is +taking 13 bits but software is programming only 12 bits +because of the incorrect bitmask for H_TOTAL bitfeild, +this is causing DSI FIFO errors. To resolve this issue, +increase the high bitfield of the DSI registers from 12 bits +to 16 bits in dsi.xml to match the SWI register configuration. + +Signed-off-by: Ayushi Makhija +Fixes: 4f52f5e63b62 ("drm/msm: import XML display registers database") +Reviewed-by: Dmitry Baryshkov +Patchwork: https://patchwork.freedesktop.org/patch/666229/ +Link: https://lore.kernel.org/r/20250730123938.1038640-1-quic_amakhija@quicinc.com +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/registers/display/dsi.xml | 28 +++++++++---------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/drivers/gpu/drm/msm/registers/display/dsi.xml b/drivers/gpu/drm/msm/registers/display/dsi.xml +index 501ffc585a9f6..c7a7b633d747b 100644 +--- a/drivers/gpu/drm/msm/registers/display/dsi.xml ++++ b/drivers/gpu/drm/msm/registers/display/dsi.xml +@@ -159,28 +159,28 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> + + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + + +@@ -209,8 +209,8 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> + + + +- +- ++ ++ + + + +-- +2.50.1 + diff --git a/queue-6.16/drm-nouveau-remove-unused-increment-in-gm200_flcn_pi.patch b/queue-6.16/drm-nouveau-remove-unused-increment-in-gm200_flcn_pi.patch new file mode 100644 index 0000000000..d7e93964e8 --- /dev/null +++ b/queue-6.16/drm-nouveau-remove-unused-increment-in-gm200_flcn_pi.patch @@ -0,0 +1,39 @@ +From cf92907fed69bcb375b4941ffd3285966c2f3939 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Aug 2025 19:10:03 -0500 +Subject: drm/nouveau: remove unused increment in gm200_flcn_pio_imem_wr + +From: Timur Tabi + +[ Upstream commit f529b8915543fb9ceb732cec5571f7fe12bc9530 ] + +The 'tag' parameter is passed by value and is not actually used after +being incremented, so remove the increment. It's the function that calls +gm200_flcn_pio_imem_wr that is supposed to (and does) increment 'tag'. + +Fixes: 0e44c2170876 ("drm/nouveau/flcn: new code to load+boot simple HS FWs (VPR scrubber)") +Reviewed-by: Philipp Stanner +Signed-off-by: Timur Tabi +Link: https://lore.kernel.org/r/20250813001004.2986092-2-ttabi@nvidia.com +Signed-off-by: Danilo Krummrich +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +index b7da3ab44c277..6a004c6e67425 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c ++++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +@@ -103,7 +103,7 @@ gm200_flcn_pio_imem_wr_init(struct nvkm_falcon *falcon, u8 port, bool sec, u32 i + static void + gm200_flcn_pio_imem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len, u16 tag) + { +- nvkm_falcon_wr32(falcon, 0x188 + (port * 0x10), tag++); ++ nvkm_falcon_wr32(falcon, 0x188 + (port * 0x10), tag); + while (len >= 4) { + nvkm_falcon_wr32(falcon, 0x184 + (port * 0x10), *(u32 *)img); + img += 4; +-- +2.50.1 + diff --git a/queue-6.16/drm-nouveau-remove-unused-memory-target-test.patch b/queue-6.16/drm-nouveau-remove-unused-memory-target-test.patch new file mode 100644 index 0000000000..e92c79a629 --- /dev/null +++ b/queue-6.16/drm-nouveau-remove-unused-memory-target-test.patch @@ -0,0 +1,57 @@ +From 496f2e1354c28ecc1b2df9953eac47b7f76ee4be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Aug 2025 19:10:04 -0500 +Subject: drm/nouveau: remove unused memory target test + +From: Timur Tabi + +[ Upstream commit 64c722b5e7f6b909b0e448e580f64628a0d76208 ] + +The memory target check is a hold-over from a refactor. It's harmless +but distracting, so just remove it. + +Fixes: 2541626cfb79 ("drm/nouveau/acr: use common falcon HS FW code for ACR FWs") +Signed-off-by: Timur Tabi +Link: https://lore.kernel.org/r/20250813001004.2986092-3-ttabi@nvidia.com +Signed-off-by: Danilo Krummrich +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c | 13 +++---------- + 1 file changed, 3 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +index 6a004c6e67425..7c43397c19e61 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c ++++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +@@ -249,9 +249,11 @@ int + gm200_flcn_fw_load(struct nvkm_falcon_fw *fw) + { + struct nvkm_falcon *falcon = fw->falcon; +- int target, ret; ++ int ret; + + if (fw->inst) { ++ int target; ++ + nvkm_falcon_mask(falcon, 0x048, 0x00000001, 0x00000001); + + switch (nvkm_memory_target(fw->inst)) { +@@ -285,15 +287,6 @@ gm200_flcn_fw_load(struct nvkm_falcon_fw *fw) + } + + if (fw->boot) { +- switch (nvkm_memory_target(&fw->fw.mem.memory)) { +- case NVKM_MEM_TARGET_VRAM: target = 4; break; +- case NVKM_MEM_TARGET_HOST: target = 5; break; +- case NVKM_MEM_TARGET_NCOH: target = 6; break; +- default: +- WARN_ON(1); +- return -EINVAL; +- } +- + ret = nvkm_falcon_pio_wr(falcon, fw->boot, 0, 0, + IMEM, falcon->code.limit - fw->boot_size, fw->boot_size, + fw->boot_addr >> 8, false); +-- +2.50.1 + diff --git a/queue-6.16/drm-xe-don-t-trigger-rebind-on-initial-dma-buf-valid.patch b/queue-6.16/drm-xe-don-t-trigger-rebind-on-initial-dma-buf-valid.patch new file mode 100644 index 0000000000..b15ac48549 --- /dev/null +++ b/queue-6.16/drm-xe-don-t-trigger-rebind-on-initial-dma-buf-valid.patch @@ -0,0 +1,48 @@ +From 5064a5a5da12f395cda17abd5fa598f63eff5443 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 08:28:41 -0700 +Subject: drm/xe: Don't trigger rebind on initial dma-buf validation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Matthew Brost + +[ Upstream commit 16ca06aa2c2218cb21907c0c45a746958c944def ] + +On the first validate of an imported dma-buf (initial bind), the device +has no GPU mappings, so a rebind is unnecessary. Rebinding here is +harmful in multi-GPU setups and for VMs using preempt-fence mode, as it +would evict in-flight GPU work. + +v2: + - Drop dma_buf_validated, check for XE_PL_SYSTEM (Thomas) + +Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs") +Signed-off-by: Matthew Brost +Reviewed-by: Thomas Hellström +Link: https://lore.kernel.org/r/20250825152841.3837378-1-matthew.brost@intel.com +(cherry picked from commit ffdf968762e4fb3cdae54e811ec3525e67440a60) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_bo.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c +index e2c6493cb70d9..74635b444122d 100644 +--- a/drivers/gpu/drm/xe/xe_bo.c ++++ b/drivers/gpu/drm/xe/xe_bo.c +@@ -796,7 +796,8 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict, + } + + if (ttm_bo->type == ttm_bo_type_sg) { +- ret = xe_bo_move_notify(bo, ctx); ++ if (new_mem->mem_type == XE_PL_SYSTEM) ++ ret = xe_bo_move_notify(bo, ctx); + if (!ret) + ret = xe_bo_move_dmabuf(ttm_bo, new_mem); + return ret; +-- +2.50.1 + diff --git a/queue-6.16/drm-xe-vm-don-t-pin-the-vm_resv-during-validation.patch b/queue-6.16/drm-xe-vm-don-t-pin-the-vm_resv-during-validation.patch new file mode 100644 index 0000000000..430b183672 --- /dev/null +++ b/queue-6.16/drm-xe-vm-don-t-pin-the-vm_resv-during-validation.patch @@ -0,0 +1,103 @@ +From 1850e2b00bbfd8a3c2a0b2bd6705101201cfe4a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Aug 2025 16:30:43 +0200 +Subject: drm/xe/vm: Don't pin the vm_resv during validation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thomas Hellström + +[ Upstream commit 7551865cd12af2dc47e5a174eebcfb0b94b5449b ] + +The pinning has the odd side-effect that unlocking *any* resv +during validation triggers an "unlocking pinned lock" warning. + +Cc: Matthew Brost +Fixes: 5cc3325584c4 ("drm/xe: Rework eviction rejection of bound external bos") +Signed-off-by: Thomas Hellström +Reviewed-by: Matthew Brost +Link: https://lore.kernel.org/r/20250821143045.106005-2-thomas.hellstrom@linux.intel.com +(cherry picked from commit 0a51bf3e54dd8b77e6f1febbbb66def0660862d2) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_bo.c | 5 ++--- + drivers/gpu/drm/xe/xe_vm.h | 15 ++------------- + 2 files changed, 4 insertions(+), 16 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c +index 7aa2c17825da9..e2c6493cb70d9 100644 +--- a/drivers/gpu/drm/xe/xe_bo.c ++++ b/drivers/gpu/drm/xe/xe_bo.c +@@ -2435,7 +2435,6 @@ int xe_bo_validate(struct xe_bo *bo, struct xe_vm *vm, bool allow_res_evict) + .no_wait_gpu = false, + .gfp_retry_mayfail = true, + }; +- struct pin_cookie cookie; + int ret; + + if (vm) { +@@ -2446,10 +2445,10 @@ int xe_bo_validate(struct xe_bo *bo, struct xe_vm *vm, bool allow_res_evict) + ctx.resv = xe_vm_resv(vm); + } + +- cookie = xe_vm_set_validating(vm, allow_res_evict); ++ xe_vm_set_validating(vm, allow_res_evict); + trace_xe_bo_validate(bo); + ret = ttm_bo_validate(&bo->ttm, &bo->placement, &ctx); +- xe_vm_clear_validating(vm, allow_res_evict, cookie); ++ xe_vm_clear_validating(vm, allow_res_evict); + + return ret; + } +diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h +index 0158ec0ae3b23..e54ca835b5828 100644 +--- a/drivers/gpu/drm/xe/xe_vm.h ++++ b/drivers/gpu/drm/xe/xe_vm.h +@@ -310,22 +310,14 @@ void xe_vm_snapshot_free(struct xe_vm_snapshot *snap); + * Register this task as currently making bos resident for the vm. Intended + * to avoid eviction by the same task of shared bos bound to the vm. + * Call with the vm's resv lock held. +- * +- * Return: A pin cookie that should be used for xe_vm_clear_validating(). + */ +-static inline struct pin_cookie xe_vm_set_validating(struct xe_vm *vm, +- bool allow_res_evict) ++static inline void xe_vm_set_validating(struct xe_vm *vm, bool allow_res_evict) + { +- struct pin_cookie cookie = {}; +- + if (vm && !allow_res_evict) { + xe_vm_assert_held(vm); +- cookie = lockdep_pin_lock(&xe_vm_resv(vm)->lock.base); + /* Pairs with READ_ONCE in xe_vm_is_validating() */ + WRITE_ONCE(vm->validating, current); + } +- +- return cookie; + } + + /** +@@ -333,17 +325,14 @@ static inline struct pin_cookie xe_vm_set_validating(struct xe_vm *vm, + * @vm: Pointer to the vm or NULL + * @allow_res_evict: Eviction from @vm was allowed. Must be set to the same + * value as for xe_vm_set_validation(). +- * @cookie: Cookie obtained from xe_vm_set_validating(). + * + * Register this task as currently making bos resident for the vm. Intended + * to avoid eviction by the same task of shared bos bound to the vm. + * Call with the vm's resv lock held. + */ +-static inline void xe_vm_clear_validating(struct xe_vm *vm, bool allow_res_evict, +- struct pin_cookie cookie) ++static inline void xe_vm_clear_validating(struct xe_vm *vm, bool allow_res_evict) + { + if (vm && !allow_res_evict) { +- lockdep_unpin_lock(&xe_vm_resv(vm)->lock.base, cookie); + /* Pairs with READ_ONCE in xe_vm_is_validating() */ + WRITE_ONCE(vm->validating, NULL); + } +-- +2.50.1 + diff --git a/queue-6.16/drm-xe-xe_sync-avoid-race-during-ufence-signaling.patch b/queue-6.16/drm-xe-xe_sync-avoid-race-during-ufence-signaling.patch new file mode 100644 index 0000000000..ea45457d74 --- /dev/null +++ b/queue-6.16/drm-xe-xe_sync-avoid-race-during-ufence-signaling.patch @@ -0,0 +1,56 @@ +From eee342b865862b49cca0f8370369fee7586cee59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Aug 2025 10:39:04 +0200 +Subject: drm/xe/xe_sync: avoid race during ufence signaling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Zbigniew Kempczyński + +[ Upstream commit 04e1f683cd28dc9407b238543871a6e09a570dc0 ] + +Marking ufence as signalled after copy_to_user() is too late. +Worker thread which signals ufence by memory write might be raced +with another userspace vm-bind call. In map/unmap scenario unmap +may still see ufence is not signalled causing -EBUSY. Change the +order of marking / write to user-fence fixes this issue. + +Fixes: 977e5b82e090 ("drm/xe: Expose user fence from xe_sync_entry") +Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/5536 +Signed-off-by: Zbigniew Kempczyński +Cc: Matthew Brost +Cc: Matthew Auld +Reviewed-by: Matthew Brost +Signed-off-by: Matthew Brost +Link: https://lore.kernel.org/r/20250820083903.2109891-2-zbigniew.kempczynski@intel.com +(cherry picked from commit 8ae04fe9ffc93d6bc3bc63ac08375427d69cee06) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_sync.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_sync.c b/drivers/gpu/drm/xe/xe_sync.c +index f87276df18f28..82872a51f0983 100644 +--- a/drivers/gpu/drm/xe/xe_sync.c ++++ b/drivers/gpu/drm/xe/xe_sync.c +@@ -77,6 +77,7 @@ static void user_fence_worker(struct work_struct *w) + { + struct xe_user_fence *ufence = container_of(w, struct xe_user_fence, worker); + ++ WRITE_ONCE(ufence->signalled, 1); + if (mmget_not_zero(ufence->mm)) { + kthread_use_mm(ufence->mm); + if (copy_to_user(ufence->addr, &ufence->value, sizeof(ufence->value))) +@@ -91,7 +92,6 @@ static void user_fence_worker(struct work_struct *w) + * Wake up waiters only after updating the ufence state, allowing the UMD + * to safely reuse the same ufence without encountering -EBUSY errors. + */ +- WRITE_ONCE(ufence->signalled, 1); + wake_up_all(&ufence->xe->ufence_wq); + user_fence_put(ufence); + } +-- +2.50.1 + diff --git a/queue-6.16/dt-bindings-display-msm-qcom-mdp5-drop-lut-clock.patch b/queue-6.16/dt-bindings-display-msm-qcom-mdp5-drop-lut-clock.patch new file mode 100644 index 0000000000..75ce100ef6 --- /dev/null +++ b/queue-6.16/dt-bindings-display-msm-qcom-mdp5-drop-lut-clock.patch @@ -0,0 +1,39 @@ +From 7e1fb54cd5fd623cd674ad162637a4030e16bb1e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 9 Aug 2025 11:36:54 +0300 +Subject: dt-bindings: display/msm: qcom,mdp5: drop lut clock + +From: Dmitry Baryshkov + +[ Upstream commit 7ab3b7579a6d2660a3425b9ea93b9a140b07f49c ] + +None of MDP5 platforms have a LUT clock on the display-controller, it +was added by the mistake. Drop it, fixing DT warnings on MSM8976 / +MSM8956 platforms. Technically it's an ABI break, but no other platforms +are affected. + +Fixes: 385c8ac763b3 ("dt-bindings: display/msm: convert MDP5 schema to YAML format") +Signed-off-by: Dmitry Baryshkov +Acked-by: Rob Herring (Arm) +Patchwork: https://patchwork.freedesktop.org/patch/667822/ +Signed-off-by: Rob Clark +Signed-off-by: Sasha Levin +--- + Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml b/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml +index e153f8d26e7aa..2735c78b0b67a 100644 +--- a/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml ++++ b/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml +@@ -60,7 +60,6 @@ properties: + - const: bus + - const: core + - const: vsync +- - const: lut + - const: tbu + - const: tbu_rt + # MSM8996 has additional iommu clock +-- +2.50.1 + diff --git a/queue-6.16/efi-stmm-fix-incorrect-buffer-allocation-method.patch b/queue-6.16/efi-stmm-fix-incorrect-buffer-allocation-method.patch new file mode 100644 index 0000000000..11904e5b8f --- /dev/null +++ b/queue-6.16/efi-stmm-fix-incorrect-buffer-allocation-method.patch @@ -0,0 +1,111 @@ +From 261aecfdcd3d8a4cdf60881d3a717a72f006e1df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 18:07:10 +0200 +Subject: efi: stmm: Fix incorrect buffer allocation method + +From: Jan Kiszka + +[ Upstream commit c5e81e672699e0c5557b2b755cc8f7a69aa92bff ] + +The communication buffer allocated by setup_mm_hdr() is later on passed +to tee_shm_register_kernel_buf(). The latter expects those buffers to be +contiguous pages, but setup_mm_hdr() just uses kmalloc(). That can cause +various corruptions or BUGs, specifically since commit 9aec2fb0fd5e +("slab: allocate frozen pages"), though it was broken before as well. + +Fix this by using alloc_pages_exact() instead of kmalloc(). + +Fixes: c44b6be62e8d ("efi: Add tee-based EFI variable driver") +Signed-off-by: Jan Kiszka +Acked-by: Ilias Apalodimas +Acked-by: Sumit Garg +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + drivers/firmware/efi/stmm/tee_stmm_efi.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/drivers/firmware/efi/stmm/tee_stmm_efi.c b/drivers/firmware/efi/stmm/tee_stmm_efi.c +index f741ca279052b..e15d11ed165ee 100644 +--- a/drivers/firmware/efi/stmm/tee_stmm_efi.c ++++ b/drivers/firmware/efi/stmm/tee_stmm_efi.c +@@ -143,6 +143,10 @@ static efi_status_t mm_communicate(u8 *comm_buf, size_t payload_size) + return var_hdr->ret_status; + } + ++#define COMM_BUF_SIZE(__payload_size) (MM_COMMUNICATE_HEADER_SIZE + \ ++ MM_VARIABLE_COMMUNICATE_SIZE + \ ++ (__payload_size)) ++ + /** + * setup_mm_hdr() - Allocate a buffer for StandAloneMM and initialize the + * header data. +@@ -173,9 +177,8 @@ static void *setup_mm_hdr(u8 **dptr, size_t payload_size, size_t func, + return NULL; + } + +- comm_buf = kzalloc(MM_COMMUNICATE_HEADER_SIZE + +- MM_VARIABLE_COMMUNICATE_SIZE + payload_size, +- GFP_KERNEL); ++ comm_buf = alloc_pages_exact(COMM_BUF_SIZE(payload_size), ++ GFP_KERNEL | __GFP_ZERO); + if (!comm_buf) { + *ret = EFI_OUT_OF_RESOURCES; + return NULL; +@@ -239,7 +242,7 @@ static efi_status_t get_max_payload(size_t *size) + */ + *size -= 2; + out: +- kfree(comm_buf); ++ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); + return ret; + } + +@@ -282,7 +285,7 @@ static efi_status_t get_property_int(u16 *name, size_t name_size, + memcpy(var_property, &smm_property->property, sizeof(*var_property)); + + out: +- kfree(comm_buf); ++ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); + return ret; + } + +@@ -347,7 +350,7 @@ static efi_status_t tee_get_variable(u16 *name, efi_guid_t *vendor, + memcpy(data, (u8 *)var_acc->name + var_acc->name_size, + var_acc->data_size); + out: +- kfree(comm_buf); ++ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); + return ret; + } + +@@ -404,7 +407,7 @@ static efi_status_t tee_get_next_variable(unsigned long *name_size, + memcpy(name, var_getnext->name, var_getnext->name_size); + + out: +- kfree(comm_buf); ++ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); + return ret; + } + +@@ -467,7 +470,7 @@ static efi_status_t tee_set_variable(efi_char16_t *name, efi_guid_t *vendor, + ret = mm_communicate(comm_buf, payload_size); + dev_dbg(pvt_data.dev, "Set Variable %s %d %lx\n", __FILE__, __LINE__, ret); + out: +- kfree(comm_buf); ++ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); + return ret; + } + +@@ -507,7 +510,7 @@ static efi_status_t tee_query_variable_info(u32 attributes, + *max_variable_size = mm_query_info->max_variable_size; + + out: +- kfree(comm_buf); ++ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); + return ret; + } + +-- +2.50.1 + diff --git a/queue-6.16/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch b/queue-6.16/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch new file mode 100644 index 0000000000..4e4a47d463 --- /dev/null +++ b/queue-6.16/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch @@ -0,0 +1,77 @@ +From 3bec7c0470fdba2b688af477fa7d1757698b677b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 15:39:54 +0800 +Subject: efivarfs: Fix slab-out-of-bounds in efivarfs_d_compare + +From: Li Nan + +[ Upstream commit a6358f8cf64850f3f27857b8ed8c1b08cfc4685c ] + +Observed on kernel 6.6 (present on master as well): + + BUG: KASAN: slab-out-of-bounds in memcmp+0x98/0xd0 + Call trace: + kasan_check_range+0xe8/0x190 + __asan_loadN+0x1c/0x28 + memcmp+0x98/0xd0 + efivarfs_d_compare+0x68/0xd8 + __d_lookup_rcu_op_compare+0x178/0x218 + __d_lookup_rcu+0x1f8/0x228 + d_alloc_parallel+0x150/0x648 + lookup_open.isra.0+0x5f0/0x8d0 + open_last_lookups+0x264/0x828 + path_openat+0x130/0x3f8 + do_filp_open+0x114/0x248 + do_sys_openat2+0x340/0x3c0 + __arm64_sys_openat+0x120/0x1a0 + +If dentry->d_name.len < EFI_VARIABLE_GUID_LEN , 'guid' can become +negative, leadings to oob. The issue can be triggered by parallel +lookups using invalid filename: + + T1 T2 + lookup_open + ->lookup + simple_lookup + d_add + // invalid dentry is added to hash list + + lookup_open + d_alloc_parallel + __d_lookup_rcu + __d_lookup_rcu_op_compare + hlist_bl_for_each_entry_rcu + // invalid dentry can be retrieved + ->d_compare + efivarfs_d_compare + // oob + +Fix it by checking 'guid' before cmp. + +Fixes: da27a24383b2 ("efivarfs: guid part of filenames are case-insensitive") +Signed-off-by: Li Nan +Signed-off-by: Wu Guanghao +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + fs/efivarfs/super.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c +index 284d6dbba2ece..5c0d45cccc10e 100644 +--- a/fs/efivarfs/super.c ++++ b/fs/efivarfs/super.c +@@ -152,6 +152,10 @@ static int efivarfs_d_compare(const struct dentry *dentry, + { + int guid = len - EFI_VARIABLE_GUID_LEN; + ++ /* Parallel lookups may produce a temporary invalid filename */ ++ if (guid <= 0) ++ return 1; ++ + if (name->len != len) + return 1; + +-- +2.50.1 + diff --git a/queue-6.16/fbnic-move-phylink-resume-out-of-service_task-and-in.patch b/queue-6.16/fbnic-move-phylink-resume-out-of-service_task-and-in.patch new file mode 100644 index 0000000000..455d267639 --- /dev/null +++ b/queue-6.16/fbnic-move-phylink-resume-out-of-service_task-and-in.patch @@ -0,0 +1,120 @@ +From 42537d367c4e534c42d1c8e149b80958ca1c994d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 15:56:13 -0700 +Subject: fbnic: Move phylink resume out of service_task and into open/close + +From: Alexander Duyck + +[ Upstream commit 6ede14a2c6365e7e5d855643c7c8390b5268c467 ] + +The fbnic driver was presenting with the following locking assert coming +out of a PM resume: +[ 42.208116][ T164] RTNL: assertion failed at drivers/net/phy/phylink.c (2611) +[ 42.208492][ T164] WARNING: CPU: 1 PID: 164 at drivers/net/phy/phylink.c:2611 phylink_resume+0x190/0x1e0 +[ 42.208872][ T164] Modules linked in: +[ 42.209140][ T164] CPU: 1 UID: 0 PID: 164 Comm: bash Not tainted 6.17.0-rc2-virtme #134 PREEMPT(full) +[ 42.209496][ T164] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.17.0-5.fc42 04/01/2014 +[ 42.209861][ T164] RIP: 0010:phylink_resume+0x190/0x1e0 +[ 42.210057][ T164] Code: 83 e5 01 0f 85 b0 fe ff ff c6 05 1c cd 3e 02 01 90 ba 33 0a 00 00 48 c7 c6 20 3a 1d a5 48 c7 c7 e0 3e 1d a5 e8 21 b8 90 fe 90 <0f> 0b 90 90 e9 86 fe ff ff e8 42 ea 1f ff e9 e2 fe ff ff 48 89 ef +[ 42.210708][ T164] RSP: 0018:ffffc90000affbd8 EFLAGS: 00010296 +[ 42.210983][ T164] RAX: 0000000000000000 RBX: ffff8880078d8400 RCX: 0000000000000000 +[ 42.211235][ T164] RDX: 0000000000000000 RSI: 1ffffffff4f10938 RDI: 0000000000000001 +[ 42.211466][ T164] RBP: 0000000000000000 R08: ffffffffa2ae79ea R09: fffffbfff4b3eb84 +[ 42.211707][ T164] R10: 0000000000000003 R11: 0000000000000000 R12: ffff888007ad8000 +[ 42.211997][ T164] R13: 0000000000000002 R14: ffff888006a18800 R15: ffffffffa34c59e0 +[ 42.212234][ T164] FS: 00007f0dc8e39740(0000) GS:ffff88808f51f000(0000) knlGS:0000000000000000 +[ 42.212505][ T164] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 42.212704][ T164] CR2: 00007f0dc8e9fe10 CR3: 000000000b56d003 CR4: 0000000000772ef0 +[ 42.213227][ T164] PKRU: 55555554 +[ 42.213366][ T164] Call Trace: +[ 42.213483][ T164] +[ 42.213565][ T164] __fbnic_pm_attach.isra.0+0x8e/0xa0 +[ 42.213725][ T164] pci_reset_function+0x116/0x1d0 +[ 42.213895][ T164] reset_store+0xa0/0x100 +[ 42.214025][ T164] ? pci_dev_reset_attr_is_visible+0x50/0x50 +[ 42.214221][ T164] ? sysfs_file_kobj+0xc1/0x1e0 +[ 42.214374][ T164] ? sysfs_kf_write+0x65/0x160 +[ 42.214526][ T164] kernfs_fop_write_iter+0x2f8/0x4c0 +[ 42.214677][ T164] ? kernfs_vma_page_mkwrite+0x1f0/0x1f0 +[ 42.214836][ T164] new_sync_write+0x308/0x6f0 +[ 42.214987][ T164] ? __lock_acquire+0x34c/0x740 +[ 42.215135][ T164] ? new_sync_read+0x6f0/0x6f0 +[ 42.215288][ T164] ? lock_acquire.part.0+0xbc/0x260 +[ 42.215440][ T164] ? ksys_write+0xff/0x200 +[ 42.215590][ T164] ? perf_trace_sched_switch+0x6d0/0x6d0 +[ 42.215742][ T164] vfs_write+0x65e/0xbb0 +[ 42.215876][ T164] ksys_write+0xff/0x200 +[ 42.215994][ T164] ? __ia32_sys_read+0xc0/0xc0 +[ 42.216141][ T164] ? do_user_addr_fault+0x269/0x9f0 +[ 42.216292][ T164] ? rcu_is_watching+0x15/0xd0 +[ 42.216442][ T164] do_syscall_64+0xbb/0x360 +[ 42.216591][ T164] entry_SYSCALL_64_after_hwframe+0x4b/0x53 +[ 42.216784][ T164] RIP: 0033:0x7f0dc8ea9986 + +A bit of digging showed that we were invoking the phylink_resume as a part +of the fbnic_up path when we were enabling the service task while not +holding the RTNL lock. We should be enabling this sooner as a part of the +ndo_open path and then just letting the service task come online later. +This will help to enforce the correct locking and brings the phylink +interface online at the same time as the network interface, instead of at a +later time. + +I tested this on QEMU to verify this was working by putting the system to +sleep using "echo mem > /sys/power/state" to put the system to sleep in the +guest and then using the command "system_wakeup" in the QEMU monitor. + +Fixes: 69684376eed5 ("eth: fbnic: Add link detection") +Signed-off-by: Alexander Duyck +Reviewed-by: Przemek Kitszel +Link: https://patch.msgid.link/175616257316.1963577.12238158800417771119.stgit@ahduyck-xeon-server.home.arpa +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/meta/fbnic/fbnic_netdev.c | 4 ++++ + drivers/net/ethernet/meta/fbnic/fbnic_pci.c | 2 -- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +index 553bd8b8bb056..d3d1003df8314 100644 +--- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c ++++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +@@ -52,6 +52,8 @@ int __fbnic_open(struct fbnic_net *fbn) + fbnic_bmc_rpc_init(fbd); + fbnic_rss_reinit(fbd, fbn); + ++ phylink_resume(fbn->phylink); ++ + return 0; + time_stop: + fbnic_time_stop(fbn); +@@ -84,6 +86,8 @@ static int fbnic_stop(struct net_device *netdev) + { + struct fbnic_net *fbn = netdev_priv(netdev); + ++ phylink_suspend(fbn->phylink, fbnic_bmc_present(fbn->fbd)); ++ + fbnic_down(fbn); + fbnic_pcs_free_irq(fbn->fbd); + +diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c +index 249d3ef862d5a..38045cce38012 100644 +--- a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c ++++ b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c +@@ -118,14 +118,12 @@ static void fbnic_service_task_start(struct fbnic_net *fbn) + struct fbnic_dev *fbd = fbn->fbd; + + schedule_delayed_work(&fbd->service_task, HZ); +- phylink_resume(fbn->phylink); + } + + static void fbnic_service_task_stop(struct fbnic_net *fbn) + { + struct fbnic_dev *fbd = fbn->fbd; + +- phylink_suspend(fbn->phylink, fbnic_bmc_present(fbd)); + cancel_delayed_work(&fbd->service_task); + } + +-- +2.50.1 + diff --git a/queue-6.16/hid-input-rename-hidinput_set_battery_charge_status.patch b/queue-6.16/hid-input-rename-hidinput_set_battery_charge_status.patch new file mode 100644 index 0000000000..26a7b92beb --- /dev/null +++ b/queue-6.16/hid-input-rename-hidinput_set_battery_charge_status.patch @@ -0,0 +1,147 @@ +From 7b4a69905042843249550d6467d8b7c6bd9b7161 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Aug 2025 12:39:39 +0200 +Subject: HID: input: rename hidinput_set_battery_charge_status() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit a82231b2a8712d0218fc286a9b0da328d419a3f4 ] + +In preparation for a patch fixing a bug affecting +hidinput_set_battery_charge_status(), rename the function to +hidinput_update_battery_charge_status() and move it up so it can be used +by hidinput_update_battery(). + +Refactor, no functional changes. + +Tested-by: 卢国宏 +Signed-off-by: José Expósito +Signed-off-by: Jiri Kosina +Stable-dep-of: e94536e1d181 ("HID: input: report battery status changes immediately") +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-input-test.c | 10 +++++----- + drivers/hid/hid-input.c | 38 ++++++++++++++++++------------------ + 2 files changed, 24 insertions(+), 24 deletions(-) + +diff --git a/drivers/hid/hid-input-test.c b/drivers/hid/hid-input-test.c +index 77c2d45ac62a7..6f5c71660d823 100644 +--- a/drivers/hid/hid-input-test.c ++++ b/drivers/hid/hid-input-test.c +@@ -7,7 +7,7 @@ + + #include + +-static void hid_test_input_set_battery_charge_status(struct kunit *test) ++static void hid_test_input_update_battery_charge_status(struct kunit *test) + { + struct hid_device *dev; + bool handled; +@@ -15,15 +15,15 @@ static void hid_test_input_set_battery_charge_status(struct kunit *test) + dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + +- handled = hidinput_set_battery_charge_status(dev, HID_DG_HEIGHT, 0); ++ handled = hidinput_update_battery_charge_status(dev, HID_DG_HEIGHT, 0); + KUNIT_EXPECT_FALSE(test, handled); + KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_UNKNOWN); + +- handled = hidinput_set_battery_charge_status(dev, HID_BAT_CHARGING, 0); ++ handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 0); + KUNIT_EXPECT_TRUE(test, handled); + KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_DISCHARGING); + +- handled = hidinput_set_battery_charge_status(dev, HID_BAT_CHARGING, 1); ++ handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 1); + KUNIT_EXPECT_TRUE(test, handled); + KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_CHARGING); + } +@@ -63,7 +63,7 @@ static void hid_test_input_get_battery_property(struct kunit *test) + } + + static struct kunit_case hid_input_tests[] = { +- KUNIT_CASE(hid_test_input_set_battery_charge_status), ++ KUNIT_CASE(hid_test_input_update_battery_charge_status), + KUNIT_CASE(hid_test_input_get_battery_property), + { } + }; +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index ff1784b5c2a47..262787e6eb204 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -595,6 +595,20 @@ static void hidinput_cleanup_battery(struct hid_device *dev) + dev->battery = NULL; + } + ++static bool hidinput_update_battery_charge_status(struct hid_device *dev, ++ unsigned int usage, int value) ++{ ++ switch (usage) { ++ case HID_BAT_CHARGING: ++ dev->battery_charge_status = value ? ++ POWER_SUPPLY_STATUS_CHARGING : ++ POWER_SUPPLY_STATUS_DISCHARGING; ++ return true; ++ } ++ ++ return false; ++} ++ + static void hidinput_update_battery(struct hid_device *dev, int value) + { + int capacity; +@@ -617,20 +631,6 @@ static void hidinput_update_battery(struct hid_device *dev, int value) + power_supply_changed(dev->battery); + } + } +- +-static bool hidinput_set_battery_charge_status(struct hid_device *dev, +- unsigned int usage, int value) +-{ +- switch (usage) { +- case HID_BAT_CHARGING: +- dev->battery_charge_status = value ? +- POWER_SUPPLY_STATUS_CHARGING : +- POWER_SUPPLY_STATUS_DISCHARGING; +- return true; +- } +- +- return false; +-} + #else /* !CONFIG_HID_BATTERY_STRENGTH */ + static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, + struct hid_field *field, bool is_percentage) +@@ -642,14 +642,14 @@ static void hidinput_cleanup_battery(struct hid_device *dev) + { + } + +-static void hidinput_update_battery(struct hid_device *dev, int value) ++static bool hidinput_update_battery_charge_status(struct hid_device *dev, ++ unsigned int usage, int value) + { ++ return false; + } + +-static bool hidinput_set_battery_charge_status(struct hid_device *dev, +- unsigned int usage, int value) ++static void hidinput_update_battery(struct hid_device *dev, int value) + { +- return false; + } + #endif /* CONFIG_HID_BATTERY_STRENGTH */ + +@@ -1515,7 +1515,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct + return; + + if (usage->type == EV_PWR) { +- bool handled = hidinput_set_battery_charge_status(hid, usage->hid, value); ++ bool handled = hidinput_update_battery_charge_status(hid, usage->hid, value); + + if (!handled) + hidinput_update_battery(hid, value); +-- +2.50.1 + diff --git a/queue-6.16/hid-input-report-battery-status-changes-immediately.patch b/queue-6.16/hid-input-report-battery-status-changes-immediately.patch new file mode 100644 index 0000000000..e46cab7200 --- /dev/null +++ b/queue-6.16/hid-input-report-battery-status-changes-immediately.patch @@ -0,0 +1,97 @@ +From 647a17f9f643be926d6ac02e2bbf7b9d91073209 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Aug 2025 12:39:40 +0200 +Subject: HID: input: report battery status changes immediately +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit e94536e1d1818b0989aa19b443b7089f50133c35 ] + +Previously, the battery status (charging/discharging) was not reported +immediately to user-space.  + +For most input devices, this wasn't problematic because changing their +battery status requires connecting them to a different bus. +For example, a gamepad would report a discharging status while +connected via Bluetooth and a charging status while connected via USB. + +However, certain devices are not connected or disconnected when their +battery status changes. For example, a phone battery changes its status +without connecting or disconnecting it. +In these cases, the battery status was not reported immediately to user +space. + +Report battery status changes immediately to user space to support +these kinds of devices. + +Fixes: a608dc1c0639 ("HID: input: map battery system charging") +Reported-by: 卢国宏 +Closes: https://lore.kernel.org/linux-input/aI49Im0sGb6fpgc8@fedora/T/ +Tested-by: 卢国宏 +Signed-off-by: José Expósito +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-input.c | 23 ++++++++++------------- + 1 file changed, 10 insertions(+), 13 deletions(-) + +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 262787e6eb204..f45f856a127fe 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -609,13 +609,19 @@ static bool hidinput_update_battery_charge_status(struct hid_device *dev, + return false; + } + +-static void hidinput_update_battery(struct hid_device *dev, int value) ++static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, ++ int value) + { + int capacity; + + if (!dev->battery) + return; + ++ if (hidinput_update_battery_charge_status(dev, usage, value)) { ++ power_supply_changed(dev->battery); ++ return; ++ } ++ + if (value == 0 || value < dev->battery_min || value > dev->battery_max) + return; + +@@ -642,13 +648,8 @@ static void hidinput_cleanup_battery(struct hid_device *dev) + { + } + +-static bool hidinput_update_battery_charge_status(struct hid_device *dev, +- unsigned int usage, int value) +-{ +- return false; +-} +- +-static void hidinput_update_battery(struct hid_device *dev, int value) ++static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, ++ int value) + { + } + #endif /* CONFIG_HID_BATTERY_STRENGTH */ +@@ -1515,11 +1516,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct + return; + + if (usage->type == EV_PWR) { +- bool handled = hidinput_update_battery_charge_status(hid, usage->hid, value); +- +- if (!handled) +- hidinput_update_battery(hid, value); +- ++ hidinput_update_battery(hid, usage->hid, value); + return; + } + +-- +2.50.1 + diff --git a/queue-6.16/hid-intel-thc-hid-intel-quicki2c-enhance-driver-re-i.patch b/queue-6.16/hid-intel-thc-hid-intel-quicki2c-enhance-driver-re-i.patch new file mode 100644 index 0000000000..2b2bd40f5f --- /dev/null +++ b/queue-6.16/hid-intel-thc-hid-intel-quicki2c-enhance-driver-re-i.patch @@ -0,0 +1,41 @@ +From f132ce581cb8a4d42085a9dba91d46ca9b0d7fc4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Aug 2025 08:23:32 +0800 +Subject: HID: intel-thc-hid: Intel-quicki2c: Enhance driver re-install flow + +From: Even Xu + +[ Upstream commit afa17a09c699410113199dc15256c6ea2b4133f7 ] + +After driver module is removed and during re-install stage, if there +is continueous user touching on the screen, it is a risk impacting +THC hardware initialization which causes driver installation failure. + +This patch enhances this flow by quiescing the external touch +interrupt after driver is removed which keeps THC hardware +ignore external interrupt during this remove and re-install stage. + +Signed-off-by: Even Xu +Tested-by: Rui Zhang +Fixes: 66b59bfce6d9 ("HID: intel-thc-hid: intel-quicki2c: Complete THC QuickI2C driver") +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c +index 8a8c4a46f9270..142e5c40192ea 100644 +--- a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c ++++ b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c +@@ -406,6 +406,7 @@ static struct quicki2c_device *quicki2c_dev_init(struct pci_dev *pdev, void __io + */ + static void quicki2c_dev_deinit(struct quicki2c_device *qcdev) + { ++ thc_interrupt_quiesce(qcdev->thc_hw, true); + thc_interrupt_enable(qcdev->thc_hw, false); + thc_ltr_unconfig(qcdev->thc_hw); + +-- +2.50.1 + diff --git a/queue-6.16/hid-intel-thc-hid-intel-quicki2c-fix-acpi-dsd-icrs-i.patch b/queue-6.16/hid-intel-thc-hid-intel-quicki2c-fix-acpi-dsd-icrs-i.patch new file mode 100644 index 0000000000..af3e045d5c --- /dev/null +++ b/queue-6.16/hid-intel-thc-hid-intel-quicki2c-fix-acpi-dsd-icrs-i.patch @@ -0,0 +1,87 @@ +From 13e9d367fbc2fc84a45b0457d3da5492ff70a1c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Aug 2025 14:57:25 +0800 +Subject: HID: intel-thc-hid: intel-quicki2c: Fix ACPI dsd ICRS/ISUB length + +From: Aaron Ma + +[ Upstream commit 1db9df89a213318a48d958385dc1b17b379dc32b ] + +The QuickI2C ACPI _DSD methods return ICRS and ISUB data with a +trailing byte, making the actual length is one more byte than the +structs defined. + +It caused stack-out-of-bounds and kernel crash: + +kernel: BUG: KASAN: stack-out-of-bounds in quicki2c_acpi_get_dsd_property.constprop.0+0x111/0x1b0 [intel_quicki2c] +kernel: Write of size 12 at addr ffff888106d1f900 by task kworker/u33:2/75 +kernel: +kernel: CPU: 3 UID: 0 PID: 75 Comm: kworker/u33:2 Not tainted 6.16.0+ #3 PREEMPT(voluntary) +kernel: Workqueue: async async_run_entry_fn +kernel: Call Trace: +kernel: +kernel: dump_stack_lvl+0x76/0xa0 +kernel: print_report+0xd1/0x660 +kernel: ? __pfx__raw_spin_lock_irqsave+0x10/0x10 +kernel: ? __kasan_slab_free+0x5d/0x80 +kernel: ? kasan_addr_to_slab+0xd/0xb0 +kernel: kasan_report+0xe1/0x120 +kernel: ? quicki2c_acpi_get_dsd_property.constprop.0+0x111/0x1b0 [intel_quicki2c] +kernel: ? quicki2c_acpi_get_dsd_property.constprop.0+0x111/0x1b0 [intel_quicki2c] +kernel: kasan_check_range+0x11c/0x200 +kernel: __asan_memcpy+0x3b/0x80 +kernel: quicki2c_acpi_get_dsd_property.constprop.0+0x111/0x1b0 [intel_quicki2c] +kernel: ? __pfx_quicki2c_acpi_get_dsd_property.constprop.0+0x10/0x10 [intel_quicki2c] +kernel: quicki2c_get_acpi_resources+0x237/0x730 [intel_quicki2c] +[...] +kernel: +kernel: +kernel: The buggy address belongs to stack of task kworker/u33:2/75 +kernel: and is located at offset 48 in frame: +kernel: quicki2c_get_acpi_resources+0x0/0x730 [intel_quicki2c] +kernel: +kernel: This frame has 3 objects: +kernel: [32, 36) 'hid_desc_addr' +kernel: [48, 59) 'i2c_param' +kernel: [80, 224) 'i2c_config' + +ACPI DSD methods return: + +\_SB.PC00.THC0.ICRS Buffer 000000003fdc947b 001 Len 0C = 0A 00 80 1A 06 00 00 00 00 00 00 00 +\_SB.PC00.THC0.ISUB Buffer 00000000f2fcbdc4 001 Len 91 = 00 00 00 00 00 00 00 00 00 00 00 00 + +Adding reserved padding to quicki2c_subip_acpi_parameter/config. + +Fixes: 5282e45ccbfa9 ("HID: intel-thc-hid: intel-quicki2c: Add THC QuickI2C ACPI interfaces") +Signed-off-by: Aaron Ma +Reviewed-by: Even Xu +Tested-by: Even Xu +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h +index 6ddb584bd6110..97085a6a7452d 100644 +--- a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h ++++ b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h +@@ -71,6 +71,7 @@ struct quicki2c_subip_acpi_parameter { + u16 device_address; + u64 connection_speed; + u8 addressing_mode; ++ u8 reserved; + } __packed; + + /** +@@ -120,6 +121,7 @@ struct quicki2c_subip_acpi_config { + u64 HMTD; + u64 HMRD; + u64 HMSL; ++ u8 reserved; + }; + + struct device; +-- +2.50.1 + diff --git a/queue-6.16/hid-intel-thc-hid-intel-thc-fix-incorrect-pointer-ar.patch b/queue-6.16/hid-intel-thc-hid-intel-thc-fix-incorrect-pointer-ar.patch new file mode 100644 index 0000000000..845d9c0045 --- /dev/null +++ b/queue-6.16/hid-intel-thc-hid-intel-thc-fix-incorrect-pointer-ar.patch @@ -0,0 +1,82 @@ +From 082e59fd3aeedb2ccd4475a4dbddb5aa8e9d27ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Aug 2025 14:57:26 +0800 +Subject: HID: intel-thc-hid: intel-thc: Fix incorrect pointer arithmetic in + I2C regs save + +From: Aaron Ma + +[ Upstream commit a7fc15ed629be89e51e09b743277c53e0a0168f5 ] + +Improper use of secondary pointer (&dev->i2c_subip_regs) caused +kernel crash and out-of-bounds error: + + BUG: KASAN: slab-out-of-bounds in _regmap_bulk_read+0x449/0x510 + Write of size 4 at addr ffff888136005dc0 by task kworker/u33:5/5107 + + CPU: 3 UID: 0 PID: 5107 Comm: kworker/u33:5 Not tainted 6.16.0+ #3 PREEMPT(voluntary) + Workqueue: async async_run_entry_fn + Call Trace: + + dump_stack_lvl+0x76/0xa0 + print_report+0xd1/0x660 + ? __pfx__raw_spin_lock_irqsave+0x10/0x10 + ? kasan_complete_mode_report_info+0x26/0x200 + kasan_report+0xe1/0x120 + ? _regmap_bulk_read+0x449/0x510 + ? _regmap_bulk_read+0x449/0x510 + __asan_report_store4_noabort+0x17/0x30 + _regmap_bulk_read+0x449/0x510 + ? __pfx__regmap_bulk_read+0x10/0x10 + regmap_bulk_read+0x270/0x3d0 + pio_complete+0x1ee/0x2c0 [intel_thc] + ? __pfx_pio_complete+0x10/0x10 [intel_thc] + ? __pfx_pio_wait+0x10/0x10 [intel_thc] + ? regmap_update_bits_base+0x13b/0x1f0 + thc_i2c_subip_pio_read+0x117/0x270 [intel_thc] + thc_i2c_subip_regs_save+0xc2/0x140 [intel_thc] + ? __pfx_thc_i2c_subip_regs_save+0x10/0x10 [intel_thc] +[...] + The buggy address belongs to the object at ffff888136005d00 + which belongs to the cache kmalloc-rnd-12-192 of size 192 + The buggy address is located 0 bytes to the right of + allocated 192-byte region [ffff888136005d00, ffff888136005dc0) + +Replaced with direct array indexing (&dev->i2c_subip_regs[i]) to ensure +safe memory access. + +Fixes: 4228966def884 ("HID: intel-thc-hid: intel-thc: Add THC I2C config interfaces") +Signed-off-by: Aaron Ma +Reviewed-by: Even Xu +Tested-by: Even Xu +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c +index c105df7f6c873..4698722e0d0a6 100644 +--- a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c ++++ b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c +@@ -1539,7 +1539,7 @@ int thc_i2c_subip_regs_save(struct thc_device *dev) + + for (int i = 0; i < ARRAY_SIZE(i2c_subip_regs); i++) { + ret = thc_i2c_subip_pio_read(dev, i2c_subip_regs[i], +- &read_size, (u32 *)&dev->i2c_subip_regs + i); ++ &read_size, &dev->i2c_subip_regs[i]); + if (ret < 0) + return ret; + } +@@ -1562,7 +1562,7 @@ int thc_i2c_subip_regs_restore(struct thc_device *dev) + + for (int i = 0; i < ARRAY_SIZE(i2c_subip_regs); i++) { + ret = thc_i2c_subip_pio_write(dev, i2c_subip_regs[i], +- write_size, (u32 *)&dev->i2c_subip_regs + i); ++ write_size, &dev->i2c_subip_regs[i]); + if (ret < 0) + return ret; + } +-- +2.50.1 + diff --git a/queue-6.16/ice-don-t-leave-device-non-functional-if-tx-schedule.patch b/queue-6.16/ice-don-t-leave-device-non-functional-if-tx-schedule.patch new file mode 100644 index 0000000000..1bcaa42eff --- /dev/null +++ b/queue-6.16/ice-don-t-leave-device-non-functional-if-tx-schedule.patch @@ -0,0 +1,238 @@ +From 7b6fe95a26cf79fc5770078e2223c940b89adb88 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Jul 2025 09:57:09 -0700 +Subject: ice: don't leave device non-functional if Tx scheduler config fails + +From: Jacob Keller + +[ Upstream commit 86aae43f21cf784c1d7f6a9af93e5116b0f232ab ] + +The ice_cfg_tx_topo function attempts to apply Tx scheduler topology +configuration based on NVM parameters, selecting either a 5 or 9 layer +topology. + +As part of this flow, the driver acquires the "Global Configuration Lock", +which is a hardware resource associated with programming the DDP package +to the device. This "lock" is implemented by firmware as a way to +guarantee that only one PF can program the DDP for a device. Unlike a +traditional lock, once a PF has acquired this lock, no other PF will be +able to acquire it again (including that PF) until a CORER of the device. +Future requests to acquire the lock report that global configuration has +already completed. + +The following flow is used to program the Tx topology: + + * Read the DDP package for scheduler configuration data + * Acquire the global configuration lock + * Program Tx scheduler topology according to DDP package data + * Trigger a CORER which clears the global configuration lock + +This is followed by the flow for programming the DDP package: + + * Acquire the global configuration lock (again) + * Download the DDP package to the device + * Release the global configuration lock. + +However, if configuration of the Tx topology fails, (i.e. +ice_get_set_tx_topo returns an error code), the driver exits +ice_cfg_tx_topo() immediately, and fails to trigger CORER. + +While the global configuration lock is held, the firmware rejects most +AdminQ commands, as it is waiting for the DDP package download (or Tx +scheduler topology programming) to occur. + +The current driver flows assume that the global configuration lock has been +reset by CORER after programming the Tx topology. Thus, the same PF +attempts to acquire the global lock again, and fails. This results in the +driver reporting "an unknown error occurred when loading the DDP package". +It then attempts to enter safe mode, but ultimately fails to finish +ice_probe() since nearly all AdminQ command report error codes, and the +driver stops loading the device at some point during its initialization. + +The only currently known way that ice_get_set_tx_topo() can fail is with +certain older DDP packages which contain invalid topology configuration, on +firmware versions which strictly validate this data. The most recent +releases of the DDP have resolved the invalid data. However, it is still +poor practice to essentially brick the device, and prevent access to the +device even through safe mode or recovery mode. It is also plausible that +this command could fail for some other reason in the future. + +We cannot simply release the global lock after a failed call to +ice_get_set_tx_topo(). Releasing the lock indicates to firmware that global +configuration (downloading of the DDP) has completed. Future attempts by +this or other PFs to load the DDP will fail with a report that the DDP +package has already been downloaded. Then, PFs will enter safe mode as they +realize that the package on the device does not meet the minimum version +requirement to load. The reported error messages are confusing, as they +indicate the version of the default "safe mode" package in the NVM, rather +than the version of the file loaded from /lib/firmware. + +Instead, we need to trigger CORER to clear global configuration. This is +the lowest level of hardware reset which clears the global configuration +lock and related state. It also clears any already downloaded DDP. +Crucially, it does *not* clear the Tx scheduler topology configuration. + +Refactor ice_cfg_tx_topo() to always trigger a CORER after acquiring the +global lock, regardless of success or failure of the topology +configuration. + +We need to re-initialize the HW structure when we trigger the CORER. Thus, +it makes sense for this to be the responsibility of ice_cfg_tx_topo() +rather than its caller, ice_init_tx_topology(). This avoids needless +re-initialization in cases where we don't attempt to update the Tx +scheduler topology, such as if it has already been programmed. + +There is one catch: failure to re-initialize the HW struct should stop +ice_probe(). If this function fails, we won't have a valid HW structure and +cannot ensure the device is functioning properly. To handle this, ensure +ice_cfg_tx_topo() returns a limited set of error codes. Set aside one +specifically, -ENODEV, to indicate that the ice_init_tx_topology() should +fail and stop probe. + +Other error codes indicate failure to apply the Tx scheduler topology. This +is treated as a non-fatal error, with an informational message informing +the system administrator that the updated Tx topology did not apply. This +allows the device to load and function with the default Tx scheduler +topology, rather than failing to load entirely. + +Note that this use of CORER will not result in loops with future PFs +attempting to also load the invalid Tx topology configuration. The first PF +will acquire the global configuration lock as part of programming the DDP. +Each PF after this will attempt to acquire the global lock as part of +programming the Tx topology, and will fail with the indication from +firmware that global configuration is already complete. Tx scheduler +topology configuration is only performed during driver init (probe or +devlink reload) and not during cleanup for a CORER that happens after probe +completes. + +Fixes: 91427e6d9030 ("ice: Support 5 layer topology") +Signed-off-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_ddp.c | 44 ++++++++++++++++------- + drivers/net/ethernet/intel/ice/ice_main.c | 16 ++++++--- + 2 files changed, 43 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ddp.c b/drivers/net/ethernet/intel/ice/ice_ddp.c +index 351824dc3c624..1d3e1b188d22c 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ddp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ddp.c +@@ -2376,7 +2376,13 @@ ice_get_set_tx_topo(struct ice_hw *hw, u8 *buf, u16 buf_size, + * The function will apply the new Tx topology from the package buffer + * if available. + * +- * Return: zero when update was successful, negative values otherwise. ++ * Return: ++ * * 0 - Successfully applied topology configuration. ++ * * -EBUSY - Failed to acquire global configuration lock. ++ * * -EEXIST - Topology configuration has already been applied. ++ * * -EIO - Unable to apply topology configuration. ++ * * -ENODEV - Failed to re-initialize device after applying configuration. ++ * * Other negative error codes indicate unexpected failures. + */ + int ice_cfg_tx_topo(struct ice_hw *hw, const void *buf, u32 len) + { +@@ -2409,7 +2415,7 @@ int ice_cfg_tx_topo(struct ice_hw *hw, const void *buf, u32 len) + + if (status) { + ice_debug(hw, ICE_DBG_INIT, "Get current topology is failed\n"); +- return status; ++ return -EIO; + } + + /* Is default topology already applied ? */ +@@ -2496,31 +2502,45 @@ int ice_cfg_tx_topo(struct ice_hw *hw, const void *buf, u32 len) + ICE_GLOBAL_CFG_LOCK_TIMEOUT); + if (status) { + ice_debug(hw, ICE_DBG_INIT, "Failed to acquire global lock\n"); +- return status; ++ return -EBUSY; + } + + /* Check if reset was triggered already. */ + reg = rd32(hw, GLGEN_RSTAT); + if (reg & GLGEN_RSTAT_DEVSTATE_M) { +- /* Reset is in progress, re-init the HW again */ + ice_debug(hw, ICE_DBG_INIT, "Reset is in progress. Layer topology might be applied already\n"); + ice_check_reset(hw); +- return 0; ++ /* Reset is in progress, re-init the HW again */ ++ goto reinit_hw; + } + + /* Set new topology */ + status = ice_get_set_tx_topo(hw, new_topo, size, NULL, NULL, true); + if (status) { +- ice_debug(hw, ICE_DBG_INIT, "Failed setting Tx topology\n"); +- return status; ++ ice_debug(hw, ICE_DBG_INIT, "Failed to set Tx topology, status %pe\n", ++ ERR_PTR(status)); ++ /* only report -EIO here as the caller checks the error value ++ * and reports an informational error message informing that ++ * the driver failed to program Tx topology. ++ */ ++ status = -EIO; + } + +- /* New topology is updated, delay 1 second before issuing the CORER */ ++ /* Even if Tx topology config failed, we need to CORE reset here to ++ * clear the global configuration lock. Delay 1 second to allow ++ * hardware to settle then issue a CORER ++ */ + msleep(1000); + ice_reset(hw, ICE_RESET_CORER); +- /* CORER will clear the global lock, so no explicit call +- * required for release. +- */ ++ ice_check_reset(hw); ++ ++reinit_hw: ++ /* Since we triggered a CORER, re-initialize hardware */ ++ ice_deinit_hw(hw); ++ if (ice_init_hw(hw)) { ++ ice_debug(hw, ICE_DBG_INIT, "Failed to re-init hardware after setting Tx topology\n"); ++ return -ENODEV; ++ } + +- return 0; ++ return status; + } +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 0a11b4281092e..d42892c8c5a12 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -4532,17 +4532,23 @@ ice_init_tx_topology(struct ice_hw *hw, const struct firmware *firmware) + dev_info(dev, "Tx scheduling layers switching feature disabled\n"); + else + dev_info(dev, "Tx scheduling layers switching feature enabled\n"); +- /* if there was a change in topology ice_cfg_tx_topo triggered +- * a CORER and we need to re-init hw ++ return 0; ++ } else if (err == -ENODEV) { ++ /* If we failed to re-initialize the device, we can no longer ++ * continue loading. + */ +- ice_deinit_hw(hw); +- err = ice_init_hw(hw); +- ++ dev_warn(dev, "Failed to initialize hardware after applying Tx scheduling configuration.\n"); + return err; + } else if (err == -EIO) { + dev_info(dev, "DDP package does not support Tx scheduling layers switching feature - please update to the latest DDP package and try again\n"); ++ return 0; ++ } else if (err == -EEXIST) { ++ return 0; + } + ++ /* Do not treat this as a fatal error. */ ++ dev_info(dev, "Failed to apply Tx scheduling configuration, err %pe\n", ++ ERR_PTR(err)); + return 0; + } + +-- +2.50.1 + diff --git a/queue-6.16/ice-fix-incorrect-counter-for-buffer-allocation-fail.patch b/queue-6.16/ice-fix-incorrect-counter-for-buffer-allocation-fail.patch new file mode 100644 index 0000000000..21ae7bda91 --- /dev/null +++ b/queue-6.16/ice-fix-incorrect-counter-for-buffer-allocation-fail.patch @@ -0,0 +1,46 @@ +From 5dc4ef77970f0bf5bdd95ce69e795fb29e76a9bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Aug 2025 17:53:10 +0200 +Subject: ice: fix incorrect counter for buffer allocation failures + +From: Michal Kubiak + +[ Upstream commit b1a0c977c6f1130f7dd125ee3db8c2435d7e3d41 ] + +Currently, the driver increments `alloc_page_failed` when buffer allocation fails +in `ice_clean_rx_irq()`. However, this counter is intended for page allocation +failures, not buffer allocation issues. + +This patch corrects the counter by incrementing `alloc_buf_failed` instead, +ensuring accurate statistics reporting for buffer allocation failures. + +Fixes: 2fba7dc5157b ("ice: Add support for XDP multi-buffer on Rx side") +Reported-by: Jacob Keller +Suggested-by: Paul Menzel +Signed-off-by: Michal Kubiak +Reviewed-by: Paul Menzel +Reviewed-by: Jason Xing +Reviewed-by: Aleksandr Loktionov +Tested-by: Priya Singh +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_txrx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c +index 0e5107fe62ad5..c50cf3ad190e9 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.c ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c +@@ -1295,7 +1295,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) + skb = ice_construct_skb(rx_ring, xdp); + /* exit if we failed to retrieve a buffer */ + if (!skb) { +- rx_ring->ring_stats->rx_stats.alloc_page_failed++; ++ rx_ring->ring_stats->rx_stats.alloc_buf_failed++; + xdp_verdict = ICE_XDP_CONSUMED; + } + ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict); +-- +2.50.1 + diff --git a/queue-6.16/ice-fix-null-pointer-dereference-in-ice_unplug_aux_d.patch b/queue-6.16/ice-fix-null-pointer-dereference-in-ice_unplug_aux_d.patch new file mode 100644 index 0000000000..e62d98deed --- /dev/null +++ b/queue-6.16/ice-fix-null-pointer-dereference-in-ice_unplug_aux_d.patch @@ -0,0 +1,94 @@ +From d76a3425c637dceb622a9a7e458ba6d762b395e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Jun 2025 07:26:40 -0700 +Subject: ice: fix NULL pointer dereference in ice_unplug_aux_dev() on reset + +From: Emil Tantilov + +[ Upstream commit 60dfe2434eed13082f26eb7409665dfafb38fa51 ] + +Issuing a reset when the driver is loaded without RDMA support, will +results in a crash as it attempts to remove RDMA's non-existent auxbus +device: +echo 1 > /sys/class/net//device/reset + +BUG: kernel NULL pointer dereference, address: 0000000000000008 +... +RIP: 0010:ice_unplug_aux_dev+0x29/0x70 [ice] +... +Call Trace: + +ice_prepare_for_reset+0x77/0x260 [ice] +pci_dev_save_and_disable+0x2c/0x70 +pci_reset_function+0x88/0x130 +reset_store+0x5a/0xa0 +kernfs_fop_write_iter+0x15e/0x210 +vfs_write+0x273/0x520 +ksys_write+0x6b/0xe0 +do_syscall_64+0x79/0x3b0 +entry_SYSCALL_64_after_hwframe+0x76/0x7e + +ice_unplug_aux_dev() checks pf->cdev_info->adev for NULL pointer, but +pf->cdev_info will also be NULL, leading to the deref in the trace above. + +Introduce a flag to be set when the creation of the auxbus device is +successful, to avoid multiple NULL pointer checks in ice_unplug_aux_dev(). + +Fixes: c24a65b6a27c7 ("iidc/ice/irdma: Update IDC to support multiple consumers") +Signed-off-by: Emil Tantilov +Reviewed-by: Przemek Kitszel +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice.h | 1 + + drivers/net/ethernet/intel/ice/ice_idc.c | 10 ++++++---- + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index ddd0ad68185b4..0ef11b7ab477e 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -509,6 +509,7 @@ enum ice_pf_flags { + ICE_FLAG_LINK_LENIENT_MODE_ENA, + ICE_FLAG_PLUG_AUX_DEV, + ICE_FLAG_UNPLUG_AUX_DEV, ++ ICE_FLAG_AUX_DEV_CREATED, + ICE_FLAG_MTU_CHANGED, + ICE_FLAG_GNSS, /* GNSS successfully initialized */ + ICE_FLAG_DPLL, /* SyncE/PTP dplls initialized */ +diff --git a/drivers/net/ethernet/intel/ice/ice_idc.c b/drivers/net/ethernet/intel/ice/ice_idc.c +index 6ab53e430f912..420d45c2558b6 100644 +--- a/drivers/net/ethernet/intel/ice/ice_idc.c ++++ b/drivers/net/ethernet/intel/ice/ice_idc.c +@@ -336,6 +336,7 @@ int ice_plug_aux_dev(struct ice_pf *pf) + mutex_lock(&pf->adev_mutex); + cdev->adev = adev; + mutex_unlock(&pf->adev_mutex); ++ set_bit(ICE_FLAG_AUX_DEV_CREATED, pf->flags); + + return 0; + } +@@ -347,15 +348,16 @@ void ice_unplug_aux_dev(struct ice_pf *pf) + { + struct auxiliary_device *adev; + ++ if (!test_and_clear_bit(ICE_FLAG_AUX_DEV_CREATED, pf->flags)) ++ return; ++ + mutex_lock(&pf->adev_mutex); + adev = pf->cdev_info->adev; + pf->cdev_info->adev = NULL; + mutex_unlock(&pf->adev_mutex); + +- if (adev) { +- auxiliary_device_delete(adev); +- auxiliary_device_uninit(adev); +- } ++ auxiliary_device_delete(adev); ++ auxiliary_device_uninit(adev); + } + + /** +-- +2.50.1 + diff --git a/queue-6.16/ice-use-fixed-adapter-index-for-e825c-embedded-devic.patch b/queue-6.16/ice-use-fixed-adapter-index-for-e825c-embedded-devic.patch new file mode 100644 index 0000000000..753a391636 --- /dev/null +++ b/queue-6.16/ice-use-fixed-adapter-index-for-e825c-embedded-devic.patch @@ -0,0 +1,202 @@ +From bf4e8ccd3b905cfc321b00fa297589c80e071d1c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Aug 2025 15:27:12 -0700 +Subject: ice: use fixed adapter index for E825C embedded devices + +From: Jacob Keller + +[ Upstream commit 5c5e5b52bf05c7fe88768318c041052c5fac36b8 ] + +The ice_adapter structure is used by the ice driver to connect multiple +physical functions of a device in software. It was introduced by +commit 0e2bddf9e5f9 ("ice: add ice_adapter for shared data across PFs on +the same NIC") and is primarily used for PTP support, as well as for +handling certain cross-PF synchronization. + +The original design of ice_adapter used PCI address information to +determine which devices should be connected. This was extended to support +E825C devices by commit fdb7f54700b1 ("ice: Initial support for E825C +hardware in ice_adapter"), which used the device ID for E825C devices +instead of the PCI address. + +Later, commit 0093cb194a75 ("ice: use DSN instead of PCI BDF for +ice_adapter index") replaced the use of Bus/Device/Function addressing with +use of the device serial number. + +E825C devices may appear in "Dual NAC" configuration which has multiple +physical devices tied to the same clock source and which need to use the +same ice_adapter. Unfortunately, each "NAC" has its own NVM which has its +own unique Device Serial Number. Thus, use of the DSN for connecting +ice_adapter does not work properly. It "worked" in the pre-production +systems because the DSN was not initialized on the test NVMs and all the +NACs had the same zero'd serial number. + +Since we cannot rely on the DSN, lets fall back to the logic in the +original E825C support which used the device ID. This is safe for E825C +only because of the embedded nature of the device. It isn't a discreet +adapter that can be plugged into an arbitrary system. All E825C devices on +a given system are connected to the same clock source and need to be +configured through the same PTP clock. + +To make this separation clear, reserve bit 63 of the 64-bit index values as +a "fixed index" indicator. Always clear this bit when using the device +serial number as an index. + +For E825C, use a fixed value defined as the 0x579C E825C backplane device +ID bitwise ORed with the fixed index indicator. This is slightly different +than the original logic of just using the device ID directly. Doing so +prevents a potential issue with systems where only one of the NACs is +connected with an external PHY over SGMII. In that case, one NAC would +have the E825C_SGMII device ID, but the other would not. + +Separate the determination of the full 64-bit index from the 32-bit +reduction logic. Provide both ice_adapter_index() and a wrapping +ice_adapter_xa_index() which handles reducing the index to a long on 32-bit +systems. As before, cache the full index value in the adapter structure to +warn about collisions. + +This fixes issues with E825C not initializing PTP on both NACs, due to +failure to connect the appropriate devices to the same ice_adapter. + +Fixes: 0093cb194a75 ("ice: use DSN instead of PCI BDF for ice_adapter index") +Signed-off-by: Jacob Keller +Reviewed-by: Grzegorz Nitka +Reviewed-by: Aleksandr Loktionov +Reviewed-by: Przemek Kitszel +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_adapter.c | 49 +++++++++++++++----- + drivers/net/ethernet/intel/ice/ice_adapter.h | 4 +- + 2 files changed, 40 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.c b/drivers/net/ethernet/intel/ice/ice_adapter.c +index 66e070095d1bb..10285995c9edd 100644 +--- a/drivers/net/ethernet/intel/ice/ice_adapter.c ++++ b/drivers/net/ethernet/intel/ice/ice_adapter.c +@@ -13,16 +13,45 @@ + static DEFINE_XARRAY(ice_adapters); + static DEFINE_MUTEX(ice_adapters_mutex); + +-static unsigned long ice_adapter_index(u64 dsn) ++#define ICE_ADAPTER_FIXED_INDEX BIT_ULL(63) ++ ++#define ICE_ADAPTER_INDEX_E825C \ ++ (ICE_DEV_ID_E825C_BACKPLANE | ICE_ADAPTER_FIXED_INDEX) ++ ++static u64 ice_adapter_index(struct pci_dev *pdev) + { ++ switch (pdev->device) { ++ case ICE_DEV_ID_E825C_BACKPLANE: ++ case ICE_DEV_ID_E825C_QSFP: ++ case ICE_DEV_ID_E825C_SFP: ++ case ICE_DEV_ID_E825C_SGMII: ++ /* E825C devices have multiple NACs which are connected to the ++ * same clock source, and which must share the same ++ * ice_adapter structure. We can't use the serial number since ++ * each NAC has its own NVM generated with its own unique ++ * Device Serial Number. Instead, rely on the embedded nature ++ * of the E825C devices, and use a fixed index. This relies on ++ * the fact that all E825C physical functions in a given ++ * system are part of the same overall device. ++ */ ++ return ICE_ADAPTER_INDEX_E825C; ++ default: ++ return pci_get_dsn(pdev) & ~ICE_ADAPTER_FIXED_INDEX; ++ } ++} ++ ++static unsigned long ice_adapter_xa_index(struct pci_dev *pdev) ++{ ++ u64 index = ice_adapter_index(pdev); ++ + #if BITS_PER_LONG == 64 +- return dsn; ++ return index; + #else +- return (u32)dsn ^ (u32)(dsn >> 32); ++ return (u32)index ^ (u32)(index >> 32); + #endif + } + +-static struct ice_adapter *ice_adapter_new(u64 dsn) ++static struct ice_adapter *ice_adapter_new(struct pci_dev *pdev) + { + struct ice_adapter *adapter; + +@@ -30,7 +59,7 @@ static struct ice_adapter *ice_adapter_new(u64 dsn) + if (!adapter) + return NULL; + +- adapter->device_serial_number = dsn; ++ adapter->index = ice_adapter_index(pdev); + spin_lock_init(&adapter->ptp_gltsyn_time_lock); + refcount_set(&adapter->refcount, 1); + +@@ -63,24 +92,23 @@ static void ice_adapter_free(struct ice_adapter *adapter) + */ + struct ice_adapter *ice_adapter_get(struct pci_dev *pdev) + { +- u64 dsn = pci_get_dsn(pdev); + struct ice_adapter *adapter; + unsigned long index; + int err; + +- index = ice_adapter_index(dsn); ++ index = ice_adapter_xa_index(pdev); + scoped_guard(mutex, &ice_adapters_mutex) { + err = xa_insert(&ice_adapters, index, NULL, GFP_KERNEL); + if (err == -EBUSY) { + adapter = xa_load(&ice_adapters, index); + refcount_inc(&adapter->refcount); +- WARN_ON_ONCE(adapter->device_serial_number != dsn); ++ WARN_ON_ONCE(adapter->index != ice_adapter_index(pdev)); + return adapter; + } + if (err) + return ERR_PTR(err); + +- adapter = ice_adapter_new(dsn); ++ adapter = ice_adapter_new(pdev); + if (!adapter) + return ERR_PTR(-ENOMEM); + xa_store(&ice_adapters, index, adapter, GFP_KERNEL); +@@ -99,11 +127,10 @@ struct ice_adapter *ice_adapter_get(struct pci_dev *pdev) + */ + void ice_adapter_put(struct pci_dev *pdev) + { +- u64 dsn = pci_get_dsn(pdev); + struct ice_adapter *adapter; + unsigned long index; + +- index = ice_adapter_index(dsn); ++ index = ice_adapter_xa_index(pdev); + scoped_guard(mutex, &ice_adapters_mutex) { + adapter = xa_load(&ice_adapters, index); + if (WARN_ON(!adapter)) +diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.h b/drivers/net/ethernet/intel/ice/ice_adapter.h +index ac15c0d2bc1a4..409467847c753 100644 +--- a/drivers/net/ethernet/intel/ice/ice_adapter.h ++++ b/drivers/net/ethernet/intel/ice/ice_adapter.h +@@ -32,7 +32,7 @@ struct ice_port_list { + * @refcount: Reference count. struct ice_pf objects hold the references. + * @ctrl_pf: Control PF of the adapter + * @ports: Ports list +- * @device_serial_number: DSN cached for collision detection on 32bit systems ++ * @index: 64-bit index cached for collision detection on 32bit systems + */ + struct ice_adapter { + refcount_t refcount; +@@ -41,7 +41,7 @@ struct ice_adapter { + + struct ice_pf *ctrl_pf; + struct ice_port_list ports; +- u64 device_serial_number; ++ u64 index; + }; + + struct ice_adapter *ice_adapter_get(struct pci_dev *pdev); +-- +2.50.1 + diff --git a/queue-6.16/idpf-add-support-for-tx-refillqs-in-flow-scheduling-.patch b/queue-6.16/idpf-add-support-for-tx-refillqs-in-flow-scheduling-.patch new file mode 100644 index 0000000000..4c9e8fd700 --- /dev/null +++ b/queue-6.16/idpf-add-support-for-tx-refillqs-in-flow-scheduling-.patch @@ -0,0 +1,287 @@ +From cf3ac9bc83ae584e60d711360dba3efd7ed75909 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Jul 2025 11:42:18 -0700 +Subject: idpf: add support for Tx refillqs in flow scheduling mode + +From: Joshua Hay + +[ Upstream commit cb83b559bea39f207ee214ee2972657e8576ed18 ] + +In certain production environments, it is possible for completion tags +to collide, meaning N packets with the same completion tag are in flight +at the same time. In this environment, any given Tx queue is effectively +used to send both slower traffic and higher throughput traffic +simultaneously. This is the result of a customer's specific +configuration in the device pipeline, the details of which Intel cannot +provide. This configuration results in a small number of out-of-order +completions, i.e., a small number of packets in flight. The existing +guardrails in the driver only protect against a large number of packets +in flight. The slower flow completions are delayed which causes the +out-of-order completions. The fast flow will continue sending traffic +and generating tags. Because tags are generated on the fly, the fast +flow eventually uses the same tag for a packet that is still in flight +from the slower flow. The driver has no idea which packet it should +clean when it processes the completion with that tag, but it will look +for the packet on the buffer ring before the hash table. If the slower +flow packet completion is processed first, it will end up cleaning the +fast flow packet on the ring prematurely. This leaves the descriptor +ring in a bad state resulting in a crash or Tx timeout. + +In summary, generating a tag when a packet is sent can lead to the same +tag being associated with multiple packets. This can lead to resource +leaks, crashes, and/or Tx timeouts. + +Before we can replace the tag generation, we need a new mechanism for +the send path to know what tag to use next. The driver will allocate and +initialize a refillq for each TxQ with all of the possible free tag +values. During send, the driver grabs the next free tag from the refillq +from next_to_clean. While cleaning the packet, the clean routine posts +the tag back to the refillq's next_to_use to indicate that it is now +free to use. + +This mechanism works exactly the same way as the existing Rx refill +queues, which post the cleaned buffer IDs back to the buffer queue to be +reposted to HW. Since we're using the refillqs for both Rx and Tx now, +genericize some of the existing refillq support. + +Note: the refillqs will not be used yet. This is only demonstrating how +they will be used to pass free tags back to the send path. + +Signed-off-by: Joshua Hay +Reviewed-by: Madhu Chittim +Tested-by: Samuel Salin +Signed-off-by: Tony Nguyen +Stable-dep-of: b61dfa9bc443 ("idpf: simplify and fix splitq Tx packet rollback error path") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/idpf/idpf_txrx.c | 93 +++++++++++++++++++-- + drivers/net/ethernet/intel/idpf/idpf_txrx.h | 8 +- + 2 files changed, 91 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c +index 89185d1b8485e..b26d054013354 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c +@@ -139,6 +139,9 @@ static void idpf_tx_desc_rel(struct idpf_tx_queue *txq) + if (!txq->desc_ring) + return; + ++ if (txq->refillq) ++ kfree(txq->refillq->ring); ++ + dmam_free_coherent(txq->dev, txq->size, txq->desc_ring, txq->dma); + txq->desc_ring = NULL; + txq->next_to_use = 0; +@@ -244,6 +247,7 @@ static int idpf_tx_desc_alloc(const struct idpf_vport *vport, + struct idpf_tx_queue *tx_q) + { + struct device *dev = tx_q->dev; ++ struct idpf_sw_queue *refillq; + int err; + + err = idpf_tx_buf_alloc_all(tx_q); +@@ -267,6 +271,29 @@ static int idpf_tx_desc_alloc(const struct idpf_vport *vport, + tx_q->next_to_clean = 0; + idpf_queue_set(GEN_CHK, tx_q); + ++ if (!idpf_queue_has(FLOW_SCH_EN, tx_q)) ++ return 0; ++ ++ refillq = tx_q->refillq; ++ refillq->desc_count = tx_q->desc_count; ++ refillq->ring = kcalloc(refillq->desc_count, sizeof(u32), ++ GFP_KERNEL); ++ if (!refillq->ring) { ++ err = -ENOMEM; ++ goto err_alloc; ++ } ++ ++ for (unsigned int i = 0; i < refillq->desc_count; i++) ++ refillq->ring[i] = ++ FIELD_PREP(IDPF_RFL_BI_BUFID_M, i) | ++ FIELD_PREP(IDPF_RFL_BI_GEN_M, ++ idpf_queue_has(GEN_CHK, refillq)); ++ ++ /* Go ahead and flip the GEN bit since this counts as filling ++ * up the ring, i.e. we already ring wrapped. ++ */ ++ idpf_queue_change(GEN_CHK, refillq); ++ + return 0; + + err_alloc: +@@ -603,18 +630,18 @@ static int idpf_rx_hdr_buf_alloc_all(struct idpf_buf_queue *bufq) + } + + /** +- * idpf_rx_post_buf_refill - Post buffer id to refill queue ++ * idpf_post_buf_refill - Post buffer id to refill queue + * @refillq: refill queue to post to + * @buf_id: buffer id to post + */ +-static void idpf_rx_post_buf_refill(struct idpf_sw_queue *refillq, u16 buf_id) ++static void idpf_post_buf_refill(struct idpf_sw_queue *refillq, u16 buf_id) + { + u32 nta = refillq->next_to_use; + + /* store the buffer ID and the SW maintained GEN bit to the refillq */ + refillq->ring[nta] = +- FIELD_PREP(IDPF_RX_BI_BUFID_M, buf_id) | +- FIELD_PREP(IDPF_RX_BI_GEN_M, ++ FIELD_PREP(IDPF_RFL_BI_BUFID_M, buf_id) | ++ FIELD_PREP(IDPF_RFL_BI_GEN_M, + idpf_queue_has(GEN_CHK, refillq)); + + if (unlikely(++nta == refillq->desc_count)) { +@@ -995,6 +1022,11 @@ static void idpf_txq_group_rel(struct idpf_vport *vport) + struct idpf_txq_group *txq_grp = &vport->txq_grps[i]; + + for (j = 0; j < txq_grp->num_txq; j++) { ++ if (flow_sch_en) { ++ kfree(txq_grp->txqs[j]->refillq); ++ txq_grp->txqs[j]->refillq = NULL; ++ } ++ + kfree(txq_grp->txqs[j]); + txq_grp->txqs[j] = NULL; + } +@@ -1414,6 +1446,13 @@ static int idpf_txq_group_alloc(struct idpf_vport *vport, u16 num_txq) + } + + idpf_queue_set(FLOW_SCH_EN, q); ++ ++ q->refillq = kzalloc(sizeof(*q->refillq), GFP_KERNEL); ++ if (!q->refillq) ++ goto err_alloc; ++ ++ idpf_queue_set(GEN_CHK, q->refillq); ++ idpf_queue_set(RFL_GEN_CHK, q->refillq); + } + + if (!split) +@@ -2005,6 +2044,8 @@ static void idpf_tx_handle_rs_completion(struct idpf_tx_queue *txq, + + compl_tag = le16_to_cpu(desc->q_head_compl_tag.compl_tag); + ++ idpf_post_buf_refill(txq->refillq, compl_tag); ++ + /* If we didn't clean anything on the ring, this packet must be + * in the hash table. Go clean it there. + */ +@@ -2364,6 +2405,37 @@ static unsigned int idpf_tx_splitq_bump_ntu(struct idpf_tx_queue *txq, u16 ntu) + return ntu; + } + ++/** ++ * idpf_tx_get_free_buf_id - get a free buffer ID from the refill queue ++ * @refillq: refill queue to get buffer ID from ++ * @buf_id: return buffer ID ++ * ++ * Return: true if a buffer ID was found, false if not ++ */ ++static bool idpf_tx_get_free_buf_id(struct idpf_sw_queue *refillq, ++ u16 *buf_id) ++{ ++ u32 ntc = refillq->next_to_clean; ++ u32 refill_desc; ++ ++ refill_desc = refillq->ring[ntc]; ++ ++ if (unlikely(idpf_queue_has(RFL_GEN_CHK, refillq) != ++ !!(refill_desc & IDPF_RFL_BI_GEN_M))) ++ return false; ++ ++ *buf_id = FIELD_GET(IDPF_RFL_BI_BUFID_M, refill_desc); ++ ++ if (unlikely(++ntc == refillq->desc_count)) { ++ idpf_queue_change(RFL_GEN_CHK, refillq); ++ ntc = 0; ++ } ++ ++ refillq->next_to_clean = ntc; ++ ++ return true; ++} ++ + /** + * idpf_tx_splitq_map - Build the Tx flex descriptor + * @tx_q: queue to send buffer on +@@ -2912,6 +2984,13 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, + } + + if (idpf_queue_has(FLOW_SCH_EN, tx_q)) { ++ if (unlikely(!idpf_tx_get_free_buf_id(tx_q->refillq, ++ &tx_params.compl_tag))) { ++ u64_stats_update_begin(&tx_q->stats_sync); ++ u64_stats_inc(&tx_q->q_stats.q_busy); ++ u64_stats_update_end(&tx_q->stats_sync); ++ } ++ + tx_params.dtype = IDPF_TX_DESC_DTYPE_FLEX_FLOW_SCHE; + tx_params.eop_cmd = IDPF_TXD_FLEX_FLOW_CMD_EOP; + /* Set the RE bit to catch any packets that may have not been +@@ -3464,7 +3543,7 @@ static int idpf_rx_splitq_clean(struct idpf_rx_queue *rxq, int budget) + skip_data: + rx_buf->page = NULL; + +- idpf_rx_post_buf_refill(refillq, buf_id); ++ idpf_post_buf_refill(refillq, buf_id); + IDPF_RX_BUMP_NTC(rxq, ntc); + + /* skip if it is non EOP desc */ +@@ -3572,10 +3651,10 @@ static void idpf_rx_clean_refillq(struct idpf_buf_queue *bufq, + bool failure; + + if (idpf_queue_has(RFL_GEN_CHK, refillq) != +- !!(refill_desc & IDPF_RX_BI_GEN_M)) ++ !!(refill_desc & IDPF_RFL_BI_GEN_M)) + break; + +- buf_id = FIELD_GET(IDPF_RX_BI_BUFID_M, refill_desc); ++ buf_id = FIELD_GET(IDPF_RFL_BI_BUFID_M, refill_desc); + failure = idpf_rx_update_bufq_desc(bufq, buf_id, buf_desc); + if (failure) + break; +diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h b/drivers/net/ethernet/intel/idpf/idpf_txrx.h +index 36a0f828a6f80..6924bee6ff5bd 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h ++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h +@@ -107,8 +107,8 @@ do { \ + */ + #define IDPF_TX_SPLITQ_RE_MIN_GAP 64 + +-#define IDPF_RX_BI_GEN_M BIT(16) +-#define IDPF_RX_BI_BUFID_M GENMASK(15, 0) ++#define IDPF_RFL_BI_GEN_M BIT(16) ++#define IDPF_RFL_BI_BUFID_M GENMASK(15, 0) + + #define IDPF_RXD_EOF_SPLITQ VIRTCHNL2_RX_FLEX_DESC_ADV_STATUS0_EOF_M + #define IDPF_RXD_EOF_SINGLEQ VIRTCHNL2_RX_BASE_DESC_STATUS_EOF_M +@@ -621,6 +621,7 @@ libeth_cacheline_set_assert(struct idpf_rx_queue, 64, + * @cleaned_pkts: Number of packets cleaned for the above said case + * @tx_max_bufs: Max buffers that can be transmitted with scatter-gather + * @stash: Tx buffer stash for Flow-based scheduling mode ++ * @refillq: Pointer to refill queue + * @compl_tag_bufid_m: Completion tag buffer id mask + * @compl_tag_cur_gen: Used to keep track of current completion tag generation + * @compl_tag_gen_max: To determine when compl_tag_cur_gen should be reset +@@ -670,6 +671,7 @@ struct idpf_tx_queue { + + u16 tx_max_bufs; + struct idpf_txq_stash *stash; ++ struct idpf_sw_queue *refillq; + + u16 compl_tag_bufid_m; + u16 compl_tag_cur_gen; +@@ -691,7 +693,7 @@ struct idpf_tx_queue { + __cacheline_group_end_aligned(cold); + }; + libeth_cacheline_set_assert(struct idpf_tx_queue, 64, +- 112 + sizeof(struct u64_stats_sync), ++ 120 + sizeof(struct u64_stats_sync), + 24); + + /** +-- +2.50.1 + diff --git a/queue-6.16/idpf-replace-flow-scheduling-buffer-ring-with-buffer.patch b/queue-6.16/idpf-replace-flow-scheduling-buffer-ring-with-buffer.patch new file mode 100644 index 0000000000..fdb0a8b872 --- /dev/null +++ b/queue-6.16/idpf-replace-flow-scheduling-buffer-ring-with-buffer.patch @@ -0,0 +1,533 @@ +From a7154cdd667ee1957f44f24f1f88e5da13a9c495 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Jul 2025 11:42:21 -0700 +Subject: idpf: replace flow scheduling buffer ring with buffer pool + +From: Joshua Hay + +[ Upstream commit 5f417d551324d2894168b362f2429d120ab06243 ] + +Replace the TxQ buffer ring with one large pool/array of buffers (only +for flow scheduling). This eliminates the tag generation and makes it +impossible for a tag to be associated with more than one packet. + +The completion tag passed to HW through the descriptor is the index into +the array. That same completion tag is posted back to the driver in the +completion descriptor, and used to index into the array to quickly +retrieve the buffer during cleaning. In this way, the tags are treated +as a fix sized resource. If all tags are in use, no more packets can be +sent on that particular queue (until some are freed up). The tag pool +size is 64K since the completion tag width is 16 bits. + +For each packet, the driver pulls a free tag from the refillq to get the +next free buffer index. When cleaning is complete, the tag is posted +back to the refillq. A multi-frag packet spans multiple buffers in the +driver, therefore it uses multiple buffer indexes/tags from the pool. +Each frag pulls from the refillq to get the next free buffer index. +These are tracked in a next_buf field that replaces the completion tag +field in the buffer struct. This chains the buffers together so that the +packet can be cleaned from the starting completion tag taken from the +completion descriptor, then from the next_buf field for each subsequent +buffer. + +In case of a dma_mapping_error occurs or the refillq runs out of free +buf_ids, the packet will execute the rollback error path. This unmaps +any buffers previously mapped for the packet. Since several free +buf_ids could have already been pulled from the refillq, we need to +restore its original state as well. Otherwise, the buf_ids/tags +will be leaked and not used again until the queue is reallocated. + +Descriptor completions only advance the descriptor ring index to "clean" +the descriptors. The packet completions only clean the buffers +associated with the given packet completion tag and do not update the +descriptor ring index. + +When operating in queue based scheduling mode, the array still acts as a +ring and will only have TxQ descriptor count entries. The tx_bufs are +still associated 1:1 with the descriptor ring entries and we can use the +conventional indexing mechanisms. + +Fixes: c2d548cad150 ("idpf: add TX splitq napi poll support") +Signed-off-by: Luigi Rizzo +Signed-off-by: Brian Vazquez +Signed-off-by: Joshua Hay +Reviewed-by: Madhu Chittim +Reviewed-by: Aleksandr Loktionov +Tested-by: Samuel Salin +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/idpf/idpf_txrx.c | 204 +++++++++----------- + drivers/net/ethernet/intel/idpf/idpf_txrx.h | 10 +- + 2 files changed, 103 insertions(+), 111 deletions(-) + +diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c +index 7c758e7281ab5..89fedc2ef247b 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c +@@ -13,6 +13,7 @@ struct idpf_tx_stash { + struct libeth_sqe buf; + }; + ++#define idpf_tx_buf_next(buf) (*(u32 *)&(buf)->priv) + #define idpf_tx_buf_compl_tag(buf) (*(u32 *)&(buf)->priv) + LIBETH_SQE_CHECK_PRIV(u32); + +@@ -91,7 +92,7 @@ static void idpf_tx_buf_rel_all(struct idpf_tx_queue *txq) + return; + + /* Free all the Tx buffer sk_buffs */ +- for (i = 0; i < txq->desc_count; i++) ++ for (i = 0; i < txq->buf_pool_size; i++) + libeth_tx_complete(&txq->tx_buf[i], &cp); + + kfree(txq->tx_buf); +@@ -199,14 +200,17 @@ static void idpf_tx_desc_rel_all(struct idpf_vport *vport) + static int idpf_tx_buf_alloc_all(struct idpf_tx_queue *tx_q) + { + struct idpf_buf_lifo *buf_stack; +- int buf_size; + int i; + + /* Allocate book keeping buffers only. Buffers to be supplied to HW + * are allocated by kernel network stack and received as part of skb + */ +- buf_size = sizeof(struct idpf_tx_buf) * tx_q->desc_count; +- tx_q->tx_buf = kzalloc(buf_size, GFP_KERNEL); ++ if (idpf_queue_has(FLOW_SCH_EN, tx_q)) ++ tx_q->buf_pool_size = U16_MAX; ++ else ++ tx_q->buf_pool_size = tx_q->desc_count; ++ tx_q->tx_buf = kcalloc(tx_q->buf_pool_size, sizeof(*tx_q->tx_buf), ++ GFP_KERNEL); + if (!tx_q->tx_buf) + return -ENOMEM; + +@@ -275,7 +279,7 @@ static int idpf_tx_desc_alloc(const struct idpf_vport *vport, + return 0; + + refillq = tx_q->refillq; +- refillq->desc_count = tx_q->desc_count; ++ refillq->desc_count = tx_q->buf_pool_size; + refillq->ring = kcalloc(refillq->desc_count, sizeof(u32), + GFP_KERNEL); + if (!refillq->ring) { +@@ -1867,6 +1871,12 @@ static bool idpf_tx_splitq_clean(struct idpf_tx_queue *tx_q, u16 end, + struct idpf_tx_buf *tx_buf; + bool clean_complete = true; + ++ if (descs_only) { ++ /* Bump ring index to mark as cleaned. */ ++ tx_q->next_to_clean = end; ++ return true; ++ } ++ + tx_desc = &tx_q->flex_tx[ntc]; + next_pending_desc = &tx_q->flex_tx[end]; + tx_buf = &tx_q->tx_buf[ntc]; +@@ -1933,87 +1943,43 @@ do { \ + } while (0) + + /** +- * idpf_tx_clean_buf_ring - clean flow scheduling TX queue buffers ++ * idpf_tx_clean_bufs - clean flow scheduling TX queue buffers + * @txq: queue to clean +- * @compl_tag: completion tag of packet to clean (from completion descriptor) ++ * @buf_id: packet's starting buffer ID, from completion descriptor + * @cleaned: pointer to stats struct to track cleaned packets/bytes + * @budget: Used to determine if we are in netpoll + * +- * Cleans all buffers associated with the input completion tag either from the +- * TX buffer ring or from the hash table if the buffers were previously +- * stashed. Returns the byte/segment count for the cleaned packet associated +- * this completion tag. ++ * Clean all buffers associated with the packet starting at buf_id. Returns the ++ * byte/segment count for the cleaned packet. + */ +-static bool idpf_tx_clean_buf_ring(struct idpf_tx_queue *txq, u16 compl_tag, +- struct libeth_sq_napi_stats *cleaned, +- int budget) ++static bool idpf_tx_clean_bufs(struct idpf_tx_queue *txq, u32 buf_id, ++ struct libeth_sq_napi_stats *cleaned, ++ int budget) + { +- u16 idx = compl_tag & txq->compl_tag_bufid_m; + struct idpf_tx_buf *tx_buf = NULL; + struct libeth_cq_pp cp = { + .dev = txq->dev, + .ss = cleaned, + .napi = budget, + }; +- u16 ntc, orig_idx = idx; +- +- tx_buf = &txq->tx_buf[idx]; +- +- if (unlikely(tx_buf->type <= LIBETH_SQE_CTX || +- idpf_tx_buf_compl_tag(tx_buf) != compl_tag)) +- return false; + ++ tx_buf = &txq->tx_buf[buf_id]; + if (tx_buf->type == LIBETH_SQE_SKB) { + if (skb_shinfo(tx_buf->skb)->tx_flags & SKBTX_IN_PROGRESS) + idpf_tx_read_tstamp(txq, tx_buf->skb); + + libeth_tx_complete(tx_buf, &cp); ++ idpf_post_buf_refill(txq->refillq, buf_id); + } + +- idpf_tx_clean_buf_ring_bump_ntc(txq, idx, tx_buf); ++ while (idpf_tx_buf_next(tx_buf) != IDPF_TXBUF_NULL) { ++ buf_id = idpf_tx_buf_next(tx_buf); + +- while (idpf_tx_buf_compl_tag(tx_buf) == compl_tag) { ++ tx_buf = &txq->tx_buf[buf_id]; + libeth_tx_complete(tx_buf, &cp); +- idpf_tx_clean_buf_ring_bump_ntc(txq, idx, tx_buf); ++ idpf_post_buf_refill(txq->refillq, buf_id); + } + +- /* +- * It's possible the packet we just cleaned was an out of order +- * completion, which means we can stash the buffers starting from +- * the original next_to_clean and reuse the descriptors. We need +- * to compare the descriptor ring next_to_clean packet's "first" buffer +- * to the "first" buffer of the packet we just cleaned to determine if +- * this is the case. Howevever, next_to_clean can point to either a +- * reserved buffer that corresponds to a context descriptor used for the +- * next_to_clean packet (TSO packet) or the "first" buffer (single +- * packet). The orig_idx from the packet we just cleaned will always +- * point to the "first" buffer. If next_to_clean points to a reserved +- * buffer, let's bump ntc once and start the comparison from there. +- */ +- ntc = txq->next_to_clean; +- tx_buf = &txq->tx_buf[ntc]; +- +- if (tx_buf->type == LIBETH_SQE_CTX) +- idpf_tx_clean_buf_ring_bump_ntc(txq, ntc, tx_buf); +- +- /* +- * If ntc still points to a different "first" buffer, clean the +- * descriptor ring and stash all of the buffers for later cleaning. If +- * we cannot stash all of the buffers, next_to_clean will point to the +- * "first" buffer of the packet that could not be stashed and cleaning +- * will start there next time. +- */ +- if (unlikely(tx_buf != &txq->tx_buf[orig_idx] && +- !idpf_tx_splitq_clean(txq, orig_idx, budget, cleaned, +- true))) +- return true; +- +- /* +- * Otherwise, update next_to_clean to reflect the cleaning that was +- * done above. +- */ +- txq->next_to_clean = idx; +- + return true; + } + +@@ -2044,12 +2010,10 @@ static void idpf_tx_handle_rs_completion(struct idpf_tx_queue *txq, + + compl_tag = le16_to_cpu(desc->q_head_compl_tag.compl_tag); + +- idpf_post_buf_refill(txq->refillq, compl_tag); +- + /* If we didn't clean anything on the ring, this packet must be + * in the hash table. Go clean it there. + */ +- if (!idpf_tx_clean_buf_ring(txq, compl_tag, cleaned, budget)) ++ if (!idpf_tx_clean_bufs(txq, compl_tag, cleaned, budget)) + idpf_tx_clean_stashed_bufs(txq, compl_tag, cleaned, budget); + } + +@@ -2362,7 +2326,7 @@ static unsigned int idpf_tx_splitq_bump_ntu(struct idpf_tx_queue *txq, u16 ntu) + * Return: true if a buffer ID was found, false if not + */ + static bool idpf_tx_get_free_buf_id(struct idpf_sw_queue *refillq, +- u16 *buf_id) ++ u32 *buf_id) + { + u32 ntc = refillq->next_to_clean; + u32 refill_desc; +@@ -2395,25 +2359,34 @@ static void idpf_tx_splitq_pkt_err_unmap(struct idpf_tx_queue *txq, + struct idpf_tx_splitq_params *params, + struct idpf_tx_buf *first) + { ++ struct idpf_sw_queue *refillq = txq->refillq; + struct libeth_sq_napi_stats ss = { }; + struct idpf_tx_buf *tx_buf = first; + struct libeth_cq_pp cp = { + .dev = txq->dev, + .ss = &ss, + }; +- u32 idx = 0; + + u64_stats_update_begin(&txq->stats_sync); + u64_stats_inc(&txq->q_stats.dma_map_errs); + u64_stats_update_end(&txq->stats_sync); + +- do { ++ libeth_tx_complete(tx_buf, &cp); ++ while (idpf_tx_buf_next(tx_buf) != IDPF_TXBUF_NULL) { ++ tx_buf = &txq->tx_buf[idpf_tx_buf_next(tx_buf)]; + libeth_tx_complete(tx_buf, &cp); +- idpf_tx_clean_buf_ring_bump_ntc(txq, idx, tx_buf); +- } while (idpf_tx_buf_compl_tag(tx_buf) == params->compl_tag); ++ } + + /* Update tail in case netdev_xmit_more was previously true. */ + idpf_tx_buf_hw_update(txq, params->prev_ntu, false); ++ ++ if (!refillq) ++ return; ++ ++ /* Restore refillq state to avoid leaking tags. */ ++ if (params->prev_refill_gen != idpf_queue_has(RFL_GEN_CHK, refillq)) ++ idpf_queue_change(RFL_GEN_CHK, refillq); ++ refillq->next_to_clean = params->prev_refill_ntc; + } + + /** +@@ -2437,6 +2410,7 @@ static void idpf_tx_splitq_map(struct idpf_tx_queue *tx_q, + struct netdev_queue *nq; + struct sk_buff *skb; + skb_frag_t *frag; ++ u32 next_buf_id; + u16 td_cmd = 0; + dma_addr_t dma; + +@@ -2454,18 +2428,16 @@ static void idpf_tx_splitq_map(struct idpf_tx_queue *tx_q, + tx_buf = first; + first->nr_frags = 0; + +- params->compl_tag = +- (tx_q->compl_tag_cur_gen << tx_q->compl_tag_gen_s) | i; +- + for (frag = &skb_shinfo(skb)->frags[0];; frag++) { + unsigned int max_data = IDPF_TX_MAX_DESC_DATA_ALIGNED; + +- if (unlikely(dma_mapping_error(tx_q->dev, dma))) ++ if (unlikely(dma_mapping_error(tx_q->dev, dma))) { ++ idpf_tx_buf_next(tx_buf) = IDPF_TXBUF_NULL; + return idpf_tx_splitq_pkt_err_unmap(tx_q, params, + first); ++ } + + first->nr_frags++; +- idpf_tx_buf_compl_tag(tx_buf) = params->compl_tag; + tx_buf->type = LIBETH_SQE_FRAG; + + /* record length, and DMA address */ +@@ -2521,29 +2493,14 @@ static void idpf_tx_splitq_map(struct idpf_tx_queue *tx_q, + max_data); + + if (unlikely(++i == tx_q->desc_count)) { +- tx_buf = tx_q->tx_buf; + tx_desc = &tx_q->flex_tx[0]; + i = 0; + tx_q->compl_tag_cur_gen = + IDPF_TX_ADJ_COMPL_TAG_GEN(tx_q); + } else { +- tx_buf++; + tx_desc++; + } + +- /* Since this packet has a buffer that is going to span +- * multiple descriptors, it's going to leave holes in +- * to the TX buffer ring. To ensure these holes do not +- * cause issues in the cleaning routines, we will clear +- * them of any stale data and assign them the same +- * completion tag as the current packet. Then when the +- * packet is being cleaned, the cleaning routines will +- * simply pass over these holes and finish cleaning the +- * rest of the packet. +- */ +- tx_buf->type = LIBETH_SQE_EMPTY; +- idpf_tx_buf_compl_tag(tx_buf) = params->compl_tag; +- + /* Adjust the DMA offset and the remaining size of the + * fragment. On the first iteration of this loop, + * max_data will be >= 12K and <= 16K-1. On any +@@ -2568,15 +2525,26 @@ static void idpf_tx_splitq_map(struct idpf_tx_queue *tx_q, + idpf_tx_splitq_build_desc(tx_desc, params, td_cmd, size); + + if (unlikely(++i == tx_q->desc_count)) { +- tx_buf = tx_q->tx_buf; + tx_desc = &tx_q->flex_tx[0]; + i = 0; + tx_q->compl_tag_cur_gen = IDPF_TX_ADJ_COMPL_TAG_GEN(tx_q); + } else { +- tx_buf++; + tx_desc++; + } + ++ if (idpf_queue_has(FLOW_SCH_EN, tx_q)) { ++ if (unlikely(!idpf_tx_get_free_buf_id(tx_q->refillq, ++ &next_buf_id))) { ++ idpf_tx_buf_next(tx_buf) = IDPF_TXBUF_NULL; ++ return idpf_tx_splitq_pkt_err_unmap(tx_q, params, ++ first); ++ } ++ } else { ++ next_buf_id = i; ++ } ++ idpf_tx_buf_next(tx_buf) = next_buf_id; ++ tx_buf = &tx_q->tx_buf[next_buf_id]; ++ + size = skb_frag_size(frag); + data_len -= size; + +@@ -2591,6 +2559,7 @@ static void idpf_tx_splitq_map(struct idpf_tx_queue *tx_q, + + /* write last descriptor with RS and EOP bits */ + first->rs_idx = i; ++ idpf_tx_buf_next(tx_buf) = IDPF_TXBUF_NULL; + td_cmd |= params->eop_cmd; + idpf_tx_splitq_build_desc(tx_desc, params, td_cmd, size); + i = idpf_tx_splitq_bump_ntu(tx_q, i); +@@ -2799,8 +2768,6 @@ idpf_tx_splitq_get_ctx_desc(struct idpf_tx_queue *txq) + union idpf_flex_tx_ctx_desc *desc; + int i = txq->next_to_use; + +- txq->tx_buf[i].type = LIBETH_SQE_CTX; +- + /* grab the next descriptor */ + desc = &txq->flex_ctx[i]; + txq->next_to_use = idpf_tx_splitq_bump_ntu(txq, i); +@@ -2910,6 +2877,7 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, + struct idpf_tx_buf *first; + unsigned int count; + int tso, idx; ++ u32 buf_id; + + count = idpf_tx_desc_count_required(tx_q, skb); + if (unlikely(!count)) +@@ -2953,26 +2921,28 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, + idpf_tx_set_tstamp_desc(ctx_desc, idx); + } + +- /* record the location of the first descriptor for this packet */ +- first = &tx_q->tx_buf[tx_q->next_to_use]; +- first->skb = skb; ++ if (idpf_queue_has(FLOW_SCH_EN, tx_q)) { ++ struct idpf_sw_queue *refillq = tx_q->refillq; + +- if (tso) { +- first->packets = tx_params.offload.tso_segs; +- first->bytes = skb->len + +- ((first->packets - 1) * tx_params.offload.tso_hdr_len); +- } else { +- first->packets = 1; +- first->bytes = max_t(unsigned int, skb->len, ETH_ZLEN); +- } ++ /* Save refillq state in case of a packet rollback. Otherwise, ++ * the tags will be leaked since they will be popped from the ++ * refillq but never reposted during cleaning. ++ */ ++ tx_params.prev_refill_gen = ++ idpf_queue_has(RFL_GEN_CHK, refillq); ++ tx_params.prev_refill_ntc = refillq->next_to_clean; + +- if (idpf_queue_has(FLOW_SCH_EN, tx_q)) { + if (unlikely(!idpf_tx_get_free_buf_id(tx_q->refillq, +- &tx_params.compl_tag))) { +- u64_stats_update_begin(&tx_q->stats_sync); +- u64_stats_inc(&tx_q->q_stats.q_busy); +- u64_stats_update_end(&tx_q->stats_sync); ++ &buf_id))) { ++ if (tx_params.prev_refill_gen != ++ idpf_queue_has(RFL_GEN_CHK, refillq)) ++ idpf_queue_change(RFL_GEN_CHK, refillq); ++ refillq->next_to_clean = tx_params.prev_refill_ntc; ++ ++ tx_q->next_to_use = tx_params.prev_ntu; ++ return idpf_tx_drop_skb(tx_q, skb); + } ++ tx_params.compl_tag = buf_id; + + tx_params.dtype = IDPF_TX_DESC_DTYPE_FLEX_FLOW_SCHE; + tx_params.eop_cmd = IDPF_TXD_FLEX_FLOW_CMD_EOP; +@@ -2990,6 +2960,8 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, + tx_params.offload.td_cmd |= IDPF_TXD_FLEX_FLOW_CMD_CS_EN; + + } else { ++ buf_id = tx_q->next_to_use; ++ + tx_params.dtype = IDPF_TX_DESC_DTYPE_FLEX_L2TAG1_L2TAG2; + tx_params.eop_cmd = IDPF_TXD_LAST_DESC_CMD; + +@@ -2997,6 +2969,18 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, + tx_params.offload.td_cmd |= IDPF_TX_FLEX_DESC_CMD_CS_EN; + } + ++ first = &tx_q->tx_buf[buf_id]; ++ first->skb = skb; ++ ++ if (tso) { ++ first->packets = tx_params.offload.tso_segs; ++ first->bytes = skb->len + ++ ((first->packets - 1) * tx_params.offload.tso_hdr_len); ++ } else { ++ first->packets = 1; ++ first->bytes = max_t(unsigned int, skb->len, ETH_ZLEN); ++ } ++ + idpf_tx_splitq_map(tx_q, &tx_params, first); + + return NETDEV_TX_OK; +diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h b/drivers/net/ethernet/intel/idpf/idpf_txrx.h +index c4070806be05c..a30b68504d73c 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h ++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h +@@ -136,6 +136,8 @@ do { \ + ((++(txq)->compl_tag_cur_gen) >= (txq)->compl_tag_gen_max ? \ + 0 : (txq)->compl_tag_cur_gen) + ++#define IDPF_TXBUF_NULL U32_MAX ++ + #define IDPF_TXD_LAST_DESC_CMD (IDPF_TX_DESC_CMD_EOP | IDPF_TX_DESC_CMD_RS) + + #define IDPF_TX_FLAGS_TSO BIT(0) +@@ -196,6 +198,8 @@ struct idpf_tx_offload_params { + * @td_tag: Descriptor tunneling tag + * @offload: Offload parameters + * @prev_ntu: stored TxQ next_to_use in case of rollback ++ * @prev_refill_ntc: stored refillq next_to_clean in case of packet rollback ++ * @prev_refill_gen: stored refillq generation bit in case of packet rollback + */ + struct idpf_tx_splitq_params { + enum idpf_tx_desc_dtype_value dtype; +@@ -208,6 +212,8 @@ struct idpf_tx_splitq_params { + struct idpf_tx_offload_params offload; + + u16 prev_ntu; ++ u16 prev_refill_ntc; ++ bool prev_refill_gen; + }; + + enum idpf_tx_ctx_desc_eipt_offload { +@@ -636,6 +642,7 @@ libeth_cacheline_set_assert(struct idpf_rx_queue, 64, + * @size: Length of descriptor ring in bytes + * @dma: Physical address of ring + * @q_vector: Backreference to associated vector ++ * @buf_pool_size: Total number of idpf_tx_buf + */ + struct idpf_tx_queue { + __cacheline_group_begin_aligned(read_mostly); +@@ -693,11 +700,12 @@ struct idpf_tx_queue { + dma_addr_t dma; + + struct idpf_q_vector *q_vector; ++ u32 buf_pool_size; + __cacheline_group_end_aligned(cold); + }; + libeth_cacheline_set_assert(struct idpf_tx_queue, 64, + 120 + sizeof(struct u64_stats_sync), +- 24); ++ 32); + + /** + * struct idpf_buf_queue - software structure representing a buffer queue +-- +2.50.1 + diff --git a/queue-6.16/idpf-simplify-and-fix-splitq-tx-packet-rollback-erro.patch b/queue-6.16/idpf-simplify-and-fix-splitq-tx-packet-rollback-erro.patch new file mode 100644 index 0000000000..7f980a3dd9 --- /dev/null +++ b/queue-6.16/idpf-simplify-and-fix-splitq-tx-packet-rollback-erro.patch @@ -0,0 +1,268 @@ +From dca28759d10ab4cbc9756cb1d4d866d7ac99a427 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Jul 2025 11:42:20 -0700 +Subject: idpf: simplify and fix splitq Tx packet rollback error path + +From: Joshua Hay + +[ Upstream commit b61dfa9bc4430ad82b96d3a7c1c485350f91b467 ] + +Move (and rename) the existing rollback logic to singleq.c since that +will be the only consumer. Create a simplified splitq specific rollback +function to loop through and unmap tx_bufs based on the completion tag. +This is critical before replacing the Tx buffer ring with the buffer +pool since the previous rollback indexing will not work to unmap the +chained buffers from the pool. + +Cache the next_to_use index before any portion of the packet is put on +the descriptor ring. In case of an error, the rollback will bump tail to +the correct next_to_use value. Because the splitq path now supports +different types of context descriptors (and potentially multiple in the +future), this will take care of rolling back any and all context +descriptors encoded on the ring for the erroneous packet. The previous +rollback logic was broken for PTP packets since it would not account for +the PTP context descriptor. + +Fixes: 1a49cf814fe1 ("idpf: add Tx timestamp flows") +Signed-off-by: Joshua Hay +Reviewed-by: Madhu Chittim +Tested-by: Samuel Salin +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + .../ethernet/intel/idpf/idpf_singleq_txrx.c | 57 +++++++++++- + drivers/net/ethernet/intel/idpf/idpf_txrx.c | 91 ++++++++----------- + drivers/net/ethernet/intel/idpf/idpf_txrx.h | 5 +- + 3 files changed, 95 insertions(+), 58 deletions(-) + +diff --git a/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c +index 993c354aa27ad..a3b3261bbdfa7 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c +@@ -179,6 +179,58 @@ static int idpf_tx_singleq_csum(struct sk_buff *skb, + return 1; + } + ++/** ++ * idpf_tx_singleq_dma_map_error - handle TX DMA map errors ++ * @txq: queue to send buffer on ++ * @skb: send buffer ++ * @first: original first buffer info buffer for packet ++ * @idx: starting point on ring to unwind ++ */ ++static void idpf_tx_singleq_dma_map_error(struct idpf_tx_queue *txq, ++ struct sk_buff *skb, ++ struct idpf_tx_buf *first, u16 idx) ++{ ++ struct libeth_sq_napi_stats ss = { }; ++ struct libeth_cq_pp cp = { ++ .dev = txq->dev, ++ .ss = &ss, ++ }; ++ ++ u64_stats_update_begin(&txq->stats_sync); ++ u64_stats_inc(&txq->q_stats.dma_map_errs); ++ u64_stats_update_end(&txq->stats_sync); ++ ++ /* clear dma mappings for failed tx_buf map */ ++ for (;;) { ++ struct idpf_tx_buf *tx_buf; ++ ++ tx_buf = &txq->tx_buf[idx]; ++ libeth_tx_complete(tx_buf, &cp); ++ if (tx_buf == first) ++ break; ++ if (idx == 0) ++ idx = txq->desc_count; ++ idx--; ++ } ++ ++ if (skb_is_gso(skb)) { ++ union idpf_tx_flex_desc *tx_desc; ++ ++ /* If we failed a DMA mapping for a TSO packet, we will have ++ * used one additional descriptor for a context ++ * descriptor. Reset that here. ++ */ ++ tx_desc = &txq->flex_tx[idx]; ++ memset(tx_desc, 0, sizeof(*tx_desc)); ++ if (idx == 0) ++ idx = txq->desc_count; ++ idx--; ++ } ++ ++ /* Update tail in case netdev_xmit_more was previously true */ ++ idpf_tx_buf_hw_update(txq, idx, false); ++} ++ + /** + * idpf_tx_singleq_map - Build the Tx base descriptor + * @tx_q: queue to send buffer on +@@ -219,8 +271,9 @@ static void idpf_tx_singleq_map(struct idpf_tx_queue *tx_q, + for (frag = &skb_shinfo(skb)->frags[0];; frag++) { + unsigned int max_data = IDPF_TX_MAX_DESC_DATA_ALIGNED; + +- if (dma_mapping_error(tx_q->dev, dma)) +- return idpf_tx_dma_map_error(tx_q, skb, first, i); ++ if (unlikely(dma_mapping_error(tx_q->dev, dma))) ++ return idpf_tx_singleq_dma_map_error(tx_q, skb, ++ first, i); + + /* record length, and DMA address */ + dma_unmap_len_set(tx_buf, len, size); +diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c +index b26d054013354..7c758e7281ab5 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c +@@ -2337,57 +2337,6 @@ unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq, + return count; + } + +-/** +- * idpf_tx_dma_map_error - handle TX DMA map errors +- * @txq: queue to send buffer on +- * @skb: send buffer +- * @first: original first buffer info buffer for packet +- * @idx: starting point on ring to unwind +- */ +-void idpf_tx_dma_map_error(struct idpf_tx_queue *txq, struct sk_buff *skb, +- struct idpf_tx_buf *first, u16 idx) +-{ +- struct libeth_sq_napi_stats ss = { }; +- struct libeth_cq_pp cp = { +- .dev = txq->dev, +- .ss = &ss, +- }; +- +- u64_stats_update_begin(&txq->stats_sync); +- u64_stats_inc(&txq->q_stats.dma_map_errs); +- u64_stats_update_end(&txq->stats_sync); +- +- /* clear dma mappings for failed tx_buf map */ +- for (;;) { +- struct idpf_tx_buf *tx_buf; +- +- tx_buf = &txq->tx_buf[idx]; +- libeth_tx_complete(tx_buf, &cp); +- if (tx_buf == first) +- break; +- if (idx == 0) +- idx = txq->desc_count; +- idx--; +- } +- +- if (skb_is_gso(skb)) { +- union idpf_tx_flex_desc *tx_desc; +- +- /* If we failed a DMA mapping for a TSO packet, we will have +- * used one additional descriptor for a context +- * descriptor. Reset that here. +- */ +- tx_desc = &txq->flex_tx[idx]; +- memset(tx_desc, 0, sizeof(*tx_desc)); +- if (idx == 0) +- idx = txq->desc_count; +- idx--; +- } +- +- /* Update tail in case netdev_xmit_more was previously true */ +- idpf_tx_buf_hw_update(txq, idx, false); +-} +- + /** + * idpf_tx_splitq_bump_ntu - adjust NTU and generation + * @txq: the tx ring to wrap +@@ -2436,6 +2385,37 @@ static bool idpf_tx_get_free_buf_id(struct idpf_sw_queue *refillq, + return true; + } + ++/** ++ * idpf_tx_splitq_pkt_err_unmap - Unmap buffers and bump tail in case of error ++ * @txq: Tx queue to unwind ++ * @params: pointer to splitq params struct ++ * @first: starting buffer for packet to unmap ++ */ ++static void idpf_tx_splitq_pkt_err_unmap(struct idpf_tx_queue *txq, ++ struct idpf_tx_splitq_params *params, ++ struct idpf_tx_buf *first) ++{ ++ struct libeth_sq_napi_stats ss = { }; ++ struct idpf_tx_buf *tx_buf = first; ++ struct libeth_cq_pp cp = { ++ .dev = txq->dev, ++ .ss = &ss, ++ }; ++ u32 idx = 0; ++ ++ u64_stats_update_begin(&txq->stats_sync); ++ u64_stats_inc(&txq->q_stats.dma_map_errs); ++ u64_stats_update_end(&txq->stats_sync); ++ ++ do { ++ libeth_tx_complete(tx_buf, &cp); ++ idpf_tx_clean_buf_ring_bump_ntc(txq, idx, tx_buf); ++ } while (idpf_tx_buf_compl_tag(tx_buf) == params->compl_tag); ++ ++ /* Update tail in case netdev_xmit_more was previously true. */ ++ idpf_tx_buf_hw_update(txq, params->prev_ntu, false); ++} ++ + /** + * idpf_tx_splitq_map - Build the Tx flex descriptor + * @tx_q: queue to send buffer on +@@ -2480,8 +2460,9 @@ static void idpf_tx_splitq_map(struct idpf_tx_queue *tx_q, + for (frag = &skb_shinfo(skb)->frags[0];; frag++) { + unsigned int max_data = IDPF_TX_MAX_DESC_DATA_ALIGNED; + +- if (dma_mapping_error(tx_q->dev, dma)) +- return idpf_tx_dma_map_error(tx_q, skb, first, i); ++ if (unlikely(dma_mapping_error(tx_q->dev, dma))) ++ return idpf_tx_splitq_pkt_err_unmap(tx_q, params, ++ first); + + first->nr_frags++; + idpf_tx_buf_compl_tag(tx_buf) = params->compl_tag; +@@ -2922,7 +2903,9 @@ static void idpf_tx_set_tstamp_desc(union idpf_flex_tx_ctx_desc *ctx_desc, + static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, + struct idpf_tx_queue *tx_q) + { +- struct idpf_tx_splitq_params tx_params = { }; ++ struct idpf_tx_splitq_params tx_params = { ++ .prev_ntu = tx_q->next_to_use, ++ }; + union idpf_flex_tx_ctx_desc *ctx_desc; + struct idpf_tx_buf *first; + unsigned int count; +diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h b/drivers/net/ethernet/intel/idpf/idpf_txrx.h +index 6924bee6ff5bd..c4070806be05c 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h ++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h +@@ -195,6 +195,7 @@ struct idpf_tx_offload_params { + * @compl_tag: Associated tag for completion + * @td_tag: Descriptor tunneling tag + * @offload: Offload parameters ++ * @prev_ntu: stored TxQ next_to_use in case of rollback + */ + struct idpf_tx_splitq_params { + enum idpf_tx_desc_dtype_value dtype; +@@ -205,6 +206,8 @@ struct idpf_tx_splitq_params { + }; + + struct idpf_tx_offload_params offload; ++ ++ u16 prev_ntu; + }; + + enum idpf_tx_ctx_desc_eipt_offload { +@@ -1039,8 +1042,6 @@ void idpf_tx_buf_hw_update(struct idpf_tx_queue *tx_q, u32 val, + bool xmit_more); + unsigned int idpf_size_to_txd_count(unsigned int size); + netdev_tx_t idpf_tx_drop_skb(struct idpf_tx_queue *tx_q, struct sk_buff *skb); +-void idpf_tx_dma_map_error(struct idpf_tx_queue *txq, struct sk_buff *skb, +- struct idpf_tx_buf *first, u16 ring_idx); + unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq, + struct sk_buff *skb); + void idpf_tx_timeout(struct net_device *netdev, unsigned int txqueue); +-- +2.50.1 + diff --git a/queue-6.16/idpf-stop-tx-if-there-are-insufficient-buffer-resour.patch b/queue-6.16/idpf-stop-tx-if-there-are-insufficient-buffer-resour.patch new file mode 100644 index 0000000000..9a5f9ac993 --- /dev/null +++ b/queue-6.16/idpf-stop-tx-if-there-are-insufficient-buffer-resour.patch @@ -0,0 +1,190 @@ +From 2cadb2bfbdf6ed29b3948a66eb3a87f12a4991bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Jul 2025 11:42:22 -0700 +Subject: idpf: stop Tx if there are insufficient buffer resources + +From: Joshua Hay + +[ Upstream commit 0c3f135e840d4a2ba4253e15d530ec61bc30718e ] + +The Tx refillq logic will cause packets to be silently dropped if there +are not enough buffer resources available to send a packet in flow +scheduling mode. Instead, determine how many buffers are needed along +with number of descriptors. Make sure there are enough of both resources +to send the packet, and stop the queue if not. + +Fixes: 7292af042bcf ("idpf: fix a race in txq wakeup") +Signed-off-by: Joshua Hay +Reviewed-by: Madhu Chittim +Tested-by: Samuel Salin +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + .../ethernet/intel/idpf/idpf_singleq_txrx.c | 4 +- + drivers/net/ethernet/intel/idpf/idpf_txrx.c | 47 +++++++++++++------ + drivers/net/ethernet/intel/idpf/idpf_txrx.h | 15 +++++- + 3 files changed, 47 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c +index a3b3261bbdfa7..bf9b820c83303 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c +@@ -415,11 +415,11 @@ netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb, + { + struct idpf_tx_offload_params offload = { }; + struct idpf_tx_buf *first; ++ u32 count, buf_count = 1; + int csum, tso, needed; +- unsigned int count; + __be16 protocol; + +- count = idpf_tx_desc_count_required(tx_q, skb); ++ count = idpf_tx_res_count_required(tx_q, skb, &buf_count); + if (unlikely(!count)) + return idpf_tx_drop_skb(tx_q, skb); + +diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c +index 89fedc2ef247b..cd83243e7c765 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c +@@ -2189,15 +2189,22 @@ void idpf_tx_splitq_build_flow_desc(union idpf_tx_flex_desc *desc, + desc->flow.qw1.compl_tag = cpu_to_le16(params->compl_tag); + } + +-/* Global conditions to tell whether the txq (and related resources) +- * has room to allow the use of "size" descriptors. ++/** ++ * idpf_tx_splitq_has_room - check if enough Tx splitq resources are available ++ * @tx_q: the queue to be checked ++ * @descs_needed: number of descriptors required for this packet ++ * @bufs_needed: number of Tx buffers required for this packet ++ * ++ * Return: 0 if no room available, 1 otherwise + */ +-static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 size) ++static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 descs_needed, ++ u32 bufs_needed) + { +- if (IDPF_DESC_UNUSED(tx_q) < size || ++ if (IDPF_DESC_UNUSED(tx_q) < descs_needed || + IDPF_TX_COMPLQ_PENDING(tx_q->txq_grp) > + IDPF_TX_COMPLQ_OVERFLOW_THRESH(tx_q->txq_grp->complq) || +- IDPF_TX_BUF_RSV_LOW(tx_q)) ++ IDPF_TX_BUF_RSV_LOW(tx_q) || ++ idpf_tx_splitq_get_free_bufs(tx_q->refillq) < bufs_needed) + return 0; + return 1; + } +@@ -2206,14 +2213,21 @@ static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 size) + * idpf_tx_maybe_stop_splitq - 1st level check for Tx splitq stop conditions + * @tx_q: the queue to be checked + * @descs_needed: number of descriptors required for this packet ++ * @bufs_needed: number of buffers needed for this packet + * +- * Returns 0 if stop is not needed ++ * Return: 0 if stop is not needed + */ + static int idpf_tx_maybe_stop_splitq(struct idpf_tx_queue *tx_q, +- unsigned int descs_needed) ++ u32 descs_needed, ++ u32 bufs_needed) + { ++ /* Since we have multiple resources to check for splitq, our ++ * start,stop_thrs becomes a boolean check instead of a count ++ * threshold. ++ */ + if (netif_subqueue_maybe_stop(tx_q->netdev, tx_q->idx, +- idpf_txq_has_room(tx_q, descs_needed), ++ idpf_txq_has_room(tx_q, descs_needed, ++ bufs_needed), + 1, 1)) + return 0; + +@@ -2255,14 +2269,16 @@ void idpf_tx_buf_hw_update(struct idpf_tx_queue *tx_q, u32 val, + } + + /** +- * idpf_tx_desc_count_required - calculate number of Tx descriptors needed ++ * idpf_tx_res_count_required - get number of Tx resources needed for this pkt + * @txq: queue to send buffer on + * @skb: send buffer ++ * @bufs_needed: (output) number of buffers needed for this skb. + * +- * Returns number of data descriptors needed for this skb. ++ * Return: number of data descriptors and buffers needed for this skb. + */ +-unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq, +- struct sk_buff *skb) ++unsigned int idpf_tx_res_count_required(struct idpf_tx_queue *txq, ++ struct sk_buff *skb, ++ u32 *bufs_needed) + { + const struct skb_shared_info *shinfo; + unsigned int count = 0, i; +@@ -2273,6 +2289,7 @@ unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq, + return count; + + shinfo = skb_shinfo(skb); ++ *bufs_needed += shinfo->nr_frags; + for (i = 0; i < shinfo->nr_frags; i++) { + unsigned int size; + +@@ -2875,11 +2892,11 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, + }; + union idpf_flex_tx_ctx_desc *ctx_desc; + struct idpf_tx_buf *first; +- unsigned int count; ++ u32 count, buf_count = 1; + int tso, idx; + u32 buf_id; + +- count = idpf_tx_desc_count_required(tx_q, skb); ++ count = idpf_tx_res_count_required(tx_q, skb, &buf_count); + if (unlikely(!count)) + return idpf_tx_drop_skb(tx_q, skb); + +@@ -2889,7 +2906,7 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, + + /* Check for splitq specific TX resources */ + count += (IDPF_TX_DESCS_PER_CACHE_LINE + tso); +- if (idpf_tx_maybe_stop_splitq(tx_q, count)) { ++ if (idpf_tx_maybe_stop_splitq(tx_q, count, buf_count)) { + idpf_tx_buf_hw_update(tx_q, tx_q->next_to_use, false); + + return NETDEV_TX_BUSY; +diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h b/drivers/net/ethernet/intel/idpf/idpf_txrx.h +index a30b68504d73c..54b314ceee738 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h ++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h +@@ -1023,6 +1023,17 @@ static inline void idpf_vport_intr_set_wb_on_itr(struct idpf_q_vector *q_vector) + reg->dyn_ctl); + } + ++/** ++ * idpf_tx_splitq_get_free_bufs - get number of free buf_ids in refillq ++ * @refillq: pointer to refillq containing buf_ids ++ */ ++static inline u32 idpf_tx_splitq_get_free_bufs(struct idpf_sw_queue *refillq) ++{ ++ return (refillq->next_to_use > refillq->next_to_clean ? ++ 0 : refillq->desc_count) + ++ refillq->next_to_use - refillq->next_to_clean - 1; ++} ++ + int idpf_vport_singleq_napi_poll(struct napi_struct *napi, int budget); + void idpf_vport_init_num_qs(struct idpf_vport *vport, + struct virtchnl2_create_vport *vport_msg); +@@ -1050,8 +1061,8 @@ void idpf_tx_buf_hw_update(struct idpf_tx_queue *tx_q, u32 val, + bool xmit_more); + unsigned int idpf_size_to_txd_count(unsigned int size); + netdev_tx_t idpf_tx_drop_skb(struct idpf_tx_queue *tx_q, struct sk_buff *skb); +-unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq, +- struct sk_buff *skb); ++unsigned int idpf_tx_res_count_required(struct idpf_tx_queue *txq, ++ struct sk_buff *skb, u32 *buf_count); + void idpf_tx_timeout(struct net_device *netdev, unsigned int txqueue); + netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb, + struct idpf_tx_queue *tx_q); +-- +2.50.1 + diff --git a/queue-6.16/io_uring-kbuf-always-use-read_once-to-read-ring-prov.patch b/queue-6.16/io_uring-kbuf-always-use-read_once-to-read-ring-prov.patch new file mode 100644 index 0000000000..0a6228aa78 --- /dev/null +++ b/queue-6.16/io_uring-kbuf-always-use-read_once-to-read-ring-prov.patch @@ -0,0 +1,91 @@ +From da5bd9f66dc7d690893f04e767e861e3027f0cc4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 15:27:30 -0600 +Subject: io_uring/kbuf: always use READ_ONCE() to read ring provided buffer + lengths + +From: Jens Axboe + +[ Upstream commit 98b6fa62c84f2e129161e976a5b9b3cb4ccd117b ] + +Since the buffers are mapped from userspace, it is prudent to use +READ_ONCE() to read the value into a local variable, and use that for +any other actions taken. Having a stable read of the buffer length +avoids worrying about it changing after checking, or being read multiple +times. + +Similarly, the buffer may well change in between it being picked and +being committed. Ensure the looping for incremental ring buffer commit +stops if it hits a zero sized buffer, as no further progress can be made +at that point. + +Fixes: ae98dbf43d75 ("io_uring/kbuf: add support for incremental buffer consumption") +Link: https://lore.kernel.org/io-uring/tencent_000C02641F6250C856D0C26228DE29A3D30A@qq.com/ +Reported-by: Qingyue Zhang +Reported-by: Suoxing Zhang +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/kbuf.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c +index 81a13338dfab3..19a8bde5e1e1c 100644 +--- a/io_uring/kbuf.c ++++ b/io_uring/kbuf.c +@@ -36,15 +36,19 @@ static bool io_kbuf_inc_commit(struct io_buffer_list *bl, int len) + { + while (len) { + struct io_uring_buf *buf; +- u32 this_len; ++ u32 buf_len, this_len; + + buf = io_ring_head_to_buf(bl->buf_ring, bl->head, bl->mask); +- this_len = min_t(u32, len, buf->len); +- buf->len -= this_len; +- if (buf->len) { ++ buf_len = READ_ONCE(buf->len); ++ this_len = min_t(u32, len, buf_len); ++ buf_len -= this_len; ++ /* Stop looping for invalid buffer length of 0 */ ++ if (buf_len || !this_len) { + buf->addr += this_len; ++ buf->len = buf_len; + return false; + } ++ buf->len = 0; + bl->head++; + len -= this_len; + } +@@ -159,6 +163,7 @@ static void __user *io_ring_buffer_select(struct io_kiocb *req, size_t *len, + __u16 tail, head = bl->head; + struct io_uring_buf *buf; + void __user *ret; ++ u32 buf_len; + + tail = smp_load_acquire(&br->tail); + if (unlikely(tail == head)) +@@ -168,8 +173,9 @@ static void __user *io_ring_buffer_select(struct io_kiocb *req, size_t *len, + req->flags |= REQ_F_BL_EMPTY; + + buf = io_ring_head_to_buf(br, head, bl->mask); +- if (*len == 0 || *len > buf->len) +- *len = buf->len; ++ buf_len = READ_ONCE(buf->len); ++ if (*len == 0 || *len > buf_len) ++ *len = buf_len; + req->flags |= REQ_F_BUFFER_RING | REQ_F_BUFFERS_COMMIT; + req->buf_list = bl; + req->buf_index = buf->bid; +@@ -265,7 +271,7 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg, + + req->buf_index = buf->bid; + do { +- u32 len = buf->len; ++ u32 len = READ_ONCE(buf->len); + + /* truncate end piece, if needed, for non partial buffers */ + if (len > arg->max_len) { +-- +2.50.1 + diff --git a/queue-6.16/io_uring-kbuf-fix-signedness-in-this_len-calculation.patch b/queue-6.16/io_uring-kbuf-fix-signedness-in-this_len-calculation.patch new file mode 100644 index 0000000000..bc876c695d --- /dev/null +++ b/queue-6.16/io_uring-kbuf-fix-signedness-in-this_len-calculation.patch @@ -0,0 +1,41 @@ +From 421bf961a2272005ac98df29928415485679707c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 19:43:39 +0800 +Subject: io_uring/kbuf: fix signedness in this_len calculation + +From: Qingyue Zhang + +[ Upstream commit c64eff368ac676e8540344d27a3de47e0ad90d21 ] + +When importing and using buffers, buf->len is considered unsigned. +However, buf->len is converted to signed int when committing. This can +lead to unexpected behavior if the buffer is large enough to be +interpreted as a negative value. Make min_t calculation unsigned. + +Fixes: ae98dbf43d75 ("io_uring/kbuf: add support for incremental buffer consumption") +Co-developed-by: Suoxing Zhang +Signed-off-by: Suoxing Zhang +Signed-off-by: Qingyue Zhang +Link: https://lore.kernel.org/r/tencent_4DBB3674C0419BEC2C0C525949DA410CA307@qq.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/kbuf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c +index f2d2cc319faac..81a13338dfab3 100644 +--- a/io_uring/kbuf.c ++++ b/io_uring/kbuf.c +@@ -39,7 +39,7 @@ static bool io_kbuf_inc_commit(struct io_buffer_list *bl, int len) + u32 this_len; + + buf = io_ring_head_to_buf(bl->buf_ring, bl->head, bl->mask); +- this_len = min_t(int, len, buf->len); ++ this_len = min_t(u32, len, buf->len); + buf->len -= this_len; + if (buf->len) { + buf->addr += this_len; +-- +2.50.1 + diff --git a/queue-6.16/ixgbe-fix-ixgbe_orom_civd_info-struct-layout.patch b/queue-6.16/ixgbe-fix-ixgbe_orom_civd_info-struct-layout.patch new file mode 100644 index 0000000000..c15c048b1d --- /dev/null +++ b/queue-6.16/ixgbe-fix-ixgbe_orom_civd_info-struct-layout.patch @@ -0,0 +1,57 @@ +From 18b6731550c67fe1a8e40dc0250f7f94588a8a3a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 31 Jul 2025 14:45:33 +0200 +Subject: ixgbe: fix ixgbe_orom_civd_info struct layout + +From: Jedrzej Jagielski + +[ Upstream commit ed913b343dcf9f623e7436fa1a153c89b22d109b ] + +The current layout of struct ixgbe_orom_civd_info causes incorrect data +storage due to compiler-inserted padding. This results in issues when +writing OROM data into the structure. + +Add the __packed attribute to ensure the structure layout matches the +expected binary format without padding. + +Fixes: 70db0788a262 ("ixgbe: read the OROM version information") +Reviewed-by: Aleksandr Loktionov +Signed-off-by: Jedrzej Jagielski +Reviewed-by: Simon Horman +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c | 2 +- + drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c +index 71ea25de1bac7..754c176fd4a7a 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c +@@ -3123,7 +3123,7 @@ static int ixgbe_get_orom_ver_info(struct ixgbe_hw *hw, + if (err) + return err; + +- combo_ver = le32_to_cpu(civd.combo_ver); ++ combo_ver = get_unaligned_le32(&civd.combo_ver); + + orom->major = (u8)FIELD_GET(IXGBE_OROM_VER_MASK, combo_ver); + orom->patch = (u8)FIELD_GET(IXGBE_OROM_VER_PATCH_MASK, combo_ver); +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h +index 09df67f03cf47..38a41d81de0fa 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h +@@ -1150,7 +1150,7 @@ struct ixgbe_orom_civd_info { + __le32 combo_ver; /* Combo Image Version number */ + u8 combo_name_len; /* Length of the unicode combo image version string, max of 32 */ + __le16 combo_name[32]; /* Unicode string representing the Combo Image version */ +-}; ++} __packed; + + /* Function specific capabilities */ + struct ixgbe_hw_func_caps { +-- +2.50.1 + diff --git a/queue-6.16/l2tp-do-not-use-sock_hold-in-pppol2tp_session_get_so.patch b/queue-6.16/l2tp-do-not-use-sock_hold-in-pppol2tp_session_get_so.patch new file mode 100644 index 0000000000..17f0d5be0b --- /dev/null +++ b/queue-6.16/l2tp-do-not-use-sock_hold-in-pppol2tp_session_get_so.patch @@ -0,0 +1,112 @@ +From 38d1b038f519229ebb42c1ea1affc52ac3a7191b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Aug 2025 13:44:35 +0000 +Subject: l2tp: do not use sock_hold() in pppol2tp_session_get_sock() + +From: Eric Dumazet + +[ Upstream commit 9b8c88f875c04d4cb9111bd5dd9291c7e9691bf5 ] + +pppol2tp_session_get_sock() is using RCU, it must be ready +for sk_refcnt being zero. + +Commit ee40fb2e1eb5 ("l2tp: protect sock pointer of +struct pppol2tp_session with RCU") was correct because it +had a call_rcu(..., pppol2tp_put_sk) which was later removed in blamed commit. + +pppol2tp_recv() can use pppol2tp_session_get_sock() as well. + +Fixes: c5cbaef992d6 ("l2tp: refactor ppp socket/session relationship") +Signed-off-by: Eric Dumazet +Cc: James Chapman +Reviewed-by: Guillaume Nault +Link: https://patch.msgid.link/20250826134435.1683435-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/l2tp/l2tp_ppp.c | 25 ++++++++----------------- + 1 file changed, 8 insertions(+), 17 deletions(-) + +diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c +index fc5c2fd8f34c7..5e12e7ce17d8a 100644 +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -129,22 +129,12 @@ static const struct ppp_channel_ops pppol2tp_chan_ops = { + + static const struct proto_ops pppol2tp_ops; + +-/* Retrieves the pppol2tp socket associated to a session. +- * A reference is held on the returned socket, so this function must be paired +- * with sock_put(). +- */ ++/* Retrieves the pppol2tp socket associated to a session. */ + static struct sock *pppol2tp_session_get_sock(struct l2tp_session *session) + { + struct pppol2tp_session *ps = l2tp_session_priv(session); +- struct sock *sk; +- +- rcu_read_lock(); +- sk = rcu_dereference(ps->sk); +- if (sk) +- sock_hold(sk); +- rcu_read_unlock(); + +- return sk; ++ return rcu_dereference(ps->sk); + } + + /* Helpers to obtain tunnel/session contexts from sockets. +@@ -206,14 +196,13 @@ static int pppol2tp_recvmsg(struct socket *sock, struct msghdr *msg, + + static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int data_len) + { +- struct pppol2tp_session *ps = l2tp_session_priv(session); +- struct sock *sk = NULL; ++ struct sock *sk; + + /* If the socket is bound, send it in to PPP's input queue. Otherwise + * queue it on the session socket. + */ + rcu_read_lock(); +- sk = rcu_dereference(ps->sk); ++ sk = pppol2tp_session_get_sock(session); + if (!sk) + goto no_sock; + +@@ -510,13 +499,14 @@ static void pppol2tp_show(struct seq_file *m, void *arg) + struct l2tp_session *session = arg; + struct sock *sk; + ++ rcu_read_lock(); + sk = pppol2tp_session_get_sock(session); + if (sk) { + struct pppox_sock *po = pppox_sk(sk); + + seq_printf(m, " interface %s\n", ppp_dev_name(&po->chan)); +- sock_put(sk); + } ++ rcu_read_unlock(); + } + + static void pppol2tp_session_init(struct l2tp_session *session) +@@ -1530,6 +1520,7 @@ static void pppol2tp_seq_session_show(struct seq_file *m, void *v) + port = ntohs(inet->inet_sport); + } + ++ rcu_read_lock(); + sk = pppol2tp_session_get_sock(session); + if (sk) { + state = sk->sk_state; +@@ -1565,8 +1556,8 @@ static void pppol2tp_seq_session_show(struct seq_file *m, void *v) + struct pppox_sock *po = pppox_sk(sk); + + seq_printf(m, " interface %s\n", ppp_dev_name(&po->chan)); +- sock_put(sk); + } ++ rcu_read_unlock(); + } + + static int pppol2tp_seq_show(struct seq_file *m, void *v) +-- +2.50.1 + diff --git a/queue-6.16/misdn-hfcpci-fix-warning-when-deleting-uninitialized.patch b/queue-6.16/misdn-hfcpci-fix-warning-when-deleting-uninitialized.patch new file mode 100644 index 0000000000..15b2fc1254 --- /dev/null +++ b/queue-6.16/misdn-hfcpci-fix-warning-when-deleting-uninitialized.patch @@ -0,0 +1,104 @@ +From 1829c7b209ea7661fd39c8d960e072ec6060acd6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Aug 2025 20:11:36 +0200 +Subject: mISDN: hfcpci: Fix warning when deleting uninitialized timer + +From: Vladimir Riabchun + +[ Upstream commit 97766512a9951b9fd6fc97f1b93211642bb0b220 ] + +With CONFIG_DEBUG_OBJECTS_TIMERS unloading hfcpci module leads +to the following splat: + +[ 250.215892] ODEBUG: assert_init not available (active state 0) object: ffffffffc01a3dc0 object type: timer_list hint: 0x0 +[ 250.217520] WARNING: CPU: 0 PID: 233 at lib/debugobjects.c:612 debug_print_object+0x1b6/0x2c0 +[ 250.218775] Modules linked in: hfcpci(-) mISDN_core +[ 250.219537] CPU: 0 UID: 0 PID: 233 Comm: rmmod Not tainted 6.17.0-rc2-g6f713187ac98 #2 PREEMPT(voluntary) +[ 250.220940] Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +[ 250.222377] RIP: 0010:debug_print_object+0x1b6/0x2c0 +[ 250.223131] Code: fc ff df 48 89 fa 48 c1 ea 03 80 3c 02 00 75 4f 41 56 48 8b 14 dd a0 4e 01 9f 48 89 ee 48 c7 c7 20 46 01 9f e8 cb 84d +[ 250.225805] RSP: 0018:ffff888015ea7c08 EFLAGS: 00010286 +[ 250.226608] RAX: 0000000000000000 RBX: 0000000000000005 RCX: ffffffff9be93a95 +[ 250.227708] RDX: 1ffff1100d945138 RSI: 0000000000000008 RDI: ffff88806ca289c0 +[ 250.228993] RBP: ffffffff9f014a00 R08: 0000000000000001 R09: ffffed1002bd4f39 +[ 250.230043] R10: ffff888015ea79cf R11: 0000000000000001 R12: 0000000000000001 +[ 250.231185] R13: ffffffff9eea0520 R14: 0000000000000000 R15: ffff888015ea7cc8 +[ 250.232454] FS: 00007f3208f01540(0000) GS:ffff8880caf5a000(0000) knlGS:0000000000000000 +[ 250.233851] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 250.234856] CR2: 00007f32090a7421 CR3: 0000000004d63000 CR4: 00000000000006f0 +[ 250.236117] Call Trace: +[ 250.236599] +[ 250.236967] ? trace_irq_enable.constprop.0+0xd4/0x130 +[ 250.237920] debug_object_assert_init+0x1f6/0x310 +[ 250.238762] ? __pfx_debug_object_assert_init+0x10/0x10 +[ 250.239658] ? __lock_acquire+0xdea/0x1c70 +[ 250.240369] __try_to_del_timer_sync+0x69/0x140 +[ 250.241172] ? __pfx___try_to_del_timer_sync+0x10/0x10 +[ 250.242058] ? __timer_delete_sync+0xc6/0x120 +[ 250.242842] ? lock_acquire+0x30/0x80 +[ 250.243474] ? __timer_delete_sync+0xc6/0x120 +[ 250.244262] __timer_delete_sync+0x98/0x120 +[ 250.245015] HFC_cleanup+0x10/0x20 [hfcpci] +[ 250.245704] __do_sys_delete_module+0x348/0x510 +[ 250.246461] ? __pfx___do_sys_delete_module+0x10/0x10 +[ 250.247338] do_syscall_64+0xc1/0x360 +[ 250.247924] entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Fix this by initializing hfc_tl timer with DEFINE_TIMER macro. +Also, use mod_timer instead of manual timeout update. + +Fixes: 87c5fa1bb426 ("mISDN: Add different different timer settings for hfc-pci") +Fixes: 175302f6b79e ("mISDN: hfcpci: Fix use-after-free bug in hfcpci_softirq") +Signed-off-by: Vladimir Riabchun +Link: https://patch.msgid.link/aKiy2D_LiWpQ5kXq@vova-pc +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/isdn/hardware/mISDN/hfcpci.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c +index 2b05722d4dbe8..ea8a0ab47afd8 100644 +--- a/drivers/isdn/hardware/mISDN/hfcpci.c ++++ b/drivers/isdn/hardware/mISDN/hfcpci.c +@@ -39,12 +39,13 @@ + + #include "hfc_pci.h" + ++static void hfcpci_softirq(struct timer_list *unused); + static const char *hfcpci_revision = "2.0"; + + static int HFC_cnt; + static uint debug; + static uint poll, tics; +-static struct timer_list hfc_tl; ++static DEFINE_TIMER(hfc_tl, hfcpci_softirq); + static unsigned long hfc_jiffies; + + MODULE_AUTHOR("Karsten Keil"); +@@ -2305,8 +2306,7 @@ hfcpci_softirq(struct timer_list *unused) + hfc_jiffies = jiffies + 1; + else + hfc_jiffies += tics; +- hfc_tl.expires = hfc_jiffies; +- add_timer(&hfc_tl); ++ mod_timer(&hfc_tl, hfc_jiffies); + } + + static int __init +@@ -2332,10 +2332,8 @@ HFC_init(void) + if (poll != HFCPCI_BTRANS_THRESHOLD) { + printk(KERN_INFO "%s: Using alternative poll value of %d\n", + __func__, poll); +- timer_setup(&hfc_tl, hfcpci_softirq, 0); +- hfc_tl.expires = jiffies + tics; +- hfc_jiffies = hfc_tl.expires; +- add_timer(&hfc_tl); ++ hfc_jiffies = jiffies + tics; ++ mod_timer(&hfc_tl, hfc_jiffies); + } else + tics = 0; /* indicate the use of controller's timer */ + +-- +2.50.1 + diff --git a/queue-6.16/net-dlink-fix-multicast-stats-being-counted-incorrec.patch b/queue-6.16/net-dlink-fix-multicast-stats-being-counted-incorrec.patch new file mode 100644 index 0000000000..744ac5d83e --- /dev/null +++ b/queue-6.16/net-dlink-fix-multicast-stats-being-counted-incorrec.patch @@ -0,0 +1,46 @@ +From 6b0c1bc755a9956062fe94d5bd766251e6c28769 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Aug 2025 03:29:24 +0900 +Subject: net: dlink: fix multicast stats being counted incorrectly + +From: Yeounsu Moon + +[ Upstream commit 007a5ffadc4fd51739527f1503b7cf048f31c413 ] + +`McstFramesRcvdOk` counts the number of received multicast packets, and +it reports the value correctly. + +However, reading `McstFramesRcvdOk` clears the register to zero. As a +result, the driver was reporting only the packets since the last read, +instead of the accumulated total. + +Fix this by updating the multicast statistics accumulatively instaed of +instantaneously. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Tested-on: D-Link DGE-550T Rev-A3 +Signed-off-by: Yeounsu Moon +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250823182927.6063-3-yyyynoom@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/dlink/dl2k.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c +index da9b7715df050..f828f38cd7682 100644 +--- a/drivers/net/ethernet/dlink/dl2k.c ++++ b/drivers/net/ethernet/dlink/dl2k.c +@@ -1091,7 +1091,7 @@ get_stats (struct net_device *dev) + dev->stats.rx_bytes += dr32(OctetRcvOk); + dev->stats.tx_bytes += dr32(OctetXmtOk); + +- dev->stats.multicast = dr32(McstFramesRcvdOk); ++ dev->stats.multicast += dr32(McstFramesRcvdOk); + dev->stats.collisions += dr32(SingleColFrames) + + dr32(MultiColFrames); + +-- +2.50.1 + diff --git a/queue-6.16/net-hv_netvsc-fix-loss-of-early-receive-events-from-.patch b/queue-6.16/net-hv_netvsc-fix-loss-of-early-receive-events-from-.patch new file mode 100644 index 0000000000..1fd75d1fb7 --- /dev/null +++ b/queue-6.16/net-hv_netvsc-fix-loss-of-early-receive-events-from-.patch @@ -0,0 +1,122 @@ +From b91ffc09095d33e7d0ed1e1375b91bb7f9ea3892 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 04:56:27 -0700 +Subject: net: hv_netvsc: fix loss of early receive events from host during + channel open. + +From: Dipayaan Roy + +[ Upstream commit 9448ccd853368582efa9db05db344f8bb9dffe0f ] + +The hv_netvsc driver currently enables NAPI after opening the primary and +subchannels. This ordering creates a race: if the Hyper-V host places data +in the host -> guest ring buffer and signals the channel before +napi_enable() has been called, the channel callback will run but +napi_schedule_prep() will return false. As a result, the NAPI poller never +gets scheduled, the data in the ring buffer is not consumed, and the +receive queue may remain permanently stuck until another interrupt happens +to arrive. + +Fix this by enabling NAPI and registering it with the RX/TX queues before +vmbus channel is opened. This guarantees that any early host signal after +open will correctly trigger NAPI scheduling and the ring buffer will be +drained. + +Fixes: 76bb5db5c749d ("netvsc: fix use after free on module removal") +Signed-off-by: Dipayaan Roy +Link: https://patch.msgid.link/20250825115627.GA32189@linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/hyperv/netvsc.c | 17 ++++++++--------- + drivers/net/hyperv/rndis_filter.c | 23 ++++++++++++++++------- + 2 files changed, 24 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +index 720104661d7f2..60a4629fe6ba7 100644 +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -1812,6 +1812,11 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, + + /* Enable NAPI handler before init callbacks */ + netif_napi_add(ndev, &net_device->chan_table[0].napi, netvsc_poll); ++ napi_enable(&net_device->chan_table[0].napi); ++ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, ++ &net_device->chan_table[0].napi); ++ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, ++ &net_device->chan_table[0].napi); + + /* Open the channel */ + device->channel->next_request_id_callback = vmbus_next_request_id; +@@ -1831,12 +1836,6 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, + /* Channel is opened */ + netdev_dbg(ndev, "hv_netvsc channel opened successfully\n"); + +- napi_enable(&net_device->chan_table[0].napi); +- netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, +- &net_device->chan_table[0].napi); +- netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, +- &net_device->chan_table[0].napi); +- + /* Connect with the NetVsp */ + ret = netvsc_connect_vsp(device, net_device, device_info); + if (ret != 0) { +@@ -1854,14 +1853,14 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, + + close: + RCU_INIT_POINTER(net_device_ctx->nvdev, NULL); +- netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, NULL); +- netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, NULL); +- napi_disable(&net_device->chan_table[0].napi); + + /* Now, we can close the channel safely */ + vmbus_close(device->channel); + + cleanup: ++ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, NULL); ++ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, NULL); ++ napi_disable(&net_device->chan_table[0].napi); + netif_napi_del(&net_device->chan_table[0].napi); + + cleanup2: +diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c +index 9e73959e61ee0..c35f9685b6bf0 100644 +--- a/drivers/net/hyperv/rndis_filter.c ++++ b/drivers/net/hyperv/rndis_filter.c +@@ -1252,17 +1252,26 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc) + new_sc->rqstor_size = netvsc_rqstor_size(netvsc_ring_bytes); + new_sc->max_pkt_size = NETVSC_MAX_PKT_SIZE; + ++ /* Enable napi before opening the vmbus channel to avoid races ++ * as the host placing data on the host->guest ring may be left ++ * out if napi was not enabled. ++ */ ++ napi_enable(&nvchan->napi); ++ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_RX, ++ &nvchan->napi); ++ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_TX, ++ &nvchan->napi); ++ + ret = vmbus_open(new_sc, netvsc_ring_bytes, + netvsc_ring_bytes, NULL, 0, + netvsc_channel_cb, nvchan); +- if (ret == 0) { +- napi_enable(&nvchan->napi); +- netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_RX, +- &nvchan->napi); +- netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_TX, +- &nvchan->napi); +- } else { ++ if (ret != 0) { + netdev_notice(ndev, "sub channel open failed: %d\n", ret); ++ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_TX, ++ NULL); ++ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_RX, ++ NULL); ++ napi_disable(&nvchan->napi); + } + + if (atomic_inc_return(&nvscdev->open_chn) == nvscdev->num_chn) +-- +2.50.1 + diff --git a/queue-6.16/net-ipv4-fix-regression-in-local-broadcast-routes.patch b/queue-6.16/net-ipv4-fix-regression-in-local-broadcast-routes.patch new file mode 100644 index 0000000000..2ca3033719 --- /dev/null +++ b/queue-6.16/net-ipv4-fix-regression-in-local-broadcast-routes.patch @@ -0,0 +1,57 @@ +From d9782636188e1f62d4cd5d8dbe706dfc2d95bec0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 08:23:21 +0200 +Subject: net: ipv4: fix regression in local-broadcast routes + +From: Oscar Maes + +[ Upstream commit 5189446ba995556eaa3755a6e875bc06675b88bd ] + +Commit 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") +introduced a regression where local-broadcast packets would have their +gateway set in __mkroute_output, which was caused by fi = NULL being +removed. + +Fix this by resetting the fib_info for local-broadcast packets. This +preserves the intended changes for directed-broadcast packets. + +Cc: stable@vger.kernel.org +Fixes: 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") +Reported-by: Brett A C Sheffield +Closes: https://lore.kernel.org/regressions/20250822165231.4353-4-bacs@librecast.net +Signed-off-by: Oscar Maes +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20250827062322.4807-1-oscmaes92@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/route.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 7b8e80c4f1d98..bf82434c3541b 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -2573,12 +2573,16 @@ static struct rtable *__mkroute_output(const struct fib_result *res, + !netif_is_l3_master(dev_out)) + return ERR_PTR(-EINVAL); + +- if (ipv4_is_lbcast(fl4->daddr)) ++ if (ipv4_is_lbcast(fl4->daddr)) { + type = RTN_BROADCAST; +- else if (ipv4_is_multicast(fl4->daddr)) ++ ++ /* reset fi to prevent gateway resolution */ ++ fi = NULL; ++ } else if (ipv4_is_multicast(fl4->daddr)) { + type = RTN_MULTICAST; +- else if (ipv4_is_zeronet(fl4->daddr)) ++ } else if (ipv4_is_zeronet(fl4->daddr)) { + return ERR_PTR(-EINVAL); ++ } + + if (dev_out->flags & IFF_LOOPBACK) + flags |= RTCF_LOCAL; +-- +2.50.1 + diff --git a/queue-6.16/net-macb-disable-clocks-once.patch b/queue-6.16/net-macb-disable-clocks-once.patch new file mode 100644 index 0000000000..3c5d480ff1 --- /dev/null +++ b/queue-6.16/net-macb-disable-clocks-once.patch @@ -0,0 +1,49 @@ +From b703a736b8f2b12f097cb66b5dafb77ebd64086b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Aug 2025 10:30:22 -0400 +Subject: net: macb: Disable clocks once + +From: Neil Mandir + +[ Upstream commit dac978e51cce0c1f00a14c4a82f81d387f79b2d4 ] + +When the driver is removed the clocks are disabled twice: once in +macb_remove and a second time by runtime pm. Disable wakeup in remove so +all the clocks are disabled and skip the second call to macb_clks_disable. +Always suspend the device as we always set it active in probe. + +Fixes: d54f89af6cc4 ("net: macb: Add pm runtime support") +Signed-off-by: Neil Mandir +Co-developed-by: Sean Anderson +Signed-off-by: Sean Anderson +Link: https://patch.msgid.link/20250826143022.935521-1-sean.anderson@linux.dev +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cadence/macb_main.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index 3cb50e5385d49..d949d2ba6cb9f 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -5396,14 +5396,11 @@ static void macb_remove(struct platform_device *pdev) + mdiobus_unregister(bp->mii_bus); + mdiobus_free(bp->mii_bus); + ++ device_set_wakeup_enable(&bp->pdev->dev, 0); + cancel_work_sync(&bp->hresp_err_bh_work); + pm_runtime_disable(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); +- if (!pm_runtime_suspended(&pdev->dev)) { +- macb_clks_disable(bp->pclk, bp->hclk, bp->tx_clk, +- bp->rx_clk, bp->tsu_clk); +- pm_runtime_set_suspended(&pdev->dev); +- } ++ pm_runtime_set_suspended(&pdev->dev); + phylink_destroy(bp->phylink); + free_netdev(dev); + } +-- +2.50.1 + diff --git a/queue-6.16/net-macb-fix-offset-error-in-gem_update_stats.patch b/queue-6.16/net-macb-fix-offset-error-in-gem_update_stats.patch new file mode 100644 index 0000000000..dcfaaa678f --- /dev/null +++ b/queue-6.16/net-macb-fix-offset-error-in-gem_update_stats.patch @@ -0,0 +1,39 @@ +From 8b9d06182a3f8a7376da2ab4a399368497d5e016 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 13:21:34 -0400 +Subject: net: macb: Fix offset error in gem_update_stats + +From: Sean Anderson + +[ Upstream commit 16c8a3a67ec799fc731919e3e51be9af6cdf541d ] + +hw_stats now has only one variable for tx_octets/rx_octets, so we should +only increment p once, not twice. This would cause the statistics to be +reported under the wrong categories in `ethtool -S --all-groups` (which +uses hw_stats) but not `ethtool -S` (which uses ethtool_stats). + +Signed-off-by: Sean Anderson +Fixes: f6af690a295a ("net: cadence: macb: Report standard stats") +Link: https://patch.msgid.link/20250825172134.681861-1-sean.anderson@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cadence/macb_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index c1e904e4a01f4..3cb50e5385d49 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -3090,7 +3090,7 @@ static void gem_update_stats(struct macb *bp) + /* Add GEM_OCTTXH, GEM_OCTRXH */ + val = bp->macb_reg_readl(bp, offset + 4); + bp->ethtool_stats[i] += ((u64)val) << 32; +- *(p++) += ((u64)val) << 32; ++ *p += ((u64)val) << 32; + } + } + +-- +2.50.1 + diff --git a/queue-6.16/net-macb-fix-unregister_netdev-call-order-in-macb_re.patch b/queue-6.16/net-macb-fix-unregister_netdev-call-order-in-macb_re.patch new file mode 100644 index 0000000000..2a21d4091f --- /dev/null +++ b/queue-6.16/net-macb-fix-unregister_netdev-call-order-in-macb_re.patch @@ -0,0 +1,63 @@ +From d010a9d7bef5b40cf6489d517fabf1c4257e548d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Aug 2025 07:25:27 +0800 +Subject: net: macb: fix unregister_netdev call order in macb_remove() + +From: luoguangfei <15388634752@163.com> + +[ Upstream commit 01b9128c5db1b470575d07b05b67ffa3cb02ebf1 ] + +When removing a macb device, the driver calls phy_exit() before +unregister_netdev(). This leads to a WARN from kernfs: + + ------------[ cut here ]------------ + kernfs: can not remove 'attached_dev', no directory + WARNING: CPU: 1 PID: 27146 at fs/kernfs/dir.c:1683 + Call trace: + kernfs_remove_by_name_ns+0xd8/0xf0 + sysfs_remove_link+0x24/0x58 + phy_detach+0x5c/0x168 + phy_disconnect+0x4c/0x70 + phylink_disconnect_phy+0x6c/0xc0 [phylink] + macb_close+0x6c/0x170 [macb] + ... + macb_remove+0x60/0x168 [macb] + platform_remove+0x5c/0x80 + ... + +The warning happens because the PHY is being exited while the netdev +is still registered. The correct order is to unregister the netdev +before shutting down the PHY and cleaning up the MDIO bus. + +Fix this by moving unregister_netdev() ahead of phy_exit() in +macb_remove(). + +Fixes: 8b73fa3ae02b ("net: macb: Added ZynqMP-specific initialization") +Signed-off-by: luoguangfei <15388634752@163.com> +Link: https://patch.msgid.link/20250818232527.1316-1-15388634752@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cadence/macb_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index d1f1ae5ea161c..c1e904e4a01f4 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -5391,11 +5391,11 @@ static void macb_remove(struct platform_device *pdev) + + if (dev) { + bp = netdev_priv(dev); ++ unregister_netdev(dev); + phy_exit(bp->sgmii_phy); + mdiobus_unregister(bp->mii_bus); + mdiobus_free(bp->mii_bus); + +- unregister_netdev(dev); + cancel_work_sync(&bp->hresp_err_bh_work); + pm_runtime_disable(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); +-- +2.50.1 + diff --git a/queue-6.16/net-mlx5-fix-lockdep-assertion-on-sync-reset-unload-.patch b/queue-6.16/net-mlx5-fix-lockdep-assertion-on-sync-reset-unload-.patch new file mode 100644 index 0000000000..060712af24 --- /dev/null +++ b/queue-6.16/net-mlx5-fix-lockdep-assertion-on-sync-reset-unload-.patch @@ -0,0 +1,259 @@ +From 281d01b35caaf4e893362835eee2e4855dbbd0ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:29 +0300 +Subject: net/mlx5: Fix lockdep assertion on sync reset unload event + +From: Moshe Shemesh + +[ Upstream commit 902a8bc23a24882200f57cadc270e15a2cfaf2bb ] + +Fix lockdep assertion triggered during sync reset unload event. When the +sync reset flow is initiated using the devlink reload fw_activate +option, the PF already holds the devlink lock while handling unload +event. In this case, delegate sync reset unload event handling back to +the devlink callback process to avoid double-locking and resolve the +lockdep warning. + +Kernel log: +WARNING: CPU: 9 PID: 1578 at devl_assert_locked+0x31/0x40 +[...] +Call Trace: + + mlx5_unload_one_devl_locked+0x2c/0xc0 [mlx5_core] + mlx5_sync_reset_unload_event+0xaf/0x2f0 [mlx5_core] + process_one_work+0x222/0x640 + worker_thread+0x199/0x350 + kthread+0x10b/0x230 + ? __pfx_worker_thread+0x10/0x10 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x8e/0x100 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + +Fixes: 7a9770f1bfea ("net/mlx5: Handle sync reset unload event") +Signed-off-by: Moshe Shemesh +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-7-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mellanox/mlx5/core/devlink.c | 2 +- + .../ethernet/mellanox/mlx5/core/fw_reset.c | 120 ++++++++++-------- + .../ethernet/mellanox/mlx5/core/fw_reset.h | 1 + + 3 files changed, 69 insertions(+), 54 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +index 42c70862095e9..ca03dbcb07da0 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +@@ -107,7 +107,7 @@ static int mlx5_devlink_reload_fw_activate(struct devlink *devlink, struct netli + if (err) + return err; + +- mlx5_unload_one_devl_locked(dev, false); ++ mlx5_sync_reset_unload_flow(dev, true); + err = mlx5_health_wait_pci_up(dev); + if (err) + NL_SET_ERR_MSG_MOD(extack, "FW activate aborted, PCI reads fail after reset"); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index 69933addd921e..38b9b184ae01b 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -12,7 +12,8 @@ enum { + MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, + MLX5_FW_RESET_FLAGS_PENDING_COMP, + MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, +- MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED ++ MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED, ++ MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, + }; + + struct mlx5_fw_reset { +@@ -219,7 +220,7 @@ int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev) + return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL0, 0, 0, false); + } + +-static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unloaded) ++static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev) + { + struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; + struct devlink *devlink = priv_to_devlink(dev); +@@ -228,8 +229,7 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unload + if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) { + complete(&fw_reset->done); + } else { +- if (!unloaded) +- mlx5_unload_one(dev, false); ++ mlx5_sync_reset_unload_flow(dev, false); + if (mlx5_health_wait_pci_up(dev)) + mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n"); + else +@@ -272,7 +272,7 @@ static void mlx5_sync_reset_reload_work(struct work_struct *work) + + mlx5_sync_reset_clear_reset_requested(dev, false); + mlx5_enter_error_state(dev, true); +- mlx5_fw_reset_complete_reload(dev, false); ++ mlx5_fw_reset_complete_reload(dev); + } + + #define MLX5_RESET_POLL_INTERVAL (HZ / 10) +@@ -586,6 +586,65 @@ static int mlx5_sync_pci_reset(struct mlx5_core_dev *dev, u8 reset_method) + return err; + } + ++void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked) ++{ ++ struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; ++ unsigned long timeout; ++ int poll_freq = 20; ++ bool reset_action; ++ u8 rst_state; ++ int err; ++ ++ if (locked) ++ mlx5_unload_one_devl_locked(dev, false); ++ else ++ mlx5_unload_one(dev, false); ++ ++ if (!test_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags)) ++ return; ++ ++ mlx5_set_fw_rst_ack(dev); ++ mlx5_core_warn(dev, "Sync Reset Unload done, device reset expected\n"); ++ ++ reset_action = false; ++ timeout = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, RESET_UNLOAD)); ++ do { ++ rst_state = mlx5_get_fw_rst_state(dev); ++ if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ || ++ rst_state == MLX5_FW_RST_STATE_IDLE) { ++ reset_action = true; ++ break; ++ } ++ if (rst_state == MLX5_FW_RST_STATE_DROP_MODE) { ++ mlx5_core_info(dev, "Sync Reset Drop mode ack\n"); ++ mlx5_set_fw_rst_ack(dev); ++ poll_freq = 1000; ++ } ++ msleep(poll_freq); ++ } while (!time_after(jiffies, timeout)); ++ ++ if (!reset_action) { ++ mlx5_core_err(dev, "Got timeout waiting for sync reset action, state = %u\n", ++ rst_state); ++ fw_reset->ret = -ETIMEDOUT; ++ goto done; ++ } ++ ++ mlx5_core_warn(dev, "Sync Reset, got reset action. rst_state = %u\n", ++ rst_state); ++ if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ) { ++ err = mlx5_sync_pci_reset(dev, fw_reset->reset_method); ++ if (err) { ++ mlx5_core_warn(dev, "mlx5_sync_pci_reset failed, err %d\n", ++ err); ++ fw_reset->ret = err; ++ } ++ } ++ ++done: ++ clear_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags); ++} ++ + static void mlx5_sync_reset_now_event(struct work_struct *work) + { + struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, +@@ -613,17 +672,13 @@ static void mlx5_sync_reset_now_event(struct work_struct *work) + mlx5_enter_error_state(dev, true); + done: + fw_reset->ret = err; +- mlx5_fw_reset_complete_reload(dev, false); ++ mlx5_fw_reset_complete_reload(dev); + } + + static void mlx5_sync_reset_unload_event(struct work_struct *work) + { + struct mlx5_fw_reset *fw_reset; + struct mlx5_core_dev *dev; +- unsigned long timeout; +- int poll_freq = 20; +- bool reset_action; +- u8 rst_state; + int err; + + fw_reset = container_of(work, struct mlx5_fw_reset, reset_unload_work); +@@ -632,6 +687,7 @@ static void mlx5_sync_reset_unload_event(struct work_struct *work) + if (mlx5_sync_reset_clear_reset_requested(dev, false)) + return; + ++ set_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags); + mlx5_core_warn(dev, "Sync Reset Unload. Function is forced down.\n"); + + err = mlx5_cmd_fast_teardown_hca(dev); +@@ -640,49 +696,7 @@ static void mlx5_sync_reset_unload_event(struct work_struct *work) + else + mlx5_enter_error_state(dev, true); + +- if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) +- mlx5_unload_one_devl_locked(dev, false); +- else +- mlx5_unload_one(dev, false); +- +- mlx5_set_fw_rst_ack(dev); +- mlx5_core_warn(dev, "Sync Reset Unload done, device reset expected\n"); +- +- reset_action = false; +- timeout = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, RESET_UNLOAD)); +- do { +- rst_state = mlx5_get_fw_rst_state(dev); +- if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ || +- rst_state == MLX5_FW_RST_STATE_IDLE) { +- reset_action = true; +- break; +- } +- if (rst_state == MLX5_FW_RST_STATE_DROP_MODE) { +- mlx5_core_info(dev, "Sync Reset Drop mode ack\n"); +- mlx5_set_fw_rst_ack(dev); +- poll_freq = 1000; +- } +- msleep(poll_freq); +- } while (!time_after(jiffies, timeout)); +- +- if (!reset_action) { +- mlx5_core_err(dev, "Got timeout waiting for sync reset action, state = %u\n", +- rst_state); +- fw_reset->ret = -ETIMEDOUT; +- goto done; +- } +- +- mlx5_core_warn(dev, "Sync Reset, got reset action. rst_state = %u\n", rst_state); +- if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ) { +- err = mlx5_sync_pci_reset(dev, fw_reset->reset_method); +- if (err) { +- mlx5_core_warn(dev, "mlx5_sync_pci_reset failed, err %d\n", err); +- fw_reset->ret = err; +- } +- } +- +-done: +- mlx5_fw_reset_complete_reload(dev, true); ++ mlx5_fw_reset_complete_reload(dev); + } + + static void mlx5_sync_reset_abort_event(struct work_struct *work) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h +index ea527d06a85f0..d5b28525c960d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h +@@ -12,6 +12,7 @@ int mlx5_fw_reset_set_reset_sync(struct mlx5_core_dev *dev, u8 reset_type_sel, + int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev); + + int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev); ++void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked); + int mlx5_fw_reset_verify_fw_complete(struct mlx5_core_dev *dev, + struct netlink_ext_ack *extack); + void mlx5_fw_reset_events_start(struct mlx5_core_dev *dev); +-- +2.50.1 + diff --git a/queue-6.16/net-mlx5-hws-fix-memory-leak-in-hws_action_get_share.patch b/queue-6.16/net-mlx5-hws-fix-memory-leak-in-hws_action_get_share.patch new file mode 100644 index 0000000000..cb11784d86 --- /dev/null +++ b/queue-6.16/net-mlx5-hws-fix-memory-leak-in-hws_action_get_share.patch @@ -0,0 +1,43 @@ +From 33771cea1d889a84185b92f2898522d15ff9be36 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:25 +0300 +Subject: net/mlx5: HWS, Fix memory leak in hws_action_get_shared_stc_nic error + flow + +From: Lama Kayal + +[ Upstream commit a630f83592cdad1253523a1b760cfe78fef6cd9c ] + +When an invalid stc_type is provided, the function allocates memory for +shared_stc but jumps to unlock_and_out without freeing it, causing a +memory leak. + +Fix by jumping to free_shared_stc label instead to ensure proper cleanup. + +Fixes: 504e536d9010 ("net/mlx5: HWS, added actions handling") +Signed-off-by: Lama Kayal +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-3-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c +index 447ea3f8722ce..8e4a085f4a2ec 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c +@@ -117,7 +117,7 @@ static int hws_action_get_shared_stc_nic(struct mlx5hws_context *ctx, + mlx5hws_err(ctx, "No such stc_type: %d\n", stc_type); + pr_warn("HWS: Invalid stc_type: %d\n", stc_type); + ret = -EINVAL; +- goto unlock_and_out; ++ goto free_shared_stc; + } + + ret = mlx5hws_action_alloc_single_stc(ctx, &stc_attr, tbl_type, +-- +2.50.1 + diff --git a/queue-6.16/net-mlx5-hws-fix-memory-leak-in-hws_pool_buddy_init-.patch b/queue-6.16/net-mlx5-hws-fix-memory-leak-in-hws_pool_buddy_init-.patch new file mode 100644 index 0000000000..a322d239e9 --- /dev/null +++ b/queue-6.16/net-mlx5-hws-fix-memory-leak-in-hws_pool_buddy_init-.patch @@ -0,0 +1,40 @@ +From e9ade0be9921b5663a464f3185d1ead12186db04 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:24 +0300 +Subject: net/mlx5: HWS, Fix memory leak in hws_pool_buddy_init error path + +From: Lama Kayal + +[ Upstream commit 2c0a959bebdc1ada13cf9a8242f177c5400299e6 ] + +In the error path of hws_pool_buddy_init(), the buddy allocator cleanup +doesn't free the allocator structure itself, causing a memory leak. + +Add the missing kfree() to properly release all allocated memory. + +Fixes: c61afff94373 ("net/mlx5: HWS, added memory management handling") +Signed-off-by: Lama Kayal +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-2-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c +index 7e37d6e9eb836..7b5071c3df368 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c +@@ -124,6 +124,7 @@ static int hws_pool_buddy_init(struct mlx5hws_pool *pool) + mlx5hws_err(pool->ctx, "Failed to create resource type: %d size %zu\n", + pool->type, pool->alloc_log_sz); + mlx5hws_buddy_cleanup(buddy); ++ kfree(buddy); + return -ENOMEM; + } + +-- +2.50.1 + diff --git a/queue-6.16/net-mlx5-hws-fix-pattern-destruction-in-mlx5hws_pat_.patch b/queue-6.16/net-mlx5-hws-fix-pattern-destruction-in-mlx5hws_pat_.patch new file mode 100644 index 0000000000..198e850a27 --- /dev/null +++ b/queue-6.16/net-mlx5-hws-fix-pattern-destruction-in-mlx5hws_pat_.patch @@ -0,0 +1,50 @@ +From 5bab21b73b609b4281b26bfaf50c90fd54eabd62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:27 +0300 +Subject: net/mlx5: HWS, Fix pattern destruction in mlx5hws_pat_get_pattern + error path + +From: Lama Kayal + +[ Upstream commit 00a50e4e8974cbf5d6a1dc91cfa5cce4aa7af05a ] + +In mlx5hws_pat_get_pattern(), when mlx5hws_pat_add_pattern_to_cache() +fails, the function attempts to clean up the pattern created by +mlx5hws_cmd_header_modify_pattern_create(). However, it incorrectly +uses *pattern_id which hasn't been set yet, instead of the local +ptrn_id variable that contains the actual pattern ID. + +This results in attempting to destroy a pattern using uninitialized +data from the output parameter, rather than the valid pattern ID +returned by the firmware. + +Use ptrn_id instead of *pattern_id in the cleanup path to properly +destroy the created pattern. + +Fixes: aefc15a0fa1c ("net/mlx5: HWS, added modify header pattern and args handling") +Signed-off-by: Lama Kayal +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-5-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c +index 622fd579f1407..d56271a9e4f01 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c +@@ -279,7 +279,7 @@ int mlx5hws_pat_get_pattern(struct mlx5hws_context *ctx, + return ret; + + clean_pattern: +- mlx5hws_cmd_header_modify_pattern_destroy(ctx->mdev, *pattern_id); ++ mlx5hws_cmd_header_modify_pattern_destroy(ctx->mdev, ptrn_id); + out_unlock: + mutex_unlock(&ctx->pattern_cache->lock); + return ret; +-- +2.50.1 + diff --git a/queue-6.16/net-mlx5-hws-fix-uninitialized-variables-in-mlx5hws_.patch b/queue-6.16/net-mlx5-hws-fix-uninitialized-variables-in-mlx5hws_.patch new file mode 100644 index 0000000000..7388e5abbb --- /dev/null +++ b/queue-6.16/net-mlx5-hws-fix-uninitialized-variables-in-mlx5hws_.patch @@ -0,0 +1,55 @@ +From b52c3d3d4495e8a6f23fbe6aa141d7a38f758288 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:26 +0300 +Subject: net/mlx5: HWS, Fix uninitialized variables in mlx5hws_pat_calc_nop + error flow + +From: Lama Kayal + +[ Upstream commit 24b6e53140475b56cadcccd4e82a93aa5bacf1eb ] + +In mlx5hws_pat_calc_nop(), src_field and dst_field are passed to +hws_action_modify_get_target_fields() which should set their values. +However, if an invalid action type is encountered, these variables +remain uninitialized and are later used to update prev_src_field +and prev_dst_field. + +Initialize both variables to INVALID_FIELD to ensure they have +defined values in all code paths. + +Fixes: 01e035fd0380 ("net/mlx5: HWS, handle modify header actions dependency") +Signed-off-by: Lama Kayal +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-4-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c +index 51e4c551e0efd..622fd579f1407 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c +@@ -527,7 +527,6 @@ int mlx5hws_pat_calc_nop(__be64 *pattern, size_t num_actions, + u32 *nop_locations, __be64 *new_pat) + { + u16 prev_src_field = INVALID_FIELD, prev_dst_field = INVALID_FIELD; +- u16 src_field, dst_field; + u8 action_type; + bool dependent; + size_t i, j; +@@ -539,6 +538,9 @@ int mlx5hws_pat_calc_nop(__be64 *pattern, size_t num_actions, + return 0; + + for (i = 0, j = 0; i < num_actions; i++, j++) { ++ u16 src_field = INVALID_FIELD; ++ u16 dst_field = INVALID_FIELD; ++ + if (j >= max_actions) + return -EINVAL; + +-- +2.50.1 + diff --git a/queue-6.16/net-mlx5-nack-sync-reset-when-sfs-are-present.patch b/queue-6.16/net-mlx5-nack-sync-reset-when-sfs-are-present.patch new file mode 100644 index 0000000000..5b39a42468 --- /dev/null +++ b/queue-6.16/net-mlx5-nack-sync-reset-when-sfs-are-present.patch @@ -0,0 +1,100 @@ +From 05d9daaf424c0a3fd15abd814a683e4f5889a7d5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:30 +0300 +Subject: net/mlx5: Nack sync reset when SFs are present + +From: Moshe Shemesh + +[ Upstream commit 26e42ec7712d392d561964514b1f253b1a96f42d ] + +If PF (Physical Function) has SFs (Sub-Functions), since the SFs are not +taking part in the synchronization flow, sync reset can lead to fatal +error on the SFs, as the function will be closed unexpectedly from the +SF point of view. + +Add a check to prevent sync reset when there are SFs on a PF device +which is not ECPF, as ECPF is teardowned gracefully before reset. + +Fixes: 92501fa6e421 ("net/mlx5: Ack on sync_reset_request only if PF can do reset_now") +Signed-off-by: Moshe Shemesh +Reviewed-by: Parav Pandit +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-8-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 6 ++++++ + drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c | 10 ++++++++++ + drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h | 6 ++++++ + 3 files changed, 22 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index 38b9b184ae01b..22995131824a0 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -6,6 +6,7 @@ + #include "fw_reset.h" + #include "diag/fw_tracer.h" + #include "lib/tout.h" ++#include "sf/sf.h" + + enum { + MLX5_FW_RESET_FLAGS_RESET_REQUESTED, +@@ -428,6 +429,11 @@ static bool mlx5_is_reset_now_capable(struct mlx5_core_dev *dev, + return false; + } + ++ if (!mlx5_core_is_ecpf(dev) && !mlx5_sf_table_empty(dev)) { ++ mlx5_core_warn(dev, "SFs should be removed before reset\n"); ++ return false; ++ } ++ + #if IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE) + if (reset_method != MLX5_MFRL_REG_PCI_RESET_METHOD_HOT_RESET) { + err = mlx5_check_hotplug_interrupt(dev, bridge); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +index 0864ba625c07d..3304f25cc8055 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +@@ -518,3 +518,13 @@ void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev) + WARN_ON(!xa_empty(&table->function_ids)); + kfree(table); + } ++ ++bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev) ++{ ++ struct mlx5_sf_table *table = dev->priv.sf_table; ++ ++ if (!table) ++ return true; ++ ++ return xa_empty(&table->function_ids); ++} +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h +index 860f9ddb7107b..89559a37997ad 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h +@@ -17,6 +17,7 @@ void mlx5_sf_hw_table_destroy(struct mlx5_core_dev *dev); + + int mlx5_sf_table_init(struct mlx5_core_dev *dev); + void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev); ++bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev); + + int mlx5_devlink_sf_port_new(struct devlink *devlink, + const struct devlink_port_new_attrs *add_attr, +@@ -61,6 +62,11 @@ static inline void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev) + { + } + ++static inline bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev) ++{ ++ return true; ++} ++ + #endif + + #endif +-- +2.50.1 + diff --git a/queue-6.16/net-mlx5-prevent-flow-steering-mode-changes-in-switc.patch b/queue-6.16/net-mlx5-prevent-flow-steering-mode-changes-in-switc.patch new file mode 100644 index 0000000000..c274bc430e --- /dev/null +++ b/queue-6.16/net-mlx5-prevent-flow-steering-mode-changes-in-switc.patch @@ -0,0 +1,59 @@ +From d879216ed12f956d2f9bedd42664259713764d4a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:31 +0300 +Subject: net/mlx5: Prevent flow steering mode changes in switchdev mode + +From: Moshe Shemesh + +[ Upstream commit cf9a8627b9a369ba01d37be6f71b297beb688faa ] + +Changing flow steering modes is not allowed when eswitch is in switchdev +mode. This fix ensures that any steering mode change, including to +firmware steering, is correctly blocked while eswitch mode is switchdev. + +Fixes: e890acd5ff18 ("net/mlx5: Add devlink flow_steering_mode parameter") +Signed-off-by: Moshe Shemesh +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-9-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 15 +++++++-------- + 1 file changed, 7 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +index 3dd9a6f407092..29ce09af59aef 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +@@ -3706,6 +3706,13 @@ static int mlx5_fs_mode_validate(struct devlink *devlink, u32 id, + char *value = val.vstr; + u8 eswitch_mode; + ++ eswitch_mode = mlx5_eswitch_mode(dev); ++ if (eswitch_mode == MLX5_ESWITCH_OFFLOADS) { ++ NL_SET_ERR_MSG_FMT_MOD(extack, ++ "Changing fs mode is not supported when eswitch offloads enabled."); ++ return -EOPNOTSUPP; ++ } ++ + if (!strcmp(value, "dmfs")) + return 0; + +@@ -3731,14 +3738,6 @@ static int mlx5_fs_mode_validate(struct devlink *devlink, u32 id, + return -EINVAL; + } + +- eswitch_mode = mlx5_eswitch_mode(dev); +- if (eswitch_mode == MLX5_ESWITCH_OFFLOADS) { +- NL_SET_ERR_MSG_FMT_MOD(extack, +- "Moving to %s is not supported when eswitch offloads enabled.", +- value); +- return -EOPNOTSUPP; +- } +- + return 0; + } + +-- +2.50.1 + diff --git a/queue-6.16/net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch b/queue-6.16/net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch new file mode 100644 index 0000000000..489d65e2cb --- /dev/null +++ b/queue-6.16/net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch @@ -0,0 +1,51 @@ +From 310697ae325b9272c640c1a2dd619dc6f61f11ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:28 +0300 +Subject: net/mlx5: Reload auxiliary drivers on fw_activate + +From: Moshe Shemesh + +[ Upstream commit 34cc6a54914f478c93e176450fae6313404f9f74 ] + +The devlink reload fw_activate command performs firmware activation +followed by driver reload, while devlink reload driver_reinit triggers +only driver reload. However, the driver reload logic differs between the +two modes, as on driver_reinit mode mlx5 also reloads auxiliary drivers, +while in fw_activate mode the auxiliary drivers are suspended where +applicable. + +Additionally, following the cited commit, if the device has multiple PFs, +the behavior during fw_activate may vary between PFs: one PF may suspend +auxiliary drivers, while another reloads them. + +Align devlink dev reload fw_activate behavior with devlink dev reload +driver_reinit, to reload all auxiliary drivers. + +Fixes: 72ed5d5624af ("net/mlx5: Suspend auxiliary devices only in case of PCI device suspend") +Signed-off-by: Moshe Shemesh +Reviewed-by: Tariq Toukan +Reviewed-by: Akiva Goldberger +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-6-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +index 73cd746443788..42c70862095e9 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +@@ -107,7 +107,7 @@ static int mlx5_devlink_reload_fw_activate(struct devlink *devlink, struct netli + if (err) + return err; + +- mlx5_unload_one_devl_locked(dev, true); ++ mlx5_unload_one_devl_locked(dev, false); + err = mlx5_health_wait_pci_up(dev); + if (err) + NL_SET_ERR_MSG_MOD(extack, "FW activate aborted, PCI reads fail after reset"); +-- +2.50.1 + diff --git a/queue-6.16/net-mlx5e-set-local-xoff-after-fw-update.patch b/queue-6.16/net-mlx5e-set-local-xoff-after-fw-update.patch new file mode 100644 index 0000000000..04bb81ed4f --- /dev/null +++ b/queue-6.16/net-mlx5e-set-local-xoff-after-fw-update.patch @@ -0,0 +1,50 @@ +From 1a5f7b91dfb061c7f29c4ef835799f17b393c8e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:34 +0300 +Subject: net/mlx5e: Set local Xoff after FW update + +From: Alexei Lazar + +[ Upstream commit aca0c31af61e0d5cf1675a0cbd29460b95ae693c ] + +The local Xoff value is being set before the firmware (FW) update. +In case of a failure where the FW is not updated with the new value, +there is no fallback to the previous value. +Update the local Xoff value after the FW has been successfully set. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Reviewed-by: Dragos Tatulea +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-12-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +index 3efa8bf1d14ef..4720523813b97 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +@@ -575,7 +575,6 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + if (err) + return err; + } +- priv->dcbx.xoff = xoff; + + /* Apply the settings */ + if (update_buffer) { +@@ -584,6 +583,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + return err; + } + ++ priv->dcbx.xoff = xoff; ++ + if (update_prio2buffer) + err = mlx5e_port_set_priority2buffer(priv->mdev, prio2buffer); + +-- +2.50.1 + diff --git a/queue-6.16/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch b/queue-6.16/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch new file mode 100644 index 0000000000..abc4a06f64 --- /dev/null +++ b/queue-6.16/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch @@ -0,0 +1,100 @@ +From 784a79caec6b854bee33120df11512feea4c406c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:32 +0300 +Subject: net/mlx5e: Update and set Xon/Xoff upon MTU set + +From: Alexei Lazar + +[ Upstream commit ceddedc969f0532b7c62ca971ee50d519d2bc0cb ] + +Xon/Xoff sizes are derived from calculation that include the MTU size. +Set Xon/Xoff when MTU is set. +If Xon/Xoff fails, set the previous MTU. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-10-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/en/port_buffer.h | 12 ++++++++++++ + .../net/ethernet/mellanox/mlx5/core/en_main.c | 17 ++++++++++++++++- + 2 files changed, 28 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +index f4a19ffbb641c..66d276a1be836 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +@@ -66,11 +66,23 @@ struct mlx5e_port_buffer { + struct mlx5e_bufferx_reg buffer[MLX5E_MAX_NETWORK_BUFFER]; + }; + ++#ifdef CONFIG_MLX5_CORE_EN_DCB + int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + u32 change, unsigned int mtu, + struct ieee_pfc *pfc, + u32 *buffer_size, + u8 *prio2buffer); ++#else ++static inline int ++mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, ++ u32 change, unsigned int mtu, ++ void *pfc, ++ u32 *buffer_size, ++ u8 *prio2buffer) ++{ ++ return 0; ++} ++#endif + + int mlx5e_port_query_buffer(struct mlx5e_priv *priv, + struct mlx5e_port_buffer *port_buffer); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 16d818943487b..f0142d32b648f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -48,6 +48,7 @@ + #include "en.h" + #include "en/dim.h" + #include "en/txrx.h" ++#include "en/port_buffer.h" + #include "en_tc.h" + #include "en_rep.h" + #include "en_accel/ipsec.h" +@@ -2985,9 +2986,11 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) + struct mlx5e_params *params = &priv->channels.params; + struct net_device *netdev = priv->netdev; + struct mlx5_core_dev *mdev = priv->mdev; +- u16 mtu; ++ u16 mtu, prev_mtu; + int err; + ++ mlx5e_query_mtu(mdev, params, &prev_mtu); ++ + err = mlx5e_set_mtu(mdev, params, params->sw_mtu); + if (err) + return err; +@@ -2997,6 +3000,18 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) + netdev_warn(netdev, "%s: VPort MTU %d is different than netdev mtu %d\n", + __func__, mtu, params->sw_mtu); + ++ if (mtu != prev_mtu && MLX5_BUFFER_SUPPORTED(mdev)) { ++ err = mlx5e_port_manual_buffer_config(priv, 0, mtu, ++ NULL, NULL, NULL); ++ if (err) { ++ netdev_warn(netdev, "%s: Failed to set Xon/Xoff values with MTU %d (err %d), setting back to previous MTU %d\n", ++ __func__, mtu, err, prev_mtu); ++ ++ mlx5e_set_mtu(mdev, params, prev_mtu); ++ return err; ++ } ++ } ++ + params->sw_mtu = mtu; + return 0; + } +-- +2.50.1 + diff --git a/queue-6.16/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch b/queue-6.16/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch new file mode 100644 index 0000000000..195199cb7d --- /dev/null +++ b/queue-6.16/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch @@ -0,0 +1,46 @@ +From 0f30b7f9a5dfe4a88629518119b3fa45cfaaa66f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:33 +0300 +Subject: net/mlx5e: Update and set Xon/Xoff upon port speed set + +From: Alexei Lazar + +[ Upstream commit d24341740fe48add8a227a753e68b6eedf4b385a ] + +Xon/Xoff sizes are derived from calculations that include +the port speed. +These settings need to be updated and applied whenever the +port speed is changed. +The port speed is typically set after the physical link goes down +and is negotiated as part of the link-up process between the two +connected interfaces. +Xon/Xoff parameters being updated at the point where the new +negotiated speed is established. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-11-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index f0142d32b648f..e39c51cfc8e6c 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -136,6 +136,8 @@ void mlx5e_update_carrier(struct mlx5e_priv *priv) + if (up) { + netdev_info(priv->netdev, "Link up\n"); + netif_carrier_on(priv->netdev); ++ mlx5e_port_manual_buffer_config(priv, 0, priv->netdev->mtu, ++ NULL, NULL, NULL); + } else { + netdev_info(priv->netdev, "Link down\n"); + netif_carrier_off(priv->netdev); +-- +2.50.1 + diff --git a/queue-6.16/net-rose-convert-use-field-to-refcount_t.patch b/queue-6.16/net-rose-convert-use-field-to-refcount_t.patch new file mode 100644 index 0000000000..2c67cacacc --- /dev/null +++ b/queue-6.16/net-rose-convert-use-field-to-refcount_t.patch @@ -0,0 +1,370 @@ +From ef9af2c7c72b0ddc7509ef210721ac47284b540d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Aug 2025 17:58:56 +0900 +Subject: net: rose: convert 'use' field to refcount_t + +From: Takamitsu Iwai + +[ Upstream commit d860d1faa6b2ce3becfdb8b0c2b048ad31800061 ] + +The 'use' field in struct rose_neigh is used as a reference counter but +lacks atomicity. This can lead to race conditions where a rose_neigh +structure is freed while still being referenced by other code paths. + +For example, when rose_neigh->use becomes zero during an ioctl operation +via rose_rt_ioctl(), the structure may be removed while its timer is +still active, potentially causing use-after-free issues. + +This patch changes the type of 'use' from unsigned short to refcount_t and +updates all code paths to use rose_neigh_hold() and rose_neigh_put() which +operate reference counts atomically. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Takamitsu Iwai +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250823085857.47674-3-takamitz@amazon.co.jp +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/rose.h | 18 +++++++++++++----- + net/rose/af_rose.c | 13 +++++++------ + net/rose/rose_in.c | 12 ++++++------ + net/rose/rose_route.c | 33 ++++++++++++++++++--------------- + net/rose/rose_timer.c | 2 +- + 5 files changed, 45 insertions(+), 33 deletions(-) + +diff --git a/include/net/rose.h b/include/net/rose.h +index 174b4f605d849..2b5491bbf39ab 100644 +--- a/include/net/rose.h ++++ b/include/net/rose.h +@@ -8,6 +8,7 @@ + #ifndef _ROSE_H + #define _ROSE_H + ++#include + #include + #include + #include +@@ -96,7 +97,7 @@ struct rose_neigh { + ax25_cb *ax25; + struct net_device *dev; + unsigned short count; +- unsigned short use; ++ refcount_t use; + unsigned int number; + char restarted; + char dce_mode; +@@ -151,12 +152,19 @@ struct rose_sock { + + #define rose_sk(sk) ((struct rose_sock *)(sk)) + ++static inline void rose_neigh_hold(struct rose_neigh *rose_neigh) ++{ ++ refcount_inc(&rose_neigh->use); ++} ++ + static inline void rose_neigh_put(struct rose_neigh *rose_neigh) + { +- if (rose_neigh->ax25) +- ax25_cb_put(rose_neigh->ax25); +- kfree(rose_neigh->digipeat); +- kfree(rose_neigh); ++ if (refcount_dec_and_test(&rose_neigh->use)) { ++ if (rose_neigh->ax25) ++ ax25_cb_put(rose_neigh->ax25); ++ kfree(rose_neigh->digipeat); ++ kfree(rose_neigh); ++ } + } + + /* af_rose.c */ +diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c +index 4e72b636a46a5..543f9e8ebb693 100644 +--- a/net/rose/af_rose.c ++++ b/net/rose/af_rose.c +@@ -170,7 +170,7 @@ void rose_kill_by_neigh(struct rose_neigh *neigh) + + if (rose->neighbour == neigh) { + rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + rose->neighbour = NULL; + } + } +@@ -212,7 +212,7 @@ static void rose_kill_by_device(struct net_device *dev) + if (rose->device == dev) { + rose_disconnect(sk, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); + if (rose->neighbour) +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + netdev_put(rose->device, &rose->dev_tracker); + rose->device = NULL; + } +@@ -655,7 +655,7 @@ static int rose_release(struct socket *sock) + break; + + case ROSE_STATE_2: +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + release_sock(sk); + rose_disconnect(sk, 0, -1, -1); + lock_sock(sk); +@@ -823,6 +823,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + rose->lci = rose_new_lci(rose->neighbour); + if (!rose->lci) { + err = -ENETUNREACH; ++ rose_neigh_put(rose->neighbour); + goto out_release; + } + +@@ -834,12 +835,14 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + dev = rose_dev_first(); + if (!dev) { + err = -ENETUNREACH; ++ rose_neigh_put(rose->neighbour); + goto out_release; + } + + user = ax25_findbyuid(current_euid()); + if (!user) { + err = -EINVAL; ++ rose_neigh_put(rose->neighbour); + dev_put(dev); + goto out_release; + } +@@ -874,8 +877,6 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + + rose->state = ROSE_STATE_1; + +- rose->neighbour->use++; +- + rose_write_internal(sk, ROSE_CALL_REQUEST); + rose_start_heartbeat(sk); + rose_start_t1timer(sk); +@@ -1077,7 +1078,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros + GFP_ATOMIC); + make_rose->facilities = facilities; + +- make_rose->neighbour->use++; ++ rose_neigh_hold(make_rose->neighbour); + + if (rose_sk(sk)->defer) { + make_rose->state = ROSE_STATE_5; +diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c +index 4d67f36dce1b4..7caae93937ee9 100644 +--- a/net/rose/rose_in.c ++++ b/net/rose/rose_in.c +@@ -56,7 +56,7 @@ static int rose_state1_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + default: +@@ -79,12 +79,12 @@ static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + case ROSE_CLEAR_CONFIRMATION: + rose_disconnect(sk, 0, -1, -1); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + default: +@@ -120,7 +120,7 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + case ROSE_RR: +@@ -233,7 +233,7 @@ static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + default: +@@ -253,7 +253,7 @@ static int rose_state5_machine(struct sock *sk, struct sk_buff *skb, int framety + if (frametype == ROSE_CLEAR_REQUEST) { + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose_sk(sk)->neighbour->use--; ++ rose_neigh_put(rose_sk(sk)->neighbour); + } + + return 0; +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index 0c44c416f4853..8efb9033c057c 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -93,11 +93,11 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, + rose_neigh->ax25 = NULL; + rose_neigh->dev = dev; + rose_neigh->count = 0; +- rose_neigh->use = 0; + rose_neigh->dce_mode = 0; + rose_neigh->loopback = 0; + rose_neigh->number = rose_neigh_no++; + rose_neigh->restarted = 0; ++ refcount_set(&rose_neigh->use, 1); + + skb_queue_head_init(&rose_neigh->queue); + +@@ -255,10 +255,10 @@ static void rose_remove_route(struct rose_route *rose_route) + struct rose_route *s; + + if (rose_route->neigh1 != NULL) +- rose_route->neigh1->use--; ++ rose_neigh_put(rose_route->neigh1); + + if (rose_route->neigh2 != NULL) +- rose_route->neigh2->use--; ++ rose_neigh_put(rose_route->neigh2); + + if ((s = rose_route_list) == rose_route) { + rose_route_list = rose_route->next; +@@ -323,7 +323,7 @@ static int rose_del_node(struct rose_route_struct *rose_route, + if (rose_node->neighbour[i] == rose_neigh) { + rose_neigh->count--; + +- if (rose_neigh->count == 0 && rose_neigh->use == 0) { ++ if (rose_neigh->count == 0) { + rose_remove_neigh(rose_neigh); + rose_neigh_put(rose_neigh); + } +@@ -375,11 +375,11 @@ void rose_add_loopback_neigh(void) + sn->ax25 = NULL; + sn->dev = NULL; + sn->count = 0; +- sn->use = 0; + sn->dce_mode = 1; + sn->loopback = 1; + sn->number = rose_neigh_no++; + sn->restarted = 1; ++ refcount_set(&sn->use, 1); + + skb_queue_head_init(&sn->queue); + +@@ -561,8 +561,7 @@ static int rose_clear_routes(void) + s = rose_neigh; + rose_neigh = rose_neigh->next; + +- if (s->use == 0 && !s->loopback) { +- s->count = 0; ++ if (!s->loopback) { + rose_remove_neigh(s); + rose_neigh_put(s); + } +@@ -680,6 +679,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, + for (i = 0; i < node->count; i++) { + if (node->neighbour[i]->restarted) { + res = node->neighbour[i]; ++ rose_neigh_hold(node->neighbour[i]); + goto out; + } + } +@@ -691,6 +691,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, + for (i = 0; i < node->count; i++) { + if (!rose_ftimer_running(node->neighbour[i])) { + res = node->neighbour[i]; ++ rose_neigh_hold(node->neighbour[i]); + goto out; + } + failed = 1; +@@ -780,13 +781,13 @@ static void rose_del_route_by_neigh(struct rose_neigh *rose_neigh) + } + + if (rose_route->neigh1 == rose_neigh) { +- rose_route->neigh1->use--; ++ rose_neigh_put(rose_route->neigh1); + rose_route->neigh1 = NULL; + rose_transmit_clear_request(rose_route->neigh2, rose_route->lci2, ROSE_OUT_OF_ORDER, 0); + } + + if (rose_route->neigh2 == rose_neigh) { +- rose_route->neigh2->use--; ++ rose_neigh_put(rose_route->neigh2); + rose_route->neigh2 = NULL; + rose_transmit_clear_request(rose_route->neigh1, rose_route->lci1, ROSE_OUT_OF_ORDER, 0); + } +@@ -915,7 +916,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + rose_clear_queues(sk); + rose->cause = ROSE_NETWORK_CONGESTION; + rose->diagnostic = 0; +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + rose->neighbour = NULL; + rose->lci = 0; + rose->state = ROSE_STATE_0; +@@ -1040,12 +1041,12 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + + if ((new_lci = rose_new_lci(new_neigh)) == 0) { + rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 71); +- goto out; ++ goto put_neigh; + } + + if ((rose_route = kmalloc(sizeof(*rose_route), GFP_ATOMIC)) == NULL) { + rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 120); +- goto out; ++ goto put_neigh; + } + + rose_route->lci1 = lci; +@@ -1058,8 +1059,8 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + rose_route->lci2 = new_lci; + rose_route->neigh2 = new_neigh; + +- rose_route->neigh1->use++; +- rose_route->neigh2->use++; ++ rose_neigh_hold(rose_route->neigh1); ++ rose_neigh_hold(rose_route->neigh2); + + rose_route->next = rose_route_list; + rose_route_list = rose_route; +@@ -1071,6 +1072,8 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + rose_transmit_link(skb, rose_route->neigh2); + res = 1; + ++put_neigh: ++ rose_neigh_put(new_neigh); + out: + spin_unlock_bh(&rose_route_list_lock); + spin_unlock_bh(&rose_neigh_list_lock); +@@ -1186,7 +1189,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v) + (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign), + rose_neigh->dev ? rose_neigh->dev->name : "???", + rose_neigh->count, +- rose_neigh->use, ++ refcount_read(&rose_neigh->use) - 1, + (rose_neigh->dce_mode) ? "DCE" : "DTE", + (rose_neigh->restarted) ? "yes" : "no", + ax25_display_timer(&rose_neigh->t0timer) / HZ, +diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c +index 020369c49587f..bb60a1654d612 100644 +--- a/net/rose/rose_timer.c ++++ b/net/rose/rose_timer.c +@@ -180,7 +180,7 @@ static void rose_timer_expiry(struct timer_list *t) + break; + + case ROSE_STATE_2: /* T3 */ +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + rose_disconnect(sk, ETIMEDOUT, -1, -1); + break; + +-- +2.50.1 + diff --git a/queue-6.16/net-rose-include-node-references-in-rose_neigh-refco.patch b/queue-6.16/net-rose-include-node-references-in-rose_neigh-refco.patch new file mode 100644 index 0000000000..e4eb8d23ee --- /dev/null +++ b/queue-6.16/net-rose-include-node-references-in-rose_neigh-refco.patch @@ -0,0 +1,142 @@ +From ca4b6653dbe36488e0e6e4174ff6c19817d58eb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Aug 2025 17:58:57 +0900 +Subject: net: rose: include node references in rose_neigh refcount + +From: Takamitsu Iwai + +[ Upstream commit da9c9c877597170b929a6121a68dcd3dd9a80f45 ] + +Current implementation maintains two separate reference counting +mechanisms: the 'count' field in struct rose_neigh tracks references from +rose_node structures, while the 'use' field (now refcount_t) tracks +references from rose_sock. + +This patch merges these two reference counting systems using 'use' field +for proper reference management. Specifically, this patch adds incrementing +and decrementing of rose_neigh->use when rose_neigh->count is incremented +or decremented. + +This patch also modifies rose_rt_free(), rose_rt_device_down() and +rose_clear_route() to properly release references to rose_neigh objects +before freeing a rose_node through rose_remove_node(). + +These changes ensure rose_neigh structures are properly freed only when +all references, including those from rose_node structures, are released. +As a result, this resolves a slab-use-after-free issue reported by Syzbot. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+942297eecf7d2d61d1f1@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=942297eecf7d2d61d1f1 +Signed-off-by: Takamitsu Iwai +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250823085857.47674-4-takamitz@amazon.co.jp +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/rose/rose_route.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index 8efb9033c057c..1adee1fbc2ed1 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -178,6 +178,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, + } + } + rose_neigh->count++; ++ rose_neigh_hold(rose_neigh); + + goto out; + } +@@ -187,6 +188,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, + rose_node->neighbour[rose_node->count] = rose_neigh; + rose_node->count++; + rose_neigh->count++; ++ rose_neigh_hold(rose_neigh); + } + + out: +@@ -322,6 +324,7 @@ static int rose_del_node(struct rose_route_struct *rose_route, + for (i = 0; i < rose_node->count; i++) { + if (rose_node->neighbour[i] == rose_neigh) { + rose_neigh->count--; ++ rose_neigh_put(rose_neigh); + + if (rose_neigh->count == 0) { + rose_remove_neigh(rose_neigh); +@@ -430,6 +433,7 @@ int rose_add_loopback_node(const rose_address *address) + rose_node_list = rose_node; + + rose_loopback_neigh->count++; ++ rose_neigh_hold(rose_loopback_neigh); + + out: + spin_unlock_bh(&rose_node_list_lock); +@@ -461,6 +465,7 @@ void rose_del_loopback_node(const rose_address *address) + rose_remove_node(rose_node); + + rose_loopback_neigh->count--; ++ rose_neigh_put(rose_loopback_neigh); + + out: + spin_unlock_bh(&rose_node_list_lock); +@@ -500,6 +505,7 @@ void rose_rt_device_down(struct net_device *dev) + memmove(&t->neighbour[i], &t->neighbour[i + 1], + sizeof(t->neighbour[0]) * + (t->count - i)); ++ rose_neigh_put(s); + } + + if (t->count <= 0) +@@ -543,6 +549,7 @@ static int rose_clear_routes(void) + { + struct rose_neigh *s, *rose_neigh; + struct rose_node *t, *rose_node; ++ int i; + + spin_lock_bh(&rose_node_list_lock); + spin_lock_bh(&rose_neigh_list_lock); +@@ -553,8 +560,12 @@ static int rose_clear_routes(void) + while (rose_node != NULL) { + t = rose_node; + rose_node = rose_node->next; +- if (!t->loopback) ++ ++ if (!t->loopback) { ++ for (i = 0; i < rose_node->count; i++) ++ rose_neigh_put(t->neighbour[i]); + rose_remove_node(t); ++ } + } + + while (rose_neigh != NULL) { +@@ -1189,7 +1200,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v) + (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign), + rose_neigh->dev ? rose_neigh->dev->name : "???", + rose_neigh->count, +- refcount_read(&rose_neigh->use) - 1, ++ refcount_read(&rose_neigh->use) - rose_neigh->count - 1, + (rose_neigh->dce_mode) ? "DCE" : "DTE", + (rose_neigh->restarted) ? "yes" : "no", + ax25_display_timer(&rose_neigh->t0timer) / HZ, +@@ -1294,6 +1305,7 @@ void __exit rose_rt_free(void) + struct rose_neigh *s, *rose_neigh = rose_neigh_list; + struct rose_node *t, *rose_node = rose_node_list; + struct rose_route *u, *rose_route = rose_route_list; ++ int i; + + while (rose_neigh != NULL) { + s = rose_neigh; +@@ -1307,6 +1319,8 @@ void __exit rose_rt_free(void) + t = rose_node; + rose_node = rose_node->next; + ++ for (i = 0; i < t->count; i++) ++ rose_neigh_put(t->neighbour[i]); + rose_remove_node(t); + } + +-- +2.50.1 + diff --git a/queue-6.16/net-rose-split-remove-and-free-operations-in-rose_re.patch b/queue-6.16/net-rose-split-remove-and-free-operations-in-rose_re.patch new file mode 100644 index 0000000000..ec2df9fc02 --- /dev/null +++ b/queue-6.16/net-rose-split-remove-and-free-operations-in-rose_re.patch @@ -0,0 +1,115 @@ +From 4487615c0f452d270b59460ed8ef914d2d8e035b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Aug 2025 17:58:55 +0900 +Subject: net: rose: split remove and free operations in rose_remove_neigh() + +From: Takamitsu Iwai + +[ Upstream commit dcb34659028f856c423a29ef9b4e2571d203444d ] + +The current rose_remove_neigh() performs two distinct operations: +1. Removes rose_neigh from rose_neigh_list +2. Frees the rose_neigh structure + +Split these operations into separate functions to improve maintainability +and prepare for upcoming refcount_t conversion. The timer cleanup remains +in rose_remove_neigh() because free operations can be called from timer +itself. + +This patch introduce rose_neigh_put() to handle the freeing of rose_neigh +structures and modify rose_remove_neigh() to handle removal only. + +Signed-off-by: Takamitsu Iwai +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250823085857.47674-2-takamitz@amazon.co.jp +Signed-off-by: Jakub Kicinski +Stable-dep-of: d860d1faa6b2 ("net: rose: convert 'use' field to refcount_t") +Signed-off-by: Sasha Levin +--- + include/net/rose.h | 8 ++++++++ + net/rose/rose_route.c | 15 ++++++--------- + 2 files changed, 14 insertions(+), 9 deletions(-) + +diff --git a/include/net/rose.h b/include/net/rose.h +index 23267b4efcfa3..174b4f605d849 100644 +--- a/include/net/rose.h ++++ b/include/net/rose.h +@@ -151,6 +151,14 @@ struct rose_sock { + + #define rose_sk(sk) ((struct rose_sock *)(sk)) + ++static inline void rose_neigh_put(struct rose_neigh *rose_neigh) ++{ ++ if (rose_neigh->ax25) ++ ax25_cb_put(rose_neigh->ax25); ++ kfree(rose_neigh->digipeat); ++ kfree(rose_neigh); ++} ++ + /* af_rose.c */ + extern ax25_address rose_callsign; + extern int sysctl_rose_restart_request_timeout; +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index b72bf8a08d489..0c44c416f4853 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -234,20 +234,12 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) + + if ((s = rose_neigh_list) == rose_neigh) { + rose_neigh_list = rose_neigh->next; +- if (rose_neigh->ax25) +- ax25_cb_put(rose_neigh->ax25); +- kfree(rose_neigh->digipeat); +- kfree(rose_neigh); + return; + } + + while (s != NULL && s->next != NULL) { + if (s->next == rose_neigh) { + s->next = rose_neigh->next; +- if (rose_neigh->ax25) +- ax25_cb_put(rose_neigh->ax25); +- kfree(rose_neigh->digipeat); +- kfree(rose_neigh); + return; + } + +@@ -331,8 +323,10 @@ static int rose_del_node(struct rose_route_struct *rose_route, + if (rose_node->neighbour[i] == rose_neigh) { + rose_neigh->count--; + +- if (rose_neigh->count == 0 && rose_neigh->use == 0) ++ if (rose_neigh->count == 0 && rose_neigh->use == 0) { + rose_remove_neigh(rose_neigh); ++ rose_neigh_put(rose_neigh); ++ } + + rose_node->count--; + +@@ -513,6 +507,7 @@ void rose_rt_device_down(struct net_device *dev) + } + + rose_remove_neigh(s); ++ rose_neigh_put(s); + } + spin_unlock_bh(&rose_neigh_list_lock); + spin_unlock_bh(&rose_node_list_lock); +@@ -569,6 +564,7 @@ static int rose_clear_routes(void) + if (s->use == 0 && !s->loopback) { + s->count = 0; + rose_remove_neigh(s); ++ rose_neigh_put(s); + } + } + +@@ -1301,6 +1297,7 @@ void __exit rose_rt_free(void) + rose_neigh = rose_neigh->next; + + rose_remove_neigh(s); ++ rose_neigh_put(s); + } + + while (rose_node != NULL) { +-- +2.50.1 + diff --git a/queue-6.16/net-stmmac-set-cic-bit-only-for-tx-queues-with-coe.patch b/queue-6.16/net-stmmac-set-cic-bit-only-for-tx-queues-with-coe.patch new file mode 100644 index 0000000000..0efaaf0f96 --- /dev/null +++ b/queue-6.16/net-stmmac-set-cic-bit-only-for-tx-queues-with-coe.patch @@ -0,0 +1,68 @@ +From 8aaa1bd4504f820f97e1827466d72d86c2058d4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 12:36:54 +0800 +Subject: net: stmmac: Set CIC bit only for TX queues with COE + +From: Rohan G Thomas + +[ Upstream commit b1eded580ab28119de0b0f21efe37ee2b4419144 ] + +Currently, in the AF_XDP transmit paths, the CIC bit of +TX Desc3 is set for all packets. Setting this bit for +packets transmitting through queues that don't support +checksum offloading causes the TX DMA to get stuck after +transmitting some packets. This patch ensures the CIC bit +of TX Desc3 is set only if the TX queue supports checksum +offloading. + +Fixes: 132c32ee5bc0 ("net: stmmac: Add TX via XDP zero-copy socket") +Signed-off-by: Rohan G Thomas +Reviewed-by: Matthew Gerlach +Link: https://patch.msgid.link/20250825-xgmac-minor-fixes-v3-3-c225fe4444c0@altera.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index e0fb06af1f940..36082d4917bcc 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -2584,6 +2584,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) + struct netdev_queue *nq = netdev_get_tx_queue(priv->dev, queue); + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; + struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[queue]; ++ bool csum = !priv->plat->tx_queues_cfg[queue].coe_unsupported; + struct xsk_buff_pool *pool = tx_q->xsk_pool; + unsigned int entry = tx_q->cur_tx; + struct dma_desc *tx_desc = NULL; +@@ -2671,7 +2672,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) + } + + stmmac_prepare_tx_desc(priv, tx_desc, 1, xdp_desc.len, +- true, priv->mode, true, true, ++ csum, priv->mode, true, true, + xdp_desc.len); + + stmmac_enable_dma_transmission(priv, priv->ioaddr, queue); +@@ -4983,6 +4984,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue, + { + struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[queue]; + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; ++ bool csum = !priv->plat->tx_queues_cfg[queue].coe_unsupported; + unsigned int entry = tx_q->cur_tx; + struct dma_desc *tx_desc; + dma_addr_t dma_addr; +@@ -5034,7 +5036,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue, + stmmac_set_desc_addr(priv, tx_desc, dma_addr); + + stmmac_prepare_tx_desc(priv, tx_desc, 1, xdpf->len, +- true, priv->mode, true, true, ++ csum, priv->mode, true, true, + xdpf->len); + + tx_q->tx_count_frames++; +-- +2.50.1 + diff --git a/queue-6.16/net-stmmac-xgmac-correct-supported-speed-modes.patch b/queue-6.16/net-stmmac-xgmac-correct-supported-speed-modes.patch new file mode 100644 index 0000000000..12c73bd06b --- /dev/null +++ b/queue-6.16/net-stmmac-xgmac-correct-supported-speed-modes.patch @@ -0,0 +1,96 @@ +From 1c085336f1ad4c97ae5197d3a69c46fd521df342 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 12:36:53 +0800 +Subject: net: stmmac: xgmac: Correct supported speed modes + +From: Rohan G Thomas + +[ Upstream commit 42ef11b2bff5b6a2910c28d2ea47cc00e0fbcaec ] + +Correct supported speed modes as per the XGMAC databook. +Commit 9cb54af214a7 ("net: stmmac: Fix IP-cores specific +MAC capabilities") removes support for 10M, 100M and +1000HD. 1000HD is not supported by XGMAC IP, but it does +support 10M and 100M FD mode for XGMAC version >= 2_20, +and it also supports 10M and 100M HD mode if the HDSEL bit +is set in the MAC_HW_FEATURE0 reg. This commit enables support +for 10M and 100M speed modes for XGMAC IP based on XGMAC +version and MAC capabilities. + +Fixes: 9cb54af214a7 ("net: stmmac: Fix IP-cores specific MAC capabilities") +Signed-off-by: Rohan G Thomas +Reviewed-by: Matthew Gerlach +Link: https://patch.msgid.link/20250825-xgmac-minor-fixes-v3-2-c225fe4444c0@altera.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 13 +++++++++++-- + drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 5 +++++ + 2 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +index 6cadf8de4fdfd..00e929bf280ba 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +@@ -49,6 +49,14 @@ static void dwxgmac2_core_init(struct mac_device_info *hw, + writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN); + } + ++static void dwxgmac2_update_caps(struct stmmac_priv *priv) ++{ ++ if (!priv->dma_cap.mbps_10_100) ++ priv->hw->link.caps &= ~(MAC_10 | MAC_100); ++ else if (!priv->dma_cap.half_duplex) ++ priv->hw->link.caps &= ~(MAC_10HD | MAC_100HD); ++} ++ + static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable) + { + u32 tx = readl(ioaddr + XGMAC_TX_CONFIG); +@@ -1424,6 +1432,7 @@ static void dwxgmac2_set_arp_offload(struct mac_device_info *hw, bool en, + + const struct stmmac_ops dwxgmac210_ops = { + .core_init = dwxgmac2_core_init, ++ .update_caps = dwxgmac2_update_caps, + .set_mac = dwxgmac2_set_mac, + .rx_ipc = dwxgmac2_rx_ipc, + .rx_queue_enable = dwxgmac2_rx_queue_enable, +@@ -1532,8 +1541,8 @@ int dwxgmac2_setup(struct stmmac_priv *priv) + mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); + + mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | +- MAC_1000FD | MAC_2500FD | MAC_5000FD | +- MAC_10000FD; ++ MAC_10 | MAC_100 | MAC_1000FD | ++ MAC_2500FD | MAC_5000FD | MAC_10000FD; + mac->link.duplex = 0; + mac->link.speed10 = XGMAC_CONFIG_SS_10_MII; + mac->link.speed100 = XGMAC_CONFIG_SS_100_MII; +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +index 7201a38842651..4d6bb995d8d84 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +@@ -382,8 +382,11 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, + static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, + struct dma_features *dma_cap) + { ++ struct stmmac_priv *priv; + u32 hw_cap; + ++ priv = container_of(dma_cap, struct stmmac_priv, dma_cap); ++ + /* MAC HW feature 0 */ + hw_cap = readl(ioaddr + XGMAC_HW_FEATURE0); + dma_cap->edma = (hw_cap & XGMAC_HWFEAT_EDMA) >> 31; +@@ -406,6 +409,8 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, + dma_cap->vlhash = (hw_cap & XGMAC_HWFEAT_VLHASH) >> 4; + dma_cap->half_duplex = (hw_cap & XGMAC_HWFEAT_HDSEL) >> 3; + dma_cap->mbps_1000 = (hw_cap & XGMAC_HWFEAT_GMIISEL) >> 1; ++ if (dma_cap->mbps_1000 && priv->synopsys_id >= DWXGMAC_CORE_2_20) ++ dma_cap->mbps_10_100 = 1; + + /* MAC HW feature 1 */ + hw_cap = readl(ioaddr + XGMAC_HW_FEATURE1); +-- +2.50.1 + diff --git a/queue-6.16/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch b/queue-6.16/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch new file mode 100644 index 0000000000..c53ebae104 --- /dev/null +++ b/queue-6.16/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch @@ -0,0 +1,49 @@ +From 0c55c97c9343a3b833ffa81a41a8b8d39183281e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 12:36:52 +0800 +Subject: net: stmmac: xgmac: Do not enable RX FIFO Overflow interrupts + +From: Rohan G Thomas + +[ Upstream commit 4f23382841e67174211271a454811dd17c0ef3c5 ] + +Enabling RX FIFO Overflow interrupts is counterproductive +and causes an interrupt storm when RX FIFO overflows. +Disabling this interrupt has no side effect and eliminates +interrupt storms when the RX FIFO overflows. + +Commit 8a7cb245cf28 ("net: stmmac: Do not enable RX FIFO +overflow interrupts") disables RX FIFO overflow interrupts +for DWMAC4 IP and removes the corresponding handling of +this interrupt. This patch is doing the same thing for +XGMAC IP. + +Fixes: 2142754f8b9c ("net: stmmac: Add MAC related callbacks for XGMAC2") +Signed-off-by: Rohan G Thomas +Reviewed-by: Matthew Gerlach +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250825-xgmac-minor-fixes-v3-1-c225fe4444c0@altera.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +index 5dcc95bc0ad28..7201a38842651 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +@@ -203,10 +203,6 @@ static void dwxgmac2_dma_rx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, + } + + writel(value, ioaddr + XGMAC_MTL_RXQ_OPMODE(channel)); +- +- /* Enable MTL RX overflow */ +- value = readl(ioaddr + XGMAC_MTL_QINTEN(channel)); +- writel(value | XGMAC_RXOIE, ioaddr + XGMAC_MTL_QINTEN(channel)); + } + + static void dwxgmac2_dma_tx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, +-- +2.50.1 + diff --git a/queue-6.16/octeontx2-af-fix-nix-x2p-calibration-failures.patch b/queue-6.16/octeontx2-af-fix-nix-x2p-calibration-failures.patch new file mode 100644 index 0000000000..9c153971a6 --- /dev/null +++ b/queue-6.16/octeontx2-af-fix-nix-x2p-calibration-failures.patch @@ -0,0 +1,79 @@ +From ed23e35ef99918fd70b98941eaf46976dd02648e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Aug 2025 16:28:05 +0530 +Subject: Octeontx2-af: Fix NIX X2P calibration failures + +From: Hariprasad Kelam + +[ Upstream commit d280233fc86692f495d5e08092e5422bc2f583a8 ] + +Before configuring the NIX block, the AF driver initiates the +"NIX block X2P bus calibration" and verifies that NIX interfaces +such as CGX and LBK are active and functioning correctly. + +On few silicon variants(CNF10KA and CNF10KB), X2P calibration failures +have been observed on some CGX blocks that are not mapped to the NIX block. + +Since both NIX-mapped and non-NIX-mapped CGX blocks share the same +VENDOR,DEVICE,SUBSYS_DEVID, it's not possible to skip probe based on +these parameters. + +This patch introuduces "is_cgx_mapped_to_nix" API to detect and skip +probe of non NIX mapped CGX blocks. + +Fixes: aba53d5dbcea ("octeontx2-af: NIX block admin queue init") +Signed-off-by: Hariprasad Kelam +Link: https://patch.msgid.link/20250822105805.2236528-1-hkelam@marvell.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 7 +++++++ + drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 14 ++++++++++++++ + 2 files changed, 21 insertions(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +index 971993586fb49..442305463cc0a 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +@@ -1940,6 +1940,13 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id) + goto err_release_regions; + } + ++ if (!is_cn20k(pdev) && ++ !is_cgx_mapped_to_nix(pdev->subsystem_device, cgx->cgx_id)) { ++ dev_notice(dev, "CGX %d not mapped to NIX, skipping probe\n", ++ cgx->cgx_id); ++ goto err_release_regions; ++ } ++ + cgx->lmac_count = cgx->mac_ops->get_nr_lmacs(cgx); + if (!cgx->lmac_count) { + dev_notice(dev, "CGX %d LMAC count is zero, skipping probe\n", cgx->cgx_id); +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +index 5c179df1f1673..9cdb7431f558c 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +@@ -761,6 +761,20 @@ static inline bool is_cn10kb(struct rvu *rvu) + return false; + } + ++static inline bool is_cgx_mapped_to_nix(unsigned short id, u8 cgx_id) ++{ ++ /* On CNF10KA and CNF10KB silicons only two CGX blocks are connected ++ * to NIX. ++ */ ++ if (id == PCI_SUBSYS_DEVID_CNF10K_A || id == PCI_SUBSYS_DEVID_CNF10K_B) ++ return cgx_id <= 1; ++ ++ return !(cgx_id && !(id == PCI_SUBSYS_DEVID_96XX || ++ id == PCI_SUBSYS_DEVID_98XX || ++ id == PCI_SUBSYS_DEVID_CN10K_A || ++ id == PCI_SUBSYS_DEVID_CN10K_B)); ++} ++ + static inline bool is_rvu_npc_hash_extract_en(struct rvu *rvu) + { + u64 npc_const3; +-- +2.50.1 + diff --git a/queue-6.16/octeontx2-set-appropriate-pf-vf-masks-and-shifts-bas.patch b/queue-6.16/octeontx2-set-appropriate-pf-vf-masks-and-shifts-bas.patch new file mode 100644 index 0000000000..5c42d5fd5d --- /dev/null +++ b/queue-6.16/octeontx2-set-appropriate-pf-vf-masks-and-shifts-bas.patch @@ -0,0 +1,1597 @@ +From 57543e65e58d97f5b4ab29823a0643b02c1f3ac4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Jun 2025 16:31:51 +0530 +Subject: octeontx2: Set appropriate PF, VF masks and shifts based on silicon + +From: Subbaraya Sundeep + +[ Upstream commit 25d51ebf0f54f9c2424f28bb29125cf24f120df0 ] + +Number of RVU PFs on CN20K silicon have increased to 96 from maximum +of 32 that were supported on earlier silicons. Every RVU PF and VF is +identified by HW using a 16bit PF_FUNC value. Due to the change in +Max number of PFs in CN20K, the bit encoding of this PF_FUNC has changed. + +This patch handles the change by using helper functions(using silicon +check) to use PF,VF masks and shifts to support both new silicon CN20K, +OcteonTx series. These helper functions are used in different modules. + +Also moved the NIX AF register offset macros to other files which +will be posted in coming patches. + +Signed-off-by: Subbaraya Sundeep +Signed-off-by: Sai Krishna +Signed-off-by: Sunil Kovvuri Goutham +Link: https://patch.msgid.link/1749639716-13868-2-git-send-email-sbhatta@marvell.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: d280233fc866 ("Octeontx2-af: Fix NIX X2P calibration failures") +Signed-off-by: Sasha Levin +--- + .../marvell/octeontx2/otx2_cpt_common.h | 5 +- + .../marvell/octeontx2/otx2_cptpf_mbox.c | 13 ++-- + .../marvell/octeontx2/otx2_cptpf_ucode.c | 4 +- + .../marvell/octeontx2/otx2_cptvf_mbox.c | 6 +- + .../marvell/octeontx2/af/mcs_rvu_if.c | 6 +- + .../net/ethernet/marvell/octeontx2/af/rvu.c | 30 ++++---- + .../net/ethernet/marvell/octeontx2/af/rvu.h | 52 +++++++++++--- + .../ethernet/marvell/octeontx2/af/rvu_cgx.c | 68 +++++++++---------- + .../ethernet/marvell/octeontx2/af/rvu_cn10k.c | 4 +- + .../ethernet/marvell/octeontx2/af/rvu_cpt.c | 4 +- + .../marvell/octeontx2/af/rvu_debugfs.c | 22 +++--- + .../ethernet/marvell/octeontx2/af/rvu_nix.c | 54 ++++++++------- + .../ethernet/marvell/octeontx2/af/rvu_npc.c | 8 ++- + .../marvell/octeontx2/af/rvu_npc_hash.c | 16 ++--- + .../marvell/octeontx2/af/rvu_npc_hash.h | 4 +- + .../ethernet/marvell/octeontx2/af/rvu_rep.c | 13 ++-- + .../ethernet/marvell/octeontx2/af/rvu_sdp.c | 10 +-- + .../marvell/octeontx2/af/rvu_switch.c | 8 +-- + .../marvell/octeontx2/nic/cn10k_ipsec.c | 2 +- + .../marvell/octeontx2/nic/cn10k_ipsec.h | 2 +- + .../marvell/octeontx2/nic/otx2_common.h | 11 +-- + .../ethernet/marvell/octeontx2/nic/otx2_pf.c | 21 +++--- + .../ethernet/marvell/octeontx2/nic/otx2_reg.h | 30 -------- + .../ethernet/marvell/octeontx2/nic/otx2_tc.c | 3 +- + .../net/ethernet/marvell/octeontx2/nic/rep.c | 7 +- + include/linux/soc/marvell/silicons.h | 25 +++++++ + 26 files changed, 225 insertions(+), 203 deletions(-) + create mode 100644 include/linux/soc/marvell/silicons.h + +diff --git a/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h b/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h +index d529bcb03775f..062def303dcea 100644 +--- a/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h ++++ b/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h +@@ -18,9 +18,8 @@ + #define OTX2_CPT_MAX_VFS_NUM 128 + #define OTX2_CPT_RVU_FUNC_ADDR_S(blk, slot, offs) \ + (((blk) << 20) | ((slot) << 12) | (offs)) +-#define OTX2_CPT_RVU_PFFUNC(pf, func) \ +- ((((pf) & RVU_PFVF_PF_MASK) << RVU_PFVF_PF_SHIFT) | \ +- (((func) & RVU_PFVF_FUNC_MASK) << RVU_PFVF_FUNC_SHIFT)) ++ ++#define OTX2_CPT_RVU_PFFUNC(pdev, pf, func) rvu_make_pcifunc(pdev, pf, func) + + #define OTX2_CPT_INVALID_CRYPTO_ENG_GRP 0xFF + #define OTX2_CPT_NAME_LENGTH 64 +diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c +index 12c0e966fa65f..b4b2d3d1cbc2a 100644 +--- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c ++++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c +@@ -142,7 +142,7 @@ static int send_inline_ipsec_inbound_msg(struct otx2_cptpf_dev *cptpf, + memset(req, 0, sizeof(*req)); + req->hdr.id = MBOX_MSG_CPT_INLINE_IPSEC_CFG; + req->hdr.sig = OTX2_MBOX_REQ_SIG; +- req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0); ++ req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptpf->pdev, cptpf->pf_id, 0); + req->dir = CPT_INLINE_INBOUND; + req->slot = slot; + req->sso_pf_func_ovrd = cptpf->sso_pf_func_ovrd; +@@ -184,7 +184,8 @@ static int rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf, u8 egrp, + nix_req->gen_cfg.opcode = cpt_inline_rx_opcode(pdev); + nix_req->gen_cfg.param1 = req->param1; + nix_req->gen_cfg.param2 = req->param2; +- nix_req->inst_qsel.cpt_pf_func = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0); ++ nix_req->inst_qsel.cpt_pf_func = ++ OTX2_CPT_RVU_PFFUNC(cptpf->pdev, cptpf->pf_id, 0); + nix_req->inst_qsel.cpt_slot = 0; + ret = otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev); + if (ret) +@@ -392,9 +393,8 @@ void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work) + msg = (struct mbox_msghdr *)(mdev->mbase + offset); + + /* Set which VF sent this message based on mbox IRQ */ +- msg->pcifunc = ((u16)cptpf->pf_id << RVU_PFVF_PF_SHIFT) | +- ((vf->vf_id + 1) & RVU_PFVF_FUNC_MASK); +- ++ msg->pcifunc = rvu_make_pcifunc(cptpf->pdev, cptpf->pf_id, ++ (vf->vf_id + 1)); + err = cptpf_handle_vf_req(cptpf, vf, msg, + msg->next_msgoff - offset); + /* +@@ -469,8 +469,7 @@ static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf, + + switch (msg->id) { + case MBOX_MSG_READY: +- cptpf->pf_id = (msg->pcifunc >> RVU_PFVF_PF_SHIFT) & +- RVU_PFVF_PF_MASK; ++ cptpf->pf_id = rvu_get_pf(cptpf->pdev, msg->pcifunc); + break; + case MBOX_MSG_MSIX_OFFSET: + rsp_msix = (struct msix_offset_rsp *) msg; +diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c +index 56645b3eb7175..cc47e361089a0 100644 +--- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c ++++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c +@@ -176,7 +176,9 @@ static int cptx_set_ucode_base(struct otx2_cpt_eng_grp_info *eng_grp, + /* Set PF number for microcode fetches */ + ret = otx2_cpt_write_af_reg(&cptpf->afpf_mbox, cptpf->pdev, + CPT_AF_PF_FUNC, +- cptpf->pf_id << RVU_PFVF_PF_SHIFT, blkaddr); ++ rvu_make_pcifunc(cptpf->pdev, ++ cptpf->pf_id, 0), ++ blkaddr); + if (ret) + return ret; + +diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_mbox.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_mbox.c +index 931b72580fd9f..92e49babd79af 100644 +--- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_mbox.c ++++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_mbox.c +@@ -189,7 +189,7 @@ int otx2_cptvf_send_eng_grp_num_msg(struct otx2_cptvf_dev *cptvf, int eng_type) + } + req->hdr.id = MBOX_MSG_GET_ENG_GRP_NUM; + req->hdr.sig = OTX2_MBOX_REQ_SIG; +- req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->vf_id, 0); ++ req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->pdev, cptvf->vf_id, 0); + req->eng_type = eng_type; + + return otx2_cpt_send_mbox_msg(mbox, pdev); +@@ -210,7 +210,7 @@ int otx2_cptvf_send_kvf_limits_msg(struct otx2_cptvf_dev *cptvf) + } + req->id = MBOX_MSG_GET_KVF_LIMITS; + req->sig = OTX2_MBOX_REQ_SIG; +- req->pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->vf_id, 0); ++ req->pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->pdev, cptvf->vf_id, 0); + + return otx2_cpt_send_mbox_msg(mbox, pdev); + } +@@ -230,7 +230,7 @@ int otx2_cptvf_send_caps_msg(struct otx2_cptvf_dev *cptvf) + } + req->id = MBOX_MSG_GET_CAPS; + req->sig = OTX2_MBOX_REQ_SIG; +- req->pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->vf_id, 0); ++ req->pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->pdev, cptvf->vf_id, 0); + + return otx2_cpt_send_mbox_msg(mbox, pdev); + } +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c b/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c +index 0277d226293e9..d7030dfa5dad2 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c +@@ -97,7 +97,7 @@ int mcs_add_intr_wq_entry(struct mcs *mcs, struct mcs_intr_event *event) + if (pcifunc & RVU_PFVF_FUNC_MASK) + pfvf = &mcs->vf[rvu_get_hwvf(rvu, pcifunc)]; + else +- pfvf = &mcs->pf[rvu_get_pf(pcifunc)]; ++ pfvf = &mcs->pf[rvu_get_pf(rvu->pdev, pcifunc)]; + + event->intr_mask &= pfvf->intr_mask; + +@@ -123,7 +123,7 @@ static int mcs_notify_pfvf(struct mcs_intr_event *event, struct rvu *rvu) + struct mcs_intr_info *req; + int pf; + +- pf = rvu_get_pf(event->pcifunc); ++ pf = rvu_get_pf(rvu->pdev, event->pcifunc); + + mutex_lock(&rvu->mbox_lock); + +@@ -193,7 +193,7 @@ int rvu_mbox_handler_mcs_intr_cfg(struct rvu *rvu, + if (pcifunc & RVU_PFVF_FUNC_MASK) + pfvf = &mcs->vf[rvu_get_hwvf(rvu, pcifunc)]; + else +- pfvf = &mcs->pf[rvu_get_pf(pcifunc)]; ++ pfvf = &mcs->pf[rvu_get_pf(rvu->pdev, pcifunc)]; + + mcs->pf_map[0] = pcifunc; + pfvf->intr_mask = req->intr_mask; +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +index a8025f0486c9f..39f664d60ecff 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +@@ -294,7 +294,7 @@ int rvu_get_blkaddr(struct rvu *rvu, int blktype, u16 pcifunc) + devnum = rvu_get_hwvf(rvu, pcifunc); + } else { + is_pf = true; +- devnum = rvu_get_pf(pcifunc); ++ devnum = rvu_get_pf(rvu->pdev, pcifunc); + } + + /* Check if the 'pcifunc' has a NIX LF from 'BLKADDR_NIX0' or +@@ -359,7 +359,7 @@ static void rvu_update_rsrc_map(struct rvu *rvu, struct rvu_pfvf *pfvf, + devnum = rvu_get_hwvf(rvu, pcifunc); + } else { + is_pf = true; +- devnum = rvu_get_pf(pcifunc); ++ devnum = rvu_get_pf(rvu->pdev, pcifunc); + } + + block->fn_map[lf] = attach ? pcifunc : 0; +@@ -400,11 +400,6 @@ static void rvu_update_rsrc_map(struct rvu *rvu, struct rvu_pfvf *pfvf, + rvu_write64(rvu, BLKADDR_RVUM, reg | (devnum << 16), num_lfs); + } + +-inline int rvu_get_pf(u16 pcifunc) +-{ +- return (pcifunc >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK; +-} +- + void rvu_get_pf_numvfs(struct rvu *rvu, int pf, int *numvfs, int *hwvf) + { + u64 cfg; +@@ -422,7 +417,7 @@ int rvu_get_hwvf(struct rvu *rvu, int pcifunc) + int pf, func; + u64 cfg; + +- pf = rvu_get_pf(pcifunc); ++ pf = rvu_get_pf(rvu->pdev, pcifunc); + func = pcifunc & RVU_PFVF_FUNC_MASK; + + /* Get first HWVF attached to this PF */ +@@ -437,7 +432,7 @@ struct rvu_pfvf *rvu_get_pfvf(struct rvu *rvu, int pcifunc) + if (pcifunc & RVU_PFVF_FUNC_MASK) + return &rvu->hwvf[rvu_get_hwvf(rvu, pcifunc)]; + else +- return &rvu->pf[rvu_get_pf(pcifunc)]; ++ return &rvu->pf[rvu_get_pf(rvu->pdev, pcifunc)]; + } + + static bool is_pf_func_valid(struct rvu *rvu, u16 pcifunc) +@@ -445,7 +440,7 @@ static bool is_pf_func_valid(struct rvu *rvu, u16 pcifunc) + int pf, vf, nvfs; + u64 cfg; + +- pf = rvu_get_pf(pcifunc); ++ pf = rvu_get_pf(rvu->pdev, pcifunc); + if (pf >= rvu->hw->total_pfs) + return false; + +@@ -1487,7 +1482,7 @@ int rvu_get_nix_blkaddr(struct rvu *rvu, u16 pcifunc) + pf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK); + + /* All CGX mapped PFs are set with assigned NIX block during init */ +- if (is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) { ++ if (is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc))) { + blkaddr = pf->nix_blkaddr; + } else if (is_lbk_vf(rvu, pcifunc)) { + vf = pcifunc - 1; +@@ -1501,7 +1496,7 @@ int rvu_get_nix_blkaddr(struct rvu *rvu, u16 pcifunc) + } + + /* if SDP1 then the blkaddr is NIX1 */ +- if (is_sdp_pfvf(pcifunc) && pf->sdp_info->node_id == 1) ++ if (is_sdp_pfvf(rvu, pcifunc) && pf->sdp_info->node_id == 1) + blkaddr = BLKADDR_NIX1; + + switch (blkaddr) { +@@ -2006,7 +2001,7 @@ int rvu_mbox_handler_vf_flr(struct rvu *rvu, struct msg_req *req, + + vf = pcifunc & RVU_PFVF_FUNC_MASK; + cfg = rvu_read64(rvu, BLKADDR_RVUM, +- RVU_PRIV_PFX_CFG(rvu_get_pf(pcifunc))); ++ RVU_PRIV_PFX_CFG(rvu_get_pf(rvu->pdev, pcifunc))); + numvfs = (cfg >> 12) & 0xFF; + + if (vf && vf <= numvfs) +@@ -2229,9 +2224,8 @@ static void __rvu_mbox_handler(struct rvu_work *mwork, int type, bool poll) + /* Set which PF/VF sent this message based on mbox IRQ */ + switch (type) { + case TYPE_AFPF: +- msg->pcifunc &= +- ~(RVU_PFVF_PF_MASK << RVU_PFVF_PF_SHIFT); +- msg->pcifunc |= (devid << RVU_PFVF_PF_SHIFT); ++ msg->pcifunc &= rvu_pcifunc_pf_mask(rvu->pdev); ++ msg->pcifunc |= rvu_make_pcifunc(rvu->pdev, devid, 0); + break; + case TYPE_AFVF: + msg->pcifunc &= +@@ -2249,7 +2243,7 @@ static void __rvu_mbox_handler(struct rvu_work *mwork, int type, bool poll) + if (msg->pcifunc & RVU_PFVF_FUNC_MASK) + dev_warn(rvu->dev, "Error %d when processing message %s (0x%x) from PF%d:VF%d\n", + err, otx2_mbox_id2name(msg->id), +- msg->id, rvu_get_pf(msg->pcifunc), ++ msg->id, rvu_get_pf(rvu->pdev, msg->pcifunc), + (msg->pcifunc & RVU_PFVF_FUNC_MASK) - 1); + else + dev_warn(rvu->dev, "Error %d when processing message %s (0x%x) from PF%d\n", +@@ -2773,7 +2767,7 @@ static void rvu_flr_handler(struct work_struct *work) + + cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf)); + numvfs = (cfg >> 12) & 0xFF; +- pcifunc = pf << RVU_PFVF_PF_SHIFT; ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); + + for (vf = 0; vf < numvfs; vf++) + __rvu_flr_handler(rvu, (pcifunc | (vf + 1))); +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +index 48f66292ad5c5..5c179df1f1673 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +@@ -10,6 +10,7 @@ + + #include + #include ++#include + + #include "rvu_struct.h" + #include "rvu_devlink.h" +@@ -43,10 +44,34 @@ + #define MAX_CPT_BLKS 2 + + /* PF_FUNC */ +-#define RVU_PFVF_PF_SHIFT 10 +-#define RVU_PFVF_PF_MASK 0x3F +-#define RVU_PFVF_FUNC_SHIFT 0 +-#define RVU_PFVF_FUNC_MASK 0x3FF ++#define RVU_OTX2_PFVF_PF_SHIFT 10 ++#define RVU_OTX2_PFVF_PF_MASK 0x3F ++#define RVU_PFVF_FUNC_SHIFT 0 ++#define RVU_PFVF_FUNC_MASK 0x3FF ++#define RVU_CN20K_PFVF_PF_SHIFT 9 ++#define RVU_CN20K_PFVF_PF_MASK 0x7F ++ ++static inline u16 rvu_make_pcifunc(struct pci_dev *pdev, int pf, int func) ++{ ++ if (is_cn20k(pdev)) ++ return ((pf & RVU_CN20K_PFVF_PF_MASK) << ++ RVU_CN20K_PFVF_PF_SHIFT) | ++ ((func & RVU_PFVF_FUNC_MASK) << ++ RVU_PFVF_FUNC_SHIFT); ++ else ++ return ((pf & RVU_OTX2_PFVF_PF_MASK) << ++ RVU_OTX2_PFVF_PF_SHIFT) | ++ ((func & RVU_PFVF_FUNC_MASK) << ++ RVU_PFVF_FUNC_SHIFT); ++} ++ ++static inline int rvu_pcifunc_pf_mask(struct pci_dev *pdev) ++{ ++ if (is_cn20k(pdev)) ++ return ~(RVU_CN20K_PFVF_PF_MASK << RVU_CN20K_PFVF_PF_SHIFT); ++ else ++ return ~(RVU_OTX2_PFVF_PF_MASK << RVU_OTX2_PFVF_PF_SHIFT); ++} + + #ifdef CONFIG_DEBUG_FS + struct dump_ctx { +@@ -836,7 +861,6 @@ int rvu_alloc_rsrc_contig(struct rsrc_bmap *rsrc, int nrsrc); + void rvu_free_rsrc_contig(struct rsrc_bmap *rsrc, int nrsrc, int start); + bool rvu_rsrc_check_contig(struct rsrc_bmap *rsrc, int nrsrc); + u16 rvu_get_rsrc_mapcount(struct rvu_pfvf *pfvf, int blkaddr); +-int rvu_get_pf(u16 pcifunc); + struct rvu_pfvf *rvu_get_pfvf(struct rvu *rvu, int pcifunc); + void rvu_get_pf_numvfs(struct rvu *rvu, int pf, int *numvfs, int *hwvf); + bool is_block_implemented(struct rvu_hwinfo *hw, int blkaddr); +@@ -865,8 +889,8 @@ void rvu_aq_free(struct rvu *rvu, struct admin_queue *aq); + + /* SDP APIs */ + int rvu_sdp_init(struct rvu *rvu); +-bool is_sdp_pfvf(u16 pcifunc); +-bool is_sdp_pf(u16 pcifunc); ++bool is_sdp_pfvf(struct rvu *rvu, u16 pcifunc); ++bool is_sdp_pf(struct rvu *rvu, u16 pcifunc); + bool is_sdp_vf(struct rvu *rvu, u16 pcifunc); + + static inline bool is_rep_dev(struct rvu *rvu, u16 pcifunc) +@@ -877,11 +901,21 @@ static inline bool is_rep_dev(struct rvu *rvu, u16 pcifunc) + return false; + } + ++static inline int rvu_get_pf(struct pci_dev *pdev, u16 pcifunc) ++{ ++ if (is_cn20k(pdev)) ++ return (pcifunc >> RVU_CN20K_PFVF_PF_SHIFT) & ++ RVU_CN20K_PFVF_PF_MASK; ++ else ++ return (pcifunc >> RVU_OTX2_PFVF_PF_SHIFT) & ++ RVU_OTX2_PFVF_PF_MASK; ++} ++ + /* CGX APIs */ + static inline bool is_pf_cgxmapped(struct rvu *rvu, u8 pf) + { + return (pf >= PF_CGXMAP_BASE && pf <= rvu->cgx_mapped_pfs) && +- !is_sdp_pf(pf << RVU_PFVF_PF_SHIFT); ++ !is_sdp_pf(rvu, rvu_make_pcifunc(rvu->pdev, pf, 0)); + } + + static inline void rvu_get_cgx_lmac_id(u8 map, u8 *cgx_id, u8 *lmac_id) +@@ -893,7 +927,7 @@ static inline void rvu_get_cgx_lmac_id(u8 map, u8 *cgx_id, u8 *lmac_id) + static inline bool is_cgx_vf(struct rvu *rvu, u16 pcifunc) + { + return ((pcifunc & RVU_PFVF_FUNC_MASK) && +- is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))); ++ is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc))); + } + + #define M(_name, _id, fn_name, req, rsp) \ +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +index d0331b0e0bfd4..b79db887ab9b2 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +@@ -457,7 +457,7 @@ int rvu_cgx_exit(struct rvu *rvu) + inline bool is_cgx_config_permitted(struct rvu *rvu, u16 pcifunc) + { + if ((pcifunc & RVU_PFVF_FUNC_MASK) || +- !is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) ++ !is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc))) + return false; + return true; + } +@@ -484,7 +484,7 @@ void rvu_cgx_enadis_rx_bp(struct rvu *rvu, int pf, bool enable) + + int rvu_cgx_config_rxtx(struct rvu *rvu, u16 pcifunc, bool start) + { +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + struct mac_ops *mac_ops; + u8 cgx_id, lmac_id; + void *cgxd; +@@ -501,7 +501,7 @@ int rvu_cgx_config_rxtx(struct rvu *rvu, u16 pcifunc, bool start) + + int rvu_cgx_tx_enable(struct rvu *rvu, u16 pcifunc, bool enable) + { +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + struct mac_ops *mac_ops; + u8 cgx_id, lmac_id; + void *cgxd; +@@ -526,7 +526,7 @@ int rvu_cgx_config_tx(void *cgxd, int lmac_id, bool enable) + + void rvu_cgx_disable_dmac_entries(struct rvu *rvu, u16 pcifunc) + { +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + int i = 0, lmac_count = 0; + struct mac_ops *mac_ops; + u8 max_dmac_filters; +@@ -577,7 +577,7 @@ int rvu_mbox_handler_cgx_stop_rxtx(struct rvu *rvu, struct msg_req *req, + static int rvu_lmac_get_stats(struct rvu *rvu, struct msg_req *req, + void *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + struct mac_ops *mac_ops; + int stat = 0, err = 0; + u64 tx_stat, rx_stat; +@@ -633,7 +633,7 @@ int rvu_mbox_handler_rpm_stats(struct rvu *rvu, struct msg_req *req, + int rvu_mbox_handler_cgx_stats_rst(struct rvu *rvu, struct msg_req *req, + struct msg_rsp *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + struct rvu_pfvf *parent_pf; + struct mac_ops *mac_ops; + u8 cgx_idx, lmac; +@@ -663,7 +663,7 @@ int rvu_mbox_handler_cgx_fec_stats(struct rvu *rvu, + struct msg_req *req, + struct cgx_fec_stats_rsp *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + struct mac_ops *mac_ops; + u8 cgx_idx, lmac; + void *cgxd; +@@ -681,7 +681,7 @@ int rvu_mbox_handler_cgx_mac_addr_set(struct rvu *rvu, + struct cgx_mac_addr_set_or_get *req, + struct cgx_mac_addr_set_or_get *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u8 cgx_id, lmac_id; + + if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) +@@ -701,7 +701,7 @@ int rvu_mbox_handler_cgx_mac_addr_add(struct rvu *rvu, + struct cgx_mac_addr_add_req *req, + struct cgx_mac_addr_add_rsp *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u8 cgx_id, lmac_id; + int rc = 0; + +@@ -725,7 +725,7 @@ int rvu_mbox_handler_cgx_mac_addr_del(struct rvu *rvu, + struct cgx_mac_addr_del_req *req, + struct msg_rsp *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u8 cgx_id, lmac_id; + + if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) +@@ -743,7 +743,7 @@ int rvu_mbox_handler_cgx_mac_max_entries_get(struct rvu *rvu, + struct cgx_max_dmac_entries_get_rsp + *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u8 cgx_id, lmac_id; + + /* If msg is received from PFs(which are not mapped to CGX LMACs) +@@ -769,7 +769,7 @@ int rvu_mbox_handler_cgx_mac_addr_get(struct rvu *rvu, + struct cgx_mac_addr_set_or_get *req, + struct cgx_mac_addr_set_or_get *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u8 cgx_id, lmac_id; + int rc = 0; + u64 cfg; +@@ -790,7 +790,7 @@ int rvu_mbox_handler_cgx_promisc_enable(struct rvu *rvu, struct msg_req *req, + struct msg_rsp *rsp) + { + u16 pcifunc = req->hdr.pcifunc; +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + u8 cgx_id, lmac_id; + + if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) +@@ -809,7 +809,7 @@ int rvu_mbox_handler_cgx_promisc_enable(struct rvu *rvu, struct msg_req *req, + int rvu_mbox_handler_cgx_promisc_disable(struct rvu *rvu, struct msg_req *req, + struct msg_rsp *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u8 cgx_id, lmac_id; + + if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) +@@ -828,7 +828,7 @@ int rvu_mbox_handler_cgx_promisc_disable(struct rvu *rvu, struct msg_req *req, + static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable) + { + struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + struct mac_ops *mac_ops; + u8 cgx_id, lmac_id; + void *cgxd; +@@ -864,7 +864,7 @@ static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable) + int rvu_mbox_handler_cgx_ptp_rx_enable(struct rvu *rvu, struct msg_req *req, + struct msg_rsp *rsp) + { +- if (!is_pf_cgxmapped(rvu, rvu_get_pf(req->hdr.pcifunc))) ++ if (!is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, req->hdr.pcifunc))) + return -EPERM; + + return rvu_cgx_ptp_rx_cfg(rvu, req->hdr.pcifunc, true); +@@ -878,7 +878,7 @@ int rvu_mbox_handler_cgx_ptp_rx_disable(struct rvu *rvu, struct msg_req *req, + + static int rvu_cgx_config_linkevents(struct rvu *rvu, u16 pcifunc, bool en) + { +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + u8 cgx_id, lmac_id; + + if (!is_cgx_config_permitted(rvu, pcifunc)) +@@ -917,7 +917,7 @@ int rvu_mbox_handler_cgx_get_linkinfo(struct rvu *rvu, struct msg_req *req, + u8 cgx_id, lmac_id; + int pf, err; + +- pf = rvu_get_pf(req->hdr.pcifunc); ++ pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + + if (!is_pf_cgxmapped(rvu, pf)) + return -ENODEV; +@@ -933,7 +933,7 @@ int rvu_mbox_handler_cgx_features_get(struct rvu *rvu, + struct msg_req *req, + struct cgx_features_info_msg *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u8 cgx_idx, lmac; + void *cgxd; + +@@ -975,7 +975,7 @@ u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac) + + static int rvu_cgx_config_intlbk(struct rvu *rvu, u16 pcifunc, bool en) + { +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + struct mac_ops *mac_ops; + u8 cgx_id, lmac_id; + +@@ -1005,7 +1005,7 @@ int rvu_mbox_handler_cgx_intlbk_disable(struct rvu *rvu, struct msg_req *req, + + int rvu_cgx_cfg_pause_frm(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_pause) + { +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + u8 rx_pfc = 0, tx_pfc = 0; + struct mac_ops *mac_ops; + u8 cgx_id, lmac_id; +@@ -1046,7 +1046,7 @@ int rvu_mbox_handler_cgx_cfg_pause_frm(struct rvu *rvu, + struct cgx_pause_frm_cfg *req, + struct cgx_pause_frm_cfg *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + struct mac_ops *mac_ops; + u8 cgx_id, lmac_id; + int err = 0; +@@ -1073,7 +1073,7 @@ int rvu_mbox_handler_cgx_cfg_pause_frm(struct rvu *rvu, + int rvu_mbox_handler_cgx_get_phy_fec_stats(struct rvu *rvu, struct msg_req *req, + struct msg_rsp *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u8 cgx_id, lmac_id; + + if (!is_pf_cgxmapped(rvu, pf)) +@@ -1106,7 +1106,7 @@ int rvu_cgx_nix_cuml_stats(struct rvu *rvu, void *cgxd, int lmac_id, + /* Assumes LF of a PF and all of its VF belongs to the same + * NIX block + */ +- pcifunc = pf << RVU_PFVF_PF_SHIFT; ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); + if (blkaddr < 0) + return 0; +@@ -1133,10 +1133,10 @@ int rvu_cgx_start_stop_io(struct rvu *rvu, u16 pcifunc, bool start) + struct rvu_pfvf *parent_pf, *pfvf; + int cgx_users, err = 0; + +- if (!is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) ++ if (!is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc))) + return 0; + +- parent_pf = &rvu->pf[rvu_get_pf(pcifunc)]; ++ parent_pf = &rvu->pf[rvu_get_pf(rvu->pdev, pcifunc)]; + pfvf = rvu_get_pfvf(rvu, pcifunc); + + mutex_lock(&rvu->cgx_cfg_lock); +@@ -1179,7 +1179,7 @@ int rvu_mbox_handler_cgx_set_fec_param(struct rvu *rvu, + struct fec_mode *req, + struct fec_mode *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u8 cgx_id, lmac_id; + + if (!is_pf_cgxmapped(rvu, pf)) +@@ -1195,7 +1195,7 @@ int rvu_mbox_handler_cgx_set_fec_param(struct rvu *rvu, + int rvu_mbox_handler_cgx_get_aux_link_info(struct rvu *rvu, struct msg_req *req, + struct cgx_fw_data *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u8 cgx_id, lmac_id; + + if (!rvu->fwdata) +@@ -1222,7 +1222,7 @@ int rvu_mbox_handler_cgx_set_link_mode(struct rvu *rvu, + struct cgx_set_link_mode_req *req, + struct cgx_set_link_mode_rsp *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u8 cgx_idx, lmac; + void *cgxd; + +@@ -1238,7 +1238,7 @@ int rvu_mbox_handler_cgx_set_link_mode(struct rvu *rvu, + int rvu_mbox_handler_cgx_mac_addr_reset(struct rvu *rvu, struct cgx_mac_addr_reset_req *req, + struct msg_rsp *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u8 cgx_id, lmac_id; + + if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) +@@ -1256,7 +1256,7 @@ int rvu_mbox_handler_cgx_mac_addr_update(struct rvu *rvu, + struct cgx_mac_addr_update_req *req, + struct cgx_mac_addr_update_rsp *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u8 cgx_id, lmac_id; + + if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) +@@ -1272,7 +1272,7 @@ int rvu_mbox_handler_cgx_mac_addr_update(struct rvu *rvu, + int rvu_cgx_prio_flow_ctrl_cfg(struct rvu *rvu, u16 pcifunc, u8 tx_pause, + u8 rx_pause, u16 pfc_en) + { +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + u8 rx_8023 = 0, tx_8023 = 0; + struct mac_ops *mac_ops; + u8 cgx_id, lmac_id; +@@ -1310,7 +1310,7 @@ int rvu_mbox_handler_cgx_prio_flow_ctrl_cfg(struct rvu *rvu, + struct cgx_pfc_cfg *req, + struct cgx_pfc_rsp *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + struct mac_ops *mac_ops; + u8 cgx_id, lmac_id; + void *cgxd; +@@ -1335,7 +1335,7 @@ int rvu_mbox_handler_cgx_prio_flow_ctrl_cfg(struct rvu *rvu, + + void rvu_mac_reset(struct rvu *rvu, u16 pcifunc) + { +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + struct mac_ops *mac_ops; + struct cgx *cgxd; + u8 cgx, lmac; +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c +index 4a3370a40dd88..05adc54535eb3 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c +@@ -66,7 +66,7 @@ static int lmtst_map_table_ops(struct rvu *rvu, u32 index, u64 *val, + #define LMT_MAP_TBL_W1_OFF 8 + static u32 rvu_get_lmtst_tbl_index(struct rvu *rvu, u16 pcifunc) + { +- return ((rvu_get_pf(pcifunc) * LMT_MAX_VFS) + ++ return ((rvu_get_pf(rvu->pdev, pcifunc) * LMT_MAX_VFS) + + (pcifunc & RVU_PFVF_FUNC_MASK)) * LMT_MAPTBL_ENTRY_SIZE; + } + +@@ -83,7 +83,7 @@ static int rvu_get_lmtaddr(struct rvu *rvu, u16 pcifunc, + + mutex_lock(&rvu->rsrc_lock); + rvu_write64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_ADDR_REQ, iova); +- pf = rvu_get_pf(pcifunc) & RVU_PFVF_PF_MASK; ++ pf = rvu_get_pf(rvu->pdev, pcifunc) & RVU_OTX2_PFVF_PF_MASK; + val = BIT_ULL(63) | BIT_ULL(14) | BIT_ULL(13) | pf << 8 | + ((pcifunc & RVU_PFVF_FUNC_MASK) & 0xFF); + rvu_write64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_TXN_REQ, val); +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c +index 3c5bbaf12e594..f404117bf6c8c 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c +@@ -410,7 +410,7 @@ static bool is_cpt_pf(struct rvu *rvu, u16 pcifunc) + { + int cpt_pf_num = rvu->cpt_pf_num; + +- if (rvu_get_pf(pcifunc) != cpt_pf_num) ++ if (rvu_get_pf(rvu->pdev, pcifunc) != cpt_pf_num) + return false; + if (pcifunc & RVU_PFVF_FUNC_MASK) + return false; +@@ -422,7 +422,7 @@ static bool is_cpt_vf(struct rvu *rvu, u16 pcifunc) + { + int cpt_pf_num = rvu->cpt_pf_num; + +- if (rvu_get_pf(pcifunc) != cpt_pf_num) ++ if (rvu_get_pf(rvu->pdev, pcifunc) != cpt_pf_num) + return false; + if (!(pcifunc & RVU_PFVF_FUNC_MASK)) + return false; +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +index c827da6264712..0c20642f81b9b 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +@@ -688,7 +688,7 @@ static int get_max_column_width(struct rvu *rvu) + + for (pf = 0; pf < rvu->hw->total_pfs; pf++) { + for (vf = 0; vf <= rvu->hw->total_vfs; vf++) { +- pcifunc = pf << 10 | vf; ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, vf); + if (!pcifunc) + continue; + +@@ -759,7 +759,7 @@ static ssize_t rvu_dbg_rsrc_attach_status(struct file *filp, + for (vf = 0; vf <= rvu->hw->total_vfs; vf++) { + off = 0; + flag = 0; +- pcifunc = pf << 10 | vf; ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, vf); + if (!pcifunc) + continue; + +@@ -842,7 +842,7 @@ static int rvu_dbg_rvu_pf_cgx_map_display(struct seq_file *filp, void *unused) + + cgx[0] = 0; + lmac[0] = 0; +- pcifunc = pf << 10; ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); + pfvf = rvu_get_pfvf(rvu, pcifunc); + + if (pfvf->nix_blkaddr == BLKADDR_NIX0) +@@ -2623,10 +2623,10 @@ static int rvu_dbg_nix_band_prof_ctx_display(struct seq_file *m, void *unused) + pcifunc = ipolicer->pfvf_map[idx]; + if (!(pcifunc & RVU_PFVF_FUNC_MASK)) + seq_printf(m, "Allocated to :: PF %d\n", +- rvu_get_pf(pcifunc)); ++ rvu_get_pf(rvu->pdev, pcifunc)); + else + seq_printf(m, "Allocated to :: PF %d VF %d\n", +- rvu_get_pf(pcifunc), ++ rvu_get_pf(rvu->pdev, pcifunc), + (pcifunc & RVU_PFVF_FUNC_MASK) - 1); + print_band_prof_ctx(m, &aq_rsp.prof); + } +@@ -2983,10 +2983,10 @@ static void rvu_print_npc_mcam_info(struct seq_file *s, + + if (!(pcifunc & RVU_PFVF_FUNC_MASK)) + seq_printf(s, "\n\t\t Device \t\t: PF%d\n", +- rvu_get_pf(pcifunc)); ++ rvu_get_pf(rvu->pdev, pcifunc)); + else + seq_printf(s, "\n\t\t Device \t\t: PF%d VF%d\n", +- rvu_get_pf(pcifunc), ++ rvu_get_pf(rvu->pdev, pcifunc), + (pcifunc & RVU_PFVF_FUNC_MASK) - 1); + + if (entry_acnt) { +@@ -3049,13 +3049,13 @@ static int rvu_dbg_npc_mcam_info_display(struct seq_file *filp, void *unsued) + seq_puts(filp, "\n\t\t Current allocation\n"); + seq_puts(filp, "\t\t====================\n"); + for (pf = 0; pf < rvu->hw->total_pfs; pf++) { +- pcifunc = (pf << RVU_PFVF_PF_SHIFT); ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); + rvu_print_npc_mcam_info(filp, pcifunc, blkaddr); + + cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf)); + numvfs = (cfg >> 12) & 0xFF; + for (vf = 0; vf < numvfs; vf++) { +- pcifunc = (pf << RVU_PFVF_PF_SHIFT) | (vf + 1); ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, (vf + 1)); + rvu_print_npc_mcam_info(filp, pcifunc, blkaddr); + } + } +@@ -3326,7 +3326,7 @@ static int rvu_dbg_npc_mcam_show_rules(struct seq_file *s, void *unused) + + mutex_lock(&mcam->lock); + list_for_each_entry(iter, &mcam->mcam_rules, list) { +- pf = (iter->owner >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK; ++ pf = rvu_get_pf(rvu->pdev, iter->owner); + seq_printf(s, "\n\tInstalled by: PF%d ", pf); + + if (iter->owner & RVU_PFVF_FUNC_MASK) { +@@ -3344,7 +3344,7 @@ static int rvu_dbg_npc_mcam_show_rules(struct seq_file *s, void *unused) + rvu_dbg_npc_mcam_show_flows(s, iter); + if (is_npc_intf_rx(iter->intf)) { + target = iter->rx_action.pf_func; +- pf = (target >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK; ++ pf = rvu_get_pf(rvu->pdev, target); + seq_printf(s, "\tForward to: PF%d ", pf); + + if (target & RVU_PFVF_FUNC_MASK) { +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +index 613655fcd34f4..bdf4d852c15de 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +@@ -315,7 +315,8 @@ static bool is_valid_txschq(struct rvu *rvu, int blkaddr, + if (lvl >= hw->cap.nix_tx_aggr_lvl) { + if ((nix_get_tx_link(rvu, map_func) != + nix_get_tx_link(rvu, pcifunc)) && +- (rvu_get_pf(map_func) != rvu_get_pf(pcifunc))) ++ (rvu_get_pf(rvu->pdev, map_func) != ++ rvu_get_pf(rvu->pdev, pcifunc))) + return false; + else + return true; +@@ -339,7 +340,7 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf, + bool from_vf; + int err; + +- pf = rvu_get_pf(pcifunc); ++ pf = rvu_get_pf(rvu->pdev, pcifunc); + if (!is_pf_cgxmapped(rvu, pf) && type != NIX_INTF_TYPE_LBK && + type != NIX_INTF_TYPE_SDP) + return 0; +@@ -416,7 +417,7 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf, + break; + case NIX_INTF_TYPE_SDP: + from_vf = !!(pcifunc & RVU_PFVF_FUNC_MASK); +- parent_pf = &rvu->pf[rvu_get_pf(pcifunc)]; ++ parent_pf = &rvu->pf[rvu_get_pf(rvu->pdev, pcifunc)]; + sdp_info = parent_pf->sdp_info; + if (!sdp_info) { + dev_err(rvu->dev, "Invalid sdp_info pointer\n"); +@@ -590,12 +591,12 @@ static int nix_bp_disable(struct rvu *rvu, + u16 chan_v; + u64 cfg; + +- pf = rvu_get_pf(pcifunc); ++ pf = rvu_get_pf(rvu->pdev, pcifunc); + type = is_lbk_vf(rvu, pcifunc) ? NIX_INTF_TYPE_LBK : NIX_INTF_TYPE_CGX; + if (!is_pf_cgxmapped(rvu, pf) && type != NIX_INTF_TYPE_LBK) + return 0; + +- if (is_sdp_pfvf(pcifunc)) ++ if (is_sdp_pfvf(rvu, pcifunc)) + type = NIX_INTF_TYPE_SDP; + + if (cpt_link && !rvu->hw->cpt_links) +@@ -736,9 +737,9 @@ static int nix_bp_enable(struct rvu *rvu, + u16 chan_v; + u64 cfg; + +- pf = rvu_get_pf(pcifunc); ++ pf = rvu_get_pf(rvu->pdev, pcifunc); + type = is_lbk_vf(rvu, pcifunc) ? NIX_INTF_TYPE_LBK : NIX_INTF_TYPE_CGX; +- if (is_sdp_pfvf(pcifunc)) ++ if (is_sdp_pfvf(rvu, pcifunc)) + type = NIX_INTF_TYPE_SDP; + + /* Enable backpressure only for CGX mapped PFs and LBK/SDP interface */ +@@ -1674,7 +1675,7 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu, + } + + intf = is_lbk_vf(rvu, pcifunc) ? NIX_INTF_TYPE_LBK : NIX_INTF_TYPE_CGX; +- if (is_sdp_pfvf(pcifunc)) ++ if (is_sdp_pfvf(rvu, pcifunc)) + intf = NIX_INTF_TYPE_SDP; + + err = nix_interface_init(rvu, pcifunc, intf, nixlf, rsp, +@@ -1798,7 +1799,8 @@ int rvu_mbox_handler_nix_mark_format_cfg(struct rvu *rvu, + rc = rvu_nix_reserve_mark_format(rvu, nix_hw, blkaddr, cfg); + if (rc < 0) { + dev_err(rvu->dev, "No mark_format_ctl for (pf:%d, vf:%d)", +- rvu_get_pf(pcifunc), pcifunc & RVU_PFVF_FUNC_MASK); ++ rvu_get_pf(rvu->pdev, pcifunc), ++ pcifunc & RVU_PFVF_FUNC_MASK); + return NIX_AF_ERR_MARK_CFG_FAIL; + } + +@@ -2050,7 +2052,7 @@ static void nix_clear_tx_xoff(struct rvu *rvu, int blkaddr, + static int nix_get_tx_link(struct rvu *rvu, u16 pcifunc) + { + struct rvu_hwinfo *hw = rvu->hw; +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + u8 cgx_id = 0, lmac_id = 0; + + if (is_lbk_vf(rvu, pcifunc)) {/* LBK links */ +@@ -2068,7 +2070,7 @@ static void nix_get_txschq_range(struct rvu *rvu, u16 pcifunc, + int link, int *start, int *end) + { + struct rvu_hwinfo *hw = rvu->hw; +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + + /* LBK links */ + if (is_lbk_vf(rvu, pcifunc) || is_rep_dev(rvu, pcifunc)) { +@@ -2426,7 +2428,7 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr, + { + struct nix_smq_flush_ctx *smq_flush_ctx; + int err, restore_tx_en = 0, i; +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + u8 cgx_id = 0, lmac_id = 0; + u16 tl2_tl3_link_schq; + u8 link, link_level; +@@ -2820,7 +2822,7 @@ void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, u16 pcifunc, + { + struct rvu_hwinfo *hw = rvu->hw; + int lbk_link_start, lbk_links; +- u8 pf = rvu_get_pf(pcifunc); ++ u8 pf = rvu_get_pf(rvu->pdev, pcifunc); + int schq; + u64 cfg; + +@@ -3190,7 +3192,8 @@ static int nix_blk_setup_mce(struct rvu *rvu, struct nix_hw *nix_hw, + err = rvu_nix_blk_aq_enq_inst(rvu, nix_hw, &aq_req, NULL); + if (err) { + dev_err(rvu->dev, "Failed to setup Bcast MCE for PF%d:VF%d\n", +- rvu_get_pf(pcifunc), pcifunc & RVU_PFVF_FUNC_MASK); ++ rvu_get_pf(rvu->pdev, pcifunc), ++ pcifunc & RVU_PFVF_FUNC_MASK); + return err; + } + return 0; +@@ -3458,7 +3461,7 @@ int nix_update_mce_list(struct rvu *rvu, u16 pcifunc, + dev_err(rvu->dev, + "%s: Idx %d > max MCE idx %d, for PF%d bcast list\n", + __func__, idx, mce_list->max, +- pcifunc >> RVU_PFVF_PF_SHIFT); ++ rvu_get_pf(rvu->pdev, pcifunc)); + return -EINVAL; + } + +@@ -3510,7 +3513,8 @@ void nix_get_mce_list(struct rvu *rvu, u16 pcifunc, int type, + struct rvu_pfvf *pfvf; + + if (!hw->cap.nix_rx_multicast || +- !is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc & ~RVU_PFVF_FUNC_MASK))) { ++ !is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, ++ pcifunc & ~RVU_PFVF_FUNC_MASK))) { + *mce_list = NULL; + *mce_idx = 0; + return; +@@ -3544,13 +3548,13 @@ static int nix_update_mce_rule(struct rvu *rvu, u16 pcifunc, + int pf; + + /* skip multicast pkt replication for AF's VFs & SDP links */ +- if (is_lbk_vf(rvu, pcifunc) || is_sdp_pfvf(pcifunc)) ++ if (is_lbk_vf(rvu, pcifunc) || is_sdp_pfvf(rvu, pcifunc)) + return 0; + + if (!hw->cap.nix_rx_multicast) + return 0; + +- pf = rvu_get_pf(pcifunc); ++ pf = rvu_get_pf(rvu->pdev, pcifunc); + if (!is_pf_cgxmapped(rvu, pf)) + return 0; + +@@ -3619,7 +3623,7 @@ static int nix_setup_mce_tables(struct rvu *rvu, struct nix_hw *nix_hw) + + for (idx = 0; idx < (numvfs + 1); idx++) { + /* idx-0 is for PF, followed by VFs */ +- pcifunc = (pf << RVU_PFVF_PF_SHIFT); ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); + pcifunc |= idx; + /* Add dummy entries now, so that we don't have to check + * for whether AQ_OP should be INIT/WRITE later on. +@@ -4554,7 +4558,7 @@ int rvu_mbox_handler_nix_set_rx_mode(struct rvu *rvu, struct nix_rx_mode *req, + static void nix_find_link_frs(struct rvu *rvu, + struct nix_frs_cfg *req, u16 pcifunc) + { +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + struct rvu_pfvf *pfvf; + int maxlen, minlen; + int numvfs, hwvf; +@@ -4601,7 +4605,7 @@ int rvu_mbox_handler_nix_set_hw_frs(struct rvu *rvu, struct nix_frs_cfg *req, + { + struct rvu_hwinfo *hw = rvu->hw; + u16 pcifunc = req->hdr.pcifunc; +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + int blkaddr, link = -1; + struct nix_hw *nix_hw; + struct rvu_pfvf *pfvf; +@@ -5251,7 +5255,7 @@ int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req, + + rvu_switch_update_rules(rvu, pcifunc, true); + +- pf = rvu_get_pf(pcifunc); ++ pf = rvu_get_pf(rvu->pdev, pcifunc); + if (is_pf_cgxmapped(rvu, pf) && rvu->rep_mode) + rvu_rep_notify_pfvf_state(rvu, pcifunc, true); + +@@ -5284,7 +5288,7 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req, + rvu_switch_update_rules(rvu, pcifunc, false); + rvu_cgx_tx_enable(rvu, pcifunc, true); + +- pf = rvu_get_pf(pcifunc); ++ pf = rvu_get_pf(rvu->pdev, pcifunc); + if (is_pf_cgxmapped(rvu, pf) && rvu->rep_mode) + rvu_rep_notify_pfvf_state(rvu, pcifunc, false); + return 0; +@@ -5296,7 +5300,7 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf) + { + struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); + struct hwctx_disable_req ctx_req; +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + struct mac_ops *mac_ops; + u8 cgx_id, lmac_id; + u64 sa_base; +@@ -5385,7 +5389,7 @@ static int rvu_nix_lf_ptp_tx_cfg(struct rvu *rvu, u16 pcifunc, bool enable) + int nixlf; + u64 cfg; + +- pf = rvu_get_pf(pcifunc); ++ pf = rvu_get_pf(rvu->pdev, pcifunc); + if (!is_mac_feature_supported(rvu, pf, RVU_LMAC_FEAT_PTP)) + return 0; + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +index da15bb4511788..c7c70429eb6c1 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +@@ -147,7 +147,9 @@ static int npc_get_ucast_mcam_index(struct npc_mcam *mcam, u16 pcifunc, + int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, + u16 pcifunc, int nixlf, int type) + { +- int pf = rvu_get_pf(pcifunc); ++ struct rvu_hwinfo *hw = container_of(mcam, struct rvu_hwinfo, mcam); ++ struct rvu *rvu = hw->rvu; ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + int index; + + /* Check if this is for a PF */ +@@ -698,7 +700,7 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc, + + /* RX_ACTION set to MCAST for CGX PF's */ + if (hw->cap.nix_rx_multicast && pfvf->use_mce_list && +- is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) { ++ is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc))) { + *(u64 *)&action = 0; + action.op = NIX_RX_ACTIONOP_MCAST; + pfvf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK); +@@ -3434,7 +3436,7 @@ int rvu_npc_set_parse_mode(struct rvu *rvu, u16 pcifunc, u64 mode, u8 dir, + { + struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); + int blkaddr, nixlf, rc, intf_mode; +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + u64 rxpkind, txpkind; + u8 cgx_id, lmac_id; + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c +index d2661e7fabdb4..999f6d93c7fe8 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c +@@ -1465,7 +1465,7 @@ static int rvu_npc_exact_update_table_entry(struct rvu *rvu, u8 cgx_id, u8 lmac_ + int rvu_npc_exact_promisc_disable(struct rvu *rvu, u16 pcifunc) + { + struct npc_exact_table *table; +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + u8 cgx_id, lmac_id; + u32 drop_mcam_idx; + bool *promisc; +@@ -1512,7 +1512,7 @@ int rvu_npc_exact_promisc_disable(struct rvu *rvu, u16 pcifunc) + int rvu_npc_exact_promisc_enable(struct rvu *rvu, u16 pcifunc) + { + struct npc_exact_table *table; +- int pf = rvu_get_pf(pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, pcifunc); + u8 cgx_id, lmac_id; + u32 drop_mcam_idx; + bool *promisc; +@@ -1560,7 +1560,7 @@ int rvu_npc_exact_promisc_enable(struct rvu *rvu, u16 pcifunc) + int rvu_npc_exact_mac_addr_reset(struct rvu *rvu, struct cgx_mac_addr_reset_req *req, + struct msg_rsp *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u32 seq_id = req->index; + struct rvu_pfvf *pfvf; + u8 cgx_id, lmac_id; +@@ -1593,7 +1593,7 @@ int rvu_npc_exact_mac_addr_update(struct rvu *rvu, + struct cgx_mac_addr_update_req *req, + struct cgx_mac_addr_update_rsp *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + struct npc_exact_table_entry *entry; + struct npc_exact_table *table; + struct rvu_pfvf *pfvf; +@@ -1675,7 +1675,7 @@ int rvu_npc_exact_mac_addr_add(struct rvu *rvu, + struct cgx_mac_addr_add_req *req, + struct cgx_mac_addr_add_rsp *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + struct rvu_pfvf *pfvf; + u8 cgx_id, lmac_id; + int rc = 0; +@@ -1711,7 +1711,7 @@ int rvu_npc_exact_mac_addr_del(struct rvu *rvu, + struct cgx_mac_addr_del_req *req, + struct msg_rsp *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + int rc; + + rc = rvu_npc_exact_del_table_entry_by_id(rvu, req->index); +@@ -1736,7 +1736,7 @@ int rvu_npc_exact_mac_addr_del(struct rvu *rvu, + int rvu_npc_exact_mac_addr_set(struct rvu *rvu, struct cgx_mac_addr_set_or_get *req, + struct cgx_mac_addr_set_or_get *rsp) + { +- int pf = rvu_get_pf(req->hdr.pcifunc); ++ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); + u32 seq_id = req->index; + struct rvu_pfvf *pfvf; + u8 cgx_id, lmac_id; +@@ -2001,7 +2001,7 @@ int rvu_npc_exact_init(struct rvu *rvu) + } + + /* Filter rules are only for PF */ +- pcifunc = RVU_PFFUNC(i, 0); ++ pcifunc = RVU_PFFUNC(rvu->pdev, i, 0); + + dev_dbg(rvu->dev, + "%s:Drop rule cgx=%d lmac=%d chan(val=0x%llx, mask=0x%llx\n", +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h +index 57a09328d46b5..cb25cf478f1fd 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h +@@ -139,9 +139,7 @@ static struct npc_mcam_kex_hash npc_mkex_hash_default __maybe_unused = { + #define NPC_MCAM_DROP_RULE_MAX 30 + #define NPC_MCAM_SDP_DROP_RULE_IDX 0 + +-#define RVU_PFFUNC(pf, func) \ +- ((((pf) & RVU_PFVF_PF_MASK) << RVU_PFVF_PF_SHIFT) | \ +- (((func) & RVU_PFVF_FUNC_MASK) << RVU_PFVF_FUNC_SHIFT)) ++#define RVU_PFFUNC(pdev, pf, func) rvu_make_pcifunc(pdev, pf, func) + + enum npc_exact_opc_type { + NPC_EXACT_OPC_MEM, +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c +index 32953cca108c8..03099bc570bd5 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c +@@ -39,7 +39,7 @@ static int rvu_rep_up_notify(struct rvu *rvu, struct rep_event *event) + struct rep_event *msg; + int pf; + +- pf = rvu_get_pf(event->pcifunc); ++ pf = rvu_get_pf(rvu->pdev, event->pcifunc); + + if (event->event & RVU_EVENT_MAC_ADDR_CHANGE) + ether_addr_copy(pfvf->mac_addr, event->evt_data.mac); +@@ -114,10 +114,10 @@ int rvu_rep_notify_pfvf_state(struct rvu *rvu, u16 pcifunc, bool enable) + struct rep_event *req; + int pf; + +- if (!is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) ++ if (!is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc))) + return 0; + +- pf = rvu_get_pf(rvu->rep_pcifunc); ++ pf = rvu_get_pf(rvu->pdev, rvu->rep_pcifunc); + + mutex_lock(&rvu->mbox_lock); + req = otx2_mbox_alloc_msg_rep_event_up_notify(rvu, pf); +@@ -325,7 +325,7 @@ int rvu_rep_install_mcam_rules(struct rvu *rvu) + if (!is_pf_cgxmapped(rvu, pf)) + continue; + +- pcifunc = pf << RVU_PFVF_PF_SHIFT; ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); + rvu_get_nix_blkaddr(rvu, pcifunc); + rep = true; + for (i = 0; i < 2; i++) { +@@ -345,8 +345,7 @@ int rvu_rep_install_mcam_rules(struct rvu *rvu) + + rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL); + for (vf = 0; vf < numvfs; vf++) { +- pcifunc = pf << RVU_PFVF_PF_SHIFT | +- ((vf + 1) & RVU_PFVF_FUNC_MASK); ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, vf + 1); + rvu_get_nix_blkaddr(rvu, pcifunc); + + /* Skip installimg rules if nixlf is not attached */ +@@ -454,7 +453,7 @@ int rvu_mbox_handler_get_rep_cnt(struct rvu *rvu, struct msg_req *req, + for (pf = 0; pf < rvu->hw->total_pfs; pf++) { + if (!is_pf_cgxmapped(rvu, pf)) + continue; +- pcifunc = pf << RVU_PFVF_PF_SHIFT; ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); + rvu->rep2pfvf_map[rep] = pcifunc; + rsp->rep_pf_map[rep] = pcifunc; + rep++; +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_sdp.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_sdp.c +index 38cfe148f4b74..e4a5f9fa6fd46 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_sdp.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_sdp.c +@@ -17,9 +17,9 @@ + /* SDP PF number */ + static int sdp_pf_num[MAX_SDP] = {-1, -1}; + +-bool is_sdp_pfvf(u16 pcifunc) ++bool is_sdp_pfvf(struct rvu *rvu, u16 pcifunc) + { +- u16 pf = rvu_get_pf(pcifunc); ++ u16 pf = rvu_get_pf(rvu->pdev, pcifunc); + u32 found = 0, i = 0; + + while (i < MAX_SDP) { +@@ -34,9 +34,9 @@ bool is_sdp_pfvf(u16 pcifunc) + return true; + } + +-bool is_sdp_pf(u16 pcifunc) ++bool is_sdp_pf(struct rvu *rvu, u16 pcifunc) + { +- return (is_sdp_pfvf(pcifunc) && ++ return (is_sdp_pfvf(rvu, pcifunc) && + !(pcifunc & RVU_PFVF_FUNC_MASK)); + } + +@@ -46,7 +46,7 @@ bool is_sdp_vf(struct rvu *rvu, u16 pcifunc) + if (!(pcifunc & ~RVU_PFVF_FUNC_MASK)) + return (rvu->vf_devid == RVU_SDP_VF_DEVID); + +- return (is_sdp_pfvf(pcifunc) && ++ return (is_sdp_pfvf(rvu, pcifunc) && + !!(pcifunc & RVU_PFVF_FUNC_MASK)); + } + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c +index 268efb7c1c15d..49ce38685a7e6 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c +@@ -93,7 +93,7 @@ static int rvu_switch_install_rules(struct rvu *rvu) + if (!is_pf_cgxmapped(rvu, pf)) + continue; + +- pcifunc = pf << 10; ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); + /* rvu_get_nix_blkaddr sets up the corresponding NIX block + * address and NIX RX and TX interfaces for a pcifunc. + * Generally it is called during attach call of a pcifunc but it +@@ -126,7 +126,7 @@ static int rvu_switch_install_rules(struct rvu *rvu) + + rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL); + for (vf = 0; vf < numvfs; vf++) { +- pcifunc = pf << 10 | ((vf + 1) & 0x3FF); ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, (vf + 1)); + rvu_get_nix_blkaddr(rvu, pcifunc); + + err = rvu_switch_install_rx_rule(rvu, pcifunc, 0x0); +@@ -236,7 +236,7 @@ void rvu_switch_disable(struct rvu *rvu) + if (!is_pf_cgxmapped(rvu, pf)) + continue; + +- pcifunc = pf << 10; ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); + err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF); + if (err) + dev_err(rvu->dev, +@@ -248,7 +248,7 @@ void rvu_switch_disable(struct rvu *rvu) + + rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL); + for (vf = 0; vf < numvfs; vf++) { +- pcifunc = pf << 10 | ((vf + 1) & 0x3FF); ++ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, (vf + 1)); + err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF); + if (err) + dev_err(rvu->dev, +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c +index a6500e3673f24..c691f07221540 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c +@@ -481,7 +481,7 @@ static int cn10k_outb_write_sa(struct otx2_nic *pf, struct qmem *sa_info) + goto set_available; + + /* Trigger CTX flush to write dirty data back to DRAM */ +- reg_val = FIELD_PREP(CPT_LF_CTX_FLUSH, sa_iova >> 7); ++ reg_val = FIELD_PREP(CPT_LF_CTX_FLUSH_CPTR, sa_iova >> 7); + otx2_write64(pf, CN10K_CPT_LF_CTX_FLUSH, reg_val); + + set_available: +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h +index 9965df0faa3e7..43fbce0d60390 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h +@@ -220,7 +220,7 @@ struct cpt_sg_s { + #define CPT_LF_Q_SIZE_DIV40 GENMASK_ULL(14, 0) + + /* CPT LF CTX Flush Register */ +-#define CPT_LF_CTX_FLUSH GENMASK_ULL(45, 0) ++#define CPT_LF_CTX_FLUSH_CPTR GENMASK_ULL(45, 0) + + #ifdef CONFIG_XFRM_OFFLOAD + int cn10k_ipsec_init(struct net_device *netdev); +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +index 5a6739d3a0688..f4fc915a0b5f1 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +@@ -28,6 +28,7 @@ + #include "otx2_reg.h" + #include "otx2_txrx.h" + #include "otx2_devlink.h" ++#include + #include + #include "qos.h" + #include "rep.h" +@@ -900,21 +901,11 @@ MBOX_UP_MCS_MESSAGES + /* Time to wait before watchdog kicks off */ + #define OTX2_TX_TIMEOUT (100 * HZ) + +-#define RVU_PFVF_PF_SHIFT 10 +-#define RVU_PFVF_PF_MASK 0x3F +-#define RVU_PFVF_FUNC_SHIFT 0 +-#define RVU_PFVF_FUNC_MASK 0x3FF +- + static inline bool is_otx2_vf(u16 pcifunc) + { + return !!(pcifunc & RVU_PFVF_FUNC_MASK); + } + +-static inline int rvu_get_pf(u16 pcifunc) +-{ +- return (pcifunc >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK; +-} +- + static inline dma_addr_t otx2_dma_map_page(struct otx2_nic *pfvf, + struct page *page, + size_t offset, size_t size, +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +index 74d0b6bac600a..c6d2f2249cc35 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +@@ -206,7 +206,8 @@ static int otx2_register_flr_me_intr(struct otx2_nic *pf, int numvfs) + + /* Register ME interrupt handler*/ + irq_name = &hw->irq_name[RVU_PF_INT_VEC_VFME0 * NAME_SIZE]; +- snprintf(irq_name, NAME_SIZE, "RVUPF%d_ME0", rvu_get_pf(pf->pcifunc)); ++ snprintf(irq_name, NAME_SIZE, "RVUPF%d_ME0", ++ rvu_get_pf(pf->pdev, pf->pcifunc)); + ret = request_irq(pci_irq_vector(pf->pdev, RVU_PF_INT_VEC_VFME0), + otx2_pf_me_intr_handler, 0, irq_name, pf); + if (ret) { +@@ -216,7 +217,8 @@ static int otx2_register_flr_me_intr(struct otx2_nic *pf, int numvfs) + + /* Register FLR interrupt handler */ + irq_name = &hw->irq_name[RVU_PF_INT_VEC_VFFLR0 * NAME_SIZE]; +- snprintf(irq_name, NAME_SIZE, "RVUPF%d_FLR0", rvu_get_pf(pf->pcifunc)); ++ snprintf(irq_name, NAME_SIZE, "RVUPF%d_FLR0", ++ rvu_get_pf(pf->pdev, pf->pcifunc)); + ret = request_irq(pci_irq_vector(pf->pdev, RVU_PF_INT_VEC_VFFLR0), + otx2_pf_flr_intr_handler, 0, irq_name, pf); + if (ret) { +@@ -228,7 +230,7 @@ static int otx2_register_flr_me_intr(struct otx2_nic *pf, int numvfs) + if (numvfs > 64) { + irq_name = &hw->irq_name[RVU_PF_INT_VEC_VFME1 * NAME_SIZE]; + snprintf(irq_name, NAME_SIZE, "RVUPF%d_ME1", +- rvu_get_pf(pf->pcifunc)); ++ rvu_get_pf(pf->pdev, pf->pcifunc)); + ret = request_irq(pci_irq_vector + (pf->pdev, RVU_PF_INT_VEC_VFME1), + otx2_pf_me_intr_handler, 0, irq_name, pf); +@@ -238,7 +240,7 @@ static int otx2_register_flr_me_intr(struct otx2_nic *pf, int numvfs) + } + irq_name = &hw->irq_name[RVU_PF_INT_VEC_VFFLR1 * NAME_SIZE]; + snprintf(irq_name, NAME_SIZE, "RVUPF%d_FLR1", +- rvu_get_pf(pf->pcifunc)); ++ rvu_get_pf(pf->pdev, pf->pcifunc)); + ret = request_irq(pci_irq_vector + (pf->pdev, RVU_PF_INT_VEC_VFFLR1), + otx2_pf_flr_intr_handler, 0, irq_name, pf); +@@ -701,7 +703,7 @@ static int otx2_register_pfvf_mbox_intr(struct otx2_nic *pf, int numvfs) + irq_name = &hw->irq_name[RVU_PF_INT_VEC_VFPF_MBOX0 * NAME_SIZE]; + if (pf->pcifunc) + snprintf(irq_name, NAME_SIZE, +- "RVUPF%d_VF Mbox0", rvu_get_pf(pf->pcifunc)); ++ "RVUPF%d_VF Mbox0", rvu_get_pf(pf->pdev, pf->pcifunc)); + else + snprintf(irq_name, NAME_SIZE, "RVUPF_VF Mbox0"); + err = request_irq(pci_irq_vector(pf->pdev, RVU_PF_INT_VEC_VFPF_MBOX0), +@@ -717,7 +719,8 @@ static int otx2_register_pfvf_mbox_intr(struct otx2_nic *pf, int numvfs) + irq_name = &hw->irq_name[RVU_PF_INT_VEC_VFPF_MBOX1 * NAME_SIZE]; + if (pf->pcifunc) + snprintf(irq_name, NAME_SIZE, +- "RVUPF%d_VF Mbox1", rvu_get_pf(pf->pcifunc)); ++ "RVUPF%d_VF Mbox1", ++ rvu_get_pf(pf->pdev, pf->pcifunc)); + else + snprintf(irq_name, NAME_SIZE, "RVUPF_VF Mbox1"); + err = request_irq(pci_irq_vector(pf->pdev, +@@ -1972,7 +1975,7 @@ int otx2_open(struct net_device *netdev) + if (err) { + dev_err(pf->dev, + "RVUPF%d: IRQ registration failed for QERR\n", +- rvu_get_pf(pf->pcifunc)); ++ rvu_get_pf(pf->pdev, pf->pcifunc)); + goto err_disable_napi; + } + +@@ -1990,7 +1993,7 @@ int otx2_open(struct net_device *netdev) + if (name_len >= NAME_SIZE) { + dev_err(pf->dev, + "RVUPF%d: IRQ registration failed for CQ%d, irq name is too long\n", +- rvu_get_pf(pf->pcifunc), qidx); ++ rvu_get_pf(pf->pdev, pf->pcifunc), qidx); + err = -EINVAL; + goto err_free_cints; + } +@@ -2001,7 +2004,7 @@ int otx2_open(struct net_device *netdev) + if (err) { + dev_err(pf->dev, + "RVUPF%d: IRQ registration failed for CQ%d\n", +- rvu_get_pf(pf->pcifunc), qidx); ++ rvu_get_pf(pf->pdev, pf->pcifunc), qidx); + goto err_free_cints; + } + vec++; +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h +index e3aee6e362151..858f084b9d474 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h +@@ -138,36 +138,6 @@ + #define NIX_LF_CINTX_ENA_W1S(a) (NIX_LFBASE | 0xD40 | (a) << 12) + #define NIX_LF_CINTX_ENA_W1C(a) (NIX_LFBASE | 0xD50 | (a) << 12) + +-/* NIX AF transmit scheduler registers */ +-#define NIX_AF_SMQX_CFG(a) (0x700 | (u64)(a) << 16) +-#define NIX_AF_TL4X_SDP_LINK_CFG(a) (0xB10 | (u64)(a) << 16) +-#define NIX_AF_TL1X_SCHEDULE(a) (0xC00 | (u64)(a) << 16) +-#define NIX_AF_TL1X_CIR(a) (0xC20 | (u64)(a) << 16) +-#define NIX_AF_TL1X_TOPOLOGY(a) (0xC80 | (u64)(a) << 16) +-#define NIX_AF_TL2X_PARENT(a) (0xE88 | (u64)(a) << 16) +-#define NIX_AF_TL2X_SCHEDULE(a) (0xE00 | (u64)(a) << 16) +-#define NIX_AF_TL2X_TOPOLOGY(a) (0xE80 | (u64)(a) << 16) +-#define NIX_AF_TL2X_CIR(a) (0xE20 | (u64)(a) << 16) +-#define NIX_AF_TL2X_PIR(a) (0xE30 | (u64)(a) << 16) +-#define NIX_AF_TL3X_PARENT(a) (0x1088 | (u64)(a) << 16) +-#define NIX_AF_TL3X_SCHEDULE(a) (0x1000 | (u64)(a) << 16) +-#define NIX_AF_TL3X_SHAPE(a) (0x1010 | (u64)(a) << 16) +-#define NIX_AF_TL3X_CIR(a) (0x1020 | (u64)(a) << 16) +-#define NIX_AF_TL3X_PIR(a) (0x1030 | (u64)(a) << 16) +-#define NIX_AF_TL3X_TOPOLOGY(a) (0x1080 | (u64)(a) << 16) +-#define NIX_AF_TL4X_PARENT(a) (0x1288 | (u64)(a) << 16) +-#define NIX_AF_TL4X_SCHEDULE(a) (0x1200 | (u64)(a) << 16) +-#define NIX_AF_TL4X_SHAPE(a) (0x1210 | (u64)(a) << 16) +-#define NIX_AF_TL4X_CIR(a) (0x1220 | (u64)(a) << 16) +-#define NIX_AF_TL4X_PIR(a) (0x1230 | (u64)(a) << 16) +-#define NIX_AF_TL4X_TOPOLOGY(a) (0x1280 | (u64)(a) << 16) +-#define NIX_AF_MDQX_SCHEDULE(a) (0x1400 | (u64)(a) << 16) +-#define NIX_AF_MDQX_SHAPE(a) (0x1410 | (u64)(a) << 16) +-#define NIX_AF_MDQX_CIR(a) (0x1420 | (u64)(a) << 16) +-#define NIX_AF_MDQX_PIR(a) (0x1430 | (u64)(a) << 16) +-#define NIX_AF_MDQX_PARENT(a) (0x1480 | (u64)(a) << 16) +-#define NIX_AF_TL3_TL2X_LINKX_CFG(a, b) (0x1700 | (u64)(a) << 16 | (b) << 3) +- + /* LMT LF registers */ + #define LMT_LFBASE BIT_ULL(RVU_FUNC_BLKADDR_SHIFT) + #define LMT_LF_LMTLINEX(a) (LMT_LFBASE | 0x000 | (a) << 12) +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +index 9a226ca744254..5f80b23c5335c 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +@@ -467,7 +467,8 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic, + target = act->dev; + if (target->dev.parent) { + priv = netdev_priv(target); +- if (rvu_get_pf(nic->pcifunc) != rvu_get_pf(priv->pcifunc)) { ++ if (rvu_get_pf(nic->pdev, nic->pcifunc) != ++ rvu_get_pf(nic->pdev, priv->pcifunc)) { + NL_SET_ERR_MSG_MOD(extack, + "can't redirect to other pf/vf"); + return -EOPNOTSUPP; +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c +index d97be15d80561..b476733a02345 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c +@@ -244,10 +244,10 @@ static int rvu_rep_devlink_port_register(struct rep_dev *rep) + + if (!(rep->pcifunc & RVU_PFVF_FUNC_MASK)) { + attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; +- attrs.phys.port_number = rvu_get_pf(rep->pcifunc); ++ attrs.phys.port_number = rvu_get_pf(priv->pdev, rep->pcifunc); + } else { + attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF; +- attrs.pci_vf.pf = rvu_get_pf(rep->pcifunc); ++ attrs.pci_vf.pf = rvu_get_pf(priv->pdev, rep->pcifunc); + attrs.pci_vf.vf = rep->pcifunc & RVU_PFVF_FUNC_MASK; + } + +@@ -683,7 +683,8 @@ int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack *extack) + rep->pcifunc = pcifunc; + + snprintf(ndev->name, sizeof(ndev->name), "Rpf%dvf%d", +- rvu_get_pf(pcifunc), (pcifunc & RVU_PFVF_FUNC_MASK)); ++ rvu_get_pf(priv->pdev, pcifunc), ++ (pcifunc & RVU_PFVF_FUNC_MASK)); + + ndev->hw_features = (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | NETIF_F_RXHASH | +diff --git a/include/linux/soc/marvell/silicons.h b/include/linux/soc/marvell/silicons.h +new file mode 100644 +index 0000000000000..66bb9bfaf17d5 +--- /dev/null ++++ b/include/linux/soc/marvell/silicons.h +@@ -0,0 +1,25 @@ ++/* SPDX-License-Identifier: GPL-2.0-only ++ * Copyright (C) 2024 Marvell. ++ */ ++ ++#ifndef __SOC_SILICON_H ++#define __SOC_SILICON_H ++ ++#include ++#include ++ ++#if defined(CONFIG_ARM64) ++ ++#define CN20K_CHIPID 0x20 ++/* ++ * Silicon check for CN20K family ++ */ ++static inline bool is_cn20k(struct pci_dev *pdev) ++{ ++ return (pdev->subsystem_device & 0xFF) == CN20K_CHIPID; ++} ++#else ++#define is_cn20k(pdev) ((void)(pdev), 0) ++#endif ++ ++#endif /* __SOC_SILICON_H */ +-- +2.50.1 + diff --git a/queue-6.16/octeontx2-vf-fix-max-packet-length-errors.patch b/queue-6.16/octeontx2-vf-fix-max-packet-length-errors.patch new file mode 100644 index 0000000000..6256088c4d --- /dev/null +++ b/queue-6.16/octeontx2-vf-fix-max-packet-length-errors.patch @@ -0,0 +1,156 @@ +From 650741f3c3c07fe4b4ca8278ea3f501591d98e1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Aug 2025 11:55:28 +0530 +Subject: Octeontx2-vf: Fix max packet length errors + +From: Hariprasad Kelam + +[ Upstream commit a64494aafc56939564e3e9e57f99df5c27204e04 ] + +Once driver submits the packets to the hardware, each packet +traverse through multiple transmit levels in the following +order: + SMQ -> TL4 -> TL3 -> TL2 -> TL1 + +The SMQ supports configurable minimum and maximum packet sizes. +It enters to a hang state, if driver submits packets with +out of bound lengths. + +To avoid the same, implement packet length validation before +submitting packets to the hardware. Increment tx_dropped counter +on failure. + +Fixes: 3184fb5ba96e ("octeontx2-vf: Virtual function driver support") +Fixes: 22f858796758 ("octeontx2-pf: Add basic net_device_ops") +Fixes: 3ca6c4c882a7 ("octeontx2-pf: Add packet transmission support") +Signed-off-by: Hariprasad Kelam +Link: https://patch.msgid.link/20250821062528.1697992-1-hkelam@marvell.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../ethernet/marvell/octeontx2/nic/otx2_common.c | 4 +++- + .../ethernet/marvell/octeontx2/nic/otx2_common.h | 1 + + .../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 3 +++ + .../net/ethernet/marvell/octeontx2/nic/otx2_vf.c | 10 ++++++++++ + drivers/net/ethernet/marvell/octeontx2/nic/rep.c | 13 ++++++++++++- + drivers/net/ethernet/marvell/octeontx2/nic/rep.h | 1 + + 6 files changed, 30 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +index 6b5c9536d26d3..6f7b608261d9c 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +@@ -124,7 +124,9 @@ void otx2_get_dev_stats(struct otx2_nic *pfvf) + dev_stats->rx_ucast_frames; + + dev_stats->tx_bytes = OTX2_GET_TX_STATS(TX_OCTS); +- dev_stats->tx_drops = OTX2_GET_TX_STATS(TX_DROP); ++ dev_stats->tx_drops = OTX2_GET_TX_STATS(TX_DROP) + ++ (unsigned long)atomic_long_read(&dev_stats->tx_discards); ++ + dev_stats->tx_bcast_frames = OTX2_GET_TX_STATS(TX_BCAST); + dev_stats->tx_mcast_frames = OTX2_GET_TX_STATS(TX_MCAST); + dev_stats->tx_ucast_frames = OTX2_GET_TX_STATS(TX_UCAST); +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +index ca0e6ab12cebe..5a6739d3a0688 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +@@ -149,6 +149,7 @@ struct otx2_dev_stats { + u64 tx_bcast_frames; + u64 tx_mcast_frames; + u64 tx_drops; ++ atomic_long_t tx_discards; + }; + + /* Driver counted stats */ +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +index db7c466fdc39e..74d0b6bac600a 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +@@ -2153,6 +2153,7 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev) + { + struct otx2_nic *pf = netdev_priv(netdev); + int qidx = skb_get_queue_mapping(skb); ++ struct otx2_dev_stats *dev_stats; + struct otx2_snd_queue *sq; + struct netdev_queue *txq; + int sq_idx; +@@ -2165,6 +2166,8 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev) + /* Check for minimum and maximum packet length */ + if (skb->len <= ETH_HLEN || + (!skb_shinfo(skb)->gso_size && skb->len > pf->tx_max_pktlen)) { ++ dev_stats = &pf->hw.dev_stats; ++ atomic_long_inc(&dev_stats->tx_discards); + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c +index 8a8b598bd389b..76dd2e965cf03 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c +@@ -391,9 +391,19 @@ static netdev_tx_t otx2vf_xmit(struct sk_buff *skb, struct net_device *netdev) + { + struct otx2_nic *vf = netdev_priv(netdev); + int qidx = skb_get_queue_mapping(skb); ++ struct otx2_dev_stats *dev_stats; + struct otx2_snd_queue *sq; + struct netdev_queue *txq; + ++ /* Check for minimum and maximum packet length */ ++ if (skb->len <= ETH_HLEN || ++ (!skb_shinfo(skb)->gso_size && skb->len > vf->tx_max_pktlen)) { ++ dev_stats = &vf->hw.dev_stats; ++ atomic_long_inc(&dev_stats->tx_discards); ++ dev_kfree_skb(skb); ++ return NETDEV_TX_OK; ++ } ++ + sq = &vf->qset.sq[qidx]; + txq = netdev_get_tx_queue(netdev, qidx); + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c +index 2cd3da3b68432..d97be15d80561 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c +@@ -371,7 +371,8 @@ static void rvu_rep_get_stats(struct work_struct *work) + stats->rx_mcast_frames = rsp->rx.mcast; + stats->tx_bytes = rsp->tx.octs; + stats->tx_frames = rsp->tx.ucast + rsp->tx.bcast + rsp->tx.mcast; +- stats->tx_drops = rsp->tx.drop; ++ stats->tx_drops = rsp->tx.drop + ++ (unsigned long)atomic_long_read(&stats->tx_discards); + exit: + mutex_unlock(&priv->mbox.lock); + } +@@ -418,6 +419,16 @@ static netdev_tx_t rvu_rep_xmit(struct sk_buff *skb, struct net_device *dev) + struct otx2_nic *pf = rep->mdev; + struct otx2_snd_queue *sq; + struct netdev_queue *txq; ++ struct rep_stats *stats; ++ ++ /* Check for minimum and maximum packet length */ ++ if (skb->len <= ETH_HLEN || ++ (!skb_shinfo(skb)->gso_size && skb->len > pf->tx_max_pktlen)) { ++ stats = &rep->stats; ++ atomic_long_inc(&stats->tx_discards); ++ dev_kfree_skb(skb); ++ return NETDEV_TX_OK; ++ } + + sq = &pf->qset.sq[rep->rep_id]; + txq = netdev_get_tx_queue(dev, 0); +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/rep.h b/drivers/net/ethernet/marvell/octeontx2/nic/rep.h +index 38446b3e4f13c..5bc9e2c7d800b 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.h ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.h +@@ -27,6 +27,7 @@ struct rep_stats { + u64 tx_bytes; + u64 tx_frames; + u64 tx_drops; ++ atomic_long_t tx_discards; + }; + + struct rep_dev { +-- +2.50.1 + diff --git a/queue-6.16/of-reserved_mem-restructure-call-site-for-dma_contig.patch b/queue-6.16/of-reserved_mem-restructure-call-site-for-dma_contig.patch new file mode 100644 index 0000000000..575cbe4854 --- /dev/null +++ b/queue-6.16/of-reserved_mem-restructure-call-site-for-dma_contig.patch @@ -0,0 +1,101 @@ +From 011cc4693733b49f9ce512a632963bc49f95b7ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Aug 2025 10:24:21 -0700 +Subject: of: reserved_mem: Restructure call site for + dma_contiguous_early_fixup() + +From: Oreoluwa Babatunde + +[ Upstream commit 2c223f7239f376a90d71903ec474ba887cf21d94 ] + +Restructure the call site for dma_contiguous_early_fixup() to +where the reserved_mem nodes are being parsed from the DT so that +dma_mmu_remap[] is populated before dma_contiguous_remap() is called. + +Fixes: 8a6e02d0c00e ("of: reserved_mem: Restructure how the reserved memory regions are processed") +Signed-off-by: Oreoluwa Babatunde +Tested-by: William Zhang +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20250806172421.2748302-1-oreoluwa.babatunde@oss.qualcomm.com +Signed-off-by: Sasha Levin +--- + drivers/of/of_reserved_mem.c | 16 ++++++++++++---- + include/linux/dma-map-ops.h | 3 +++ + kernel/dma/contiguous.c | 2 -- + 3 files changed, 15 insertions(+), 6 deletions(-) + +diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c +index d3b7c4ae429c7..2e9ea751ed2df 100644 +--- a/drivers/of/of_reserved_mem.c ++++ b/drivers/of/of_reserved_mem.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include "of_private.h" + +@@ -175,13 +176,17 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, + base = dt_mem_next_cell(dt_root_addr_cells, &prop); + size = dt_mem_next_cell(dt_root_size_cells, &prop); + +- if (size && +- early_init_dt_reserve_memory(base, size, nomap) == 0) ++ if (size && early_init_dt_reserve_memory(base, size, nomap) == 0) { ++ /* Architecture specific contiguous memory fixup. */ ++ if (of_flat_dt_is_compatible(node, "shared-dma-pool") && ++ of_get_flat_dt_prop(node, "reusable", NULL)) ++ dma_contiguous_early_fixup(base, size); + pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n", + uname, &base, (unsigned long)(size / SZ_1M)); +- else ++ } else { + pr_err("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n", + uname, &base, (unsigned long)(size / SZ_1M)); ++ } + + len -= t_len; + } +@@ -472,7 +477,10 @@ static int __init __reserved_mem_alloc_size(unsigned long node, const char *unam + uname, (unsigned long)(size / SZ_1M)); + return -ENOMEM; + } +- ++ /* Architecture specific contiguous memory fixup. */ ++ if (of_flat_dt_is_compatible(node, "shared-dma-pool") && ++ of_get_flat_dt_prop(node, "reusable", NULL)) ++ dma_contiguous_early_fixup(base, size); + /* Save region in the reserved_mem array */ + fdt_reserved_mem_save_node(node, uname, base, size); + return 0; +diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h +index f48e5fb88bd5d..332b80c42b6f3 100644 +--- a/include/linux/dma-map-ops.h ++++ b/include/linux/dma-map-ops.h +@@ -153,6 +153,9 @@ static inline void dma_free_contiguous(struct device *dev, struct page *page, + { + __free_pages(page, get_order(size)); + } ++static inline void dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) ++{ ++} + #endif /* CONFIG_DMA_CMA*/ + + #ifdef CONFIG_DMA_DECLARE_COHERENT +diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c +index 67af8a55185d9..d9b9dcba6ff7c 100644 +--- a/kernel/dma/contiguous.c ++++ b/kernel/dma/contiguous.c +@@ -483,8 +483,6 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem) + pr_err("Reserved memory: unable to setup CMA region\n"); + return err; + } +- /* Architecture specific contiguous memory fixup. */ +- dma_contiguous_early_fixup(rmem->base, rmem->size); + + if (default_cma) + dma_contiguous_default_area = cma; +-- +2.50.1 + diff --git a/queue-6.16/page_pool-fix-incorrect-mp_ops-error-handling.patch b/queue-6.16/page_pool-fix-incorrect-mp_ops-error-handling.patch new file mode 100644 index 0000000000..2fbf095b8a --- /dev/null +++ b/queue-6.16/page_pool-fix-incorrect-mp_ops-error-handling.patch @@ -0,0 +1,46 @@ +From c53ae8ac389477d45e1cc59d48be124c3c8e7ff8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Aug 2025 03:03:46 +0000 +Subject: page_pool: fix incorrect mp_ops error handling + +From: Mina Almasry + +[ Upstream commit abadf0ff63be488dc502ecfc9f622929a21b7117 ] + +Minor fix to the memory provider error handling, we should be jumping to +free_ptr_ring in this error case rather than returning directly. + +Found by code-inspection. + +Cc: skhawaja@google.com + +Fixes: b400f4b87430 ("page_pool: Set `dma_sync` to false for devmem memory provider") +Signed-off-by: Mina Almasry +Reviewed-by: Samiullah Khawaja +Link: https://patch.msgid.link/20250821030349.705244-1-almasrymina@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/page_pool.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/core/page_pool.c b/net/core/page_pool.c +index 368412baad264..e14d743554ec1 100644 +--- a/net/core/page_pool.c ++++ b/net/core/page_pool.c +@@ -287,8 +287,10 @@ static int page_pool_init(struct page_pool *pool, + } + + if (pool->mp_ops) { +- if (!pool->dma_map || !pool->dma_sync) +- return -EOPNOTSUPP; ++ if (!pool->dma_map || !pool->dma_sync) { ++ err = -EOPNOTSUPP; ++ goto free_ptr_ring; ++ } + + if (WARN_ON(!is_kernel_rodata((unsigned long)pool->mp_ops))) { + err = -EFAULT; +-- +2.50.1 + diff --git a/queue-6.16/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch b/queue-6.16/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch new file mode 100644 index 0000000000..843a53da42 --- /dev/null +++ b/queue-6.16/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch @@ -0,0 +1,135 @@ +From 203965066ac6acb399e44104df66d14c343cebad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 08:55:43 +0200 +Subject: phy: mscc: Fix when PTP clock is register and unregister + +From: Horatiu Vultur + +[ Upstream commit 882e57cbc7204662f6c5672d5b04336c1d790b03 ] + +It looks like that every time when the interface was set down and up the +driver was creating a new ptp clock. On top of this the function +ptp_clock_unregister was never called. +Therefore fix this by calling ptp_clock_register and initialize the +mii_ts struct inside the probe function and call ptp_clock_unregister when +driver is removed. + +Fixes: 7d272e63e0979d ("net: phy: mscc: timestamping and PHC support") +Signed-off-by: Horatiu Vultur +Reviewed-by: Vadim Fedorenko +Reviewed-by: Vladimir Oltean +Link: https://patch.msgid.link/20250825065543.2916334-1-horatiu.vultur@microchip.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mscc/mscc.h | 4 ++++ + drivers/net/phy/mscc/mscc_main.c | 4 +--- + drivers/net/phy/mscc/mscc_ptp.c | 34 ++++++++++++++++++++------------ + 3 files changed, 26 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h +index 58c6d47fbe046..2bfe314ef881c 100644 +--- a/drivers/net/phy/mscc/mscc.h ++++ b/drivers/net/phy/mscc/mscc.h +@@ -481,6 +481,7 @@ static inline void vsc8584_config_macsec_intr(struct phy_device *phydev) + void vsc85xx_link_change_notify(struct phy_device *phydev); + void vsc8584_config_ts_intr(struct phy_device *phydev); + int vsc8584_ptp_init(struct phy_device *phydev); ++void vsc8584_ptp_deinit(struct phy_device *phydev); + int vsc8584_ptp_probe_once(struct phy_device *phydev); + int vsc8584_ptp_probe(struct phy_device *phydev); + irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev); +@@ -495,6 +496,9 @@ static inline int vsc8584_ptp_init(struct phy_device *phydev) + { + return 0; + } ++static inline void vsc8584_ptp_deinit(struct phy_device *phydev) ++{ ++} + static inline int vsc8584_ptp_probe_once(struct phy_device *phydev) + { + return 0; +diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c +index c3209cf00e960..ac9b6130ef502 100644 +--- a/drivers/net/phy/mscc/mscc_main.c ++++ b/drivers/net/phy/mscc/mscc_main.c +@@ -2338,9 +2338,7 @@ static int vsc85xx_probe(struct phy_device *phydev) + + static void vsc85xx_remove(struct phy_device *phydev) + { +- struct vsc8531_private *priv = phydev->priv; +- +- skb_queue_purge(&priv->rx_skbs_list); ++ vsc8584_ptp_deinit(phydev); + } + + /* Microsemi VSC85xx PHYs */ +diff --git a/drivers/net/phy/mscc/mscc_ptp.c b/drivers/net/phy/mscc/mscc_ptp.c +index de6c7312e8f29..72847320cb652 100644 +--- a/drivers/net/phy/mscc/mscc_ptp.c ++++ b/drivers/net/phy/mscc/mscc_ptp.c +@@ -1298,7 +1298,6 @@ static void vsc8584_set_input_clk_configured(struct phy_device *phydev) + + static int __vsc8584_init_ptp(struct phy_device *phydev) + { +- struct vsc8531_private *vsc8531 = phydev->priv; + static const u32 ltc_seq_e[] = { 0, 400000, 0, 0, 0 }; + static const u8 ltc_seq_a[] = { 8, 6, 5, 4, 2 }; + u32 val; +@@ -1515,17 +1514,7 @@ static int __vsc8584_init_ptp(struct phy_device *phydev) + + vsc85xx_ts_eth_cmp1_sig(phydev); + +- vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; +- vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; +- vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; +- vsc8531->mii_ts.ts_info = vsc85xx_ts_info; +- phydev->mii_ts = &vsc8531->mii_ts; +- +- memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); +- +- vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, +- &phydev->mdio.dev); +- return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); ++ return 0; + } + + void vsc8584_config_ts_intr(struct phy_device *phydev) +@@ -1552,6 +1541,16 @@ int vsc8584_ptp_init(struct phy_device *phydev) + return 0; + } + ++void vsc8584_ptp_deinit(struct phy_device *phydev) ++{ ++ struct vsc8531_private *vsc8531 = phydev->priv; ++ ++ if (vsc8531->ptp->ptp_clock) { ++ ptp_clock_unregister(vsc8531->ptp->ptp_clock); ++ skb_queue_purge(&vsc8531->rx_skbs_list); ++ } ++} ++ + irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev) + { + struct vsc8531_private *priv = phydev->priv; +@@ -1612,7 +1611,16 @@ int vsc8584_ptp_probe(struct phy_device *phydev) + + vsc8531->ptp->phydev = phydev; + +- return 0; ++ vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; ++ vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; ++ vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; ++ vsc8531->mii_ts.ts_info = vsc85xx_ts_info; ++ phydev->mii_ts = &vsc8531->mii_ts; ++ ++ memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); ++ vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, ++ &phydev->mdio.dev); ++ return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); + } + + int vsc8584_ptp_probe_once(struct phy_device *phydev) +-- +2.50.1 + diff --git a/queue-6.16/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch b/queue-6.16/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch new file mode 100644 index 0000000000..a4f088253f --- /dev/null +++ b/queue-6.16/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch @@ -0,0 +1,68 @@ +From c95e064ba88c7e1c685a340d958000e362bea7a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 May 2025 10:11:04 +0530 +Subject: powerpc/kvm: Fix ifdef to remove build warning + +From: Madhavan Srinivasan + +[ Upstream commit 88688a2c8ac6c8036d983ad8b34ce191c46a10aa ] + +When compiling for pseries or powernv defconfig with "make C=1", +these warning were reported bu sparse tool in powerpc/kernel/kvm.c + +arch/powerpc/kernel/kvm.c:635:9: warning: switch with no cases +arch/powerpc/kernel/kvm.c:646:9: warning: switch with no cases + +Currently #ifdef were added after the switch case which are specific +for BOOKE and PPC_BOOK3S_32. These are not enabled in pseries/powernv +defconfig. Fix it by moving the #ifdef before switch(){} + +Fixes: cbe487fac7fc0 ("KVM: PPC: Add mtsrin PV code") +Tested-by: Venkat Rao Bagalkote +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250518044107.39928-1-maddy@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/kvm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c +index 5b3c093611baf..7209d00a9c257 100644 +--- a/arch/powerpc/kernel/kvm.c ++++ b/arch/powerpc/kernel/kvm.c +@@ -632,19 +632,19 @@ static void __init kvm_check_ins(u32 *inst, u32 features) + #endif + } + +- switch (inst_no_rt & ~KVM_MASK_RB) { + #ifdef CONFIG_PPC_BOOK3S_32 ++ switch (inst_no_rt & ~KVM_MASK_RB) { + case KVM_INST_MTSRIN: + if (features & KVM_MAGIC_FEAT_SR) { + u32 inst_rb = _inst & KVM_MASK_RB; + kvm_patch_ins_mtsrin(inst, inst_rt, inst_rb); + } + break; +-#endif + } ++#endif + +- switch (_inst) { + #ifdef CONFIG_BOOKE ++ switch (_inst) { + case KVM_INST_WRTEEI_0: + kvm_patch_ins_wrteei_0(inst); + break; +@@ -652,8 +652,8 @@ static void __init kvm_check_ins(u32 *inst, u32 features) + case KVM_INST_WRTEEI_1: + kvm_patch_ins_wrtee(inst, 0, 1); + break; +-#endif + } ++#endif + } + + extern u32 kvm_template_start[]; +-- +2.50.1 + diff --git a/queue-6.16/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch b/queue-6.16/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch new file mode 100644 index 0000000000..850ab6c6b5 --- /dev/null +++ b/queue-6.16/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch @@ -0,0 +1,72 @@ +From fa513dc18c41cbc491a7e1c04372864eab73042d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Aug 2025 14:13:14 +0000 +Subject: sctp: initialize more fields in sctp_v6_from_sk() + +From: Eric Dumazet + +[ Upstream commit 2e8750469242cad8f01f320131fd5a6f540dbb99 ] + +syzbot found that sin6_scope_id was not properly initialized, +leading to undefined behavior. + +Clear sin6_scope_id and sin6_flowinfo. + +BUG: KMSAN: uninit-value in __sctp_v6_cmp_addr+0x887/0x8c0 net/sctp/ipv6.c:649 + __sctp_v6_cmp_addr+0x887/0x8c0 net/sctp/ipv6.c:649 + sctp_inet6_cmp_addr+0x4f2/0x510 net/sctp/ipv6.c:983 + sctp_bind_addr_conflict+0x22a/0x3b0 net/sctp/bind_addr.c:390 + sctp_get_port_local+0x21eb/0x2440 net/sctp/socket.c:8452 + sctp_get_port net/sctp/socket.c:8523 [inline] + sctp_listen_start net/sctp/socket.c:8567 [inline] + sctp_inet_listen+0x710/0xfd0 net/sctp/socket.c:8636 + __sys_listen_socket net/socket.c:1912 [inline] + __sys_listen net/socket.c:1927 [inline] + __do_sys_listen net/socket.c:1932 [inline] + __se_sys_listen net/socket.c:1930 [inline] + __x64_sys_listen+0x343/0x4c0 net/socket.c:1930 + x64_sys_call+0x271d/0x3e20 arch/x86/include/generated/asm/syscalls_64.h:51 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xd9/0x210 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Local variable addr.i.i created at: + sctp_get_port net/sctp/socket.c:8515 [inline] + sctp_listen_start net/sctp/socket.c:8567 [inline] + sctp_inet_listen+0x650/0xfd0 net/sctp/socket.c:8636 + __sys_listen_socket net/socket.c:1912 [inline] + __sys_listen net/socket.c:1927 [inline] + __do_sys_listen net/socket.c:1932 [inline] + __se_sys_listen net/socket.c:1930 [inline] + __x64_sys_listen+0x343/0x4c0 net/socket.c:1930 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+e69f06a0f30116c68056@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68adc0a2.050a0220.37038e.00c4.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Marcelo Ricardo Leitner +Acked-by: Xin Long +Link: https://patch.msgid.link/20250826141314.1802610-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/ipv6.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c +index a9ed2ccab1bdb..2bb5e19e10caa 100644 +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -546,7 +546,9 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) + { + addr->v6.sin6_family = AF_INET6; + addr->v6.sin6_port = 0; ++ addr->v6.sin6_flowinfo = 0; + addr->v6.sin6_addr = sk->sk_v6_rcv_saddr; ++ addr->v6.sin6_scope_id = 0; + } + + /* Initialize sk->sk_rcv_saddr from sctp_addr. */ +-- +2.50.1 + diff --git a/queue-6.16/series b/queue-6.16/series index 848ae1e826..445048d92a 100644 --- a/queue-6.16/series +++ b/queue-6.16/series @@ -25,3 +25,79 @@ erofs-fix-atomic-context-detection-when-config_debug.patch io_uring-io-wq-add-check-free-worker-before-create-n.patch platform-x86-int3472-add-hpd-pin-support.patch vhost-net-protect-ubufs-with-rcu-read-lock-in-vhost_net_ubuf_put.patch +net-ipv4-fix-regression-in-local-broadcast-routes.patch +drm-msm-defer-fd_install-in-submit-ioctl.patch +of-reserved_mem-restructure-call-site-for-dma_contig.patch +hid-intel-thc-hid-intel-quicki2c-fix-acpi-dsd-icrs-i.patch +hid-intel-thc-hid-intel-thc-fix-incorrect-pointer-ar.patch +hid-intel-thc-hid-intel-quicki2c-enhance-driver-re-i.patch +drm-msm-kms-move-snapshot-init-earlier-in-kms-init.patch +drm-msm-dpu-correct-dpu_plane_virtual_atomic_check.patch +drm-msm-update-the-high-bitfield-of-certain-dsi-regi.patch +drm-mediatek-add-error-handling-for-old-state-crtc-i.patch +powerpc-kvm-fix-ifdef-to-remove-build-warning.patch +hid-input-rename-hidinput_set_battery_charge_status.patch +hid-input-report-battery-status-changes-immediately.patch +idpf-add-support-for-tx-refillqs-in-flow-scheduling-.patch +idpf-simplify-and-fix-splitq-tx-packet-rollback-erro.patch +idpf-replace-flow-scheduling-buffer-ring-with-buffer.patch +idpf-stop-tx-if-there-are-insufficient-buffer-resour.patch +net-macb-fix-unregister_netdev-call-order-in-macb_re.patch +bluetooth-hci_conn-make-unacked-packet-handling-more.patch +bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch +bluetooth-hci_event-mark-connection-as-closed-during.patch +bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch +bluetooth-hci_event-disconnect-device-when-big-sync-.patch +bluetooth-hci_sync-fix-set_local_name-race-condition.patch +page_pool-fix-incorrect-mp_ops-error-handling.patch +octeontx2-vf-fix-max-packet-length-errors.patch +atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch +drm-nouveau-remove-unused-increment-in-gm200_flcn_pi.patch +drm-nouveau-remove-unused-memory-target-test.patch +ice-fix-null-pointer-dereference-in-ice_unplug_aux_d.patch +ice-don-t-leave-device-non-functional-if-tx-schedule.patch +ice-use-fixed-adapter-index-for-e825c-embedded-devic.patch +ice-fix-incorrect-counter-for-buffer-allocation-fail.patch +ixgbe-fix-ixgbe_orom_civd_info-struct-layout.patch +dt-bindings-display-msm-qcom-mdp5-drop-lut-clock.patch +drm-msm-dpu-add-a-null-ptr-check-for-dpu_encoder_nee.patch +octeontx2-set-appropriate-pf-vf-masks-and-shifts-bas.patch +octeontx2-af-fix-nix-x2p-calibration-failures.patch +misdn-hfcpci-fix-warning-when-deleting-uninitialized.patch +net-dlink-fix-multicast-stats-being-counted-incorrec.patch +efi-stmm-fix-incorrect-buffer-allocation-method.patch +drm-xe-xe_sync-avoid-race-during-ufence-signaling.patch +drm-xe-vm-don-t-pin-the-vm_resv-during-validation.patch +drm-xe-don-t-trigger-rebind-on-initial-dma-buf-valid.patch +block-validate-qos-before-calling-__rq_qos_done_bio.patch +phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch +net-macb-fix-offset-error-in-gem_update_stats.patch +bnxt_en-fix-memory-corruption-when-fw-resources-chan.patch +bnxt_en-adjust-tx-rings-if-reservation-is-less-than-.patch +bnxt_en-fix-stats-context-reservation-logic.patch +net-mlx5-hws-fix-memory-leak-in-hws_pool_buddy_init-.patch +net-mlx5-hws-fix-memory-leak-in-hws_action_get_share.patch +net-mlx5-hws-fix-uninitialized-variables-in-mlx5hws_.patch +net-mlx5-hws-fix-pattern-destruction-in-mlx5hws_pat_.patch +net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch +net-mlx5-fix-lockdep-assertion-on-sync-reset-unload-.patch +net-mlx5-nack-sync-reset-when-sfs-are-present.patch +net-mlx5-prevent-flow-steering-mode-changes-in-switc.patch +net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch +net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch +net-mlx5e-set-local-xoff-after-fw-update.patch +net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch +net-stmmac-xgmac-correct-supported-speed-modes.patch +net-stmmac-set-cic-bit-only-for-tx-queues-with-coe.patch +net-hv_netvsc-fix-loss-of-early-receive-events-from-.patch +io_uring-kbuf-fix-signedness-in-this_len-calculation.patch +net-rose-split-remove-and-free-operations-in-rose_re.patch +net-rose-convert-use-field-to-refcount_t.patch +net-rose-include-node-references-in-rose_neigh-refco.patch +sctp-initialize-more-fields-in-sctp_v6_from_sk.patch +l2tp-do-not-use-sock_hold-in-pppol2tp_session_get_so.patch +fbnic-move-phylink-resume-out-of-service_task-and-in.patch +efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch +net-macb-disable-clocks-once.patch +io_uring-kbuf-always-use-read_once-to-read-ring-prov.patch +drm-mediatek-mtk_hdmi-fix-inverted-parameters-in-som.patch diff --git a/queue-6.6/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch b/queue-6.6/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch new file mode 100644 index 0000000000..0c21e58313 --- /dev/null +++ b/queue-6.6/atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch @@ -0,0 +1,192 @@ +From b5f82bcf10808933c86a10e78ef2e0f3efb0e4ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Aug 2025 02:18:24 +0000 +Subject: atm: atmtcp: Prevent arbitrary write in atmtcp_recv_control(). + +From: Kuniyuki Iwashima + +[ Upstream commit ec79003c5f9d2c7f9576fc69b8dbda80305cbe3a ] + +syzbot reported the splat below. [0] + +When atmtcp_v_open() or atmtcp_v_close() is called via connect() +or close(), atmtcp_send_control() is called to send an in-kernel +special message. + +The message has ATMTCP_HDR_MAGIC in atmtcp_control.hdr.length. +Also, a pointer of struct atm_vcc is set to atmtcp_control.vcc. + +The notable thing is struct atmtcp_control is uAPI but has a +space for an in-kernel pointer. + + struct atmtcp_control { + struct atmtcp_hdr hdr; /* must be first */ + ... + atm_kptr_t vcc; /* both directions */ + ... + } __ATM_API_ALIGN; + + typedef struct { unsigned char _[8]; } __ATM_API_ALIGN atm_kptr_t; + +The special message is processed in atmtcp_recv_control() called +from atmtcp_c_send(). + +atmtcp_c_send() is vcc->dev->ops->send() and called from 2 paths: + + 1. .ndo_start_xmit() (vcc->send() == atm_send_aal0()) + 2. vcc_sendmsg() + +The problem is sendmsg() does not validate the message length and +userspace can abuse atmtcp_recv_control() to overwrite any kptr +by atmtcp_control. + +Let's add a new ->pre_send() hook to validate messages from sendmsg(). + +[0]: +Oops: general protection fault, probably for non-canonical address 0xdffffc00200000ab: 0000 [#1] SMP KASAN PTI +KASAN: probably user-memory-access in range [0x0000000100000558-0x000000010000055f] +CPU: 0 UID: 0 PID: 5865 Comm: syz-executor331 Not tainted 6.17.0-rc1-syzkaller-00215-gbab3ce404553 #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/12/2025 +RIP: 0010:atmtcp_recv_control drivers/atm/atmtcp.c:93 [inline] +RIP: 0010:atmtcp_c_send+0x1da/0x950 drivers/atm/atmtcp.c:297 +Code: 4d 8d 75 1a 4c 89 f0 48 c1 e8 03 42 0f b6 04 20 84 c0 0f 85 15 06 00 00 41 0f b7 1e 4d 8d b7 60 05 00 00 4c 89 f0 48 c1 e8 03 <42> 0f b6 04 20 84 c0 0f 85 13 06 00 00 66 41 89 1e 4d 8d 75 1c 4c +RSP: 0018:ffffc90003f5f810 EFLAGS: 00010203 +RAX: 00000000200000ab RBX: 0000000000000000 RCX: 0000000000000000 +RDX: ffff88802a510000 RSI: 00000000ffffffff RDI: ffff888030a6068c +RBP: ffff88802699fb40 R08: ffff888030a606eb R09: 1ffff1100614c0dd +R10: dffffc0000000000 R11: ffffffff8718fc40 R12: dffffc0000000000 +R13: ffff888030a60680 R14: 000000010000055f R15: 00000000ffffffff +FS: 00007f8d7e9236c0(0000) GS:ffff888125c1c000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 000000000045ad50 CR3: 0000000075bde000 CR4: 00000000003526f0 +Call Trace: + + vcc_sendmsg+0xa10/0xc60 net/atm/common.c:645 + sock_sendmsg_nosec net/socket.c:714 [inline] + __sock_sendmsg+0x219/0x270 net/socket.c:729 + ____sys_sendmsg+0x505/0x830 net/socket.c:2614 + ___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668 + __sys_sendmsg net/socket.c:2700 [inline] + __do_sys_sendmsg net/socket.c:2705 [inline] + __se_sys_sendmsg net/socket.c:2703 [inline] + __x64_sys_sendmsg+0x19b/0x260 net/socket.c:2703 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +RIP: 0033:0x7f8d7e96a4a9 +Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 51 18 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f8d7e923198 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +RAX: ffffffffffffffda RBX: 00007f8d7e9f4308 RCX: 00007f8d7e96a4a9 +RDX: 0000000000000000 RSI: 0000200000000240 RDI: 0000000000000005 +RBP: 00007f8d7e9f4300 R08: 65732f636f72702f R09: 65732f636f72702f +R10: 65732f636f72702f R11: 0000000000000246 R12: 00007f8d7e9c10ac +R13: 00007f8d7e9231a0 R14: 0000200000000200 R15: 0000200000000250 + +Modules linked in: + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+1741b56d54536f4ec349@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68a6767c.050a0220.3d78fd.0011.GAE@google.com/ +Tested-by: syzbot+1741b56d54536f4ec349@syzkaller.appspotmail.com +Signed-off-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250821021901.2814721-1-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/atm/atmtcp.c | 17 ++++++++++++++--- + include/linux/atmdev.h | 1 + + net/atm/common.c | 15 ++++++++++++--- + 3 files changed, 27 insertions(+), 6 deletions(-) + +diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c +index ff558908897f3..9c83fb29b2f1b 100644 +--- a/drivers/atm/atmtcp.c ++++ b/drivers/atm/atmtcp.c +@@ -279,6 +279,19 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) + return NULL; + } + ++static int atmtcp_c_pre_send(struct atm_vcc *vcc, struct sk_buff *skb) ++{ ++ struct atmtcp_hdr *hdr; ++ ++ if (skb->len < sizeof(struct atmtcp_hdr)) ++ return -EINVAL; ++ ++ hdr = (struct atmtcp_hdr *)skb->data; ++ if (hdr->length == ATMTCP_HDR_MAGIC) ++ return -EINVAL; ++ ++ return 0; ++} + + static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + { +@@ -288,9 +301,6 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + struct sk_buff *new_skb; + int result = 0; + +- if (skb->len < sizeof(struct atmtcp_hdr)) +- goto done; +- + dev = vcc->dev_data; + hdr = (struct atmtcp_hdr *) skb->data; + if (hdr->length == ATMTCP_HDR_MAGIC) { +@@ -347,6 +357,7 @@ static const struct atmdev_ops atmtcp_v_dev_ops = { + + static const struct atmdev_ops atmtcp_c_dev_ops = { + .close = atmtcp_c_close, ++ .pre_send = atmtcp_c_pre_send, + .send = atmtcp_c_send + }; + +diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h +index 45f2f278b50a8..70807c679f1ab 100644 +--- a/include/linux/atmdev.h ++++ b/include/linux/atmdev.h +@@ -185,6 +185,7 @@ struct atmdev_ops { /* only send is required */ + int (*compat_ioctl)(struct atm_dev *dev,unsigned int cmd, + void __user *arg); + #endif ++ int (*pre_send)(struct atm_vcc *vcc, struct sk_buff *skb); + int (*send)(struct atm_vcc *vcc,struct sk_buff *skb); + int (*send_bh)(struct atm_vcc *vcc, struct sk_buff *skb); + int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags); +diff --git a/net/atm/common.c b/net/atm/common.c +index 9cc82acbc7358..48bb3f66a3f2a 100644 +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -635,18 +635,27 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size) + + skb->dev = NULL; /* for paths shared with net_device interfaces */ + if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) { +- atm_return_tx(vcc, skb); +- kfree_skb(skb); + error = -EFAULT; +- goto out; ++ goto free_skb; + } + if (eff != size) + memset(skb->data + size, 0, eff-size); ++ ++ if (vcc->dev->ops->pre_send) { ++ error = vcc->dev->ops->pre_send(vcc, skb); ++ if (error) ++ goto free_skb; ++ } ++ + error = vcc->dev->ops->send(vcc, skb); + error = error ? error : size; + out: + release_sock(sk); + return error; ++free_skb: ++ atm_return_tx(vcc, skb); ++ kfree_skb(skb); ++ goto out; + } + + __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait) +-- +2.50.1 + diff --git a/queue-6.6/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch b/queue-6.6/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch new file mode 100644 index 0000000000..b255bb7bf9 --- /dev/null +++ b/queue-6.6/bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch @@ -0,0 +1,47 @@ +From 4fc487d1c4efa2becb85150b0763d1918b00dcee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Aug 2025 17:04:00 -0400 +Subject: Bluetooth: hci_event: Detect if HCI_EV_NUM_COMP_PKTS is unbalanced + +From: Luiz Augusto von Dentz + +[ Upstream commit 15bf2c6391bafb14a3020d06ec0761bce0803463 ] + +This attempts to detect if HCI_EV_NUM_COMP_PKTS contain an unbalanced +(more than currently considered outstanding) number of packets otherwise +it could cause the hcon->sent to underflow and loop around breaking the +tracking of the outstanding packets pending acknowledgment. + +Fixes: f42809185896 ("Bluetooth: Simplify num_comp_pkts_evt function") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index a07ad1c99a4b0..5eed23b8d6c33 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -4392,7 +4392,17 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, + if (!conn) + continue; + +- conn->sent -= count; ++ /* Check if there is really enough packets outstanding before ++ * attempting to decrease the sent counter otherwise it could ++ * underflow.. ++ */ ++ if (conn->sent >= count) { ++ conn->sent -= count; ++ } else { ++ bt_dev_warn(hdev, "hcon %p sent %u < count %u", ++ conn, conn->sent, count); ++ conn->sent = 0; ++ } + + switch (conn->type) { + case ACL_LINK: +-- +2.50.1 + diff --git a/queue-6.6/bluetooth-hci_event-mark-connection-as-closed-during.patch b/queue-6.6/bluetooth-hci_event-mark-connection-as-closed-during.patch new file mode 100644 index 0000000000..fbc7f836ce --- /dev/null +++ b/queue-6.6/bluetooth-hci_event-mark-connection-as-closed-during.patch @@ -0,0 +1,80 @@ +From e96a8d41136d799832dc0a75f3ef866fed855b78 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Aug 2025 17:55:27 +0200 +Subject: Bluetooth: hci_event: Mark connection as closed during suspend + disconnect + +From: Ludovico de Nittis + +[ Upstream commit b7fafbc499b5ee164018eb0eefe9027f5a6aaad2 ] + +When suspending, the disconnect command for an active Bluetooth +connection could be issued, but the corresponding +`HCI_EV_DISCONN_COMPLETE` event might not be received before the system +completes the suspend process. This can lead to an inconsistent state. + +On resume, the controller may auto-accept reconnections from the same +device (due to suspend event filters), but these new connections are +rejected by the kernel which still has connection objects from before +suspend. Resulting in errors like: +``` +kernel: Bluetooth: hci0: ACL packet for unknown connection handle 1 +kernel: Bluetooth: hci0: Ignoring HCI_Connection_Complete for existing +connection +``` + +This is a btmon snippet that shows the issue: +``` +< HCI Command: Disconnect (0x01|0x0006) plen 3 + Handle: 1 Address: 78:20:A5:4A:DF:28 (Nintendo Co.,Ltd) + Reason: Remote User Terminated Connection (0x13) +> HCI Event: Command Status (0x0f) plen 4 + Disconnect (0x01|0x0006) ncmd 2 + Status: Success (0x00) +[...] +// Host suspends with the event filter set for the device +// On resume, the device tries to reconnect with a new handle + +> HCI Event: Connect Complete (0x03) plen 11 + Status: Success (0x00) + Handle: 2 + Address: 78:20:A5:4A:DF:28 (Nintendo Co.,Ltd) + +// Kernel ignores this event because there is an existing connection +with +// handle 1 +``` + +By explicitly setting the connection state to BT_CLOSED we can ensure a +consistent state, even if we don't receive the disconnect complete event +in time. + +Link: https://github.com/bluez/bluez/issues/1226 +Fixes: 182ee45da083 ("Bluetooth: hci_sync: Rework hci_suspend_notifier") +Signed-off-by: Ludovico de Nittis +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index fb5e4e4858f77..a07ad1c99a4b0 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -2707,6 +2707,12 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) + goto done; + } + ++ /* During suspend, mark connection as closed immediately ++ * since we might not receive HCI_EV_DISCONN_COMPLETE ++ */ ++ if (hdev->suspended) ++ conn->state = BT_CLOSED; ++ + mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); + + if (conn->type == ACL_LINK) { +-- +2.50.1 + diff --git a/queue-6.6/bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch b/queue-6.6/bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch new file mode 100644 index 0000000000..57d390a750 --- /dev/null +++ b/queue-6.6/bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch @@ -0,0 +1,84 @@ +From 20ddcc5dba9be8ec57cb33fae759b1ba02e0815e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Aug 2025 17:55:26 +0200 +Subject: Bluetooth: hci_event: Treat UNKNOWN_CONN_ID on disconnect as success + +From: Ludovico de Nittis + +[ Upstream commit 2f050a5392b7a0928bf836d9891df4851463512c ] + +When the host sends an HCI_OP_DISCONNECT command, the controller may +respond with the status HCI_ERROR_UNKNOWN_CONN_ID (0x02). E.g. this can +happen on resume from suspend, if the link was terminated by the remote +device before the event mask was correctly set. + +This is a btmon snippet that shows the issue: +``` +> ACL Data RX: Handle 3 flags 0x02 dlen 12 + L2CAP: Disconnection Request (0x06) ident 5 len 4 + Destination CID: 65 + Source CID: 72 +< ACL Data TX: Handle 3 flags 0x00 dlen 12 + L2CAP: Disconnection Response (0x07) ident 5 len 4 + Destination CID: 65 + Source CID: 72 +> ACL Data RX: Handle 3 flags 0x02 dlen 12 + L2CAP: Disconnection Request (0x06) ident 6 len 4 + Destination CID: 64 + Source CID: 71 +< ACL Data TX: Handle 3 flags 0x00 dlen 12 + L2CAP: Disconnection Response (0x07) ident 6 len 4 + Destination CID: 64 + Source CID: 71 +< HCI Command: Set Event Mask (0x03|0x0001) plen 8 + Mask: 0x3dbff807fffbffff + Inquiry Complete + Inquiry Result + Connection Complete + Connection Request + Disconnection Complete + Authentication Complete +[...] +< HCI Command: Disconnect (0x01|0x0006) plen 3 + Handle: 3 Address: 78:20:A5:4A:DF:28 (Nintendo Co.,Ltd) + Reason: Remote User Terminated Connection (0x13) +> HCI Event: Command Status (0x0f) plen 4 + Disconnect (0x01|0x0006) ncmd 1 + Status: Unknown Connection Identifier (0x02) +``` + +Currently, the hci_cs_disconnect function treats any non-zero status +as a command failure. This can be misleading because the connection is +indeed being terminated and the controller is confirming that is has no +knowledge of that connection handle. Meaning that the initial request of +disconnecting a device should be treated as done. + +With this change we allow the function to proceed, following the success +path, which correctly calls `mgmt_device_disconnected` and ensures a +consistent state. + +Link: https://github.com/bluez/bluez/issues/1226 +Fixes: 182ee45da083 ("Bluetooth: hci_sync: Rework hci_suspend_notifier") +Signed-off-by: Ludovico de Nittis +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index c06010c0d8829..fb5e4e4858f77 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -2692,7 +2692,7 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) + if (!conn) + goto unlock; + +- if (status) { ++ if (status && status != HCI_ERROR_UNKNOWN_CONN_ID) { + mgmt_disconnect_failed(hdev, &conn->dst, conn->type, + conn->dst_type, status); + +-- +2.50.1 + diff --git a/queue-6.6/bluetooth-hci_sync-fix-set_local_name-race-condition.patch b/queue-6.6/bluetooth-hci_sync-fix-set_local_name-race-condition.patch new file mode 100644 index 0000000000..2f9b3cecd9 --- /dev/null +++ b/queue-6.6/bluetooth-hci_sync-fix-set_local_name-race-condition.patch @@ -0,0 +1,90 @@ +From f89392b975eceaa442c3fc8ea797d98242860861 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Aug 2025 12:20:55 +0300 +Subject: Bluetooth: hci_sync: fix set_local_name race condition + +From: Pavel Shpakovskiy + +[ Upstream commit 6bbd0d3f0c23fc53c17409dd7476f38ae0ff0cd9 ] + +Function set_name_sync() uses hdev->dev_name field to send +HCI_OP_WRITE_LOCAL_NAME command, but copying from data to hdev->dev_name +is called after mgmt cmd was queued, so it is possible that function +set_name_sync() will read old name value. + +This change adds name as a parameter for function hci_update_name_sync() +to avoid race condition. + +Fixes: 6f6ff38a1e14 ("Bluetooth: hci_sync: Convert MGMT_OP_SET_LOCAL_NAME") +Signed-off-by: Pavel Shpakovskiy +Reviewed-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci_sync.h | 2 +- + net/bluetooth/hci_sync.c | 6 +++--- + net/bluetooth/mgmt.c | 5 ++++- + 3 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h +index 3cb2d10cac930..e2e588b08fe90 100644 +--- a/include/net/bluetooth/hci_sync.h ++++ b/include/net/bluetooth/hci_sync.h +@@ -72,7 +72,7 @@ int hci_update_class_sync(struct hci_dev *hdev); + + int hci_update_eir_sync(struct hci_dev *hdev); + int hci_update_class_sync(struct hci_dev *hdev); +-int hci_update_name_sync(struct hci_dev *hdev); ++int hci_update_name_sync(struct hci_dev *hdev, const u8 *name); + int hci_write_ssp_mode_sync(struct hci_dev *hdev, u8 mode); + + int hci_get_random_address(struct hci_dev *hdev, bool require_privacy, +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index 01aca07707117..020f1809fc994 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -3491,13 +3491,13 @@ int hci_update_scan_sync(struct hci_dev *hdev) + return hci_write_scan_enable_sync(hdev, scan); + } + +-int hci_update_name_sync(struct hci_dev *hdev) ++int hci_update_name_sync(struct hci_dev *hdev, const u8 *name) + { + struct hci_cp_write_local_name cp; + + memset(&cp, 0, sizeof(cp)); + +- memcpy(cp.name, hdev->dev_name, sizeof(cp.name)); ++ memcpy(cp.name, name, sizeof(cp.name)); + + return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_LOCAL_NAME, + sizeof(cp), &cp, +@@ -3550,7 +3550,7 @@ int hci_powered_update_sync(struct hci_dev *hdev) + hci_write_fast_connectable_sync(hdev, false); + hci_update_scan_sync(hdev); + hci_update_class_sync(hdev); +- hci_update_name_sync(hdev); ++ hci_update_name_sync(hdev, hdev->dev_name); + hci_update_eir_sync(hdev); + } + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 82fa8c28438f2..9b01eaaa0eb2d 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -3819,8 +3819,11 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err) + + static int set_name_sync(struct hci_dev *hdev, void *data) + { ++ struct mgmt_pending_cmd *cmd = data; ++ struct mgmt_cp_set_local_name *cp = cmd->param; ++ + if (lmp_bredr_capable(hdev)) { +- hci_update_name_sync(hdev); ++ hci_update_name_sync(hdev, cp->name); + hci_update_eir_sync(hdev); + } + +-- +2.50.1 + diff --git a/queue-6.6/drm-msm-defer-fd_install-in-submit-ioctl.patch b/queue-6.6/drm-msm-defer-fd_install-in-submit-ioctl.patch new file mode 100644 index 0000000000..de36f58673 --- /dev/null +++ b/queue-6.6/drm-msm-defer-fd_install-in-submit-ioctl.patch @@ -0,0 +1,59 @@ +From a03fa1a6628bde0d8f40b6af39118a4b88397457 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Jul 2025 13:28:22 -0700 +Subject: drm/msm: Defer fd_install in SUBMIT ioctl + +From: Rob Clark + +[ Upstream commit f22853435bbd1e9836d0dce7fd99c040b94c2bf1 ] + +Avoid fd_install() until there are no more potential error paths, to +avoid put_unused_fd() after the fd is made visible to userspace. + +Fixes: 68dc6c2d5eec ("drm/msm: Fix submit error-path leaks") +Reported-by: Dan Carpenter +Signed-off-by: Rob Clark +Patchwork: https://patchwork.freedesktop.org/patch/665363/ +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/msm_gem_submit.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c +index bbe4f1665b603..dc142f9e4f602 100644 +--- a/drivers/gpu/drm/msm/msm_gem_submit.c ++++ b/drivers/gpu/drm/msm/msm_gem_submit.c +@@ -981,12 +981,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, + + if (ret == 0 && args->flags & MSM_SUBMIT_FENCE_FD_OUT) { + sync_file = sync_file_create(submit->user_fence); +- if (!sync_file) { ++ if (!sync_file) + ret = -ENOMEM; +- } else { +- fd_install(out_fence_fd, sync_file->file); +- args->fence_fd = out_fence_fd; +- } + } + + submit_attach_object_fences(submit); +@@ -1013,10 +1009,14 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, + out_unlock: + mutex_unlock(&queue->lock); + out_post_unlock: +- if (ret && (out_fence_fd >= 0)) { +- put_unused_fd(out_fence_fd); ++ if (ret) { ++ if (out_fence_fd >= 0) ++ put_unused_fd(out_fence_fd); + if (sync_file) + fput(sync_file->file); ++ } else if (sync_file) { ++ fd_install(out_fence_fd, sync_file->file); ++ args->fence_fd = out_fence_fd; + } + + if (!IS_ERR_OR_NULL(submit)) { +-- +2.50.1 + diff --git a/queue-6.6/drm-nouveau-remove-unused-increment-in-gm200_flcn_pi.patch b/queue-6.6/drm-nouveau-remove-unused-increment-in-gm200_flcn_pi.patch new file mode 100644 index 0000000000..730dac5aa3 --- /dev/null +++ b/queue-6.6/drm-nouveau-remove-unused-increment-in-gm200_flcn_pi.patch @@ -0,0 +1,39 @@ +From fc83643fe0827a46683640052a4287ae9bf5109b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Aug 2025 19:10:03 -0500 +Subject: drm/nouveau: remove unused increment in gm200_flcn_pio_imem_wr + +From: Timur Tabi + +[ Upstream commit f529b8915543fb9ceb732cec5571f7fe12bc9530 ] + +The 'tag' parameter is passed by value and is not actually used after +being incremented, so remove the increment. It's the function that calls +gm200_flcn_pio_imem_wr that is supposed to (and does) increment 'tag'. + +Fixes: 0e44c2170876 ("drm/nouveau/flcn: new code to load+boot simple HS FWs (VPR scrubber)") +Reviewed-by: Philipp Stanner +Signed-off-by: Timur Tabi +Link: https://lore.kernel.org/r/20250813001004.2986092-2-ttabi@nvidia.com +Signed-off-by: Danilo Krummrich +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +index b7da3ab44c277..6a004c6e67425 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c ++++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +@@ -103,7 +103,7 @@ gm200_flcn_pio_imem_wr_init(struct nvkm_falcon *falcon, u8 port, bool sec, u32 i + static void + gm200_flcn_pio_imem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len, u16 tag) + { +- nvkm_falcon_wr32(falcon, 0x188 + (port * 0x10), tag++); ++ nvkm_falcon_wr32(falcon, 0x188 + (port * 0x10), tag); + while (len >= 4) { + nvkm_falcon_wr32(falcon, 0x184 + (port * 0x10), *(u32 *)img); + img += 4; +-- +2.50.1 + diff --git a/queue-6.6/drm-nouveau-remove-unused-memory-target-test.patch b/queue-6.6/drm-nouveau-remove-unused-memory-target-test.patch new file mode 100644 index 0000000000..0ce1da3408 --- /dev/null +++ b/queue-6.6/drm-nouveau-remove-unused-memory-target-test.patch @@ -0,0 +1,57 @@ +From fc29d890a49f334fc8a809b2a8b2381604528a56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Aug 2025 19:10:04 -0500 +Subject: drm/nouveau: remove unused memory target test + +From: Timur Tabi + +[ Upstream commit 64c722b5e7f6b909b0e448e580f64628a0d76208 ] + +The memory target check is a hold-over from a refactor. It's harmless +but distracting, so just remove it. + +Fixes: 2541626cfb79 ("drm/nouveau/acr: use common falcon HS FW code for ACR FWs") +Signed-off-by: Timur Tabi +Link: https://lore.kernel.org/r/20250813001004.2986092-3-ttabi@nvidia.com +Signed-off-by: Danilo Krummrich +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c | 13 +++---------- + 1 file changed, 3 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +index 6a004c6e67425..7c43397c19e61 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c ++++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +@@ -249,9 +249,11 @@ int + gm200_flcn_fw_load(struct nvkm_falcon_fw *fw) + { + struct nvkm_falcon *falcon = fw->falcon; +- int target, ret; ++ int ret; + + if (fw->inst) { ++ int target; ++ + nvkm_falcon_mask(falcon, 0x048, 0x00000001, 0x00000001); + + switch (nvkm_memory_target(fw->inst)) { +@@ -285,15 +287,6 @@ gm200_flcn_fw_load(struct nvkm_falcon_fw *fw) + } + + if (fw->boot) { +- switch (nvkm_memory_target(&fw->fw.mem.memory)) { +- case NVKM_MEM_TARGET_VRAM: target = 4; break; +- case NVKM_MEM_TARGET_HOST: target = 5; break; +- case NVKM_MEM_TARGET_NCOH: target = 6; break; +- default: +- WARN_ON(1); +- return -EINVAL; +- } +- + ret = nvkm_falcon_pio_wr(falcon, fw->boot, 0, 0, + IMEM, falcon->code.limit - fw->boot_size, fw->boot_size, + fw->boot_addr >> 8, false); +-- +2.50.1 + diff --git a/queue-6.6/dt-bindings-display-msm-qcom-mdp5-drop-lut-clock.patch b/queue-6.6/dt-bindings-display-msm-qcom-mdp5-drop-lut-clock.patch new file mode 100644 index 0000000000..5f96f4c8f1 --- /dev/null +++ b/queue-6.6/dt-bindings-display-msm-qcom-mdp5-drop-lut-clock.patch @@ -0,0 +1,39 @@ +From cfa3271a53d1cc123f2329f18fe2256bc3265c45 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 9 Aug 2025 11:36:54 +0300 +Subject: dt-bindings: display/msm: qcom,mdp5: drop lut clock + +From: Dmitry Baryshkov + +[ Upstream commit 7ab3b7579a6d2660a3425b9ea93b9a140b07f49c ] + +None of MDP5 platforms have a LUT clock on the display-controller, it +was added by the mistake. Drop it, fixing DT warnings on MSM8976 / +MSM8956 platforms. Technically it's an ABI break, but no other platforms +are affected. + +Fixes: 385c8ac763b3 ("dt-bindings: display/msm: convert MDP5 schema to YAML format") +Signed-off-by: Dmitry Baryshkov +Acked-by: Rob Herring (Arm) +Patchwork: https://patchwork.freedesktop.org/patch/667822/ +Signed-off-by: Rob Clark +Signed-off-by: Sasha Levin +--- + Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml b/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml +index 91c774f106ceb..ab1196d1ec2dd 100644 +--- a/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml ++++ b/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml +@@ -59,7 +59,6 @@ properties: + - const: bus + - const: core + - const: vsync +- - const: lut + - const: tbu + - const: tbu_rt + # MSM8996 has additional iommu clock +-- +2.50.1 + diff --git a/queue-6.6/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch b/queue-6.6/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch new file mode 100644 index 0000000000..c7e6250320 --- /dev/null +++ b/queue-6.6/efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch @@ -0,0 +1,77 @@ +From 4bd779158a3bfc1c9c06f418a2df5d81a7ce02b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 15:39:54 +0800 +Subject: efivarfs: Fix slab-out-of-bounds in efivarfs_d_compare + +From: Li Nan + +[ Upstream commit a6358f8cf64850f3f27857b8ed8c1b08cfc4685c ] + +Observed on kernel 6.6 (present on master as well): + + BUG: KASAN: slab-out-of-bounds in memcmp+0x98/0xd0 + Call trace: + kasan_check_range+0xe8/0x190 + __asan_loadN+0x1c/0x28 + memcmp+0x98/0xd0 + efivarfs_d_compare+0x68/0xd8 + __d_lookup_rcu_op_compare+0x178/0x218 + __d_lookup_rcu+0x1f8/0x228 + d_alloc_parallel+0x150/0x648 + lookup_open.isra.0+0x5f0/0x8d0 + open_last_lookups+0x264/0x828 + path_openat+0x130/0x3f8 + do_filp_open+0x114/0x248 + do_sys_openat2+0x340/0x3c0 + __arm64_sys_openat+0x120/0x1a0 + +If dentry->d_name.len < EFI_VARIABLE_GUID_LEN , 'guid' can become +negative, leadings to oob. The issue can be triggered by parallel +lookups using invalid filename: + + T1 T2 + lookup_open + ->lookup + simple_lookup + d_add + // invalid dentry is added to hash list + + lookup_open + d_alloc_parallel + __d_lookup_rcu + __d_lookup_rcu_op_compare + hlist_bl_for_each_entry_rcu + // invalid dentry can be retrieved + ->d_compare + efivarfs_d_compare + // oob + +Fix it by checking 'guid' before cmp. + +Fixes: da27a24383b2 ("efivarfs: guid part of filenames are case-insensitive") +Signed-off-by: Li Nan +Signed-off-by: Wu Guanghao +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + fs/efivarfs/super.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c +index 586c5709dfb55..34438981ddd80 100644 +--- a/fs/efivarfs/super.c ++++ b/fs/efivarfs/super.c +@@ -90,6 +90,10 @@ static int efivarfs_d_compare(const struct dentry *dentry, + { + int guid = len - EFI_VARIABLE_GUID_LEN; + ++ /* Parallel lookups may produce a temporary invalid filename */ ++ if (guid <= 0) ++ return 1; ++ + if (name->len != len) + return 1; + +-- +2.50.1 + diff --git a/queue-6.6/hid-input-rename-hidinput_set_battery_charge_status.patch b/queue-6.6/hid-input-rename-hidinput_set_battery_charge_status.patch new file mode 100644 index 0000000000..59a4a990cd --- /dev/null +++ b/queue-6.6/hid-input-rename-hidinput_set_battery_charge_status.patch @@ -0,0 +1,147 @@ +From c0e020b69ab9cc830030b0eb40c9d9a68875e070 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Aug 2025 12:39:39 +0200 +Subject: HID: input: rename hidinput_set_battery_charge_status() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit a82231b2a8712d0218fc286a9b0da328d419a3f4 ] + +In preparation for a patch fixing a bug affecting +hidinput_set_battery_charge_status(), rename the function to +hidinput_update_battery_charge_status() and move it up so it can be used +by hidinput_update_battery(). + +Refactor, no functional changes. + +Tested-by: 卢国宏 +Signed-off-by: José Expósito +Signed-off-by: Jiri Kosina +Stable-dep-of: e94536e1d181 ("HID: input: report battery status changes immediately") +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-input-test.c | 10 +++++----- + drivers/hid/hid-input.c | 38 ++++++++++++++++++------------------ + 2 files changed, 24 insertions(+), 24 deletions(-) + +diff --git a/drivers/hid/hid-input-test.c b/drivers/hid/hid-input-test.c +index 77c2d45ac62a7..6f5c71660d823 100644 +--- a/drivers/hid/hid-input-test.c ++++ b/drivers/hid/hid-input-test.c +@@ -7,7 +7,7 @@ + + #include + +-static void hid_test_input_set_battery_charge_status(struct kunit *test) ++static void hid_test_input_update_battery_charge_status(struct kunit *test) + { + struct hid_device *dev; + bool handled; +@@ -15,15 +15,15 @@ static void hid_test_input_set_battery_charge_status(struct kunit *test) + dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + +- handled = hidinput_set_battery_charge_status(dev, HID_DG_HEIGHT, 0); ++ handled = hidinput_update_battery_charge_status(dev, HID_DG_HEIGHT, 0); + KUNIT_EXPECT_FALSE(test, handled); + KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_UNKNOWN); + +- handled = hidinput_set_battery_charge_status(dev, HID_BAT_CHARGING, 0); ++ handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 0); + KUNIT_EXPECT_TRUE(test, handled); + KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_DISCHARGING); + +- handled = hidinput_set_battery_charge_status(dev, HID_BAT_CHARGING, 1); ++ handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 1); + KUNIT_EXPECT_TRUE(test, handled); + KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_CHARGING); + } +@@ -63,7 +63,7 @@ static void hid_test_input_get_battery_property(struct kunit *test) + } + + static struct kunit_case hid_input_tests[] = { +- KUNIT_CASE(hid_test_input_set_battery_charge_status), ++ KUNIT_CASE(hid_test_input_update_battery_charge_status), + KUNIT_CASE(hid_test_input_get_battery_property), + { } + }; +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 9d80635a91ebd..b372b74f3e24b 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -595,6 +595,20 @@ static void hidinput_cleanup_battery(struct hid_device *dev) + dev->battery = NULL; + } + ++static bool hidinput_update_battery_charge_status(struct hid_device *dev, ++ unsigned int usage, int value) ++{ ++ switch (usage) { ++ case HID_BAT_CHARGING: ++ dev->battery_charge_status = value ? ++ POWER_SUPPLY_STATUS_CHARGING : ++ POWER_SUPPLY_STATUS_DISCHARGING; ++ return true; ++ } ++ ++ return false; ++} ++ + static void hidinput_update_battery(struct hid_device *dev, int value) + { + int capacity; +@@ -617,20 +631,6 @@ static void hidinput_update_battery(struct hid_device *dev, int value) + power_supply_changed(dev->battery); + } + } +- +-static bool hidinput_set_battery_charge_status(struct hid_device *dev, +- unsigned int usage, int value) +-{ +- switch (usage) { +- case HID_BAT_CHARGING: +- dev->battery_charge_status = value ? +- POWER_SUPPLY_STATUS_CHARGING : +- POWER_SUPPLY_STATUS_DISCHARGING; +- return true; +- } +- +- return false; +-} + #else /* !CONFIG_HID_BATTERY_STRENGTH */ + static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, + struct hid_field *field, bool is_percentage) +@@ -642,14 +642,14 @@ static void hidinput_cleanup_battery(struct hid_device *dev) + { + } + +-static void hidinput_update_battery(struct hid_device *dev, int value) ++static bool hidinput_update_battery_charge_status(struct hid_device *dev, ++ unsigned int usage, int value) + { ++ return false; + } + +-static bool hidinput_set_battery_charge_status(struct hid_device *dev, +- unsigned int usage, int value) ++static void hidinput_update_battery(struct hid_device *dev, int value) + { +- return false; + } + #endif /* CONFIG_HID_BATTERY_STRENGTH */ + +@@ -1515,7 +1515,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct + return; + + if (usage->type == EV_PWR) { +- bool handled = hidinput_set_battery_charge_status(hid, usage->hid, value); ++ bool handled = hidinput_update_battery_charge_status(hid, usage->hid, value); + + if (!handled) + hidinput_update_battery(hid, value); +-- +2.50.1 + diff --git a/queue-6.6/hid-input-report-battery-status-changes-immediately.patch b/queue-6.6/hid-input-report-battery-status-changes-immediately.patch new file mode 100644 index 0000000000..bf869624b4 --- /dev/null +++ b/queue-6.6/hid-input-report-battery-status-changes-immediately.patch @@ -0,0 +1,97 @@ +From 9c99b289313b7897a310c5628ed9ba80accbe2f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Aug 2025 12:39:40 +0200 +Subject: HID: input: report battery status changes immediately +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit e94536e1d1818b0989aa19b443b7089f50133c35 ] + +Previously, the battery status (charging/discharging) was not reported +immediately to user-space.  + +For most input devices, this wasn't problematic because changing their +battery status requires connecting them to a different bus. +For example, a gamepad would report a discharging status while +connected via Bluetooth and a charging status while connected via USB. + +However, certain devices are not connected or disconnected when their +battery status changes. For example, a phone battery changes its status +without connecting or disconnecting it. +In these cases, the battery status was not reported immediately to user +space. + +Report battery status changes immediately to user space to support +these kinds of devices. + +Fixes: a608dc1c0639 ("HID: input: map battery system charging") +Reported-by: 卢国宏 +Closes: https://lore.kernel.org/linux-input/aI49Im0sGb6fpgc8@fedora/T/ +Tested-by: 卢国宏 +Signed-off-by: José Expósito +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-input.c | 23 ++++++++++------------- + 1 file changed, 10 insertions(+), 13 deletions(-) + +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index b372b74f3e24b..f5c217ac4bfaa 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -609,13 +609,19 @@ static bool hidinput_update_battery_charge_status(struct hid_device *dev, + return false; + } + +-static void hidinput_update_battery(struct hid_device *dev, int value) ++static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, ++ int value) + { + int capacity; + + if (!dev->battery) + return; + ++ if (hidinput_update_battery_charge_status(dev, usage, value)) { ++ power_supply_changed(dev->battery); ++ return; ++ } ++ + if (value == 0 || value < dev->battery_min || value > dev->battery_max) + return; + +@@ -642,13 +648,8 @@ static void hidinput_cleanup_battery(struct hid_device *dev) + { + } + +-static bool hidinput_update_battery_charge_status(struct hid_device *dev, +- unsigned int usage, int value) +-{ +- return false; +-} +- +-static void hidinput_update_battery(struct hid_device *dev, int value) ++static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, ++ int value) + { + } + #endif /* CONFIG_HID_BATTERY_STRENGTH */ +@@ -1515,11 +1516,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct + return; + + if (usage->type == EV_PWR) { +- bool handled = hidinput_update_battery_charge_status(hid, usage->hid, value); +- +- if (!handled) +- hidinput_update_battery(hid, value); +- ++ hidinput_update_battery(hid, usage->hid, value); + return; + } + +-- +2.50.1 + diff --git a/queue-6.6/ice-fix-incorrect-counter-for-buffer-allocation-fail.patch b/queue-6.6/ice-fix-incorrect-counter-for-buffer-allocation-fail.patch new file mode 100644 index 0000000000..83db42fa44 --- /dev/null +++ b/queue-6.6/ice-fix-incorrect-counter-for-buffer-allocation-fail.patch @@ -0,0 +1,46 @@ +From 542aaf000548c5e1c84555586ca0c1086792d8c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Aug 2025 17:53:10 +0200 +Subject: ice: fix incorrect counter for buffer allocation failures + +From: Michal Kubiak + +[ Upstream commit b1a0c977c6f1130f7dd125ee3db8c2435d7e3d41 ] + +Currently, the driver increments `alloc_page_failed` when buffer allocation fails +in `ice_clean_rx_irq()`. However, this counter is intended for page allocation +failures, not buffer allocation issues. + +This patch corrects the counter by incrementing `alloc_buf_failed` instead, +ensuring accurate statistics reporting for buffer allocation failures. + +Fixes: 2fba7dc5157b ("ice: Add support for XDP multi-buffer on Rx side") +Reported-by: Jacob Keller +Suggested-by: Paul Menzel +Signed-off-by: Michal Kubiak +Reviewed-by: Paul Menzel +Reviewed-by: Jason Xing +Reviewed-by: Aleksandr Loktionov +Tested-by: Priya Singh +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_txrx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c +index e7084c6aab6da..eae4376c68595 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.c ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c +@@ -1297,7 +1297,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) + skb = ice_construct_skb(rx_ring, xdp); + /* exit if we failed to retrieve a buffer */ + if (!skb) { +- rx_ring->ring_stats->rx_stats.alloc_page_failed++; ++ rx_ring->ring_stats->rx_stats.alloc_buf_failed++; + xdp_verdict = ICE_XDP_CONSUMED; + } + ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict); +-- +2.50.1 + diff --git a/queue-6.6/ice-gather-page_count-s-of-each-frag-right-before-xd.patch b/queue-6.6/ice-gather-page_count-s-of-each-frag-right-before-xd.patch new file mode 100644 index 0000000000..75ec3dc149 --- /dev/null +++ b/queue-6.6/ice-gather-page_count-s-of-each-frag-right-before-xd.patch @@ -0,0 +1,97 @@ +From f1efbf972a288ff9f706dd2c69e6745f21199b32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 16:01:17 +0100 +Subject: ice: gather page_count()'s of each frag right before XDP prog call + +From: Maciej Fijalkowski + +[ Upstream commit 11c4aa074d547d825b19cd8d9f288254d89d805c ] + +If we store the pgcnt on few fragments while being in the middle of +gathering the whole frame and we stumbled upon DD bit not being set, we +terminate the NAPI Rx processing loop and come back later on. Then on +next NAPI execution we work on previously stored pgcnt. + +Imagine that second half of page was used actively by networking stack +and by the time we came back, stack is not busy with this page anymore +and decremented the refcnt. The page reuse algorithm in this case should +be good to reuse the page but given the old refcnt it will not do so and +attempt to release the page via page_frag_cache_drain() with +pagecnt_bias used as an arg. This in turn will result in negative refcnt +on struct page, which was initially observed by Xu Du. + +Therefore, move the page count storage from ice_get_rx_buf() to a place +where we are sure that whole frame has been collected, but before +calling XDP program as it internally can also change the page count of +fragments belonging to xdp_buff. + +Fixes: ac0753391195 ("ice: Store page count inside ice_rx_buf") +Reported-and-tested-by: Xu Du +Reviewed-by: Przemek Kitszel +Reviewed-by: Simon Horman +Co-developed-by: Jacob Keller +Signed-off-by: Jacob Keller +Signed-off-by: Maciej Fijalkowski +Tested-by: Chandan Kumar Rout (A Contingent Worker at Intel) +Signed-off-by: Tony Nguyen +Stable-dep-of: b1a0c977c6f1 ("ice: fix incorrect counter for buffer allocation failures") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_txrx.c | 27 ++++++++++++++++++++++- + 1 file changed, 26 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c +index 46f10f32924ee..beb5c8643fe7d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.c ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c +@@ -924,7 +924,6 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size, + struct ice_rx_buf *rx_buf; + + rx_buf = &rx_ring->rx_buf[ntc]; +- rx_buf->pgcnt = page_count(rx_buf->page); + prefetchw(rx_buf->page); + + if (!size) +@@ -940,6 +939,31 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size, + return rx_buf; + } + ++/** ++ * ice_get_pgcnts - grab page_count() for gathered fragments ++ * @rx_ring: Rx descriptor ring to store the page counts on ++ * ++ * This function is intended to be called right before running XDP ++ * program so that the page recycling mechanism will be able to take ++ * a correct decision regarding underlying pages; this is done in such ++ * way as XDP program can change the refcount of page ++ */ ++static void ice_get_pgcnts(struct ice_rx_ring *rx_ring) ++{ ++ u32 nr_frags = rx_ring->nr_frags + 1; ++ u32 idx = rx_ring->first_desc; ++ struct ice_rx_buf *rx_buf; ++ u32 cnt = rx_ring->count; ++ ++ for (int i = 0; i < nr_frags; i++) { ++ rx_buf = &rx_ring->rx_buf[idx]; ++ rx_buf->pgcnt = page_count(rx_buf->page); ++ ++ if (++idx == cnt) ++ idx = 0; ++ } ++} ++ + /** + * ice_build_skb - Build skb around an existing buffer + * @rx_ring: Rx descriptor ring to transact packets on +@@ -1243,6 +1267,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) + if (ice_is_non_eop(rx_ring, rx_desc)) + continue; + ++ ice_get_pgcnts(rx_ring); + ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_buf, rx_desc); + if (rx_buf->act == ICE_XDP_PASS) + goto construct_skb; +-- +2.50.1 + diff --git a/queue-6.6/ice-introduce-ice_xdp_buff.patch b/queue-6.6/ice-introduce-ice_xdp_buff.patch new file mode 100644 index 0000000000..6863d82f28 --- /dev/null +++ b/queue-6.6/ice-introduce-ice_xdp_buff.patch @@ -0,0 +1,150 @@ +From a5a6221a29b14c86f4ff94984cbe9bd80c30aea0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Dec 2023 22:08:33 +0100 +Subject: ice: Introduce ice_xdp_buff + +From: Larysa Zaremba + +[ Upstream commit d951c14ad237b087f0d1377c44932fcc0b322c40 ] + +In order to use XDP hints via kfuncs we need to put +RX descriptor and miscellaneous data next to xdp_buff. +Same as in hints implementations in other drivers, we achieve +this through putting xdp_buff into a child structure. + +Currently, xdp_buff is stored in the ring structure, +so replace it with union that includes child structure. +This way enough memory is available while existing XDP code +remains isolated from hints. + +Minimum size of the new child structure (ice_xdp_buff) is exactly +64 bytes (single cache line). To place it at the start of a cache line, +move 'next' field from CL1 to CL4, as it isn't used often. This still +leaves 192 bits available in CL3 for packet context extensions. + +Signed-off-by: Larysa Zaremba +Reviewed-by: Maciej Fijalkowski +Link: https://lore.kernel.org/r/20231205210847.28460-5-larysa.zaremba@intel.com +Signed-off-by: Alexei Starovoitov +Stable-dep-of: b1a0c977c6f1 ("ice: fix incorrect counter for buffer allocation failures") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_txrx.c | 7 +++++-- + drivers/net/ethernet/intel/ice/ice_txrx.h | 18 +++++++++++++++--- + drivers/net/ethernet/intel/ice/ice_txrx_lib.h | 10 ++++++++++ + 3 files changed, 30 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c +index f5023ac9ab832..46f10f32924ee 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.c ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c +@@ -528,13 +528,14 @@ int ice_setup_rx_ring(struct ice_rx_ring *rx_ring) + * @xdp_prog: XDP program to run + * @xdp_ring: ring to be used for XDP_TX action + * @rx_buf: Rx buffer to store the XDP action ++ * @eop_desc: Last descriptor in packet to read metadata from + * + * Returns any of ICE_XDP_{PASS, CONSUMED, TX, REDIR} + */ + static void + ice_run_xdp(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, + struct bpf_prog *xdp_prog, struct ice_tx_ring *xdp_ring, +- struct ice_rx_buf *rx_buf) ++ struct ice_rx_buf *rx_buf, union ice_32b_rx_flex_desc *eop_desc) + { + unsigned int ret = ICE_XDP_PASS; + u32 act; +@@ -542,6 +543,8 @@ ice_run_xdp(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, + if (!xdp_prog) + goto exit; + ++ ice_xdp_meta_set_desc(xdp, eop_desc); ++ + act = bpf_prog_run_xdp(xdp_prog, xdp); + switch (act) { + case XDP_PASS: +@@ -1240,7 +1243,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) + if (ice_is_non_eop(rx_ring, rx_desc)) + continue; + +- ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_buf); ++ ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_buf, rx_desc); + if (rx_buf->act == ICE_XDP_PASS) + goto construct_skb; + total_rx_bytes += xdp_get_buff_len(xdp); +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h +index 407d4c320097f..ad2d286bd359d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.h ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.h +@@ -257,6 +257,14 @@ enum ice_rx_dtype { + ICE_RX_DTYPE_SPLIT_ALWAYS = 2, + }; + ++struct ice_xdp_buff { ++ struct xdp_buff xdp_buff; ++ const union ice_32b_rx_flex_desc *eop_desc; ++}; ++ ++/* Required for compatibility with xdp_buffs from xsk_pool */ ++static_assert(offsetof(struct ice_xdp_buff, xdp_buff) == 0); ++ + /* indices into GLINT_ITR registers */ + #define ICE_RX_ITR ICE_IDX_ITR0 + #define ICE_TX_ITR ICE_IDX_ITR1 +@@ -298,7 +306,6 @@ enum ice_dynamic_itr { + /* descriptor ring, associated with a VSI */ + struct ice_rx_ring { + /* CL1 - 1st cacheline starts here */ +- struct ice_rx_ring *next; /* pointer to next ring in q_vector */ + void *desc; /* Descriptor ring memory */ + struct device *dev; /* Used for DMA mapping */ + struct net_device *netdev; /* netdev ring maps to */ +@@ -310,12 +317,16 @@ struct ice_rx_ring { + u16 count; /* Number of descriptors */ + u16 reg_idx; /* HW register index of the ring */ + u16 next_to_alloc; +- /* CL2 - 2nd cacheline starts here */ ++ + union { + struct ice_rx_buf *rx_buf; + struct xdp_buff **xdp_buf; + }; +- struct xdp_buff xdp; ++ /* CL2 - 2nd cacheline starts here */ ++ union { ++ struct ice_xdp_buff xdp_ext; ++ struct xdp_buff xdp; ++ }; + /* CL3 - 3rd cacheline starts here */ + struct bpf_prog *xdp_prog; + u16 rx_offset; +@@ -332,6 +343,7 @@ struct ice_rx_ring { + /* CL4 - 4th cacheline starts here */ + struct ice_channel *ch; + struct ice_tx_ring *xdp_ring; ++ struct ice_rx_ring *next; /* pointer to next ring in q_vector */ + struct xsk_buff_pool *xsk_pool; + u32 nr_frags; + dma_addr_t dma; /* physical address of ring */ +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx_lib.h b/drivers/net/ethernet/intel/ice/ice_txrx_lib.h +index b0e56675f98b2..00971f8491358 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx_lib.h ++++ b/drivers/net/ethernet/intel/ice/ice_txrx_lib.h +@@ -164,4 +164,14 @@ ice_process_skb_fields(struct ice_rx_ring *rx_ring, + struct sk_buff *skb, u16 ptype); + void + ice_receive_skb(struct ice_rx_ring *rx_ring, struct sk_buff *skb, u16 vlan_tag); ++ ++static inline void ++ice_xdp_meta_set_desc(struct xdp_buff *xdp, ++ union ice_32b_rx_flex_desc *eop_desc) ++{ ++ struct ice_xdp_buff *xdp_ext = container_of(xdp, struct ice_xdp_buff, ++ xdp_buff); ++ ++ xdp_ext->eop_desc = eop_desc; ++} + #endif /* !_ICE_TXRX_LIB_H_ */ +-- +2.50.1 + diff --git a/queue-6.6/ice-stop-storing-xdp-verdict-within-ice_rx_buf.patch b/queue-6.6/ice-stop-storing-xdp-verdict-within-ice_rx_buf.patch new file mode 100644 index 0000000000..101c7aaff8 --- /dev/null +++ b/queue-6.6/ice-stop-storing-xdp-verdict-within-ice_rx_buf.patch @@ -0,0 +1,274 @@ +From 995eca567db21c04c41f7106762898c7fabae519 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 16:01:18 +0100 +Subject: ice: stop storing XDP verdict within ice_rx_buf + +From: Maciej Fijalkowski + +[ Upstream commit 468a1952df78f65c5991b7ac885c8b5b7dd87bab ] + +Idea behind having ice_rx_buf::act was to simplify and speed up the Rx +data path by walking through buffers that were representing cleaned HW +Rx descriptors. Since it caused us a major headache recently and we +rolled back to old approach that 'puts' Rx buffers right after running +XDP prog/creating skb, this is useless now and should be removed. + +Get rid of ice_rx_buf::act and related logic. We still need to take care +of a corner case where XDP program releases a particular fragment. + +Make ice_run_xdp() to return its result and use it within +ice_put_rx_mbuf(). + +Fixes: 2fba7dc5157b ("ice: Add support for XDP multi-buffer on Rx side") +Reviewed-by: Przemek Kitszel +Reviewed-by: Simon Horman +Signed-off-by: Maciej Fijalkowski +Tested-by: Chandan Kumar Rout (A Contingent Worker at Intel) +Signed-off-by: Tony Nguyen +Stable-dep-of: b1a0c977c6f1 ("ice: fix incorrect counter for buffer allocation failures") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_txrx.c | 62 +++++++++++-------- + drivers/net/ethernet/intel/ice/ice_txrx.h | 1 - + drivers/net/ethernet/intel/ice/ice_txrx_lib.h | 43 ------------- + 3 files changed, 36 insertions(+), 70 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c +index beb5c8643fe7d..e7084c6aab6da 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.c ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c +@@ -527,15 +527,14 @@ int ice_setup_rx_ring(struct ice_rx_ring *rx_ring) + * @xdp: xdp_buff used as input to the XDP program + * @xdp_prog: XDP program to run + * @xdp_ring: ring to be used for XDP_TX action +- * @rx_buf: Rx buffer to store the XDP action + * @eop_desc: Last descriptor in packet to read metadata from + * + * Returns any of ICE_XDP_{PASS, CONSUMED, TX, REDIR} + */ +-static void ++static u32 + ice_run_xdp(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, + struct bpf_prog *xdp_prog, struct ice_tx_ring *xdp_ring, +- struct ice_rx_buf *rx_buf, union ice_32b_rx_flex_desc *eop_desc) ++ union ice_32b_rx_flex_desc *eop_desc) + { + unsigned int ret = ICE_XDP_PASS; + u32 act; +@@ -574,7 +573,7 @@ ice_run_xdp(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, + ret = ICE_XDP_CONSUMED; + } + exit: +- ice_set_rx_bufs_act(xdp, rx_ring, ret); ++ return ret; + } + + /** +@@ -860,10 +859,8 @@ ice_add_xdp_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, + xdp_buff_set_frags_flag(xdp); + } + +- if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) { +- ice_set_rx_bufs_act(xdp, rx_ring, ICE_XDP_CONSUMED); ++ if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) + return -ENOMEM; +- } + + __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, rx_buf->page, + rx_buf->page_offset, size); +@@ -1076,12 +1073,12 @@ ice_construct_skb(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp) + rx_buf->page_offset + headlen, size, + xdp->frame_sz); + } else { +- /* buffer is unused, change the act that should be taken later +- * on; data was copied onto skb's linear part so there's no ++ /* buffer is unused, restore biased page count in Rx buffer; ++ * data was copied onto skb's linear part so there's no + * need for adjusting page offset and we can reuse this buffer + * as-is + */ +- rx_buf->act = ICE_SKB_CONSUMED; ++ rx_buf->pagecnt_bias++; + } + + if (unlikely(xdp_buff_has_frags(xdp))) { +@@ -1134,29 +1131,34 @@ ice_put_rx_buf(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf) + * @xdp: XDP buffer carrying linear + frags part + * @xdp_xmit: XDP_TX/XDP_REDIRECT verdict storage + * @ntc: a current next_to_clean value to be stored at rx_ring ++ * @verdict: return code from XDP program execution + * + * Walk through gathered fragments and satisfy internal page + * recycle mechanism; we take here an action related to verdict + * returned by XDP program; + */ + static void ice_put_rx_mbuf(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, +- u32 *xdp_xmit, u32 ntc) ++ u32 *xdp_xmit, u32 ntc, u32 verdict) + { + u32 nr_frags = rx_ring->nr_frags + 1; + u32 idx = rx_ring->first_desc; + u32 cnt = rx_ring->count; ++ u32 post_xdp_frags = 1; + struct ice_rx_buf *buf; + int i; + +- for (i = 0; i < nr_frags; i++) { ++ if (unlikely(xdp_buff_has_frags(xdp))) ++ post_xdp_frags += xdp_get_shared_info_from_buff(xdp)->nr_frags; ++ ++ for (i = 0; i < post_xdp_frags; i++) { + buf = &rx_ring->rx_buf[idx]; + +- if (buf->act & (ICE_XDP_TX | ICE_XDP_REDIR)) { ++ if (verdict & (ICE_XDP_TX | ICE_XDP_REDIR)) { + ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz); +- *xdp_xmit |= buf->act; +- } else if (buf->act & ICE_XDP_CONSUMED) { ++ *xdp_xmit |= verdict; ++ } else if (verdict & ICE_XDP_CONSUMED) { + buf->pagecnt_bias++; +- } else if (buf->act == ICE_XDP_PASS) { ++ } else if (verdict == ICE_XDP_PASS) { + ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz); + } + +@@ -1165,6 +1167,17 @@ static void ice_put_rx_mbuf(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, + if (++idx == cnt) + idx = 0; + } ++ /* handle buffers that represented frags released by XDP prog; ++ * for these we keep pagecnt_bias as-is; refcount from struct page ++ * has been decremented within XDP prog and we do not have to increase ++ * the biased refcnt ++ */ ++ for (; i < nr_frags; i++) { ++ buf = &rx_ring->rx_buf[idx]; ++ ice_put_rx_buf(rx_ring, buf); ++ if (++idx == cnt) ++ idx = 0; ++ } + + xdp->data = NULL; + rx_ring->first_desc = ntc; +@@ -1191,9 +1204,9 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) + struct ice_tx_ring *xdp_ring = NULL; + struct bpf_prog *xdp_prog = NULL; + u32 ntc = rx_ring->next_to_clean; ++ u32 cached_ntu, xdp_verdict; + u32 cnt = rx_ring->count; + u32 xdp_xmit = 0; +- u32 cached_ntu; + bool failure; + + xdp_prog = READ_ONCE(rx_ring->xdp_prog); +@@ -1257,7 +1270,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) + xdp_prepare_buff(xdp, hard_start, offset, size, !!offset); + xdp_buff_clear_frags_flag(xdp); + } else if (ice_add_xdp_frag(rx_ring, xdp, rx_buf, size)) { +- ice_put_rx_mbuf(rx_ring, xdp, NULL, ntc); ++ ice_put_rx_mbuf(rx_ring, xdp, NULL, ntc, ICE_XDP_CONSUMED); + break; + } + if (++ntc == cnt) +@@ -1268,13 +1281,13 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) + continue; + + ice_get_pgcnts(rx_ring); +- ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_buf, rx_desc); +- if (rx_buf->act == ICE_XDP_PASS) ++ xdp_verdict = ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_desc); ++ if (xdp_verdict == ICE_XDP_PASS) + goto construct_skb; + total_rx_bytes += xdp_get_buff_len(xdp); + total_rx_pkts++; + +- ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc); ++ ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict); + + continue; + construct_skb: +@@ -1285,12 +1298,9 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) + /* exit if we failed to retrieve a buffer */ + if (!skb) { + rx_ring->ring_stats->rx_stats.alloc_page_failed++; +- rx_buf->act = ICE_XDP_CONSUMED; +- if (unlikely(xdp_buff_has_frags(xdp))) +- ice_set_rx_bufs_act(xdp, rx_ring, +- ICE_XDP_CONSUMED); ++ xdp_verdict = ICE_XDP_CONSUMED; + } +- ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc); ++ ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict); + + if (!skb) + break; +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h +index ad2d286bd359d..53a155dde3e32 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.h ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.h +@@ -201,7 +201,6 @@ struct ice_rx_buf { + struct page *page; + unsigned int page_offset; + unsigned int pgcnt; +- unsigned int act; + unsigned int pagecnt_bias; + }; + +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx_lib.h b/drivers/net/ethernet/intel/ice/ice_txrx_lib.h +index 00971f8491358..41efafc5eb386 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx_lib.h ++++ b/drivers/net/ethernet/intel/ice/ice_txrx_lib.h +@@ -5,49 +5,6 @@ + #define _ICE_TXRX_LIB_H_ + #include "ice.h" + +-/** +- * ice_set_rx_bufs_act - propagate Rx buffer action to frags +- * @xdp: XDP buffer representing frame (linear and frags part) +- * @rx_ring: Rx ring struct +- * act: action to store onto Rx buffers related to XDP buffer parts +- * +- * Set action that should be taken before putting Rx buffer from first frag +- * to the last. +- */ +-static inline void +-ice_set_rx_bufs_act(struct xdp_buff *xdp, const struct ice_rx_ring *rx_ring, +- const unsigned int act) +-{ +- u32 sinfo_frags = xdp_get_shared_info_from_buff(xdp)->nr_frags; +- u32 nr_frags = rx_ring->nr_frags + 1; +- u32 idx = rx_ring->first_desc; +- u32 cnt = rx_ring->count; +- struct ice_rx_buf *buf; +- +- for (int i = 0; i < nr_frags; i++) { +- buf = &rx_ring->rx_buf[idx]; +- buf->act = act; +- +- if (++idx == cnt) +- idx = 0; +- } +- +- /* adjust pagecnt_bias on frags freed by XDP prog */ +- if (sinfo_frags < rx_ring->nr_frags && act == ICE_XDP_CONSUMED) { +- u32 delta = rx_ring->nr_frags - sinfo_frags; +- +- while (delta) { +- if (idx == 0) +- idx = cnt - 1; +- else +- idx--; +- buf = &rx_ring->rx_buf[idx]; +- buf->pagecnt_bias--; +- delta--; +- } +- } +-} +- + /** + * ice_test_staterr - tests bits in Rx descriptor status and error fields + * @status_err_n: Rx descriptor status_error0 or status_error1 bits +-- +2.50.1 + diff --git a/queue-6.6/net-dlink-fix-multicast-stats-being-counted-incorrec.patch b/queue-6.6/net-dlink-fix-multicast-stats-being-counted-incorrec.patch new file mode 100644 index 0000000000..efc3d3fa6e --- /dev/null +++ b/queue-6.6/net-dlink-fix-multicast-stats-being-counted-incorrec.patch @@ -0,0 +1,46 @@ +From 873765c16ba313611e466623793a24b8e13469af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Aug 2025 03:29:24 +0900 +Subject: net: dlink: fix multicast stats being counted incorrectly + +From: Yeounsu Moon + +[ Upstream commit 007a5ffadc4fd51739527f1503b7cf048f31c413 ] + +`McstFramesRcvdOk` counts the number of received multicast packets, and +it reports the value correctly. + +However, reading `McstFramesRcvdOk` clears the register to zero. As a +result, the driver was reporting only the packets since the last read, +instead of the accumulated total. + +Fix this by updating the multicast statistics accumulatively instaed of +instantaneously. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Tested-on: D-Link DGE-550T Rev-A3 +Signed-off-by: Yeounsu Moon +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250823182927.6063-3-yyyynoom@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/dlink/dl2k.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c +index fad5a72d3b167..f1208591ed67e 100644 +--- a/drivers/net/ethernet/dlink/dl2k.c ++++ b/drivers/net/ethernet/dlink/dl2k.c +@@ -1092,7 +1092,7 @@ get_stats (struct net_device *dev) + dev->stats.rx_bytes += dr32(OctetRcvOk); + dev->stats.tx_bytes += dr32(OctetXmtOk); + +- dev->stats.multicast = dr32(McstFramesRcvdOk); ++ dev->stats.multicast += dr32(McstFramesRcvdOk); + dev->stats.collisions += dr32(SingleColFrames) + + dr32(MultiColFrames); + +-- +2.50.1 + diff --git a/queue-6.6/net-ipv4-fix-regression-in-local-broadcast-routes.patch b/queue-6.6/net-ipv4-fix-regression-in-local-broadcast-routes.patch new file mode 100644 index 0000000000..ca9ad6f525 --- /dev/null +++ b/queue-6.6/net-ipv4-fix-regression-in-local-broadcast-routes.patch @@ -0,0 +1,57 @@ +From 1ed62904f05e264e2cf8232c0ee98ef03c920dee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Aug 2025 08:23:21 +0200 +Subject: net: ipv4: fix regression in local-broadcast routes + +From: Oscar Maes + +[ Upstream commit 5189446ba995556eaa3755a6e875bc06675b88bd ] + +Commit 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") +introduced a regression where local-broadcast packets would have their +gateway set in __mkroute_output, which was caused by fi = NULL being +removed. + +Fix this by resetting the fib_info for local-broadcast packets. This +preserves the intended changes for directed-broadcast packets. + +Cc: stable@vger.kernel.org +Fixes: 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") +Reported-by: Brett A C Sheffield +Closes: https://lore.kernel.org/regressions/20250822165231.4353-4-bacs@librecast.net +Signed-off-by: Oscar Maes +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20250827062322.4807-1-oscmaes92@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/route.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 8672ebbace980..20f5c8307443d 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -2547,12 +2547,16 @@ static struct rtable *__mkroute_output(const struct fib_result *res, + !netif_is_l3_master(dev_out)) + return ERR_PTR(-EINVAL); + +- if (ipv4_is_lbcast(fl4->daddr)) ++ if (ipv4_is_lbcast(fl4->daddr)) { + type = RTN_BROADCAST; +- else if (ipv4_is_multicast(fl4->daddr)) ++ ++ /* reset fi to prevent gateway resolution */ ++ fi = NULL; ++ } else if (ipv4_is_multicast(fl4->daddr)) { + type = RTN_MULTICAST; +- else if (ipv4_is_zeronet(fl4->daddr)) ++ } else if (ipv4_is_zeronet(fl4->daddr)) { + return ERR_PTR(-EINVAL); ++ } + + if (dev_out->flags & IFF_LOOPBACK) + flags |= RTCF_LOCAL; +-- +2.50.1 + diff --git a/queue-6.6/net-mlx5-add-device-cap-for-supporting-hot-reset-in-.patch b/queue-6.6/net-mlx5-add-device-cap-for-supporting-hot-reset-in-.patch new file mode 100644 index 0000000000..09e4e2394b --- /dev/null +++ b/queue-6.6/net-mlx5-add-device-cap-for-supporting-hot-reset-in-.patch @@ -0,0 +1,64 @@ +From 15f719a86bda9471820e5d022e59ac3d60d69ae5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Sep 2024 13:17:51 -0700 +Subject: net/mlx5: Add device cap for supporting hot reset in sync reset flow + +From: Moshe Shemesh + +[ Upstream commit 9947204cdad97d22d171039019a4aad4d6899cdd ] + +New devices with new FW can support sync reset for firmware activate +using hot reset. Add capability for supporting it and add MFRL field to +query from FW which type of PCI reset method to use while handling sync +reset events. + +Signed-off-by: Moshe Shemesh +Signed-off-by: Saeed Mahameed +Reviewed-by: Jacob Keller +Link: https://patch.msgid.link/20240911201757.1505453-10-saeed@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 902a8bc23a24 ("net/mlx5: Fix lockdep assertion on sync reset unload event") +Signed-off-by: Sasha Levin +--- + include/linux/mlx5/mlx5_ifc.h | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h +index 9106771bb92f0..4913d364e9774 100644 +--- a/include/linux/mlx5/mlx5_ifc.h ++++ b/include/linux/mlx5/mlx5_ifc.h +@@ -1731,7 +1731,8 @@ struct mlx5_ifc_cmd_hca_cap_bits { + u8 reserved_at_328[0x2]; + u8 relaxed_ordering_read[0x1]; + u8 log_max_pd[0x5]; +- u8 reserved_at_330[0x6]; ++ u8 reserved_at_330[0x5]; ++ u8 pcie_reset_using_hotreset_method[0x1]; + u8 pci_sync_for_fw_update_with_driver_unload[0x1]; + u8 vnic_env_cnt_steering_fail[0x1]; + u8 vport_counter_local_loopback[0x1]; +@@ -10824,6 +10825,11 @@ struct mlx5_ifc_mcda_reg_bits { + u8 data[][0x20]; + }; + ++enum { ++ MLX5_MFRL_REG_PCI_RESET_METHOD_LINK_TOGGLE = 0, ++ MLX5_MFRL_REG_PCI_RESET_METHOD_HOT_RESET = 1, ++}; ++ + enum { + MLX5_MFRL_REG_RESET_STATE_IDLE = 0, + MLX5_MFRL_REG_RESET_STATE_IN_NEGOTIATION = 1, +@@ -10851,7 +10857,8 @@ struct mlx5_ifc_mfrl_reg_bits { + u8 pci_sync_for_fw_update_start[0x1]; + u8 pci_sync_for_fw_update_resp[0x2]; + u8 rst_type_sel[0x3]; +- u8 reserved_at_28[0x4]; ++ u8 pci_reset_req_method[0x3]; ++ u8 reserved_at_2b[0x1]; + u8 reset_state[0x4]; + u8 reset_type[0x8]; + u8 reset_level[0x8]; +-- +2.50.1 + diff --git a/queue-6.6/net-mlx5-add-support-for-sync-reset-using-hot-reset.patch b/queue-6.6/net-mlx5-add-support-for-sync-reset-using-hot-reset.patch new file mode 100644 index 0000000000..65c98536c4 --- /dev/null +++ b/queue-6.6/net-mlx5-add-support-for-sync-reset-using-hot-reset.patch @@ -0,0 +1,208 @@ +From 67f945582744ec16678dfbbc9b5b2c3e6cfdf89e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Sep 2024 13:17:52 -0700 +Subject: net/mlx5: Add support for sync reset using hot reset + +From: Moshe Shemesh + +[ Upstream commit 57502f62678ced0149d415324931bde37b42885a ] + +On device that supports sync reset for firmware activate using hot +reset, the driver queries the required reset method while handling the +sync reset request. If the required reset method is hot reset, the +driver will use pci_reset_bus() to reset the PCI link instead of the +link toggle. + +Signed-off-by: Moshe Shemesh +Signed-off-by: Saeed Mahameed +Reviewed-by: Jacob Keller +Link: https://patch.msgid.link/20240911201757.1505453-11-saeed@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 902a8bc23a24 ("net/mlx5: Fix lockdep assertion on sync reset unload event") +Signed-off-by: Sasha Levin +--- + .../ethernet/mellanox/mlx5/core/fw_reset.c | 82 +++++++++++++++---- + .../net/ethernet/mellanox/mlx5/core/main.c | 3 + + 2 files changed, 69 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index 6b17346aa4cef..a1c2dd7f5c2c0 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -26,6 +26,7 @@ struct mlx5_fw_reset { + struct work_struct reset_now_work; + struct work_struct reset_abort_work; + unsigned long reset_flags; ++ u8 reset_method; + struct timer_list timer; + struct completion done; + int ret; +@@ -94,7 +95,7 @@ static int mlx5_reg_mfrl_set(struct mlx5_core_dev *dev, u8 reset_level, + } + + static int mlx5_reg_mfrl_query(struct mlx5_core_dev *dev, u8 *reset_level, +- u8 *reset_type, u8 *reset_state) ++ u8 *reset_type, u8 *reset_state, u8 *reset_method) + { + u32 out[MLX5_ST_SZ_DW(mfrl_reg)] = {}; + u32 in[MLX5_ST_SZ_DW(mfrl_reg)] = {}; +@@ -110,13 +111,26 @@ static int mlx5_reg_mfrl_query(struct mlx5_core_dev *dev, u8 *reset_level, + *reset_type = MLX5_GET(mfrl_reg, out, reset_type); + if (reset_state) + *reset_state = MLX5_GET(mfrl_reg, out, reset_state); ++ if (reset_method) ++ *reset_method = MLX5_GET(mfrl_reg, out, pci_reset_req_method); + + return 0; + } + + int mlx5_fw_reset_query(struct mlx5_core_dev *dev, u8 *reset_level, u8 *reset_type) + { +- return mlx5_reg_mfrl_query(dev, reset_level, reset_type, NULL); ++ return mlx5_reg_mfrl_query(dev, reset_level, reset_type, NULL, NULL); ++} ++ ++static int mlx5_fw_reset_get_reset_method(struct mlx5_core_dev *dev, ++ u8 *reset_method) ++{ ++ if (!MLX5_CAP_GEN(dev, pcie_reset_using_hotreset_method)) { ++ *reset_method = MLX5_MFRL_REG_PCI_RESET_METHOD_LINK_TOGGLE; ++ return 0; ++ } ++ ++ return mlx5_reg_mfrl_query(dev, NULL, NULL, NULL, reset_method); + } + + static int mlx5_fw_reset_get_reset_state_err(struct mlx5_core_dev *dev, +@@ -124,7 +138,7 @@ static int mlx5_fw_reset_get_reset_state_err(struct mlx5_core_dev *dev, + { + u8 reset_state; + +- if (mlx5_reg_mfrl_query(dev, NULL, NULL, &reset_state)) ++ if (mlx5_reg_mfrl_query(dev, NULL, NULL, &reset_state, NULL)) + goto out; + + if (!reset_state) +@@ -402,7 +416,11 @@ static void mlx5_sync_reset_request_event(struct work_struct *work) + struct mlx5_core_dev *dev = fw_reset->dev; + int err; + +- if (test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags) || ++ err = mlx5_fw_reset_get_reset_method(dev, &fw_reset->reset_method); ++ if (err) ++ mlx5_core_warn(dev, "Failed reading MFRL, err %d\n", err); ++ ++ if (err || test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags) || + !mlx5_is_reset_now_capable(dev)) { + err = mlx5_fw_reset_set_reset_sync_nack(dev); + mlx5_core_warn(dev, "PCI Sync FW Update Reset Nack %s", +@@ -419,21 +437,15 @@ static void mlx5_sync_reset_request_event(struct work_struct *work) + mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack. Device reset is expected.\n"); + } + +-static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev) ++static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev, u16 dev_id) + { + struct pci_bus *bridge_bus = dev->pdev->bus; + struct pci_dev *bridge = bridge_bus->self; + unsigned long timeout; + struct pci_dev *sdev; +- u16 reg16, dev_id; + int cap, err; ++ u16 reg16; + +- err = pci_read_config_word(dev->pdev, PCI_DEVICE_ID, &dev_id); +- if (err) +- return pcibios_err_to_errno(err); +- err = mlx5_check_dev_ids(dev, dev_id); +- if (err) +- return err; + cap = pci_find_capability(bridge, PCI_CAP_ID_EXP); + if (!cap) + return -EOPNOTSUPP; +@@ -503,6 +515,44 @@ static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev) + return err; + } + ++static int mlx5_pci_reset_bus(struct mlx5_core_dev *dev) ++{ ++ if (!MLX5_CAP_GEN(dev, pcie_reset_using_hotreset_method)) ++ return -EOPNOTSUPP; ++ ++ return pci_reset_bus(dev->pdev); ++} ++ ++static int mlx5_sync_pci_reset(struct mlx5_core_dev *dev, u8 reset_method) ++{ ++ u16 dev_id; ++ int err; ++ ++ err = pci_read_config_word(dev->pdev, PCI_DEVICE_ID, &dev_id); ++ if (err) ++ return pcibios_err_to_errno(err); ++ err = mlx5_check_dev_ids(dev, dev_id); ++ if (err) ++ return err; ++ ++ switch (reset_method) { ++ case MLX5_MFRL_REG_PCI_RESET_METHOD_LINK_TOGGLE: ++ err = mlx5_pci_link_toggle(dev, dev_id); ++ if (err) ++ mlx5_core_warn(dev, "mlx5_pci_link_toggle failed\n"); ++ break; ++ case MLX5_MFRL_REG_PCI_RESET_METHOD_HOT_RESET: ++ err = mlx5_pci_reset_bus(dev); ++ if (err) ++ mlx5_core_warn(dev, "mlx5_pci_reset_bus failed\n"); ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return err; ++} ++ + static void mlx5_sync_reset_now_event(struct work_struct *work) + { + struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, +@@ -521,9 +571,9 @@ static void mlx5_sync_reset_now_event(struct work_struct *work) + goto done; + } + +- err = mlx5_pci_link_toggle(dev); ++ err = mlx5_sync_pci_reset(dev, fw_reset->reset_method); + if (err) { +- mlx5_core_warn(dev, "mlx5_pci_link_toggle failed, no reset done, err %d\n", err); ++ mlx5_core_warn(dev, "mlx5_sync_pci_reset failed, no reset done, err %d\n", err); + set_bit(MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED, &fw_reset->reset_flags); + } + +@@ -585,9 +635,9 @@ static void mlx5_sync_reset_unload_event(struct work_struct *work) + + mlx5_core_warn(dev, "Sync Reset, got reset action. rst_state = %u\n", rst_state); + if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ) { +- err = mlx5_pci_link_toggle(dev); ++ err = mlx5_sync_pci_reset(dev, fw_reset->reset_method); + if (err) { +- mlx5_core_warn(dev, "mlx5_pci_link_toggle failed, err %d\n", err); ++ mlx5_core_warn(dev, "mlx5_sync_pci_reset failed, err %d\n", err); + fw_reset->ret = err; + } + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index 62a85f09b52fd..8a11e410f7c13 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -627,6 +627,9 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx) + if (MLX5_CAP_GEN_MAX(dev, pci_sync_for_fw_update_with_driver_unload)) + MLX5_SET(cmd_hca_cap, set_hca_cap, + pci_sync_for_fw_update_with_driver_unload, 1); ++ if (MLX5_CAP_GEN_MAX(dev, pcie_reset_using_hotreset_method)) ++ MLX5_SET(cmd_hca_cap, set_hca_cap, ++ pcie_reset_using_hotreset_method, 1); + + if (MLX5_CAP_GEN_MAX(dev, num_vhca_ports)) + MLX5_SET(cmd_hca_cap, +-- +2.50.1 + diff --git a/queue-6.6/net-mlx5-call-mlx5_sf_id_erase-once-in-mlx5_sf_deall.patch b/queue-6.6/net-mlx5-call-mlx5_sf_id_erase-once-in-mlx5_sf_deall.patch new file mode 100644 index 0000000000..17be371310 --- /dev/null +++ b/queue-6.6/net-mlx5-call-mlx5_sf_id_erase-once-in-mlx5_sf_deall.patch @@ -0,0 +1,63 @@ +From a9d4f19c2bd7009548765f7889228d5b65f048c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Jun 2023 13:43:42 +0200 +Subject: net/mlx5: Call mlx5_sf_id_erase() once in mlx5_sf_dealloc() + +From: Jiri Pirko + +[ Upstream commit 2597ee190b4eb48d3b7d35b7bb2cc18046ae087e ] + +Before every call of mlx5_sf_dealloc(), there is a call to +mlx5_sf_id_erase(). So move it to the beginning of mlx5_sf_dealloc(). +Also remove redundant mlx5_sf_id_erase() call from mlx5_sf_free() +as it is called only from mlx5_sf_dealloc(). + +Signed-off-by: Jiri Pirko +Reviewed-by: Shay Drory +Signed-off-by: Saeed Mahameed +Stable-dep-of: 26e42ec7712d ("net/mlx5: Nack sync reset when SFs are present") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +index e34a8f88c518c..1dd01701df20e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +@@ -111,7 +111,6 @@ mlx5_sf_alloc(struct mlx5_sf_table *table, struct mlx5_eswitch *esw, + + static void mlx5_sf_free(struct mlx5_sf_table *table, struct mlx5_sf *sf) + { +- mlx5_sf_id_erase(table, sf); + mlx5_sf_hw_table_sf_free(table->dev, sf->controller, sf->id); + trace_mlx5_sf_free(table->dev, sf->port_index, sf->controller, sf->hw_fn_id); + kfree(sf); +@@ -361,6 +360,8 @@ int mlx5_devlink_sf_port_new(struct devlink *devlink, + + static void mlx5_sf_dealloc(struct mlx5_sf_table *table, struct mlx5_sf *sf) + { ++ mlx5_sf_id_erase(table, sf); ++ + if (sf->hw_state == MLX5_VHCA_STATE_ALLOCATED) { + mlx5_sf_free(table, sf); + } else if (mlx5_sf_is_active(sf)) { +@@ -401,7 +402,6 @@ int mlx5_devlink_sf_port_del(struct devlink *devlink, + } + + mlx5_eswitch_unload_sf_vport(esw, sf->hw_fn_id); +- mlx5_sf_id_erase(table, sf); + + mutex_lock(&table->sf_state_lock); + mlx5_sf_dealloc(table, sf); +@@ -473,7 +473,6 @@ static void mlx5_sf_deactivate_all(struct mlx5_sf_table *table) + */ + xa_for_each(&table->port_indices, index, sf) { + mlx5_eswitch_unload_sf_vport(esw, sf->hw_fn_id); +- mlx5_sf_id_erase(table, sf); + mlx5_sf_dealloc(table, sf); + } + } +-- +2.50.1 + diff --git a/queue-6.6/net-mlx5-convert-sf-port_indices-xarray-to-function_.patch b/queue-6.6/net-mlx5-convert-sf-port_indices-xarray-to-function_.patch new file mode 100644 index 0000000000..dc5cae53a3 --- /dev/null +++ b/queue-6.6/net-mlx5-convert-sf-port_indices-xarray-to-function_.patch @@ -0,0 +1,112 @@ +From e8e34b31f43733bc8af5b694cf341343cb4884bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 May 2023 11:33:16 +0200 +Subject: net/mlx5: Convert SF port_indices xarray to function_ids xarray + +From: Jiri Pirko + +[ Upstream commit 2284a4836251b3dee348172f69ac84157aa7b03e ] + +No need to lookup for sf by a port index. Convert the xarray to have +function id as an index and optimize the remaining function id +based lookup. + +Signed-off-by: Jiri Pirko +Reviewed-by: Shay Drory +Signed-off-by: Saeed Mahameed +Stable-dep-of: 26e42ec7712d ("net/mlx5: Nack sync reset when SFs are present") +Signed-off-by: Sasha Levin +--- + .../ethernet/mellanox/mlx5/core/sf/devlink.c | 29 +++++++------------ + 1 file changed, 11 insertions(+), 18 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +index 4711dcfe8ba83..3f0ac2d1dde68 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +@@ -29,7 +29,7 @@ static void *mlx5_sf_by_dl_port(struct devlink_port *dl_port) + + struct mlx5_sf_table { + struct mlx5_core_dev *dev; /* To refer from notifier context. */ +- struct xarray port_indices; /* port index based lookup. */ ++ struct xarray function_ids; /* function id based lookup. */ + refcount_t refcount; + struct completion disable_complete; + struct mutex sf_state_lock; /* Serializes sf state among user cmds & vhca event handler. */ +@@ -40,24 +40,17 @@ struct mlx5_sf_table { + static struct mlx5_sf * + mlx5_sf_lookup_by_function_id(struct mlx5_sf_table *table, unsigned int fn_id) + { +- unsigned long index; +- struct mlx5_sf *sf; +- +- xa_for_each(&table->port_indices, index, sf) { +- if (sf->hw_fn_id == fn_id) +- return sf; +- } +- return NULL; ++ return xa_load(&table->function_ids, fn_id); + } + +-static int mlx5_sf_id_insert(struct mlx5_sf_table *table, struct mlx5_sf *sf) ++static int mlx5_sf_function_id_insert(struct mlx5_sf_table *table, struct mlx5_sf *sf) + { +- return xa_insert(&table->port_indices, sf->port_index, sf, GFP_KERNEL); ++ return xa_insert(&table->function_ids, sf->hw_fn_id, sf, GFP_KERNEL); + } + +-static void mlx5_sf_id_erase(struct mlx5_sf_table *table, struct mlx5_sf *sf) ++static void mlx5_sf_function_id_erase(struct mlx5_sf_table *table, struct mlx5_sf *sf) + { +- xa_erase(&table->port_indices, sf->port_index); ++ xa_erase(&table->function_ids, sf->hw_fn_id); + } + + static struct mlx5_sf * +@@ -94,7 +87,7 @@ mlx5_sf_alloc(struct mlx5_sf_table *table, struct mlx5_eswitch *esw, + sf->hw_state = MLX5_VHCA_STATE_ALLOCATED; + sf->controller = controller; + +- err = mlx5_sf_id_insert(table, sf); ++ err = mlx5_sf_function_id_insert(table, sf); + if (err) + goto insert_err; + +@@ -347,7 +340,7 @@ int mlx5_devlink_sf_port_new(struct devlink *devlink, + + static void mlx5_sf_dealloc(struct mlx5_sf_table *table, struct mlx5_sf *sf) + { +- mlx5_sf_id_erase(table, sf); ++ mlx5_sf_function_id_erase(table, sf); + + if (sf->hw_state == MLX5_VHCA_STATE_ALLOCATED) { + mlx5_sf_free(table, sf); +@@ -451,7 +444,7 @@ static void mlx5_sf_deactivate_all(struct mlx5_sf_table *table) + /* At this point, no new user commands can start and no vhca event can + * arrive. It is safe to destroy all user created SFs. + */ +- xa_for_each(&table->port_indices, index, sf) { ++ xa_for_each(&table->function_ids, index, sf) { + mlx5_eswitch_unload_sf_vport(esw, sf->hw_fn_id); + mlx5_sf_dealloc(table, sf); + } +@@ -510,7 +503,7 @@ int mlx5_sf_table_init(struct mlx5_core_dev *dev) + + mutex_init(&table->sf_state_lock); + table->dev = dev; +- xa_init(&table->port_indices); ++ xa_init(&table->function_ids); + dev->priv.sf_table = table; + refcount_set(&table->refcount, 0); + table->esw_nb.notifier_call = mlx5_sf_esw_event; +@@ -545,6 +538,6 @@ void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev) + mlx5_esw_event_notifier_unregister(dev->priv.eswitch, &table->esw_nb); + WARN_ON(refcount_read(&table->refcount)); + mutex_destroy(&table->sf_state_lock); +- WARN_ON(!xa_empty(&table->port_indices)); ++ WARN_ON(!xa_empty(&table->function_ids)); + kfree(table); + } +-- +2.50.1 + diff --git a/queue-6.6/net-mlx5-fix-lockdep-assertion-on-sync-reset-unload-.patch b/queue-6.6/net-mlx5-fix-lockdep-assertion-on-sync-reset-unload-.patch new file mode 100644 index 0000000000..b7c5ce8537 --- /dev/null +++ b/queue-6.6/net-mlx5-fix-lockdep-assertion-on-sync-reset-unload-.patch @@ -0,0 +1,247 @@ +From 879ac7b238ecec0f9e67a75e763f9557f23314b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:29 +0300 +Subject: net/mlx5: Fix lockdep assertion on sync reset unload event + +From: Moshe Shemesh + +[ Upstream commit 902a8bc23a24882200f57cadc270e15a2cfaf2bb ] + +Fix lockdep assertion triggered during sync reset unload event. When the +sync reset flow is initiated using the devlink reload fw_activate +option, the PF already holds the devlink lock while handling unload +event. In this case, delegate sync reset unload event handling back to +the devlink callback process to avoid double-locking and resolve the +lockdep warning. + +Kernel log: +WARNING: CPU: 9 PID: 1578 at devl_assert_locked+0x31/0x40 +[...] +Call Trace: + + mlx5_unload_one_devl_locked+0x2c/0xc0 [mlx5_core] + mlx5_sync_reset_unload_event+0xaf/0x2f0 [mlx5_core] + process_one_work+0x222/0x640 + worker_thread+0x199/0x350 + kthread+0x10b/0x230 + ? __pfx_worker_thread+0x10/0x10 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x8e/0x100 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + +Fixes: 7a9770f1bfea ("net/mlx5: Handle sync reset unload event") +Signed-off-by: Moshe Shemesh +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-7-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mellanox/mlx5/core/devlink.c | 2 +- + .../ethernet/mellanox/mlx5/core/fw_reset.c | 108 ++++++++++-------- + .../ethernet/mellanox/mlx5/core/fw_reset.h | 1 + + 3 files changed, 63 insertions(+), 48 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +index f2d1f7cad7e72..8489b5087d9c6 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +@@ -107,7 +107,7 @@ static int mlx5_devlink_reload_fw_activate(struct devlink *devlink, struct netli + if (err) + return err; + +- mlx5_unload_one_devl_locked(dev, false); ++ mlx5_sync_reset_unload_flow(dev, true); + err = mlx5_health_wait_pci_up(dev); + if (err) + NL_SET_ERR_MSG_MOD(extack, "FW activate aborted, PCI reads fail after reset"); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index a1c2dd7f5c2c0..b9986a2656083 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -12,7 +12,8 @@ enum { + MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, + MLX5_FW_RESET_FLAGS_PENDING_COMP, + MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, +- MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED ++ MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED, ++ MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, + }; + + struct mlx5_fw_reset { +@@ -217,7 +218,7 @@ int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev) + return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL0, 0, 0, false); + } + +-static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unloaded) ++static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev) + { + struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; + struct devlink *devlink = priv_to_devlink(dev); +@@ -226,8 +227,7 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unload + if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) { + complete(&fw_reset->done); + } else { +- if (!unloaded) +- mlx5_unload_one(dev, false); ++ mlx5_sync_reset_unload_flow(dev, false); + if (mlx5_health_wait_pci_up(dev)) + mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n"); + else +@@ -270,7 +270,7 @@ static void mlx5_sync_reset_reload_work(struct work_struct *work) + + mlx5_sync_reset_clear_reset_requested(dev, false); + mlx5_enter_error_state(dev, true); +- mlx5_fw_reset_complete_reload(dev, false); ++ mlx5_fw_reset_complete_reload(dev); + } + + #define MLX5_RESET_POLL_INTERVAL (HZ / 10) +@@ -553,6 +553,59 @@ static int mlx5_sync_pci_reset(struct mlx5_core_dev *dev, u8 reset_method) + return err; + } + ++void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked) ++{ ++ struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; ++ unsigned long timeout; ++ bool reset_action; ++ u8 rst_state; ++ int err; ++ ++ if (locked) ++ mlx5_unload_one_devl_locked(dev, false); ++ else ++ mlx5_unload_one(dev, false); ++ ++ if (!test_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags)) ++ return; ++ ++ mlx5_set_fw_rst_ack(dev); ++ mlx5_core_warn(dev, "Sync Reset Unload done, device reset expected\n"); ++ ++ reset_action = false; ++ timeout = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, RESET_UNLOAD)); ++ do { ++ rst_state = mlx5_get_fw_rst_state(dev); ++ if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ || ++ rst_state == MLX5_FW_RST_STATE_IDLE) { ++ reset_action = true; ++ break; ++ } ++ msleep(20); ++ } while (!time_after(jiffies, timeout)); ++ ++ if (!reset_action) { ++ mlx5_core_err(dev, "Got timeout waiting for sync reset action, state = %u\n", ++ rst_state); ++ fw_reset->ret = -ETIMEDOUT; ++ goto done; ++ } ++ ++ mlx5_core_warn(dev, "Sync Reset, got reset action. rst_state = %u\n", ++ rst_state); ++ if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ) { ++ err = mlx5_sync_pci_reset(dev, fw_reset->reset_method); ++ if (err) { ++ mlx5_core_warn(dev, "mlx5_sync_pci_reset failed, err %d\n", ++ err); ++ fw_reset->ret = err; ++ } ++ } ++ ++done: ++ clear_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags); ++} ++ + static void mlx5_sync_reset_now_event(struct work_struct *work) + { + struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, +@@ -580,16 +633,13 @@ static void mlx5_sync_reset_now_event(struct work_struct *work) + mlx5_enter_error_state(dev, true); + done: + fw_reset->ret = err; +- mlx5_fw_reset_complete_reload(dev, false); ++ mlx5_fw_reset_complete_reload(dev); + } + + static void mlx5_sync_reset_unload_event(struct work_struct *work) + { + struct mlx5_fw_reset *fw_reset; + struct mlx5_core_dev *dev; +- unsigned long timeout; +- bool reset_action; +- u8 rst_state; + int err; + + fw_reset = container_of(work, struct mlx5_fw_reset, reset_unload_work); +@@ -598,6 +648,7 @@ static void mlx5_sync_reset_unload_event(struct work_struct *work) + if (mlx5_sync_reset_clear_reset_requested(dev, false)) + return; + ++ set_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags); + mlx5_core_warn(dev, "Sync Reset Unload. Function is forced down.\n"); + + err = mlx5_cmd_fast_teardown_hca(dev); +@@ -606,44 +657,7 @@ static void mlx5_sync_reset_unload_event(struct work_struct *work) + else + mlx5_enter_error_state(dev, true); + +- if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) +- mlx5_unload_one_devl_locked(dev, false); +- else +- mlx5_unload_one(dev, false); +- +- mlx5_set_fw_rst_ack(dev); +- mlx5_core_warn(dev, "Sync Reset Unload done, device reset expected\n"); +- +- reset_action = false; +- timeout = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, RESET_UNLOAD)); +- do { +- rst_state = mlx5_get_fw_rst_state(dev); +- if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ || +- rst_state == MLX5_FW_RST_STATE_IDLE) { +- reset_action = true; +- break; +- } +- msleep(20); +- } while (!time_after(jiffies, timeout)); +- +- if (!reset_action) { +- mlx5_core_err(dev, "Got timeout waiting for sync reset action, state = %u\n", +- rst_state); +- fw_reset->ret = -ETIMEDOUT; +- goto done; +- } +- +- mlx5_core_warn(dev, "Sync Reset, got reset action. rst_state = %u\n", rst_state); +- if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ) { +- err = mlx5_sync_pci_reset(dev, fw_reset->reset_method); +- if (err) { +- mlx5_core_warn(dev, "mlx5_sync_pci_reset failed, err %d\n", err); +- fw_reset->ret = err; +- } +- } +- +-done: +- mlx5_fw_reset_complete_reload(dev, true); ++ mlx5_fw_reset_complete_reload(dev); + } + + static void mlx5_sync_reset_abort_event(struct work_struct *work) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h +index ea527d06a85f0..d5b28525c960d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h +@@ -12,6 +12,7 @@ int mlx5_fw_reset_set_reset_sync(struct mlx5_core_dev *dev, u8 reset_type_sel, + int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev); + + int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev); ++void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked); + int mlx5_fw_reset_verify_fw_complete(struct mlx5_core_dev *dev, + struct netlink_ext_ack *extack); + void mlx5_fw_reset_events_start(struct mlx5_core_dev *dev); +-- +2.50.1 + diff --git a/queue-6.6/net-mlx5-nack-sync-reset-when-sfs-are-present.patch b/queue-6.6/net-mlx5-nack-sync-reset-when-sfs-are-present.patch new file mode 100644 index 0000000000..d0ee892b31 --- /dev/null +++ b/queue-6.6/net-mlx5-nack-sync-reset-when-sfs-are-present.patch @@ -0,0 +1,100 @@ +From b21262d4f99e687d7fc8da8ccc2760a8444a2c3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:30 +0300 +Subject: net/mlx5: Nack sync reset when SFs are present + +From: Moshe Shemesh + +[ Upstream commit 26e42ec7712d392d561964514b1f253b1a96f42d ] + +If PF (Physical Function) has SFs (Sub-Functions), since the SFs are not +taking part in the synchronization flow, sync reset can lead to fatal +error on the SFs, as the function will be closed unexpectedly from the +SF point of view. + +Add a check to prevent sync reset when there are SFs on a PF device +which is not ECPF, as ECPF is teardowned gracefully before reset. + +Fixes: 92501fa6e421 ("net/mlx5: Ack on sync_reset_request only if PF can do reset_now") +Signed-off-by: Moshe Shemesh +Reviewed-by: Parav Pandit +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-8-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 6 ++++++ + drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c | 10 ++++++++++ + drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h | 6 ++++++ + 3 files changed, 22 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index b9986a2656083..1547704c89767 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -6,6 +6,7 @@ + #include "fw_reset.h" + #include "diag/fw_tracer.h" + #include "lib/tout.h" ++#include "sf/sf.h" + + enum { + MLX5_FW_RESET_FLAGS_RESET_REQUESTED, +@@ -397,6 +398,11 @@ static bool mlx5_is_reset_now_capable(struct mlx5_core_dev *dev) + return false; + } + ++ if (!mlx5_core_is_ecpf(dev) && !mlx5_sf_table_empty(dev)) { ++ mlx5_core_warn(dev, "SFs should be removed before reset\n"); ++ return false; ++ } ++ + #if IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE) + err = mlx5_check_hotplug_interrupt(dev); + if (err) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +index 3f0ac2d1dde68..c9089f2ec5f25 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +@@ -541,3 +541,13 @@ void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev) + WARN_ON(!xa_empty(&table->function_ids)); + kfree(table); + } ++ ++bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev) ++{ ++ struct mlx5_sf_table *table = dev->priv.sf_table; ++ ++ if (!table) ++ return true; ++ ++ return xa_empty(&table->function_ids); ++} +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h +index 860f9ddb7107b..89559a37997ad 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h +@@ -17,6 +17,7 @@ void mlx5_sf_hw_table_destroy(struct mlx5_core_dev *dev); + + int mlx5_sf_table_init(struct mlx5_core_dev *dev); + void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev); ++bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev); + + int mlx5_devlink_sf_port_new(struct devlink *devlink, + const struct devlink_port_new_attrs *add_attr, +@@ -61,6 +62,11 @@ static inline void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev) + { + } + ++static inline bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev) ++{ ++ return true; ++} ++ + #endif + + #endif +-- +2.50.1 + diff --git a/queue-6.6/net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch b/queue-6.6/net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch new file mode 100644 index 0000000000..9b9ab406ac --- /dev/null +++ b/queue-6.6/net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch @@ -0,0 +1,51 @@ +From 422436abfb60fb8c885b171070635649ce062a8b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:28 +0300 +Subject: net/mlx5: Reload auxiliary drivers on fw_activate + +From: Moshe Shemesh + +[ Upstream commit 34cc6a54914f478c93e176450fae6313404f9f74 ] + +The devlink reload fw_activate command performs firmware activation +followed by driver reload, while devlink reload driver_reinit triggers +only driver reload. However, the driver reload logic differs between the +two modes, as on driver_reinit mode mlx5 also reloads auxiliary drivers, +while in fw_activate mode the auxiliary drivers are suspended where +applicable. + +Additionally, following the cited commit, if the device has multiple PFs, +the behavior during fw_activate may vary between PFs: one PF may suspend +auxiliary drivers, while another reloads them. + +Align devlink dev reload fw_activate behavior with devlink dev reload +driver_reinit, to reload all auxiliary drivers. + +Fixes: 72ed5d5624af ("net/mlx5: Suspend auxiliary devices only in case of PCI device suspend") +Signed-off-by: Moshe Shemesh +Reviewed-by: Tariq Toukan +Reviewed-by: Akiva Goldberger +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-6-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +index f66788a2ed77e..f2d1f7cad7e72 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +@@ -107,7 +107,7 @@ static int mlx5_devlink_reload_fw_activate(struct devlink *devlink, struct netli + if (err) + return err; + +- mlx5_unload_one_devl_locked(dev, true); ++ mlx5_unload_one_devl_locked(dev, false); + err = mlx5_health_wait_pci_up(dev); + if (err) + NL_SET_ERR_MSG_MOD(extack, "FW activate aborted, PCI reads fail after reset"); +-- +2.50.1 + diff --git a/queue-6.6/net-mlx5-use-devlink-port-pointer-to-get-the-pointer.patch b/queue-6.6/net-mlx5-use-devlink-port-pointer-to-get-the-pointer.patch new file mode 100644 index 0000000000..3933aba300 --- /dev/null +++ b/queue-6.6/net-mlx5-use-devlink-port-pointer-to-get-the-pointer.patch @@ -0,0 +1,145 @@ +From 4003b3bacd9920125af73f19eb1dfd88d7f4ccc2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 May 2023 13:59:34 +0200 +Subject: net/mlx5: Use devlink port pointer to get the pointer of container SF + struct + +From: Jiri Pirko + +[ Upstream commit 9caeb1475c3e852bcfa6332227c6bb2feaa8eb23 ] + +Benefit from the fact that struct devlink_port is eventually embedded +in struct mlx5_sf and use container_of() macro to get it instead of the +xarray lookup in every devlink port op. + +Signed-off-by: Jiri Pirko +Reviewed-by: Shay Drory +Signed-off-by: Saeed Mahameed +Stable-dep-of: 26e42ec7712d ("net/mlx5: Nack sync reset when SFs are present") +Signed-off-by: Sasha Levin +--- + .../ethernet/mellanox/mlx5/core/sf/devlink.c | 44 +++++-------------- + 1 file changed, 12 insertions(+), 32 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +index 1dd01701df20e..4711dcfe8ba83 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +@@ -20,6 +20,13 @@ struct mlx5_sf { + u16 hw_state; + }; + ++static void *mlx5_sf_by_dl_port(struct devlink_port *dl_port) ++{ ++ struct mlx5_devlink_port *mlx5_dl_port = mlx5_devlink_port_get(dl_port); ++ ++ return container_of(mlx5_dl_port, struct mlx5_sf, dl_port); ++} ++ + struct mlx5_sf_table { + struct mlx5_core_dev *dev; /* To refer from notifier context. */ + struct xarray port_indices; /* port index based lookup. */ +@@ -30,12 +37,6 @@ struct mlx5_sf_table { + struct notifier_block vhca_nb; + }; + +-static struct mlx5_sf * +-mlx5_sf_lookup_by_index(struct mlx5_sf_table *table, unsigned int port_index) +-{ +- return xa_load(&table->port_indices, port_index); +-} +- + static struct mlx5_sf * + mlx5_sf_lookup_by_function_id(struct mlx5_sf_table *table, unsigned int fn_id) + { +@@ -171,26 +172,19 @@ int mlx5_devlink_sf_port_fn_state_get(struct devlink_port *dl_port, + struct netlink_ext_ack *extack) + { + struct mlx5_core_dev *dev = devlink_priv(dl_port->devlink); ++ struct mlx5_sf *sf = mlx5_sf_by_dl_port(dl_port); + struct mlx5_sf_table *table; +- struct mlx5_sf *sf; +- int err = 0; + + table = mlx5_sf_table_try_get(dev); + if (!table) + return -EOPNOTSUPP; + +- sf = mlx5_sf_lookup_by_index(table, dl_port->index); +- if (!sf) { +- err = -EOPNOTSUPP; +- goto sf_err; +- } + mutex_lock(&table->sf_state_lock); + *state = mlx5_sf_to_devlink_state(sf->hw_state); + *opstate = mlx5_sf_to_devlink_opstate(sf->hw_state); + mutex_unlock(&table->sf_state_lock); +-sf_err: + mlx5_sf_table_put(table); +- return err; ++ return 0; + } + + static int mlx5_sf_activate(struct mlx5_core_dev *dev, struct mlx5_sf *sf, +@@ -256,8 +250,8 @@ int mlx5_devlink_sf_port_fn_state_set(struct devlink_port *dl_port, + struct netlink_ext_ack *extack) + { + struct mlx5_core_dev *dev = devlink_priv(dl_port->devlink); ++ struct mlx5_sf *sf = mlx5_sf_by_dl_port(dl_port); + struct mlx5_sf_table *table; +- struct mlx5_sf *sf; + int err; + + table = mlx5_sf_table_try_get(dev); +@@ -266,14 +260,7 @@ int mlx5_devlink_sf_port_fn_state_set(struct devlink_port *dl_port, + "Port state set is only supported in eswitch switchdev mode or SF ports are disabled."); + return -EOPNOTSUPP; + } +- sf = mlx5_sf_lookup_by_index(table, dl_port->index); +- if (!sf) { +- err = -ENODEV; +- goto out; +- } +- + err = mlx5_sf_state_set(dev, table, sf, state, extack); +-out: + mlx5_sf_table_put(table); + return err; + } +@@ -384,10 +371,9 @@ int mlx5_devlink_sf_port_del(struct devlink *devlink, + struct netlink_ext_ack *extack) + { + struct mlx5_core_dev *dev = devlink_priv(devlink); ++ struct mlx5_sf *sf = mlx5_sf_by_dl_port(dl_port); + struct mlx5_eswitch *esw = dev->priv.eswitch; + struct mlx5_sf_table *table; +- struct mlx5_sf *sf; +- int err = 0; + + table = mlx5_sf_table_try_get(dev); + if (!table) { +@@ -395,20 +381,14 @@ int mlx5_devlink_sf_port_del(struct devlink *devlink, + "Port del is only supported in eswitch switchdev mode or SF ports are disabled."); + return -EOPNOTSUPP; + } +- sf = mlx5_sf_lookup_by_index(table, dl_port->index); +- if (!sf) { +- err = -ENODEV; +- goto sf_err; +- } + + mlx5_eswitch_unload_sf_vport(esw, sf->hw_fn_id); + + mutex_lock(&table->sf_state_lock); + mlx5_sf_dealloc(table, sf); + mutex_unlock(&table->sf_state_lock); +-sf_err: + mlx5_sf_table_put(table); +- return err; ++ return 0; + } + + static bool mlx5_sf_state_update_check(const struct mlx5_sf *sf, u8 new_state) +-- +2.50.1 + diff --git a/queue-6.6/net-mlx5e-set-local-xoff-after-fw-update.patch b/queue-6.6/net-mlx5e-set-local-xoff-after-fw-update.patch new file mode 100644 index 0000000000..86fb41935a --- /dev/null +++ b/queue-6.6/net-mlx5e-set-local-xoff-after-fw-update.patch @@ -0,0 +1,50 @@ +From d8f10dce13db9cb33c70242c5defdb7a34e0ed09 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:34 +0300 +Subject: net/mlx5e: Set local Xoff after FW update + +From: Alexei Lazar + +[ Upstream commit aca0c31af61e0d5cf1675a0cbd29460b95ae693c ] + +The local Xoff value is being set before the firmware (FW) update. +In case of a failure where the FW is not updated with the new value, +there is no fallback to the previous value. +Update the local Xoff value after the FW has been successfully set. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Reviewed-by: Dragos Tatulea +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-12-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +index 3efa8bf1d14ef..4720523813b97 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +@@ -575,7 +575,6 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + if (err) + return err; + } +- priv->dcbx.xoff = xoff; + + /* Apply the settings */ + if (update_buffer) { +@@ -584,6 +583,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + return err; + } + ++ priv->dcbx.xoff = xoff; ++ + if (update_prio2buffer) + err = mlx5e_port_set_priority2buffer(priv->mdev, prio2buffer); + +-- +2.50.1 + diff --git a/queue-6.6/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch b/queue-6.6/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch new file mode 100644 index 0000000000..97a1039cdc --- /dev/null +++ b/queue-6.6/net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch @@ -0,0 +1,100 @@ +From 77fc8620dc459df9fabc242ff50f80487757a7a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:32 +0300 +Subject: net/mlx5e: Update and set Xon/Xoff upon MTU set + +From: Alexei Lazar + +[ Upstream commit ceddedc969f0532b7c62ca971ee50d519d2bc0cb ] + +Xon/Xoff sizes are derived from calculation that include the MTU size. +Set Xon/Xoff when MTU is set. +If Xon/Xoff fails, set the previous MTU. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-10-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/en/port_buffer.h | 12 ++++++++++++ + .../net/ethernet/mellanox/mlx5/core/en_main.c | 17 ++++++++++++++++- + 2 files changed, 28 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +index f4a19ffbb641c..66d276a1be836 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +@@ -66,11 +66,23 @@ struct mlx5e_port_buffer { + struct mlx5e_bufferx_reg buffer[MLX5E_MAX_NETWORK_BUFFER]; + }; + ++#ifdef CONFIG_MLX5_CORE_EN_DCB + int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + u32 change, unsigned int mtu, + struct ieee_pfc *pfc, + u32 *buffer_size, + u8 *prio2buffer); ++#else ++static inline int ++mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, ++ u32 change, unsigned int mtu, ++ void *pfc, ++ u32 *buffer_size, ++ u8 *prio2buffer) ++{ ++ return 0; ++} ++#endif + + int mlx5e_port_query_buffer(struct mlx5e_priv *priv, + struct mlx5e_port_buffer *port_buffer); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 5c6f01abdcb91..09ba60b2e744b 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -44,6 +44,7 @@ + #include "eswitch.h" + #include "en.h" + #include "en/txrx.h" ++#include "en/port_buffer.h" + #include "en_tc.h" + #include "en_rep.h" + #include "en_accel/ipsec.h" +@@ -2722,9 +2723,11 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) + struct mlx5e_params *params = &priv->channels.params; + struct net_device *netdev = priv->netdev; + struct mlx5_core_dev *mdev = priv->mdev; +- u16 mtu; ++ u16 mtu, prev_mtu; + int err; + ++ mlx5e_query_mtu(mdev, params, &prev_mtu); ++ + err = mlx5e_set_mtu(mdev, params, params->sw_mtu); + if (err) + return err; +@@ -2734,6 +2737,18 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) + netdev_warn(netdev, "%s: VPort MTU %d is different than netdev mtu %d\n", + __func__, mtu, params->sw_mtu); + ++ if (mtu != prev_mtu && MLX5_BUFFER_SUPPORTED(mdev)) { ++ err = mlx5e_port_manual_buffer_config(priv, 0, mtu, ++ NULL, NULL, NULL); ++ if (err) { ++ netdev_warn(netdev, "%s: Failed to set Xon/Xoff values with MTU %d (err %d), setting back to previous MTU %d\n", ++ __func__, mtu, err, prev_mtu); ++ ++ mlx5e_set_mtu(mdev, params, prev_mtu); ++ return err; ++ } ++ } ++ + params->sw_mtu = mtu; + return 0; + } +-- +2.50.1 + diff --git a/queue-6.6/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch b/queue-6.6/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch new file mode 100644 index 0000000000..ad5d38bc9d --- /dev/null +++ b/queue-6.6/net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch @@ -0,0 +1,46 @@ +From 9cf9b2f104bdf25466fc38648440c45456850785 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 17:34:33 +0300 +Subject: net/mlx5e: Update and set Xon/Xoff upon port speed set + +From: Alexei Lazar + +[ Upstream commit d24341740fe48add8a227a753e68b6eedf4b385a ] + +Xon/Xoff sizes are derived from calculations that include +the port speed. +These settings need to be updated and applied whenever the +port speed is changed. +The port speed is typically set after the physical link goes down +and is negotiated as part of the link-up process between the two +connected interfaces. +Xon/Xoff parameters being updated at the point where the new +negotiated speed is established. + +Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration") +Signed-off-by: Alexei Lazar +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250825143435.598584-11-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 09ba60b2e744b..d378aa55f22f9 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -109,6 +109,8 @@ void mlx5e_update_carrier(struct mlx5e_priv *priv) + if (up) { + netdev_info(priv->netdev, "Link up\n"); + netif_carrier_on(priv->netdev); ++ mlx5e_port_manual_buffer_config(priv, 0, priv->netdev->mtu, ++ NULL, NULL, NULL); + } else { + netdev_info(priv->netdev, "Link down\n"); + netif_carrier_off(priv->netdev); +-- +2.50.1 + diff --git a/queue-6.6/net-rose-convert-use-field-to-refcount_t.patch b/queue-6.6/net-rose-convert-use-field-to-refcount_t.patch new file mode 100644 index 0000000000..0cd4709c96 --- /dev/null +++ b/queue-6.6/net-rose-convert-use-field-to-refcount_t.patch @@ -0,0 +1,370 @@ +From ea4d53c4008cae4f229baffd5cb00438bce6437d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Aug 2025 17:58:56 +0900 +Subject: net: rose: convert 'use' field to refcount_t + +From: Takamitsu Iwai + +[ Upstream commit d860d1faa6b2ce3becfdb8b0c2b048ad31800061 ] + +The 'use' field in struct rose_neigh is used as a reference counter but +lacks atomicity. This can lead to race conditions where a rose_neigh +structure is freed while still being referenced by other code paths. + +For example, when rose_neigh->use becomes zero during an ioctl operation +via rose_rt_ioctl(), the structure may be removed while its timer is +still active, potentially causing use-after-free issues. + +This patch changes the type of 'use' from unsigned short to refcount_t and +updates all code paths to use rose_neigh_hold() and rose_neigh_put() which +operate reference counts atomically. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Takamitsu Iwai +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250823085857.47674-3-takamitz@amazon.co.jp +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/rose.h | 18 +++++++++++++----- + net/rose/af_rose.c | 13 +++++++------ + net/rose/rose_in.c | 12 ++++++------ + net/rose/rose_route.c | 33 ++++++++++++++++++--------------- + net/rose/rose_timer.c | 2 +- + 5 files changed, 45 insertions(+), 33 deletions(-) + +diff --git a/include/net/rose.h b/include/net/rose.h +index 174b4f605d849..2b5491bbf39ab 100644 +--- a/include/net/rose.h ++++ b/include/net/rose.h +@@ -8,6 +8,7 @@ + #ifndef _ROSE_H + #define _ROSE_H + ++#include + #include + #include + #include +@@ -96,7 +97,7 @@ struct rose_neigh { + ax25_cb *ax25; + struct net_device *dev; + unsigned short count; +- unsigned short use; ++ refcount_t use; + unsigned int number; + char restarted; + char dce_mode; +@@ -151,12 +152,19 @@ struct rose_sock { + + #define rose_sk(sk) ((struct rose_sock *)(sk)) + ++static inline void rose_neigh_hold(struct rose_neigh *rose_neigh) ++{ ++ refcount_inc(&rose_neigh->use); ++} ++ + static inline void rose_neigh_put(struct rose_neigh *rose_neigh) + { +- if (rose_neigh->ax25) +- ax25_cb_put(rose_neigh->ax25); +- kfree(rose_neigh->digipeat); +- kfree(rose_neigh); ++ if (refcount_dec_and_test(&rose_neigh->use)) { ++ if (rose_neigh->ax25) ++ ax25_cb_put(rose_neigh->ax25); ++ kfree(rose_neigh->digipeat); ++ kfree(rose_neigh); ++ } + } + + /* af_rose.c */ +diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c +index 66e9ceaaa43a1..614695444b6ac 100644 +--- a/net/rose/af_rose.c ++++ b/net/rose/af_rose.c +@@ -170,7 +170,7 @@ void rose_kill_by_neigh(struct rose_neigh *neigh) + + if (rose->neighbour == neigh) { + rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + rose->neighbour = NULL; + } + } +@@ -212,7 +212,7 @@ static void rose_kill_by_device(struct net_device *dev) + if (rose->device == dev) { + rose_disconnect(sk, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); + if (rose->neighbour) +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + netdev_put(rose->device, &rose->dev_tracker); + rose->device = NULL; + } +@@ -655,7 +655,7 @@ static int rose_release(struct socket *sock) + break; + + case ROSE_STATE_2: +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + release_sock(sk); + rose_disconnect(sk, 0, -1, -1); + lock_sock(sk); +@@ -823,6 +823,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + rose->lci = rose_new_lci(rose->neighbour); + if (!rose->lci) { + err = -ENETUNREACH; ++ rose_neigh_put(rose->neighbour); + goto out_release; + } + +@@ -834,12 +835,14 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + dev = rose_dev_first(); + if (!dev) { + err = -ENETUNREACH; ++ rose_neigh_put(rose->neighbour); + goto out_release; + } + + user = ax25_findbyuid(current_euid()); + if (!user) { + err = -EINVAL; ++ rose_neigh_put(rose->neighbour); + dev_put(dev); + goto out_release; + } +@@ -874,8 +877,6 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + + rose->state = ROSE_STATE_1; + +- rose->neighbour->use++; +- + rose_write_internal(sk, ROSE_CALL_REQUEST); + rose_start_heartbeat(sk); + rose_start_t1timer(sk); +@@ -1077,7 +1078,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros + GFP_ATOMIC); + make_rose->facilities = facilities; + +- make_rose->neighbour->use++; ++ rose_neigh_hold(make_rose->neighbour); + + if (rose_sk(sk)->defer) { + make_rose->state = ROSE_STATE_5; +diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c +index 4d67f36dce1b4..7caae93937ee9 100644 +--- a/net/rose/rose_in.c ++++ b/net/rose/rose_in.c +@@ -56,7 +56,7 @@ static int rose_state1_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + default: +@@ -79,12 +79,12 @@ static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + case ROSE_CLEAR_CONFIRMATION: + rose_disconnect(sk, 0, -1, -1); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + default: +@@ -120,7 +120,7 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + case ROSE_RR: +@@ -233,7 +233,7 @@ static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int framety + case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + break; + + default: +@@ -253,7 +253,7 @@ static int rose_state5_machine(struct sock *sk, struct sk_buff *skb, int framety + if (frametype == ROSE_CLEAR_REQUEST) { + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); + rose_disconnect(sk, 0, skb->data[3], skb->data[4]); +- rose_sk(sk)->neighbour->use--; ++ rose_neigh_put(rose_sk(sk)->neighbour); + } + + return 0; +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index b406b1e0fb1e7..42460da0854d5 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -93,11 +93,11 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, + rose_neigh->ax25 = NULL; + rose_neigh->dev = dev; + rose_neigh->count = 0; +- rose_neigh->use = 0; + rose_neigh->dce_mode = 0; + rose_neigh->loopback = 0; + rose_neigh->number = rose_neigh_no++; + rose_neigh->restarted = 0; ++ refcount_set(&rose_neigh->use, 1); + + skb_queue_head_init(&rose_neigh->queue); + +@@ -255,10 +255,10 @@ static void rose_remove_route(struct rose_route *rose_route) + struct rose_route *s; + + if (rose_route->neigh1 != NULL) +- rose_route->neigh1->use--; ++ rose_neigh_put(rose_route->neigh1); + + if (rose_route->neigh2 != NULL) +- rose_route->neigh2->use--; ++ rose_neigh_put(rose_route->neigh2); + + if ((s = rose_route_list) == rose_route) { + rose_route_list = rose_route->next; +@@ -323,7 +323,7 @@ static int rose_del_node(struct rose_route_struct *rose_route, + if (rose_node->neighbour[i] == rose_neigh) { + rose_neigh->count--; + +- if (rose_neigh->count == 0 && rose_neigh->use == 0) { ++ if (rose_neigh->count == 0) { + rose_remove_neigh(rose_neigh); + rose_neigh_put(rose_neigh); + } +@@ -375,11 +375,11 @@ void rose_add_loopback_neigh(void) + sn->ax25 = NULL; + sn->dev = NULL; + sn->count = 0; +- sn->use = 0; + sn->dce_mode = 1; + sn->loopback = 1; + sn->number = rose_neigh_no++; + sn->restarted = 1; ++ refcount_set(&sn->use, 1); + + skb_queue_head_init(&sn->queue); + +@@ -561,8 +561,7 @@ static int rose_clear_routes(void) + s = rose_neigh; + rose_neigh = rose_neigh->next; + +- if (s->use == 0 && !s->loopback) { +- s->count = 0; ++ if (!s->loopback) { + rose_remove_neigh(s); + rose_neigh_put(s); + } +@@ -680,6 +679,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, + for (i = 0; i < node->count; i++) { + if (node->neighbour[i]->restarted) { + res = node->neighbour[i]; ++ rose_neigh_hold(node->neighbour[i]); + goto out; + } + } +@@ -691,6 +691,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, + for (i = 0; i < node->count; i++) { + if (!rose_ftimer_running(node->neighbour[i])) { + res = node->neighbour[i]; ++ rose_neigh_hold(node->neighbour[i]); + goto out; + } + failed = 1; +@@ -780,13 +781,13 @@ static void rose_del_route_by_neigh(struct rose_neigh *rose_neigh) + } + + if (rose_route->neigh1 == rose_neigh) { +- rose_route->neigh1->use--; ++ rose_neigh_put(rose_route->neigh1); + rose_route->neigh1 = NULL; + rose_transmit_clear_request(rose_route->neigh2, rose_route->lci2, ROSE_OUT_OF_ORDER, 0); + } + + if (rose_route->neigh2 == rose_neigh) { +- rose_route->neigh2->use--; ++ rose_neigh_put(rose_route->neigh2); + rose_route->neigh2 = NULL; + rose_transmit_clear_request(rose_route->neigh1, rose_route->lci1, ROSE_OUT_OF_ORDER, 0); + } +@@ -915,7 +916,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + rose_clear_queues(sk); + rose->cause = ROSE_NETWORK_CONGESTION; + rose->diagnostic = 0; +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + rose->neighbour = NULL; + rose->lci = 0; + rose->state = ROSE_STATE_0; +@@ -1040,12 +1041,12 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + + if ((new_lci = rose_new_lci(new_neigh)) == 0) { + rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 71); +- goto out; ++ goto put_neigh; + } + + if ((rose_route = kmalloc(sizeof(*rose_route), GFP_ATOMIC)) == NULL) { + rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 120); +- goto out; ++ goto put_neigh; + } + + rose_route->lci1 = lci; +@@ -1058,8 +1059,8 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + rose_route->lci2 = new_lci; + rose_route->neigh2 = new_neigh; + +- rose_route->neigh1->use++; +- rose_route->neigh2->use++; ++ rose_neigh_hold(rose_route->neigh1); ++ rose_neigh_hold(rose_route->neigh2); + + rose_route->next = rose_route_list; + rose_route_list = rose_route; +@@ -1071,6 +1072,8 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) + rose_transmit_link(skb, rose_route->neigh2); + res = 1; + ++put_neigh: ++ rose_neigh_put(new_neigh); + out: + spin_unlock_bh(&rose_route_list_lock); + spin_unlock_bh(&rose_neigh_list_lock); +@@ -1186,7 +1189,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v) + (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign), + rose_neigh->dev ? rose_neigh->dev->name : "???", + rose_neigh->count, +- rose_neigh->use, ++ refcount_read(&rose_neigh->use) - 1, + (rose_neigh->dce_mode) ? "DCE" : "DTE", + (rose_neigh->restarted) ? "yes" : "no", + ax25_display_timer(&rose_neigh->t0timer) / HZ, +diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c +index 1525773e94aa1..c52d7d20c5199 100644 +--- a/net/rose/rose_timer.c ++++ b/net/rose/rose_timer.c +@@ -180,7 +180,7 @@ static void rose_timer_expiry(struct timer_list *t) + break; + + case ROSE_STATE_2: /* T3 */ +- rose->neighbour->use--; ++ rose_neigh_put(rose->neighbour); + rose_disconnect(sk, ETIMEDOUT, -1, -1); + break; + +-- +2.50.1 + diff --git a/queue-6.6/net-rose-include-node-references-in-rose_neigh-refco.patch b/queue-6.6/net-rose-include-node-references-in-rose_neigh-refco.patch new file mode 100644 index 0000000000..566c313e76 --- /dev/null +++ b/queue-6.6/net-rose-include-node-references-in-rose_neigh-refco.patch @@ -0,0 +1,142 @@ +From ef0b2fc4f9ca9e4f777ccb13eaae3ba3ce851928 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Aug 2025 17:58:57 +0900 +Subject: net: rose: include node references in rose_neigh refcount + +From: Takamitsu Iwai + +[ Upstream commit da9c9c877597170b929a6121a68dcd3dd9a80f45 ] + +Current implementation maintains two separate reference counting +mechanisms: the 'count' field in struct rose_neigh tracks references from +rose_node structures, while the 'use' field (now refcount_t) tracks +references from rose_sock. + +This patch merges these two reference counting systems using 'use' field +for proper reference management. Specifically, this patch adds incrementing +and decrementing of rose_neigh->use when rose_neigh->count is incremented +or decremented. + +This patch also modifies rose_rt_free(), rose_rt_device_down() and +rose_clear_route() to properly release references to rose_neigh objects +before freeing a rose_node through rose_remove_node(). + +These changes ensure rose_neigh structures are properly freed only when +all references, including those from rose_node structures, are released. +As a result, this resolves a slab-use-after-free issue reported by Syzbot. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+942297eecf7d2d61d1f1@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=942297eecf7d2d61d1f1 +Signed-off-by: Takamitsu Iwai +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250823085857.47674-4-takamitz@amazon.co.jp +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/rose/rose_route.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index 42460da0854d5..6acbb795c506d 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -178,6 +178,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, + } + } + rose_neigh->count++; ++ rose_neigh_hold(rose_neigh); + + goto out; + } +@@ -187,6 +188,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, + rose_node->neighbour[rose_node->count] = rose_neigh; + rose_node->count++; + rose_neigh->count++; ++ rose_neigh_hold(rose_neigh); + } + + out: +@@ -322,6 +324,7 @@ static int rose_del_node(struct rose_route_struct *rose_route, + for (i = 0; i < rose_node->count; i++) { + if (rose_node->neighbour[i] == rose_neigh) { + rose_neigh->count--; ++ rose_neigh_put(rose_neigh); + + if (rose_neigh->count == 0) { + rose_remove_neigh(rose_neigh); +@@ -430,6 +433,7 @@ int rose_add_loopback_node(const rose_address *address) + rose_node_list = rose_node; + + rose_loopback_neigh->count++; ++ rose_neigh_hold(rose_loopback_neigh); + + out: + spin_unlock_bh(&rose_node_list_lock); +@@ -461,6 +465,7 @@ void rose_del_loopback_node(const rose_address *address) + rose_remove_node(rose_node); + + rose_loopback_neigh->count--; ++ rose_neigh_put(rose_loopback_neigh); + + out: + spin_unlock_bh(&rose_node_list_lock); +@@ -500,6 +505,7 @@ void rose_rt_device_down(struct net_device *dev) + memmove(&t->neighbour[i], &t->neighbour[i + 1], + sizeof(t->neighbour[0]) * + (t->count - i)); ++ rose_neigh_put(s); + } + + if (t->count <= 0) +@@ -543,6 +549,7 @@ static int rose_clear_routes(void) + { + struct rose_neigh *s, *rose_neigh; + struct rose_node *t, *rose_node; ++ int i; + + spin_lock_bh(&rose_node_list_lock); + spin_lock_bh(&rose_neigh_list_lock); +@@ -553,8 +560,12 @@ static int rose_clear_routes(void) + while (rose_node != NULL) { + t = rose_node; + rose_node = rose_node->next; +- if (!t->loopback) ++ ++ if (!t->loopback) { ++ for (i = 0; i < rose_node->count; i++) ++ rose_neigh_put(t->neighbour[i]); + rose_remove_node(t); ++ } + } + + while (rose_neigh != NULL) { +@@ -1189,7 +1200,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v) + (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign), + rose_neigh->dev ? rose_neigh->dev->name : "???", + rose_neigh->count, +- refcount_read(&rose_neigh->use) - 1, ++ refcount_read(&rose_neigh->use) - rose_neigh->count - 1, + (rose_neigh->dce_mode) ? "DCE" : "DTE", + (rose_neigh->restarted) ? "yes" : "no", + ax25_display_timer(&rose_neigh->t0timer) / HZ, +@@ -1294,6 +1305,7 @@ void __exit rose_rt_free(void) + struct rose_neigh *s, *rose_neigh = rose_neigh_list; + struct rose_node *t, *rose_node = rose_node_list; + struct rose_route *u, *rose_route = rose_route_list; ++ int i; + + while (rose_neigh != NULL) { + s = rose_neigh; +@@ -1307,6 +1319,8 @@ void __exit rose_rt_free(void) + t = rose_node; + rose_node = rose_node->next; + ++ for (i = 0; i < t->count; i++) ++ rose_neigh_put(t->neighbour[i]); + rose_remove_node(t); + } + +-- +2.50.1 + diff --git a/queue-6.6/net-rose-split-remove-and-free-operations-in-rose_re.patch b/queue-6.6/net-rose-split-remove-and-free-operations-in-rose_re.patch new file mode 100644 index 0000000000..fe05a12221 --- /dev/null +++ b/queue-6.6/net-rose-split-remove-and-free-operations-in-rose_re.patch @@ -0,0 +1,115 @@ +From 7dcf66da101ce72d7691bf6ecc16b81acb41eca5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Aug 2025 17:58:55 +0900 +Subject: net: rose: split remove and free operations in rose_remove_neigh() + +From: Takamitsu Iwai + +[ Upstream commit dcb34659028f856c423a29ef9b4e2571d203444d ] + +The current rose_remove_neigh() performs two distinct operations: +1. Removes rose_neigh from rose_neigh_list +2. Frees the rose_neigh structure + +Split these operations into separate functions to improve maintainability +and prepare for upcoming refcount_t conversion. The timer cleanup remains +in rose_remove_neigh() because free operations can be called from timer +itself. + +This patch introduce rose_neigh_put() to handle the freeing of rose_neigh +structures and modify rose_remove_neigh() to handle removal only. + +Signed-off-by: Takamitsu Iwai +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250823085857.47674-2-takamitz@amazon.co.jp +Signed-off-by: Jakub Kicinski +Stable-dep-of: d860d1faa6b2 ("net: rose: convert 'use' field to refcount_t") +Signed-off-by: Sasha Levin +--- + include/net/rose.h | 8 ++++++++ + net/rose/rose_route.c | 15 ++++++--------- + 2 files changed, 14 insertions(+), 9 deletions(-) + +diff --git a/include/net/rose.h b/include/net/rose.h +index 23267b4efcfa3..174b4f605d849 100644 +--- a/include/net/rose.h ++++ b/include/net/rose.h +@@ -151,6 +151,14 @@ struct rose_sock { + + #define rose_sk(sk) ((struct rose_sock *)(sk)) + ++static inline void rose_neigh_put(struct rose_neigh *rose_neigh) ++{ ++ if (rose_neigh->ax25) ++ ax25_cb_put(rose_neigh->ax25); ++ kfree(rose_neigh->digipeat); ++ kfree(rose_neigh); ++} ++ + /* af_rose.c */ + extern ax25_address rose_callsign; + extern int sysctl_rose_restart_request_timeout; +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index a7054546f52df..b406b1e0fb1e7 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -234,20 +234,12 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) + + if ((s = rose_neigh_list) == rose_neigh) { + rose_neigh_list = rose_neigh->next; +- if (rose_neigh->ax25) +- ax25_cb_put(rose_neigh->ax25); +- kfree(rose_neigh->digipeat); +- kfree(rose_neigh); + return; + } + + while (s != NULL && s->next != NULL) { + if (s->next == rose_neigh) { + s->next = rose_neigh->next; +- if (rose_neigh->ax25) +- ax25_cb_put(rose_neigh->ax25); +- kfree(rose_neigh->digipeat); +- kfree(rose_neigh); + return; + } + +@@ -331,8 +323,10 @@ static int rose_del_node(struct rose_route_struct *rose_route, + if (rose_node->neighbour[i] == rose_neigh) { + rose_neigh->count--; + +- if (rose_neigh->count == 0 && rose_neigh->use == 0) ++ if (rose_neigh->count == 0 && rose_neigh->use == 0) { + rose_remove_neigh(rose_neigh); ++ rose_neigh_put(rose_neigh); ++ } + + rose_node->count--; + +@@ -513,6 +507,7 @@ void rose_rt_device_down(struct net_device *dev) + } + + rose_remove_neigh(s); ++ rose_neigh_put(s); + } + spin_unlock_bh(&rose_neigh_list_lock); + spin_unlock_bh(&rose_node_list_lock); +@@ -569,6 +564,7 @@ static int rose_clear_routes(void) + if (s->use == 0 && !s->loopback) { + s->count = 0; + rose_remove_neigh(s); ++ rose_neigh_put(s); + } + } + +@@ -1301,6 +1297,7 @@ void __exit rose_rt_free(void) + rose_neigh = rose_neigh->next; + + rose_remove_neigh(s); ++ rose_neigh_put(s); + } + + while (rose_node != NULL) { +-- +2.50.1 + diff --git a/queue-6.6/net-stmmac-rename-phylink_get_caps-callback-to-updat.patch b/queue-6.6/net-stmmac-rename-phylink_get_caps-callback-to-updat.patch new file mode 100644 index 0000000000..df4aba59aa --- /dev/null +++ b/queue-6.6/net-stmmac-rename-phylink_get_caps-callback-to-updat.patch @@ -0,0 +1,118 @@ +From c13941d8583162065671e8da74728f84e5e132a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Apr 2024 12:03:05 +0300 +Subject: net: stmmac: Rename phylink_get_caps() callback to update_caps() + +From: Serge Semin + +[ Upstream commit dc144baeb4fbfa0d91ce9c3875307566f58704ec ] + +Since recent commits the stmmac_ops::phylink_get_caps() callback has no +longer been responsible for the phylink MAC capabilities getting, but +merely updates the MAC capabilities in the mac_device_info::link::caps +field. Rename the callback to comply with the what the method does now. + +Signed-off-by: Serge Semin +Reviewed-by: Romain Gantois +Signed-off-by: Paolo Abeni +Stable-dep-of: 42ef11b2bff5 ("net: stmmac: xgmac: Correct supported speed modes") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 8 ++++---- + drivers/net/ethernet/stmicro/stmmac/hwif.h | 8 ++++---- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +++--- + 3 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +index a9837985a483d..bdb4f527289d2 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +@@ -69,7 +69,7 @@ static void dwmac4_core_init(struct mac_device_info *hw, + init_waitqueue_head(&priv->tstamp_busy_wait); + } + +-static void dwmac4_phylink_get_caps(struct stmmac_priv *priv) ++static void dwmac4_update_caps(struct stmmac_priv *priv) + { + if (priv->plat->tx_queues_to_use > 1) + priv->hw->link.caps &= ~(MAC_10HD | MAC_100HD | MAC_1000HD); +@@ -1161,7 +1161,7 @@ static int dwmac4_config_l4_filter(struct mac_device_info *hw, u32 filter_no, + + const struct stmmac_ops dwmac4_ops = { + .core_init = dwmac4_core_init, +- .phylink_get_caps = dwmac4_phylink_get_caps, ++ .update_caps = dwmac4_update_caps, + .set_mac = stmmac_set_mac, + .rx_ipc = dwmac4_rx_ipc_enable, + .rx_queue_enable = dwmac4_rx_queue_enable, +@@ -1204,7 +1204,7 @@ const struct stmmac_ops dwmac4_ops = { + + const struct stmmac_ops dwmac410_ops = { + .core_init = dwmac4_core_init, +- .phylink_get_caps = dwmac4_phylink_get_caps, ++ .update_caps = dwmac4_update_caps, + .set_mac = stmmac_dwmac4_set_mac, + .rx_ipc = dwmac4_rx_ipc_enable, + .rx_queue_enable = dwmac4_rx_queue_enable, +@@ -1253,7 +1253,7 @@ const struct stmmac_ops dwmac410_ops = { + + const struct stmmac_ops dwmac510_ops = { + .core_init = dwmac4_core_init, +- .phylink_get_caps = dwmac4_phylink_get_caps, ++ .update_caps = dwmac4_update_caps, + .set_mac = stmmac_dwmac4_set_mac, + .rx_ipc = dwmac4_rx_ipc_enable, + .rx_queue_enable = dwmac4_rx_queue_enable, +diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h +index 47fb8e1646c2e..ee9a7d98648b0 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h ++++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h +@@ -300,8 +300,8 @@ struct stmmac_est; + struct stmmac_ops { + /* MAC core initialization */ + void (*core_init)(struct mac_device_info *hw, struct net_device *dev); +- /* Get phylink capabilities */ +- void (*phylink_get_caps)(struct stmmac_priv *priv); ++ /* Update MAC capabilities */ ++ void (*update_caps)(struct stmmac_priv *priv); + /* Enable the MAC RX/TX */ + void (*set_mac)(void __iomem *ioaddr, bool enable); + /* Enable and verify that the IPC module is supported */ +@@ -423,8 +423,8 @@ struct stmmac_ops { + + #define stmmac_core_init(__priv, __args...) \ + stmmac_do_void_callback(__priv, mac, core_init, __args) +-#define stmmac_mac_phylink_get_caps(__priv) \ +- stmmac_do_void_callback(__priv, mac, phylink_get_caps, __priv) ++#define stmmac_mac_update_caps(__priv) \ ++ stmmac_do_void_callback(__priv, mac, update_caps, __priv) + #define stmmac_mac_set(__priv, __args...) \ + stmmac_do_void_callback(__priv, mac, set_mac, __args) + #define stmmac_rx_ipc(__priv, __args...) \ +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 615d25a0e46be..fa8ee0624f2f2 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -1230,8 +1230,8 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) + xpcs_get_interfaces(priv->hw->xpcs, + priv->phylink_config.supported_interfaces); + +- /* Get the MAC specific capabilities */ +- stmmac_mac_phylink_get_caps(priv); ++ /* Refresh the MAC-specific capabilities */ ++ stmmac_mac_update_caps(priv); + + priv->phylink_config.mac_capabilities = priv->hw->link.caps; + +@@ -7232,7 +7232,7 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt) + priv->rss.table[i] = ethtool_rxfh_indir_default(i, + rx_cnt); + +- stmmac_mac_phylink_get_caps(priv); ++ stmmac_mac_update_caps(priv); + + priv->phylink_config.mac_capabilities = priv->hw->link.caps; + +-- +2.50.1 + diff --git a/queue-6.6/net-stmmac-set-cic-bit-only-for-tx-queues-with-coe.patch b/queue-6.6/net-stmmac-set-cic-bit-only-for-tx-queues-with-coe.patch new file mode 100644 index 0000000000..e38b916194 --- /dev/null +++ b/queue-6.6/net-stmmac-set-cic-bit-only-for-tx-queues-with-coe.patch @@ -0,0 +1,68 @@ +From 70d5703b835a692e70b28d80b73eb51b16e492fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 12:36:54 +0800 +Subject: net: stmmac: Set CIC bit only for TX queues with COE + +From: Rohan G Thomas + +[ Upstream commit b1eded580ab28119de0b0f21efe37ee2b4419144 ] + +Currently, in the AF_XDP transmit paths, the CIC bit of +TX Desc3 is set for all packets. Setting this bit for +packets transmitting through queues that don't support +checksum offloading causes the TX DMA to get stuck after +transmitting some packets. This patch ensures the CIC bit +of TX Desc3 is set only if the TX queue supports checksum +offloading. + +Fixes: 132c32ee5bc0 ("net: stmmac: Add TX via XDP zero-copy socket") +Signed-off-by: Rohan G Thomas +Reviewed-by: Matthew Gerlach +Link: https://patch.msgid.link/20250825-xgmac-minor-fixes-v3-3-c225fe4444c0@altera.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index fa8ee0624f2f2..ff5389a8efc33 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -2426,6 +2426,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) + struct netdev_queue *nq = netdev_get_tx_queue(priv->dev, queue); + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; + struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[queue]; ++ bool csum = !priv->plat->tx_queues_cfg[queue].coe_unsupported; + struct xsk_buff_pool *pool = tx_q->xsk_pool; + unsigned int entry = tx_q->cur_tx; + struct dma_desc *tx_desc = NULL; +@@ -2496,7 +2497,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) + } + + stmmac_prepare_tx_desc(priv, tx_desc, 1, xdp_desc.len, +- true, priv->mode, true, true, ++ csum, priv->mode, true, true, + xdp_desc.len); + + stmmac_enable_dma_transmission(priv, priv->ioaddr); +@@ -4789,6 +4790,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue, + { + struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[queue]; + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; ++ bool csum = !priv->plat->tx_queues_cfg[queue].coe_unsupported; + unsigned int entry = tx_q->cur_tx; + struct dma_desc *tx_desc; + dma_addr_t dma_addr; +@@ -4833,7 +4835,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue, + stmmac_set_desc_addr(priv, tx_desc, dma_addr); + + stmmac_prepare_tx_desc(priv, tx_desc, 1, xdpf->len, +- true, priv->mode, true, true, ++ csum, priv->mode, true, true, + xdpf->len); + + tx_q->tx_count_frames++; +-- +2.50.1 + diff --git a/queue-6.6/net-stmmac-xgmac-correct-supported-speed-modes.patch b/queue-6.6/net-stmmac-xgmac-correct-supported-speed-modes.patch new file mode 100644 index 0000000000..2f7725bf49 --- /dev/null +++ b/queue-6.6/net-stmmac-xgmac-correct-supported-speed-modes.patch @@ -0,0 +1,96 @@ +From c3be2a69b1d2e2d1b8e80a1b63e29db53152f337 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 12:36:53 +0800 +Subject: net: stmmac: xgmac: Correct supported speed modes + +From: Rohan G Thomas + +[ Upstream commit 42ef11b2bff5b6a2910c28d2ea47cc00e0fbcaec ] + +Correct supported speed modes as per the XGMAC databook. +Commit 9cb54af214a7 ("net: stmmac: Fix IP-cores specific +MAC capabilities") removes support for 10M, 100M and +1000HD. 1000HD is not supported by XGMAC IP, but it does +support 10M and 100M FD mode for XGMAC version >= 2_20, +and it also supports 10M and 100M HD mode if the HDSEL bit +is set in the MAC_HW_FEATURE0 reg. This commit enables support +for 10M and 100M speed modes for XGMAC IP based on XGMAC +version and MAC capabilities. + +Fixes: 9cb54af214a7 ("net: stmmac: Fix IP-cores specific MAC capabilities") +Signed-off-by: Rohan G Thomas +Reviewed-by: Matthew Gerlach +Link: https://patch.msgid.link/20250825-xgmac-minor-fixes-v3-2-c225fe4444c0@altera.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 13 +++++++++++-- + drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 5 +++++ + 2 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +index 052566f5b7f36..0bcb378fa0bc9 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +@@ -47,6 +47,14 @@ static void dwxgmac2_core_init(struct mac_device_info *hw, + writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN); + } + ++static void dwxgmac2_update_caps(struct stmmac_priv *priv) ++{ ++ if (!priv->dma_cap.mbps_10_100) ++ priv->hw->link.caps &= ~(MAC_10 | MAC_100); ++ else if (!priv->dma_cap.half_duplex) ++ priv->hw->link.caps &= ~(MAC_10HD | MAC_100HD); ++} ++ + static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable) + { + u32 tx = readl(ioaddr + XGMAC_TX_CONFIG); +@@ -1583,6 +1591,7 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg * + + const struct stmmac_ops dwxgmac210_ops = { + .core_init = dwxgmac2_core_init, ++ .update_caps = dwxgmac2_update_caps, + .set_mac = dwxgmac2_set_mac, + .rx_ipc = dwxgmac2_rx_ipc, + .rx_queue_enable = dwxgmac2_rx_queue_enable, +@@ -1705,8 +1714,8 @@ int dwxgmac2_setup(struct stmmac_priv *priv) + mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); + + mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | +- MAC_1000FD | MAC_2500FD | MAC_5000FD | +- MAC_10000FD; ++ MAC_10 | MAC_100 | MAC_1000FD | ++ MAC_2500FD | MAC_5000FD | MAC_10000FD; + mac->link.duplex = 0; + mac->link.speed10 = XGMAC_CONFIG_SS_10_MII; + mac->link.speed100 = XGMAC_CONFIG_SS_100_MII; +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +index 37c4258fef794..b2c03cb65c7cc 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +@@ -382,8 +382,11 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, + static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, + struct dma_features *dma_cap) + { ++ struct stmmac_priv *priv; + u32 hw_cap; + ++ priv = container_of(dma_cap, struct stmmac_priv, dma_cap); ++ + /* MAC HW feature 0 */ + hw_cap = readl(ioaddr + XGMAC_HW_FEATURE0); + dma_cap->edma = (hw_cap & XGMAC_HWFEAT_EDMA) >> 31; +@@ -406,6 +409,8 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, + dma_cap->vlhash = (hw_cap & XGMAC_HWFEAT_VLHASH) >> 4; + dma_cap->half_duplex = (hw_cap & XGMAC_HWFEAT_HDSEL) >> 3; + dma_cap->mbps_1000 = (hw_cap & XGMAC_HWFEAT_GMIISEL) >> 1; ++ if (dma_cap->mbps_1000 && priv->synopsys_id >= DWXGMAC_CORE_2_20) ++ dma_cap->mbps_10_100 = 1; + + /* MAC HW feature 1 */ + hw_cap = readl(ioaddr + XGMAC_HW_FEATURE1); +-- +2.50.1 + diff --git a/queue-6.6/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch b/queue-6.6/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch new file mode 100644 index 0000000000..a634b74ee1 --- /dev/null +++ b/queue-6.6/net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch @@ -0,0 +1,49 @@ +From 5fbfd8e6fa5005293c49fc6d46ea7b9a12ac785d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 12:36:52 +0800 +Subject: net: stmmac: xgmac: Do not enable RX FIFO Overflow interrupts + +From: Rohan G Thomas + +[ Upstream commit 4f23382841e67174211271a454811dd17c0ef3c5 ] + +Enabling RX FIFO Overflow interrupts is counterproductive +and causes an interrupt storm when RX FIFO overflows. +Disabling this interrupt has no side effect and eliminates +interrupt storms when the RX FIFO overflows. + +Commit 8a7cb245cf28 ("net: stmmac: Do not enable RX FIFO +overflow interrupts") disables RX FIFO overflow interrupts +for DWMAC4 IP and removes the corresponding handling of +this interrupt. This patch is doing the same thing for +XGMAC IP. + +Fixes: 2142754f8b9c ("net: stmmac: Add MAC related callbacks for XGMAC2") +Signed-off-by: Rohan G Thomas +Reviewed-by: Matthew Gerlach +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250825-xgmac-minor-fixes-v3-1-c225fe4444c0@altera.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +index 05ea74e937939..37c4258fef794 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +@@ -203,10 +203,6 @@ static void dwxgmac2_dma_rx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, + } + + writel(value, ioaddr + XGMAC_MTL_RXQ_OPMODE(channel)); +- +- /* Enable MTL RX overflow */ +- value = readl(ioaddr + XGMAC_MTL_QINTEN(channel)); +- writel(value | XGMAC_RXOIE, ioaddr + XGMAC_MTL_QINTEN(channel)); + } + + static void dwxgmac2_dma_tx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, +-- +2.50.1 + diff --git a/queue-6.6/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch b/queue-6.6/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch new file mode 100644 index 0000000000..2ca950f778 --- /dev/null +++ b/queue-6.6/phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch @@ -0,0 +1,135 @@ +From ab8b27d03d86e08bfd0667fd0965c5dbeab92974 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Aug 2025 08:55:43 +0200 +Subject: phy: mscc: Fix when PTP clock is register and unregister + +From: Horatiu Vultur + +[ Upstream commit 882e57cbc7204662f6c5672d5b04336c1d790b03 ] + +It looks like that every time when the interface was set down and up the +driver was creating a new ptp clock. On top of this the function +ptp_clock_unregister was never called. +Therefore fix this by calling ptp_clock_register and initialize the +mii_ts struct inside the probe function and call ptp_clock_unregister when +driver is removed. + +Fixes: 7d272e63e0979d ("net: phy: mscc: timestamping and PHC support") +Signed-off-by: Horatiu Vultur +Reviewed-by: Vadim Fedorenko +Reviewed-by: Vladimir Oltean +Link: https://patch.msgid.link/20250825065543.2916334-1-horatiu.vultur@microchip.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mscc/mscc.h | 4 ++++ + drivers/net/phy/mscc/mscc_main.c | 4 +--- + drivers/net/phy/mscc/mscc_ptp.c | 34 ++++++++++++++++++++------------ + 3 files changed, 26 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h +index cdb343779a8fb..4ba6e32cf6d8d 100644 +--- a/drivers/net/phy/mscc/mscc.h ++++ b/drivers/net/phy/mscc/mscc.h +@@ -476,6 +476,7 @@ static inline void vsc8584_config_macsec_intr(struct phy_device *phydev) + void vsc85xx_link_change_notify(struct phy_device *phydev); + void vsc8584_config_ts_intr(struct phy_device *phydev); + int vsc8584_ptp_init(struct phy_device *phydev); ++void vsc8584_ptp_deinit(struct phy_device *phydev); + int vsc8584_ptp_probe_once(struct phy_device *phydev); + int vsc8584_ptp_probe(struct phy_device *phydev); + irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev); +@@ -490,6 +491,9 @@ static inline int vsc8584_ptp_init(struct phy_device *phydev) + { + return 0; + } ++static inline void vsc8584_ptp_deinit(struct phy_device *phydev) ++{ ++} + static inline int vsc8584_ptp_probe_once(struct phy_device *phydev) + { + return 0; +diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c +index 3de72d9cc22bd..3a932b30f4358 100644 +--- a/drivers/net/phy/mscc/mscc_main.c ++++ b/drivers/net/phy/mscc/mscc_main.c +@@ -2337,9 +2337,7 @@ static int vsc85xx_probe(struct phy_device *phydev) + + static void vsc85xx_remove(struct phy_device *phydev) + { +- struct vsc8531_private *priv = phydev->priv; +- +- skb_queue_purge(&priv->rx_skbs_list); ++ vsc8584_ptp_deinit(phydev); + } + + /* Microsemi VSC85xx PHYs */ +diff --git a/drivers/net/phy/mscc/mscc_ptp.c b/drivers/net/phy/mscc/mscc_ptp.c +index add1a9ee721af..1f6237705b44b 100644 +--- a/drivers/net/phy/mscc/mscc_ptp.c ++++ b/drivers/net/phy/mscc/mscc_ptp.c +@@ -1297,7 +1297,6 @@ static void vsc8584_set_input_clk_configured(struct phy_device *phydev) + + static int __vsc8584_init_ptp(struct phy_device *phydev) + { +- struct vsc8531_private *vsc8531 = phydev->priv; + static const u32 ltc_seq_e[] = { 0, 400000, 0, 0, 0 }; + static const u8 ltc_seq_a[] = { 8, 6, 5, 4, 2 }; + u32 val; +@@ -1514,17 +1513,7 @@ static int __vsc8584_init_ptp(struct phy_device *phydev) + + vsc85xx_ts_eth_cmp1_sig(phydev); + +- vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; +- vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; +- vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; +- vsc8531->mii_ts.ts_info = vsc85xx_ts_info; +- phydev->mii_ts = &vsc8531->mii_ts; +- +- memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); +- +- vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, +- &phydev->mdio.dev); +- return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); ++ return 0; + } + + void vsc8584_config_ts_intr(struct phy_device *phydev) +@@ -1551,6 +1540,16 @@ int vsc8584_ptp_init(struct phy_device *phydev) + return 0; + } + ++void vsc8584_ptp_deinit(struct phy_device *phydev) ++{ ++ struct vsc8531_private *vsc8531 = phydev->priv; ++ ++ if (vsc8531->ptp->ptp_clock) { ++ ptp_clock_unregister(vsc8531->ptp->ptp_clock); ++ skb_queue_purge(&vsc8531->rx_skbs_list); ++ } ++} ++ + irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev) + { + struct vsc8531_private *priv = phydev->priv; +@@ -1608,7 +1607,16 @@ int vsc8584_ptp_probe(struct phy_device *phydev) + + vsc8531->ptp->phydev = phydev; + +- return 0; ++ vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; ++ vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; ++ vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; ++ vsc8531->mii_ts.ts_info = vsc85xx_ts_info; ++ phydev->mii_ts = &vsc8531->mii_ts; ++ ++ memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); ++ vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, ++ &phydev->mdio.dev); ++ return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); + } + + int vsc8584_ptp_probe_once(struct phy_device *phydev) +-- +2.50.1 + diff --git a/queue-6.6/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch b/queue-6.6/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch new file mode 100644 index 0000000000..ed85575765 --- /dev/null +++ b/queue-6.6/powerpc-kvm-fix-ifdef-to-remove-build-warning.patch @@ -0,0 +1,68 @@ +From cfe438e147daae11209186e775761e2046c90a6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 May 2025 10:11:04 +0530 +Subject: powerpc/kvm: Fix ifdef to remove build warning + +From: Madhavan Srinivasan + +[ Upstream commit 88688a2c8ac6c8036d983ad8b34ce191c46a10aa ] + +When compiling for pseries or powernv defconfig with "make C=1", +these warning were reported bu sparse tool in powerpc/kernel/kvm.c + +arch/powerpc/kernel/kvm.c:635:9: warning: switch with no cases +arch/powerpc/kernel/kvm.c:646:9: warning: switch with no cases + +Currently #ifdef were added after the switch case which are specific +for BOOKE and PPC_BOOK3S_32. These are not enabled in pseries/powernv +defconfig. Fix it by moving the #ifdef before switch(){} + +Fixes: cbe487fac7fc0 ("KVM: PPC: Add mtsrin PV code") +Tested-by: Venkat Rao Bagalkote +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250518044107.39928-1-maddy@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/kvm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c +index 5b3c093611baf..7209d00a9c257 100644 +--- a/arch/powerpc/kernel/kvm.c ++++ b/arch/powerpc/kernel/kvm.c +@@ -632,19 +632,19 @@ static void __init kvm_check_ins(u32 *inst, u32 features) + #endif + } + +- switch (inst_no_rt & ~KVM_MASK_RB) { + #ifdef CONFIG_PPC_BOOK3S_32 ++ switch (inst_no_rt & ~KVM_MASK_RB) { + case KVM_INST_MTSRIN: + if (features & KVM_MAGIC_FEAT_SR) { + u32 inst_rb = _inst & KVM_MASK_RB; + kvm_patch_ins_mtsrin(inst, inst_rt, inst_rb); + } + break; +-#endif + } ++#endif + +- switch (_inst) { + #ifdef CONFIG_BOOKE ++ switch (_inst) { + case KVM_INST_WRTEEI_0: + kvm_patch_ins_wrteei_0(inst); + break; +@@ -652,8 +652,8 @@ static void __init kvm_check_ins(u32 *inst, u32 features) + case KVM_INST_WRTEEI_1: + kvm_patch_ins_wrtee(inst, 0, 1); + break; +-#endif + } ++#endif + } + + extern u32 kvm_template_start[]; +-- +2.50.1 + diff --git a/queue-6.6/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch b/queue-6.6/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch new file mode 100644 index 0000000000..c257aa99c8 --- /dev/null +++ b/queue-6.6/sctp-initialize-more-fields-in-sctp_v6_from_sk.patch @@ -0,0 +1,72 @@ +From a320809ab02399bdd639e1c8797621bf26bc94e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Aug 2025 14:13:14 +0000 +Subject: sctp: initialize more fields in sctp_v6_from_sk() + +From: Eric Dumazet + +[ Upstream commit 2e8750469242cad8f01f320131fd5a6f540dbb99 ] + +syzbot found that sin6_scope_id was not properly initialized, +leading to undefined behavior. + +Clear sin6_scope_id and sin6_flowinfo. + +BUG: KMSAN: uninit-value in __sctp_v6_cmp_addr+0x887/0x8c0 net/sctp/ipv6.c:649 + __sctp_v6_cmp_addr+0x887/0x8c0 net/sctp/ipv6.c:649 + sctp_inet6_cmp_addr+0x4f2/0x510 net/sctp/ipv6.c:983 + sctp_bind_addr_conflict+0x22a/0x3b0 net/sctp/bind_addr.c:390 + sctp_get_port_local+0x21eb/0x2440 net/sctp/socket.c:8452 + sctp_get_port net/sctp/socket.c:8523 [inline] + sctp_listen_start net/sctp/socket.c:8567 [inline] + sctp_inet_listen+0x710/0xfd0 net/sctp/socket.c:8636 + __sys_listen_socket net/socket.c:1912 [inline] + __sys_listen net/socket.c:1927 [inline] + __do_sys_listen net/socket.c:1932 [inline] + __se_sys_listen net/socket.c:1930 [inline] + __x64_sys_listen+0x343/0x4c0 net/socket.c:1930 + x64_sys_call+0x271d/0x3e20 arch/x86/include/generated/asm/syscalls_64.h:51 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xd9/0x210 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Local variable addr.i.i created at: + sctp_get_port net/sctp/socket.c:8515 [inline] + sctp_listen_start net/sctp/socket.c:8567 [inline] + sctp_inet_listen+0x650/0xfd0 net/sctp/socket.c:8636 + __sys_listen_socket net/socket.c:1912 [inline] + __sys_listen net/socket.c:1927 [inline] + __do_sys_listen net/socket.c:1932 [inline] + __se_sys_listen net/socket.c:1930 [inline] + __x64_sys_listen+0x343/0x4c0 net/socket.c:1930 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+e69f06a0f30116c68056@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68adc0a2.050a0220.37038e.00c4.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Marcelo Ricardo Leitner +Acked-by: Xin Long +Link: https://patch.msgid.link/20250826141314.1802610-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/ipv6.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c +index 717828e531621..0673857cb3d8b 100644 +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -547,7 +547,9 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) + { + addr->v6.sin6_family = AF_INET6; + addr->v6.sin6_port = 0; ++ addr->v6.sin6_flowinfo = 0; + addr->v6.sin6_addr = sk->sk_v6_rcv_saddr; ++ addr->v6.sin6_scope_id = 0; + } + + /* Initialize sk->sk_rcv_saddr from sctp_addr. */ +-- +2.50.1 + diff --git a/queue-6.6/series b/queue-6.6/series index c20bf8bd67..9d008b55dc 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -14,3 +14,42 @@ acpi-ec-add-device-to-acpi_ec_no_wakeup-qurik-list.patch nfs-fold-nfs_page_group_lock_subrequests-into-nfs_lock_and_join_requests.patch nfs-fix-a-race-when-updating-an-existing-write.patch vhost-net-protect-ubufs-with-rcu-read-lock-in-vhost_net_ubuf_put.patch +net-ipv4-fix-regression-in-local-broadcast-routes.patch +drm-msm-defer-fd_install-in-submit-ioctl.patch +powerpc-kvm-fix-ifdef-to-remove-build-warning.patch +hid-input-rename-hidinput_set_battery_charge_status.patch +hid-input-report-battery-status-changes-immediately.patch +bluetooth-hci_event-treat-unknown_conn_id-on-disconn.patch +bluetooth-hci_event-mark-connection-as-closed-during.patch +bluetooth-hci_event-detect-if-hci_ev_num_comp_pkts-i.patch +bluetooth-hci_sync-fix-set_local_name-race-condition.patch +atm-atmtcp-prevent-arbitrary-write-in-atmtcp_recv_co.patch +drm-nouveau-remove-unused-increment-in-gm200_flcn_pi.patch +drm-nouveau-remove-unused-memory-target-test.patch +ice-introduce-ice_xdp_buff.patch +ice-gather-page_count-s-of-each-frag-right-before-xd.patch +ice-stop-storing-xdp-verdict-within-ice_rx_buf.patch +ice-fix-incorrect-counter-for-buffer-allocation-fail.patch +dt-bindings-display-msm-qcom-mdp5-drop-lut-clock.patch +net-dlink-fix-multicast-stats-being-counted-incorrec.patch +phy-mscc-fix-when-ptp-clock-is-register-and-unregist.patch +net-mlx5-reload-auxiliary-drivers-on-fw_activate.patch +net-mlx5-add-device-cap-for-supporting-hot-reset-in-.patch +net-mlx5-add-support-for-sync-reset-using-hot-reset.patch +net-mlx5-fix-lockdep-assertion-on-sync-reset-unload-.patch +net-mlx5-call-mlx5_sf_id_erase-once-in-mlx5_sf_deall.patch +net-mlx5-use-devlink-port-pointer-to-get-the-pointer.patch +net-mlx5-convert-sf-port_indices-xarray-to-function_.patch +net-mlx5-nack-sync-reset-when-sfs-are-present.patch +net-mlx5e-update-and-set-xon-xoff-upon-mtu-set.patch +net-mlx5e-update-and-set-xon-xoff-upon-port-speed-se.patch +net-mlx5e-set-local-xoff-after-fw-update.patch +net-stmmac-xgmac-do-not-enable-rx-fifo-overflow-inte.patch +net-stmmac-rename-phylink_get_caps-callback-to-updat.patch +net-stmmac-xgmac-correct-supported-speed-modes.patch +net-stmmac-set-cic-bit-only-for-tx-queues-with-coe.patch +net-rose-split-remove-and-free-operations-in-rose_re.patch +net-rose-convert-use-field-to-refcount_t.patch +net-rose-include-node-references-in-rose_neigh-refco.patch +sctp-initialize-more-fields-in-sctp_v6_from_sk.patch +efivarfs-fix-slab-out-of-bounds-in-efivarfs_d_compar.patch