From: Sasha Levin Date: Fri, 25 Jul 2025 15:06:09 +0000 (-0400) Subject: Fixes for 5.10 X-Git-Tag: v6.6.101~42 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f758c378380b64e1c4e1c1c8f43166449703b8d1;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.10 Signed-off-by: Sasha Levin --- 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 index 0000000000..b5592999b7 --- /dev/null +++ b/queue-5.10/i40e-add-rx_missed_errors-for-buffer-exhaustion.patch @@ -0,0 +1,120 @@ +From a212b3f6845d77077628baf58c91f16d593461cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Sep 2023 15:27:57 +0800 +Subject: i40e: Add rx_missed_errors for buffer exhaustion + +From: Yajun Deng + +[ 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 +Tested-by: Arpana Arland (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Stable-dep-of: 50b2af451597 ("i40e: report VF tx_dropped with tx_errors instead of tx_discards") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..350de09f2b --- /dev/null +++ b/queue-5.10/i40e-report-vf-tx_dropped-with-tx_errors-instead-of-.patch @@ -0,0 +1,108 @@ +From 8dc722c56ac9f9c4174fdfc76352d946fe7ccca8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: 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: 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: 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 +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 +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..a605f38663 --- /dev/null +++ b/queue-5.10/net-appletalk-fix-kerneldoc-warnings.patch @@ -0,0 +1,83 @@ +From 6efeb36ea3eb128db7f32b67ace4d58ce24c35d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Oct 2020 01:55:27 +0100 +Subject: net: appletalk: fix kerneldoc warnings + +From: Andrew Lunn + +[ 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 +Link: https://lore.kernel.org/r/20201028005527.930388-1-andrew@lunn.ch +Signed-off-by: Jakub Kicinski +Stable-dep-of: 6c4a92d07b08 ("net: appletalk: Fix use-after-free in AARP proxy probe") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..1da3eab02e --- /dev/null +++ b/queue-5.10/net-appletalk-fix-use-after-free-in-aarp-proxy-probe.patch @@ -0,0 +1,185 @@ +From 4e5d5d748094a176c452935ac2ba8ca30a0eeb1f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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: + + __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 + + +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) +Link: https://patch.msgid.link/20250717012843.880423-1-hxzene@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + + 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 index 0000000000..ff2571f0b1 --- /dev/null +++ b/queue-5.10/net-hns3-fixed-vf-get-max-channels-bug.patch @@ -0,0 +1,45 @@ +From 5d4db7517acf6b10513bb38ef191e4acad6ffede Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Jul 2025 20:54:22 +0800 +Subject: net: hns3: fixed vf get max channels bug + +From: Jian Shen + +[ 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 +Signed-off-by: Hao Lan +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250722125423.1270673-4-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..b648afcff2 --- /dev/null +++ b/queue-5.10/net-hns3-refine-the-struct-hane3_tc_info.patch @@ -0,0 +1,441 @@ +From 9f5334657d050454a7d483d78ae192e02603f8ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Dec 2020 11:42:06 +0800 +Subject: net: hns3: refine the struct hane3_tc_info + +From: Jian Shen + +[ 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 +Signed-off-by: Huazhong Tan +Signed-off-by: David S. Miller +Stable-dep-of: b3e75c0bcc53 ("net: hns3: fixed vf get max channels bug") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..479a890463 --- /dev/null +++ b/queue-5.10/net-sched-sch_qfq-avoid-triggering-might_sleep-in-at.patch @@ -0,0 +1,74 @@ +From 37f9f975617a10d205164c67ca37268a0527649c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Xiang Mei +Link: https://patch.msgid.link/4a04e0cc-a64b-44e7-9213-2880ed641d77@sabinyo.mountain +Reviewed-by: Cong Wang +Reviewed-by: Dan Carpenter +Link: https://patch.msgid.link/20250717230128.159766-1-xmei5@asu.edu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/series b/queue-5.10/series index 5082cf9498..25e5d21c81 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -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