]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Fri, 25 Jul 2025 15:06:09 +0000 (11:06 -0400)
committerSasha Levin <sashal@kernel.org>
Fri, 25 Jul 2025 15:06:09 +0000 (11:06 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.10/i40e-add-rx_missed_errors-for-buffer-exhaustion.patch [new file with mode: 0644]
queue-5.10/i40e-report-vf-tx_dropped-with-tx_errors-instead-of-.patch [new file with mode: 0644]
queue-5.10/net-appletalk-fix-kerneldoc-warnings.patch [new file with mode: 0644]
queue-5.10/net-appletalk-fix-use-after-free-in-aarp-proxy-probe.patch [new file with mode: 0644]
queue-5.10/net-hns3-fixed-vf-get-max-channels-bug.patch [new file with mode: 0644]
queue-5.10/net-hns3-refine-the-struct-hane3_tc_info.patch [new file with mode: 0644]
queue-5.10/net-sched-sch_qfq-avoid-triggering-might_sleep-in-at.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/i40e-add-rx_missed_errors-for-buffer-exhaustion.patch b/queue-5.10/i40e-add-rx_missed_errors-for-buffer-exhaustion.patch
new file mode 100644 (file)
index 0000000..b559299
--- /dev/null
@@ -0,0 +1,120 @@
+From a212b3f6845d77077628baf58c91f16d593461cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Sep 2023 15:27:57 +0800
+Subject: i40e: Add rx_missed_errors for buffer exhaustion
+
+From: Yajun Deng <yajun.deng@linux.dev>
+
+[ Upstream commit 5337d294973331660e84e41836a54014de22e5b0 ]
+
+As the comment in struct rtnl_link_stats64, rx_dropped should not
+include packets dropped by the device due to buffer exhaustion.
+They are counted in rx_missed_errors, procfs folds those two counters
+together.
+
+Add rx_missed_errors for buffer exhaustion, rx_missed_errors corresponds
+to rx_discards, rx_dropped corresponds to rx_discards_other.
+
+Signed-off-by: Yajun Deng <yajun.deng@linux.dev>
+Tested-by: Arpana Arland <arpanax.arland@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Stable-dep-of: 50b2af451597 ("i40e: report VF tx_dropped with tx_errors instead of tx_discards")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/i40e/i40e_ethtool.c |  3 ++-
+ drivers/net/ethernet/intel/i40e/i40e_main.c    | 18 +++++++-----------
+ .../net/ethernet/intel/i40e/i40e_virtchnl_pf.c |  2 +-
+ 3 files changed, 10 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+index 520929f4d535f..7f8fc9b3b105f 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+@@ -247,6 +247,7 @@ static const struct i40e_stats i40e_gstrings_net_stats[] = {
+       I40E_NETDEV_STAT(rx_errors),
+       I40E_NETDEV_STAT(tx_errors),
+       I40E_NETDEV_STAT(rx_dropped),
++      I40E_NETDEV_STAT(rx_missed_errors),
+       I40E_NETDEV_STAT(tx_dropped),
+       I40E_NETDEV_STAT(collisions),
+       I40E_NETDEV_STAT(rx_length_errors),
+@@ -317,7 +318,7 @@ static const struct i40e_stats i40e_gstrings_stats[] = {
+       I40E_PF_STAT("port.rx_broadcast", stats.eth.rx_broadcast),
+       I40E_PF_STAT("port.tx_broadcast", stats.eth.tx_broadcast),
+       I40E_PF_STAT("port.tx_errors", stats.eth.tx_errors),
+-      I40E_PF_STAT("port.rx_dropped", stats.eth.rx_discards),
++      I40E_PF_STAT("port.rx_discards", stats.eth.rx_discards),
+       I40E_PF_STAT("port.tx_dropped_link_down", stats.tx_dropped_link_down),
+       I40E_PF_STAT("port.rx_crc_errors", stats.crc_errors),
+       I40E_PF_STAT("port.illegal_bytes", stats.illegal_bytes),
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
+index 35a903f6df215..aa24d1808c981 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
+@@ -492,6 +492,7 @@ static void i40e_get_netdev_stats_struct(struct net_device *netdev,
+       stats->tx_dropped       = vsi_stats->tx_dropped;
+       stats->rx_errors        = vsi_stats->rx_errors;
+       stats->rx_dropped       = vsi_stats->rx_dropped;
++      stats->rx_missed_errors = vsi_stats->rx_missed_errors;
+       stats->rx_crc_errors    = vsi_stats->rx_crc_errors;
+       stats->rx_length_errors = vsi_stats->rx_length_errors;
+ }
+@@ -683,17 +684,13 @@ i40e_stats_update_rx_discards(struct i40e_vsi *vsi, struct i40e_hw *hw,
+                             struct i40e_eth_stats *stat_offset,
+                             struct i40e_eth_stats *stat)
+ {
+-      u64 rx_rdpc, rx_rxerr;
+-
+       i40e_stat_update32(hw, I40E_GLV_RDPC(stat_idx), offset_loaded,
+-                         &stat_offset->rx_discards, &rx_rdpc);
++                         &stat_offset->rx_discards, &stat->rx_discards);
+       i40e_stat_update64(hw,
+                          I40E_GL_RXERR1H(i40e_compute_pci_to_hw_id(vsi, hw)),
+                          I40E_GL_RXERR1L(i40e_compute_pci_to_hw_id(vsi, hw)),
+                          offset_loaded, &stat_offset->rx_discards_other,
+-                         &rx_rxerr);
+-
+-      stat->rx_discards = rx_rdpc + rx_rxerr;
++                         &stat->rx_discards_other);
+ }
+ /**
+@@ -715,9 +712,6 @@ void i40e_update_eth_stats(struct i40e_vsi *vsi)
+       i40e_stat_update32(hw, I40E_GLV_TEPC(stat_idx),
+                          vsi->stat_offsets_loaded,
+                          &oes->tx_errors, &es->tx_errors);
+-      i40e_stat_update32(hw, I40E_GLV_RDPC(stat_idx),
+-                         vsi->stat_offsets_loaded,
+-                         &oes->rx_discards, &es->rx_discards);
+       i40e_stat_update32(hw, I40E_GLV_RUPP(stat_idx),
+                          vsi->stat_offsets_loaded,
+                          &oes->rx_unknown_protocol, &es->rx_unknown_protocol);
+@@ -958,8 +952,10 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
+       ns->tx_errors = es->tx_errors;
+       ons->multicast = oes->rx_multicast;
+       ns->multicast = es->rx_multicast;
+-      ons->rx_dropped = oes->rx_discards;
+-      ns->rx_dropped = es->rx_discards;
++      ons->rx_dropped = oes->rx_discards_other;
++      ns->rx_dropped = es->rx_discards_other;
++      ons->rx_missed_errors = oes->rx_discards;
++      ns->rx_missed_errors = es->rx_discards;
+       ons->tx_dropped = oes->tx_discards;
+       ns->tx_dropped = es->tx_discards;
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+index 852ece241a278..65093c310dce8 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+@@ -4835,7 +4835,7 @@ int i40e_get_vf_stats(struct net_device *netdev, int vf_id,
+       vf_stats->tx_bytes   = stats->tx_bytes;
+       vf_stats->broadcast  = stats->rx_broadcast;
+       vf_stats->multicast  = stats->rx_multicast;
+-      vf_stats->rx_dropped = stats->rx_discards;
++      vf_stats->rx_dropped = stats->rx_discards + stats->rx_discards_other;
+       vf_stats->tx_dropped = stats->tx_discards;
+       return 0;
+-- 
+2.39.5
+
diff --git a/queue-5.10/i40e-report-vf-tx_dropped-with-tx_errors-instead-of-.patch b/queue-5.10/i40e-report-vf-tx_dropped-with-tx_errors-instead-of-.patch
new file mode 100644 (file)
index 0000000..350de09
--- /dev/null
@@ -0,0 +1,108 @@
+From 8dc722c56ac9f9c4174fdfc76352d946fe7ccca8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 18 Jun 2025 15:52:40 -0400
+Subject: i40e: report VF tx_dropped with tx_errors instead of tx_discards
+
+From: Dennis Chen <dechen@redhat.com>
+
+[ Upstream commit 50b2af451597ca6eefe9d4543f8bbf8de8aa00e7 ]
+
+Currently the tx_dropped field in VF stats is not updated correctly
+when reading stats from the PF. This is because it reads from
+i40e_eth_stats.tx_discards which seems to be unused for per VSI stats,
+as it is not updated by i40e_update_eth_stats() and the corresponding
+register, GLV_TDPC, is not implemented[1].
+
+Use i40e_eth_stats.tx_errors instead, which is actually updated by
+i40e_update_eth_stats() by reading from GLV_TEPC.
+
+To test, create a VF and try to send bad packets through it:
+
+$ echo 1 > /sys/class/net/enp2s0f0/device/sriov_numvfs
+$ cat test.py
+from scapy.all import *
+
+vlan_pkt = Ether(dst="ff:ff:ff:ff:ff:ff") / Dot1Q(vlan=999) / IP(dst="192.168.0.1") / ICMP()
+ttl_pkt = IP(dst="8.8.8.8", ttl=0) / ICMP()
+
+print("Send packet with bad VLAN tag")
+sendp(vlan_pkt, iface="enp2s0f0v0")
+print("Send packet with TTL=0")
+sendp(ttl_pkt, iface="enp2s0f0v0")
+$ ip -s link show dev enp2s0f0
+16: enp2s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
+    link/ether 3c:ec:ef:b7:e0:ac brd ff:ff:ff:ff:ff:ff
+    RX:  bytes packets errors dropped  missed   mcast
+             0       0      0       0       0       0
+    TX:  bytes packets errors dropped carrier collsns
+             0       0      0       0       0       0
+    vf 0     link/ether e2:c6:fd:c1:1e:92 brd ff:ff:ff:ff:ff:ff, spoof checking on, link-state auto, trust off
+    RX: bytes  packets  mcast   bcast   dropped
+             0        0       0       0        0
+    TX: bytes  packets   dropped
+             0        0        0
+$ python test.py
+Send packet with bad VLAN tag
+.
+Sent 1 packets.
+Send packet with TTL=0
+.
+Sent 1 packets.
+$ ip -s link show dev enp2s0f0
+16: enp2s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
+    link/ether 3c:ec:ef:b7:e0:ac brd ff:ff:ff:ff:ff:ff
+    RX:  bytes packets errors dropped  missed   mcast
+             0       0      0       0       0       0
+    TX:  bytes packets errors dropped carrier collsns
+             0       0      0       0       0       0
+    vf 0     link/ether e2:c6:fd:c1:1e:92 brd ff:ff:ff:ff:ff:ff, spoof checking on, link-state auto, trust off
+    RX: bytes  packets  mcast   bcast   dropped
+             0        0       0       0        0
+    TX: bytes  packets   dropped
+             0        0        0
+
+A packet with non-existent VLAN tag and a packet with TTL = 0 are sent,
+but tx_dropped is not incremented.
+
+After patch:
+
+$ ip -s link show dev enp2s0f0
+19: enp2s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
+    link/ether 3c:ec:ef:b7:e0:ac brd ff:ff:ff:ff:ff:ff
+    RX:  bytes packets errors dropped  missed   mcast
+             0       0      0       0       0       0
+    TX:  bytes packets errors dropped carrier collsns
+             0       0      0       0       0       0
+    vf 0     link/ether 4a:b7:3d:37:f7:56 brd ff:ff:ff:ff:ff:ff, spoof checking on, link-state auto, trust off
+    RX: bytes  packets  mcast   bcast   dropped
+             0        0       0       0        0
+    TX: bytes  packets   dropped
+             0        0        2
+
+Fixes: dc645daef9af5bcbd9c ("i40e: implement VF stats NDO")
+Signed-off-by: Dennis Chen <dechen@redhat.com>
+Link: https://www.intel.com/content/www/us/en/content-details/596333/intel-ethernet-controller-x710-tm4-at2-carlsville-datasheet.html
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+index 65093c310dce8..c86c429e9a3a3 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+@@ -4836,7 +4836,7 @@ int i40e_get_vf_stats(struct net_device *netdev, int vf_id,
+       vf_stats->broadcast  = stats->rx_broadcast;
+       vf_stats->multicast  = stats->rx_multicast;
+       vf_stats->rx_dropped = stats->rx_discards + stats->rx_discards_other;
+-      vf_stats->tx_dropped = stats->tx_discards;
++      vf_stats->tx_dropped = stats->tx_errors;
+       return 0;
+ }
+-- 
+2.39.5
+
diff --git a/queue-5.10/net-appletalk-fix-kerneldoc-warnings.patch b/queue-5.10/net-appletalk-fix-kerneldoc-warnings.patch
new file mode 100644 (file)
index 0000000..a605f38
--- /dev/null
@@ -0,0 +1,83 @@
+From 6efeb36ea3eb128db7f32b67ace4d58ce24c35d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Oct 2020 01:55:27 +0100
+Subject: net: appletalk: fix kerneldoc warnings
+
+From: Andrew Lunn <andrew@lunn.ch>
+
+[ Upstream commit 709565ae14aa2670d6b480be46720856e804af41 ]
+
+net/appletalk/aarp.c:68: warning: Function parameter or member 'dev' not described in 'aarp_entry'
+net/appletalk/aarp.c:68: warning: Function parameter or member 'expires_at' not described in 'aarp_entry'
+net/appletalk/aarp.c:68: warning: Function parameter or member 'hwaddr' not described in 'aarp_entry'
+net/appletalk/aarp.c:68: warning: Function parameter or member 'last_sent' not described in 'aarp_entry'
+net/appletalk/aarp.c:68: warning: Function parameter or member 'next' not described in 'aarp_entry'
+net/appletalk/aarp.c:68: warning: Function parameter or member 'packet_queue' not described in 'aarp_entry'
+net/appletalk/aarp.c:68: warning: Function parameter or member 'status' not described in 'aarp_entry'
+net/appletalk/aarp.c:68: warning: Function parameter or member 'target_addr' not described in 'aarp_entry'
+net/appletalk/aarp.c:68: warning: Function parameter or member 'xmit_count' not described in 'aarp_entry'
+net/appletalk/ddp.c:1422: warning: Function parameter or member 'dev' not described in 'atalk_rcv'
+net/appletalk/ddp.c:1422: warning: Function parameter or member 'orig_dev' not described in 'atalk_rcv'
+net/appletalk/ddp.c:1422: warning: Function parameter or member 'pt' not described in 'atalk_rcv'
+net/appletalk/ddp.c:1422: warning: Function parameter or member 'skb' not described in 'atalk_rcv'
+
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://lore.kernel.org/r/20201028005527.930388-1-andrew@lunn.ch
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 6c4a92d07b08 ("net: appletalk: Fix use-after-free in AARP proxy probe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/appletalk/aarp.c | 18 +++++++++---------
+ net/appletalk/ddp.c  |  7 ++++---
+ 2 files changed, 13 insertions(+), 12 deletions(-)
+
+diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
+index 45f584171de79..be18af481d7d5 100644
+--- a/net/appletalk/aarp.c
++++ b/net/appletalk/aarp.c
+@@ -44,15 +44,15 @@ int sysctl_aarp_resolve_time = AARP_RESOLVE_TIME;
+ /* Lists of aarp entries */
+ /**
+  *    struct aarp_entry - AARP entry
+- *    @last_sent - Last time we xmitted the aarp request
+- *    @packet_queue - Queue of frames wait for resolution
+- *    @status - Used for proxy AARP
+- *    expires_at - Entry expiry time
+- *    target_addr - DDP Address
+- *    dev - Device to use
+- *    hwaddr - Physical i/f address of target/router
+- *    xmit_count - When this hits 10 we give up
+- *    next - Next entry in chain
++ *    @last_sent: Last time we xmitted the aarp request
++ *    @packet_queue: Queue of frames wait for resolution
++ *    @status: Used for proxy AARP
++ *    @expires_at: Entry expiry time
++ *    @target_addr: DDP Address
++ *    @dev:  Device to use
++ *    @hwaddr:  Physical i/f address of target/router
++ *    @xmit_count:  When this hits 10 we give up
++ *    @next: Next entry in chain
+  */
+ struct aarp_entry {
+       /* These first two are only used for unresolved entries */
+diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
+index c9edfca153c99..f38b170a51af0 100644
+--- a/net/appletalk/ddp.c
++++ b/net/appletalk/ddp.c
+@@ -1408,9 +1408,10 @@ static int atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
+ /**
+  *    atalk_rcv - Receive a packet (in skb) from device dev
+- *    @skb - packet received
+- *    @dev - network device where the packet comes from
+- *    @pt - packet type
++ *    @skb: packet received
++ *    @dev: network device where the packet comes from
++ *    @pt: packet type
++ *    @orig_dev: the original receive net device
+  *
+  *    Receive a packet (in skb) from device dev. This has come from the SNAP
+  *    decoder, and on entry skb->transport_header is the DDP header, skb->len
+-- 
+2.39.5
+
diff --git a/queue-5.10/net-appletalk-fix-use-after-free-in-aarp-proxy-probe.patch b/queue-5.10/net-appletalk-fix-use-after-free-in-aarp-proxy-probe.patch
new file mode 100644 (file)
index 0000000..1da3eab
--- /dev/null
@@ -0,0 +1,185 @@
+From 4e5d5d748094a176c452935ac2ba8ca30a0eeb1f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Jul 2025 01:28:43 +0000
+Subject: net: appletalk: Fix use-after-free in AARP proxy probe
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kito Xu (veritas501) <hxzene@gmail.com>
+
+[ Upstream commit 6c4a92d07b0850342d3becf2e608f805e972467c ]
+
+The AARP proxy‐probe routine (aarp_proxy_probe_network) sends a probe,
+releases the aarp_lock, sleeps, then re-acquires the lock.  During that
+window an expire timer thread (__aarp_expire_timer) can remove and
+kfree() the same entry, leading to a use-after-free.
+
+race condition:
+
+         cpu 0                          |            cpu 1
+    atalk_sendmsg()                     |   atif_proxy_probe_device()
+    aarp_send_ddp()                     |   aarp_proxy_probe_network()
+    mod_timer()                         |   lock(aarp_lock) // LOCK!!
+    timeout around 200ms                |   alloc(aarp_entry)
+    and then call                       |   proxies[hash] = aarp_entry
+    aarp_expire_timeout()               |   aarp_send_probe()
+                                        |   unlock(aarp_lock) // UNLOCK!!
+    lock(aarp_lock) // LOCK!!           |   msleep(100);
+    __aarp_expire_timer(&proxies[ct])   |
+    free(aarp_entry)                    |
+    unlock(aarp_lock) // UNLOCK!!       |
+                                        |   lock(aarp_lock) // LOCK!!
+                                        |   UAF aarp_entry !!
+
+==================================================================
+BUG: KASAN: slab-use-after-free in aarp_proxy_probe_network+0x560/0x630 net/appletalk/aarp.c:493
+Read of size 4 at addr ffff8880123aa360 by task repro/13278
+
+CPU: 3 UID: 0 PID: 13278 Comm: repro Not tainted 6.15.2 #3 PREEMPT(full)
+Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:94 [inline]
+ dump_stack_lvl+0x116/0x1b0 lib/dump_stack.c:120
+ print_address_description mm/kasan/report.c:408 [inline]
+ print_report+0xc1/0x630 mm/kasan/report.c:521
+ kasan_report+0xca/0x100 mm/kasan/report.c:634
+ aarp_proxy_probe_network+0x560/0x630 net/appletalk/aarp.c:493
+ atif_proxy_probe_device net/appletalk/ddp.c:332 [inline]
+ atif_ioctl+0xb58/0x16c0 net/appletalk/ddp.c:857
+ atalk_ioctl+0x198/0x2f0 net/appletalk/ddp.c:1818
+ sock_do_ioctl+0xdc/0x260 net/socket.c:1190
+ sock_ioctl+0x239/0x6a0 net/socket.c:1311
+ vfs_ioctl fs/ioctl.c:51 [inline]
+ __do_sys_ioctl fs/ioctl.c:906 [inline]
+ __se_sys_ioctl fs/ioctl.c:892 [inline]
+ __x64_sys_ioctl+0x194/0x200 fs/ioctl.c:892
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0xcb/0x250 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+ </TASK>
+
+Allocated:
+ aarp_alloc net/appletalk/aarp.c:382 [inline]
+ aarp_proxy_probe_network+0xd8/0x630 net/appletalk/aarp.c:468
+ atif_proxy_probe_device net/appletalk/ddp.c:332 [inline]
+ atif_ioctl+0xb58/0x16c0 net/appletalk/ddp.c:857
+ atalk_ioctl+0x198/0x2f0 net/appletalk/ddp.c:1818
+
+Freed:
+ kfree+0x148/0x4d0 mm/slub.c:4841
+ __aarp_expire net/appletalk/aarp.c:90 [inline]
+ __aarp_expire_timer net/appletalk/aarp.c:261 [inline]
+ aarp_expire_timeout+0x480/0x6e0 net/appletalk/aarp.c:317
+
+The buggy address belongs to the object at ffff8880123aa300
+ which belongs to the cache kmalloc-192 of size 192
+The buggy address is located 96 bytes inside of
+ freed 192-byte region [ffff8880123aa300, ffff8880123aa3c0)
+
+Memory state around the buggy address:
+ ffff8880123aa200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ ffff8880123aa280: 00 00 00 00 fc fc fc fc fc fc fc fc fc fc fc fc
+>ffff8880123aa300: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+                                                       ^
+ ffff8880123aa380: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
+ ffff8880123aa400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+==================================================================
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Kito Xu (veritas501) <hxzene@gmail.com>
+Link: https://patch.msgid.link/20250717012843.880423-1-hxzene@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/appletalk/aarp.c | 24 +++++++++++++++++++++---
+ 1 file changed, 21 insertions(+), 3 deletions(-)
+
+diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
+index be18af481d7d5..17d9cb380e7bd 100644
+--- a/net/appletalk/aarp.c
++++ b/net/appletalk/aarp.c
+@@ -35,6 +35,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/export.h>
+ #include <linux/etherdevice.h>
++#include <linux/refcount.h>
+ int sysctl_aarp_expiry_time = AARP_EXPIRY_TIME;
+ int sysctl_aarp_tick_time = AARP_TICK_TIME;
+@@ -44,6 +45,7 @@ int sysctl_aarp_resolve_time = AARP_RESOLVE_TIME;
+ /* Lists of aarp entries */
+ /**
+  *    struct aarp_entry - AARP entry
++ *    @refcnt: Reference count
+  *    @last_sent: Last time we xmitted the aarp request
+  *    @packet_queue: Queue of frames wait for resolution
+  *    @status: Used for proxy AARP
+@@ -55,6 +57,7 @@ int sysctl_aarp_resolve_time = AARP_RESOLVE_TIME;
+  *    @next: Next entry in chain
+  */
+ struct aarp_entry {
++      refcount_t                      refcnt;
+       /* These first two are only used for unresolved entries */
+       unsigned long           last_sent;
+       struct sk_buff_head     packet_queue;
+@@ -79,6 +82,17 @@ static DEFINE_RWLOCK(aarp_lock);
+ /* Used to walk the list and purge/kick entries.  */
+ static struct timer_list aarp_timer;
++static inline void aarp_entry_get(struct aarp_entry *a)
++{
++      refcount_inc(&a->refcnt);
++}
++
++static inline void aarp_entry_put(struct aarp_entry *a)
++{
++      if (refcount_dec_and_test(&a->refcnt))
++              kfree(a);
++}
++
+ /*
+  *    Delete an aarp queue
+  *
+@@ -87,7 +101,7 @@ static struct timer_list aarp_timer;
+ static void __aarp_expire(struct aarp_entry *a)
+ {
+       skb_queue_purge(&a->packet_queue);
+-      kfree(a);
++      aarp_entry_put(a);
+ }
+ /*
+@@ -380,9 +394,11 @@ static void aarp_purge(void)
+ static struct aarp_entry *aarp_alloc(void)
+ {
+       struct aarp_entry *a = kmalloc(sizeof(*a), GFP_ATOMIC);
++      if (!a)
++              return NULL;
+-      if (a)
+-              skb_queue_head_init(&a->packet_queue);
++      refcount_set(&a->refcnt, 1);
++      skb_queue_head_init(&a->packet_queue);
+       return a;
+ }
+@@ -508,6 +524,7 @@ int aarp_proxy_probe_network(struct atalk_iface *atif, struct atalk_addr *sa)
+       entry->dev = atif->dev;
+       write_lock_bh(&aarp_lock);
++      aarp_entry_get(entry);
+       hash = sa->s_node % (AARP_HASH_SIZE - 1);
+       entry->next = proxies[hash];
+@@ -533,6 +550,7 @@ int aarp_proxy_probe_network(struct atalk_iface *atif, struct atalk_addr *sa)
+               retval = 1;
+       }
++      aarp_entry_put(entry);
+       write_unlock_bh(&aarp_lock);
+ out:
+       return retval;
+-- 
+2.39.5
+
diff --git a/queue-5.10/net-hns3-fixed-vf-get-max-channels-bug.patch b/queue-5.10/net-hns3-fixed-vf-get-max-channels-bug.patch
new file mode 100644 (file)
index 0000000..ff2571f
--- /dev/null
@@ -0,0 +1,45 @@
+From 5d4db7517acf6b10513bb38ef191e4acad6ffede Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Jul 2025 20:54:22 +0800
+Subject: net: hns3: fixed vf get max channels bug
+
+From: Jian Shen <shenjian15@huawei.com>
+
+[ Upstream commit b3e75c0bcc53f647311960bc1b0970b9b480ca5a ]
+
+Currently, the queried maximum of vf channels is the maximum of channels
+supported by each TC. However, the actual maximum of channels is
+the maximum of channels supported by the device.
+
+Fixes: 849e46077689 ("net: hns3: add ethtool_ops.get_channels support for VF")
+Signed-off-by: Jian Shen <shenjian15@huawei.com>
+Signed-off-by: Hao Lan <lanhao@huawei.com>
+Signed-off-by: Jijie Shao <shaojijie@huawei.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20250722125423.1270673-4-shaojijie@huawei.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+index cf03c2ab7b2eb..15dca78fd736c 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+@@ -3346,11 +3346,7 @@ static void hclgevf_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
+ static u32 hclgevf_get_max_channels(struct hclgevf_dev *hdev)
+ {
+-      struct hnae3_handle *nic = &hdev->nic;
+-      struct hnae3_knic_private_info *kinfo = &nic->kinfo;
+-
+-      return min_t(u32, hdev->rss_size_max,
+-                   hdev->num_tqps / kinfo->tc_info.num_tc);
++      return min(hdev->rss_size_max, hdev->num_tqps);
+ }
+ /**
+-- 
+2.39.5
+
diff --git a/queue-5.10/net-hns3-refine-the-struct-hane3_tc_info.patch b/queue-5.10/net-hns3-refine-the-struct-hane3_tc_info.patch
new file mode 100644 (file)
index 0000000..b648afc
--- /dev/null
@@ -0,0 +1,441 @@
+From 9f5334657d050454a7d483d78ae192e02603f8ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Dec 2020 11:42:06 +0800
+Subject: net: hns3: refine the struct hane3_tc_info
+
+From: Jian Shen <shenjian15@huawei.com>
+
+[ Upstream commit 35244430d62422e96b4c9c9b4c00c0ebece91d73 ]
+
+Currently, there are multiple members related to tc information
+in struct hnae3_knic_private_info. Merge them into a new struct
+hnae3_tc_info.
+
+Signed-off-by: Jian Shen <shenjian15@huawei.com>
+Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: b3e75c0bcc53 ("net: hns3: fixed vf get max channels bug")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hns3/hnae3.h   | 17 +++----
+ .../ethernet/hisilicon/hns3/hns3_debugfs.c    |  3 +-
+ .../net/ethernet/hisilicon/hns3/hns3_enet.c   | 33 ++++++-------
+ .../hisilicon/hns3/hns3pf/hclge_debugfs.c     |  2 +-
+ .../hisilicon/hns3/hns3pf/hclge_main.c        |  4 +-
+ .../hisilicon/hns3/hns3pf/hclge_mbx.c         |  2 +-
+ .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 49 +++++++++----------
+ .../hisilicon/hns3/hns3vf/hclgevf_main.c      | 21 ++++----
+ 8 files changed, 64 insertions(+), 67 deletions(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+index 25b6b4f780f1d..b0b5324e7f990 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
++++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+@@ -656,15 +656,16 @@ struct hnae3_ae_algo {
+ #define HNAE3_INT_NAME_LEN        32
+ #define HNAE3_ITR_COUNTDOWN_START 100
++#define HNAE3_MAX_TC          8
++#define HNAE3_MAX_USER_PRIO   8
+ struct hnae3_tc_info {
+-      u16     tqp_offset;     /* TQP offset from base TQP */
+-      u16     tqp_count;      /* Total TQPs */
+-      u8      tc;             /* TC index */
+-      bool    enable;         /* If this TC is enable or not */
++      u8 prio_tc[HNAE3_MAX_USER_PRIO]; /* TC indexed by prio */
++      u16 tqp_count[HNAE3_MAX_TC];
++      u16 tqp_offset[HNAE3_MAX_TC];
++      unsigned long tc_en; /* bitmap of TC enabled */
++      u8 num_tc; /* Total number of enabled TCs */
+ };
+-#define HNAE3_MAX_TC          8
+-#define HNAE3_MAX_USER_PRIO   8
+ struct hnae3_knic_private_info {
+       struct net_device *netdev; /* Set by KNIC client when init instance */
+       u16 rss_size;              /* Allocated RSS queues */
+@@ -673,9 +674,7 @@ struct hnae3_knic_private_info {
+       u16 num_tx_desc;
+       u16 num_rx_desc;
+-      u8 num_tc;                 /* Total number of enabled TCs */
+-      u8 prio_tc[HNAE3_MAX_USER_PRIO];  /* TC indexed by prio */
+-      struct hnae3_tc_info tc_info[HNAE3_MAX_TC]; /* Idx of array is HW TC */
++      struct hnae3_tc_info tc_info;
+       u16 num_tqps;             /* total number of TQPs in this handle */
+       struct hnae3_queue **tqp;  /* array base of all TQPs in this instance */
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+index dc9a85745e62b..d299787eae29a 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+@@ -347,7 +347,8 @@ static void hns3_dbg_dev_specs(struct hnae3_handle *h)
+       dev_info(priv->dev, "RX buffer length: %u\n", kinfo->rx_buf_len);
+       dev_info(priv->dev, "Desc num per TX queue: %u\n", kinfo->num_tx_desc);
+       dev_info(priv->dev, "Desc num per RX queue: %u\n", kinfo->num_rx_desc);
+-      dev_info(priv->dev, "Total number of enabled TCs: %u\n", kinfo->num_tc);
++      dev_info(priv->dev, "Total number of enabled TCs: %u\n",
++               kinfo->tc_info.num_tc);
+       dev_info(priv->dev, "MAX INT QL: %u\n", dev_specs->int_ql_max);
+ }
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+index 110baa9949a0c..727b18cd6c4a9 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+@@ -273,13 +273,14 @@ static int hns3_nic_set_real_num_queue(struct net_device *netdev)
+ {
+       struct hnae3_handle *h = hns3_get_handle(netdev);
+       struct hnae3_knic_private_info *kinfo = &h->kinfo;
+-      unsigned int queue_size = kinfo->rss_size * kinfo->num_tc;
++      struct hnae3_tc_info *tc_info = &kinfo->tc_info;
++      unsigned int queue_size = kinfo->rss_size * tc_info->num_tc;
+       int i, ret;
+-      if (kinfo->num_tc <= 1) {
++      if (tc_info->num_tc <= 1) {
+               netdev_reset_tc(netdev);
+       } else {
+-              ret = netdev_set_num_tc(netdev, kinfo->num_tc);
++              ret = netdev_set_num_tc(netdev, tc_info->num_tc);
+               if (ret) {
+                       netdev_err(netdev,
+                                  "netdev_set_num_tc fail, ret=%d!\n", ret);
+@@ -287,13 +288,11 @@ static int hns3_nic_set_real_num_queue(struct net_device *netdev)
+               }
+               for (i = 0; i < HNAE3_MAX_TC; i++) {
+-                      if (!kinfo->tc_info[i].enable)
++                      if (!test_bit(i, &tc_info->tc_en))
+                               continue;
+-                      netdev_set_tc_queue(netdev,
+-                                          kinfo->tc_info[i].tc,
+-                                          kinfo->tc_info[i].tqp_count,
+-                                          kinfo->tc_info[i].tqp_offset);
++                      netdev_set_tc_queue(netdev, i, tc_info->tqp_count[i],
++                                          tc_info->tqp_offset[i]);
+               }
+       }
+@@ -319,7 +318,7 @@ static u16 hns3_get_max_available_channels(struct hnae3_handle *h)
+       u16 alloc_tqps, max_rss_size, rss_size;
+       h->ae_algo->ops->get_tqps_and_rss_info(h, &alloc_tqps, &max_rss_size);
+-      rss_size = alloc_tqps / h->kinfo.num_tc;
++      rss_size = alloc_tqps / h->kinfo.tc_info.num_tc;
+       return min_t(u16, rss_size, max_rss_size);
+ }
+@@ -463,7 +462,7 @@ static int hns3_nic_net_open(struct net_device *netdev)
+       kinfo = &h->kinfo;
+       for (i = 0; i < HNAE3_MAX_USER_PRIO; i++)
+-              netdev_set_prio_tc_map(netdev, i, kinfo->prio_tc[i]);
++              netdev_set_prio_tc_map(netdev, i, kinfo->tc_info.prio_tc[i]);
+       if (h->ae_algo->ops->set_timer_task)
+               h->ae_algo->ops->set_timer_task(priv->ae_handle, true);
+@@ -3914,21 +3913,20 @@ static void hns3_init_ring_hw(struct hns3_enet_ring *ring)
+ static void hns3_init_tx_ring_tc(struct hns3_nic_priv *priv)
+ {
+       struct hnae3_knic_private_info *kinfo = &priv->ae_handle->kinfo;
++      struct hnae3_tc_info *tc_info = &kinfo->tc_info;
+       int i;
+       for (i = 0; i < HNAE3_MAX_TC; i++) {
+-              struct hnae3_tc_info *tc_info = &kinfo->tc_info[i];
+               int j;
+-              if (!tc_info->enable)
++              if (!test_bit(i, &tc_info->tc_en))
+                       continue;
+-              for (j = 0; j < tc_info->tqp_count; j++) {
++              for (j = 0; j < tc_info->tqp_count[i]; j++) {
+                       struct hnae3_queue *q;
+-                      q = priv->ring[tc_info->tqp_offset + j].tqp;
+-                      hns3_write_dev(q, HNS3_RING_TX_RING_TC_REG,
+-                                     tc_info->tc);
++                      q = priv->ring[tc_info->tqp_offset[i] + j].tqp;
++                      hns3_write_dev(q, HNS3_RING_TX_RING_TC_REG, i);
+               }
+       }
+ }
+@@ -4056,7 +4054,8 @@ static void hns3_info_show(struct hns3_nic_priv *priv)
+       dev_info(priv->dev, "RX buffer length: %u\n", kinfo->rx_buf_len);
+       dev_info(priv->dev, "Desc num per TX queue: %u\n", kinfo->num_tx_desc);
+       dev_info(priv->dev, "Desc num per RX queue: %u\n", kinfo->num_rx_desc);
+-      dev_info(priv->dev, "Total number of enabled TCs: %u\n", kinfo->num_tc);
++      dev_info(priv->dev, "Total number of enabled TCs: %u\n",
++               kinfo->tc_info.num_tc);
+       dev_info(priv->dev, "Max mtu size: %u\n", priv->netdev->max_mtu);
+ }
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+index 16df050e72cfc..9688b394634f1 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+@@ -1418,7 +1418,7 @@ static void hclge_dbg_dump_qs_shaper_all(struct hclge_dev *hdev)
+               dev_info(&hdev->pdev->dev, "qs cfg of vport%d:\n", vport_id);
+-              for (i = 0; i < kinfo->num_tc; i++) {
++              for (i = 0; i < kinfo->tc_info.num_tc; i++) {
+                       u16 qsid = vport->qs_offset + i;
+                       hclge_dbg_dump_qs_shaper_single(hdev, qsid);
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+index ec918f2981ec2..aa987cad7cadf 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+@@ -10682,7 +10682,7 @@ static u32 hclge_get_max_channels(struct hnae3_handle *handle)
+       struct hclge_dev *hdev = vport->back;
+       return min_t(u32, hdev->rss_size_max,
+-                   vport->alloc_tqps / kinfo->num_tc);
++                   vport->alloc_tqps / kinfo->tc_info.num_tc);
+ }
+ static void hclge_get_channels(struct hnae3_handle *handle,
+@@ -10769,7 +10769,7 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num,
+               dev_info(&hdev->pdev->dev,
+                        "Channels changed, rss_size from %u to %u, tqps from %u to %u",
+                        cur_rss_size, kinfo->rss_size,
+-                       cur_tqps, kinfo->rss_size * kinfo->num_tc);
++                       cur_tqps, kinfo->rss_size * kinfo->tc_info.num_tc);
+       return ret;
+ }
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+index 9969714d1133d..cdfa04bc45988 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+@@ -423,7 +423,7 @@ static void hclge_get_vf_tcinfo(struct hclge_vport *vport,
+       struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
+       unsigned int i;
+-      for (i = 0; i < kinfo->num_tc; i++)
++      for (i = 0; i < kinfo->tc_info.num_tc; i++)
+               resp_msg->data[0] |= BIT(i);
+       resp_msg->len = sizeof(u8);
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
+index 8c5c5562c0a73..df42458d909b3 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
+@@ -535,7 +535,7 @@ int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate)
+                                                HCLGE_SHAPER_BS_U_DEF,
+                                                HCLGE_SHAPER_BS_S_DEF);
+-      for (i = 0; i < kinfo->num_tc; i++) {
++      for (i = 0; i < kinfo->tc_info.num_tc; i++) {
+               hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QCN_SHAPPING_CFG,
+                                          false);
+@@ -566,13 +566,13 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport)
+       /* TC configuration is shared by PF/VF in one port, only allow
+        * one tc for VF for simplicity. VF's vport_id is non zero.
+        */
+-      kinfo->num_tc = vport->vport_id ? 1 :
++      kinfo->tc_info.num_tc = vport->vport_id ? 1 :
+                       min_t(u16, vport->alloc_tqps, hdev->tm_info.num_tc);
+       vport->qs_offset = (vport->vport_id ? HNAE3_MAX_TC : 0) +
+                               (vport->vport_id ? (vport->vport_id - 1) : 0);
+       max_rss_size = min_t(u16, hdev->rss_size_max,
+-                           vport->alloc_tqps / kinfo->num_tc);
++                           vport->alloc_tqps / kinfo->tc_info.num_tc);
+       /* Set to user value, no larger than max_rss_size. */
+       if (kinfo->req_rss_size != kinfo->rss_size && kinfo->req_rss_size &&
+@@ -589,34 +589,32 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport)
+               if (!kinfo->req_rss_size)
+                       max_rss_size = min_t(u16, max_rss_size,
+                                            (hdev->num_nic_msi - 1) /
+-                                           kinfo->num_tc);
++                                           kinfo->tc_info.num_tc);
+               /* Set to the maximum specification value (max_rss_size). */
+               kinfo->rss_size = max_rss_size;
+       }
+-      kinfo->num_tqps = kinfo->num_tc * kinfo->rss_size;
++      kinfo->num_tqps = kinfo->tc_info.num_tc * kinfo->rss_size;
+       vport->dwrr = 100;  /* 100 percent as init */
+       vport->alloc_rss_size = kinfo->rss_size;
+       vport->bw_limit = hdev->tm_info.pg_info[0].bw_limit;
+       for (i = 0; i < HNAE3_MAX_TC; i++) {
+-              if (hdev->hw_tc_map & BIT(i) && i < kinfo->num_tc) {
+-                      kinfo->tc_info[i].enable = true;
+-                      kinfo->tc_info[i].tqp_offset = i * kinfo->rss_size;
+-                      kinfo->tc_info[i].tqp_count = kinfo->rss_size;
+-                      kinfo->tc_info[i].tc = i;
++              if (hdev->hw_tc_map & BIT(i) && i < kinfo->tc_info.num_tc) {
++                      set_bit(i, &kinfo->tc_info.tc_en);
++                      kinfo->tc_info.tqp_offset[i] = i * kinfo->rss_size;
++                      kinfo->tc_info.tqp_count[i] = kinfo->rss_size;
+               } else {
+                       /* Set to default queue if TC is disable */
+-                      kinfo->tc_info[i].enable = false;
+-                      kinfo->tc_info[i].tqp_offset = 0;
+-                      kinfo->tc_info[i].tqp_count = 1;
+-                      kinfo->tc_info[i].tc = 0;
++                      clear_bit(i, &kinfo->tc_info.tc_en);
++                      kinfo->tc_info.tqp_offset[i] = 0;
++                      kinfo->tc_info.tqp_count[i] = 1;
+               }
+       }
+-      memcpy(kinfo->prio_tc, hdev->tm_info.prio_tc,
+-             sizeof_field(struct hnae3_knic_private_info, prio_tc));
++      memcpy(kinfo->tc_info.prio_tc, hdev->tm_info.prio_tc,
++             sizeof_field(struct hnae3_tc_info, prio_tc));
+ }
+ static void hclge_tm_vport_info_update(struct hclge_dev *hdev)
+@@ -815,15 +813,14 @@ static int hclge_vport_q_to_qs_map(struct hclge_dev *hdev,
+                                  struct hclge_vport *vport)
+ {
+       struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
++      struct hnae3_tc_info *tc_info = &kinfo->tc_info;
+       struct hnae3_queue **tqp = kinfo->tqp;
+-      struct hnae3_tc_info *v_tc_info;
+       u32 i, j;
+       int ret;
+-      for (i = 0; i < kinfo->num_tc; i++) {
+-              v_tc_info = &kinfo->tc_info[i];
+-              for (j = 0; j < v_tc_info->tqp_count; j++) {
+-                      struct hnae3_queue *q = tqp[v_tc_info->tqp_offset + j];
++      for (i = 0; i < tc_info->num_tc; i++) {
++              for (j = 0; j < tc_info->tqp_count[i]; j++) {
++                      struct hnae3_queue *q = tqp[tc_info->tqp_offset[i] + j];
+                       ret = hclge_tm_q_to_qs_map_cfg(hdev,
+                                                      hclge_get_queue_id(q),
+@@ -848,7 +845,7 @@ static int hclge_tm_pri_q_qs_cfg(struct hclge_dev *hdev)
+                       struct hnae3_knic_private_info *kinfo =
+                               &vport[k].nic.kinfo;
+-                      for (i = 0; i < kinfo->num_tc; i++) {
++                      for (i = 0; i < kinfo->tc_info.num_tc; i++) {
+                               ret = hclge_tm_qs_to_pri_map_cfg(
+                                       hdev, vport[k].qs_offset + i, i);
+                               if (ret)
+@@ -959,7 +956,7 @@ static int hclge_tm_pri_vnet_base_shaper_qs_cfg(struct hclge_vport *vport)
+       u32 i;
+       int ret;
+-      for (i = 0; i < kinfo->num_tc; i++) {
++      for (i = 0; i < kinfo->tc_info.num_tc; i++) {
+               ret = hclge_shaper_para_calc(hdev->tm_info.tc_info[i].bw_limit,
+                                            HCLGE_SHAPER_LVL_QSET,
+                                            &ir_para, max_tm_rate);
+@@ -1074,7 +1071,7 @@ static int hclge_tm_pri_vnet_base_dwrr_pri_cfg(struct hclge_vport *vport)
+               return ret;
+       /* Qset dwrr */
+-      for (i = 0; i < kinfo->num_tc; i++) {
++      for (i = 0; i < kinfo->tc_info.num_tc; i++) {
+               ret = hclge_tm_qs_weight_cfg(
+                       hdev, vport->qs_offset + i,
+                       hdev->tm_info.pg_info[0].tc_dwrr[i]);
+@@ -1205,7 +1202,7 @@ static int hclge_tm_schd_mode_vnet_base_cfg(struct hclge_vport *vport)
+       if (ret)
+               return ret;
+-      for (i = 0; i < kinfo->num_tc; i++) {
++      for (i = 0; i < kinfo->tc_info.num_tc; i++) {
+               u8 sch_mode = hdev->tm_info.tc_info[i].tc_sch_mode;
+               ret = hclge_tm_qs_schd_mode_cfg(hdev, vport->qs_offset + i,
+@@ -1428,7 +1425,7 @@ void hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc)
+               for (k = 0;  k < hdev->num_alloc_vport; k++) {
+                       kinfo = &vport[k].nic.kinfo;
+-                      kinfo->prio_tc[i] = prio_tc[i];
++                      kinfo->tc_info.prio_tc[i] = prio_tc[i];
+               }
+       }
+ }
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+index aa026eb5cf588..cf03c2ab7b2eb 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+@@ -418,19 +418,20 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev)
+       struct hnae3_knic_private_info *kinfo;
+       u16 new_tqps = hdev->num_tqps;
+       unsigned int i;
++      u8 num_tc = 0;
+       kinfo = &nic->kinfo;
+-      kinfo->num_tc = 0;
+       kinfo->num_tx_desc = hdev->num_tx_desc;
+       kinfo->num_rx_desc = hdev->num_rx_desc;
+       kinfo->rx_buf_len = hdev->rx_buf_len;
+       for (i = 0; i < HCLGEVF_MAX_TC_NUM; i++)
+               if (hdev->hw_tc_map & BIT(i))
+-                      kinfo->num_tc++;
++                      num_tc++;
+-      kinfo->rss_size
+-              = min_t(u16, hdev->rss_size_max, new_tqps / kinfo->num_tc);
+-      new_tqps = kinfo->rss_size * kinfo->num_tc;
++      num_tc = num_tc ? num_tc : 1;
++      kinfo->tc_info.num_tc = num_tc;
++      kinfo->rss_size = min_t(u16, hdev->rss_size_max, new_tqps / num_tc);
++      new_tqps = kinfo->rss_size * num_tc;
+       kinfo->num_tqps = min(new_tqps, hdev->num_tqps);
+       kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps,
+@@ -448,7 +449,7 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev)
+        * and rss size with the actual vector numbers
+        */
+       kinfo->num_tqps = min_t(u16, hdev->num_nic_msix - 1, kinfo->num_tqps);
+-      kinfo->rss_size = min_t(u16, kinfo->num_tqps / kinfo->num_tc,
++      kinfo->rss_size = min_t(u16, kinfo->num_tqps / num_tc,
+                               kinfo->rss_size);
+       return 0;
+@@ -3349,7 +3350,7 @@ static u32 hclgevf_get_max_channels(struct hclgevf_dev *hdev)
+       struct hnae3_knic_private_info *kinfo = &nic->kinfo;
+       return min_t(u32, hdev->rss_size_max,
+-                   hdev->num_tqps / kinfo->num_tc);
++                   hdev->num_tqps / kinfo->tc_info.num_tc);
+ }
+ /**
+@@ -3392,7 +3393,7 @@ static void hclgevf_update_rss_size(struct hnae3_handle *handle,
+       kinfo->req_rss_size = new_tqps_num;
+       max_rss_size = min_t(u16, hdev->rss_size_max,
+-                           hdev->num_tqps / kinfo->num_tc);
++                           hdev->num_tqps / kinfo->tc_info.num_tc);
+       /* Use the user's configuration when it is not larger than
+        * max_rss_size, otherwise, use the maximum specification value.
+@@ -3404,7 +3405,7 @@ static void hclgevf_update_rss_size(struct hnae3_handle *handle,
+                (!kinfo->req_rss_size && kinfo->rss_size < max_rss_size))
+               kinfo->rss_size = max_rss_size;
+-      kinfo->num_tqps = kinfo->num_tc * kinfo->rss_size;
++      kinfo->num_tqps = kinfo->tc_info.num_tc * kinfo->rss_size;
+ }
+ static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num,
+@@ -3450,7 +3451,7 @@ static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num,
+               dev_info(&hdev->pdev->dev,
+                        "Channels changed, rss_size from %u to %u, tqps from %u to %u",
+                        cur_rss_size, kinfo->rss_size,
+-                       cur_tqps, kinfo->rss_size * kinfo->num_tc);
++                       cur_tqps, kinfo->rss_size * kinfo->tc_info.num_tc);
+       return ret;
+ }
+-- 
+2.39.5
+
diff --git a/queue-5.10/net-sched-sch_qfq-avoid-triggering-might_sleep-in-at.patch b/queue-5.10/net-sched-sch_qfq-avoid-triggering-might_sleep-in-at.patch
new file mode 100644 (file)
index 0000000..479a890
--- /dev/null
@@ -0,0 +1,74 @@
+From 37f9f975617a10d205164c67ca37268a0527649c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Jul 2025 16:01:28 -0700
+Subject: net/sched: sch_qfq: Avoid triggering might_sleep in atomic context in
+ qfq_delete_class
+
+From: Xiang Mei <xmei5@asu.edu>
+
+[ Upstream commit cf074eca0065bc5142e6004ae236bb35a2687fdf ]
+
+might_sleep could be trigger in the atomic context in qfq_delete_class.
+
+qfq_destroy_class was moved into atomic context locked
+by sch_tree_lock to avoid a race condition bug on
+qfq_aggregate. However, might_sleep could be triggered by
+qfq_destroy_class, which introduced sleeping in atomic context (path:
+qfq_destroy_class->qdisc_put->__qdisc_destroy->lockdep_unregister_key
+->might_sleep).
+
+Considering the race is on the qfq_aggregate objects, keeping
+qfq_rm_from_agg in the lock but moving the left part out can solve
+this issue.
+
+Fixes: 5e28d5a3f774 ("net/sched: sch_qfq: Fix race condition on qfq_aggregate")
+Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
+Signed-off-by: Xiang Mei <xmei5@asu.edu>
+Link: https://patch.msgid.link/4a04e0cc-a64b-44e7-9213-2880ed641d77@sabinyo.mountain
+Reviewed-by: Cong Wang <xiyou.wangcong@gmail.com>
+Reviewed-by: Dan Carpenter <dan.carpenter@linaro.org>
+Link: https://patch.msgid.link/20250717230128.159766-1-xmei5@asu.edu
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_qfq.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
+index e412340f639d2..d8e01cca576e7 100644
+--- a/net/sched/sch_qfq.c
++++ b/net/sched/sch_qfq.c
+@@ -538,9 +538,6 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
+ static void qfq_destroy_class(struct Qdisc *sch, struct qfq_class *cl)
+ {
+-      struct qfq_sched *q = qdisc_priv(sch);
+-
+-      qfq_rm_from_agg(q, cl);
+       gen_kill_estimator(&cl->rate_est);
+       qdisc_put(cl->qdisc);
+       kfree(cl);
+@@ -558,10 +555,11 @@ static int qfq_delete_class(struct Qdisc *sch, unsigned long arg)
+       qdisc_purge_queue(cl->qdisc);
+       qdisc_class_hash_remove(&q->clhash, &cl->common);
+-      qfq_destroy_class(sch, cl);
++      qfq_rm_from_agg(q, cl);
+       sch_tree_unlock(sch);
++      qfq_destroy_class(sch, cl);
+       return 0;
+ }
+@@ -1509,6 +1507,7 @@ static void qfq_destroy_qdisc(struct Qdisc *sch)
+       for (i = 0; i < q->clhash.hashsize; i++) {
+               hlist_for_each_entry_safe(cl, next, &q->clhash.hash[i],
+                                         common.hnode) {
++                      qfq_rm_from_agg(q, cl);
+                       qfq_destroy_class(sch, cl);
+               }
+       }
+-- 
+2.39.5
+
index 5082cf9498c2c3d3cecf065b7977d7c0f2684e5d..25e5d21c81615132b07bd2e29bbe4a91fc07a41c 100644 (file)
@@ -54,3 +54,10 @@ virtio-net-ensure-the-received-length-does-not-exceed-allocated-size.patch
 xhci-disable-stream-for-xhc-controller-with-xhci_broken_streams.patch
 regulator-core-fix-null-dereference-on-unbind-due-to.patch
 rdma-core-rate-limit-gid-cache-warning-messages.patch
+i40e-add-rx_missed_errors-for-buffer-exhaustion.patch
+i40e-report-vf-tx_dropped-with-tx_errors-instead-of-.patch
+net-appletalk-fix-kerneldoc-warnings.patch
+net-appletalk-fix-use-after-free-in-aarp-proxy-probe.patch
+net-sched-sch_qfq-avoid-triggering-might_sleep-in-at.patch
+net-hns3-refine-the-struct-hane3_tc_info.patch
+net-hns3-fixed-vf-get-max-channels-bug.patch