From 4187c29c2abdd2144f5bcf5936c7f997d1fdef66 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 31 Aug 2026 15:41:29 +0000 Subject: net: optimize netif_is_l3_master() and netif_is_l3_slave() IFF_L3MDEV_MASTER and IFF_L3MDEV_SLAVE flags are only set and used by the VRF driver (CONFIG_NET_VRF). netif_is_l3_master() and netif_is_l3_slave() are called in multiple performance-critical fast paths (such as GRO, IP routing/FIB lookups, TCP/UDP processing, etc.). When CONFIG_NET_VRF is disabled, neither flag can ever be set on any net_device. Adding IS_ENABLED(CONFIG_NET_VRF) allows the compiler to optimize these checks away as false at compile time, eliminating unnecessary conditional branches in the fast path when VRF is not enabled. scripts/bloat-o-meter shows a nice code size reduction on a kernel built with CONFIG_NET_VRF=n (and CONFIG_NET_L3_MASTER_DEV=y): add/remove: 2/5 grow/shrink: 18/71 up/down: 1593/-5642 (-4049) Function old new delta ipip6_tunnel_lookup.constprop - 931 +931 tcp_v6_parse_md5_keys 1607 1742 +135 ipip6_err 617 738 +121 bpf_lwt_xmit_reroute 1492 1555 +63 ip6_pol_route 1810 1843 +33 rt6_multipath_rebalance.part 1448 1480 +32 bpf_msg_pull_data 1255 1287 +32 __unlikely_text_end 3092 3124 +32 ipv6_add_addr 2257 2287 +30 __ip4_datagram_connect 1131 1158 +27 ip6_rt_cache_alloc 476 500 +24 fib6_clean_tohost 308 328 +20 sit_exit_rtnl_net 461 477 +16 nf_nat_register_fn 581 597 +16 ip6_forward 4573 4589 +16 inet_rtm_getroute 2906 2922 +16 __pfx_ipip6_tunnel_lookup.constprop - 16 +16 __ip_do_redirect 2005 2021 +16 __bpf_skc_lookup 449 464 +15 addrconf_add_dev 134 136 +2 ip6_rcv_finish 203 201 -2 icmp6_dev 159 153 -6 ipip6_tunnel_bind_dev 419 409 -10 bpf_xdp_skc_lookup_tcp 122 107 -15 bpf_tc_skc_lookup_tcp 125 110 -15 rt6_nh_dump_exceptions 243 227 -16 ip_mc_source 1385 1369 -16 ip6_fragment 2450 2434 -16 input_action_end_x 278 262 -16 fib6_nh_age_exceptions.part 822 806 -16 __pfx_ipip6_tunnel_lookup 16 - -16 __pfx_ip6_rt_get_dev_rcu 16 - -16 __addrconf_sysctl_register 365 349 -16 bpf_xdp_sk_lookup_udp 155 138 -17 bpf_xdp_sk_lookup_tcp 155 138 -17 bpf_tc_sk_lookup_udp 158 141 -17 bpf_tc_sk_lookup_tcp 158 141 -17 addrconf_addr_gen 339 322 -17 ip6_rcv_core 2084 2066 -18 fib_nl2rule_locked 517 499 -18 l3mdev_master_upper_ifindex_by_index_rcu 61 42 -19 ipip6_rcv 1960 1941 -19 addrconf_notify 2563 2543 -20 l3mdev_fib_table_by_index 304 282 -22 nf_nat_inet_fn 777 754 -23 attach_rules 176 150 -26 ipv6_rcv 867 840 -27 ip_sublist_rcv 1342 1315 -27 ip6_sublist_rcv 1528 1501 -27 sit_tunnel_rcv 498 470 -28 ndisc_send_redirect 1474 1445 -29 ip_mr_input 1175 1143 -32 ip6_mr_input 627 595 -32 tcp_ao_add_cmd.cold 33 - -33 ip_error 1059 1023 -36 raw_sendmsg 5291 5253 -38 end_dt_vrf_core 466 426 -40 ip_rcv 886 844 -42 ip_send_unicast_reply 1487 1443 -44 udp_sendmsg 4135 4089 -46 delete_tempaddrs 259 211 -48 udp6_gro_receive 1142 1092 -50 udp4_lib_lookup_skb 259 208 -51 l3mdev_fib_rule_match 337 286 -51 ping_v4_sendmsg 2692 2640 -52 tcp6_check_fraglist_gro 341 288 -53 l3mdev_master_ifindex_rcu 69 16 -53 ip6_dst_lookup_tail.constprop 1533 1480 -53 udp4_gro_receive 1139 1085 -54 igmp_rcv 3215 3160 -55 ndisc_recv_ns 1699 1642 -57 fib_netdev_event 771 714 -57 l3mdev_link_scope_lookup 124 65 -59 udp6_lib_lookup_skb 173 113 -60 __ip_local_out 1182 1120 -62 ipv6_frag_rcv 3670 3601 -69 ip_route_output_key_hash_rcu 3024 2951 -73 __ip6_local_out 1164 1091 -73 tcp_v6_send_response 3056 2982 -74 rt6_fill_node 4103 4027 -76 rawv6_sendmsg 6225 6149 -76 l3mdev_fib_table_rcu 92 16 -76 tcp4_gro_receive 1375 1295 -80 ip6_xmit 2771 2690 -81 fib_select_path 2190 2105 -85 tcp_v4_parse_md5_keys 1160 1058 -102 ip_route_input_slow 4471 4354 -117 ip6_pkt_drop.isra 572 453 -119 l3mdev_update_flow 516 360 -156 ip6_rt_get_dev_rcu 182 - -182 __ipv6_chk_addr_and_flags 750 568 -182 ip_route_input_rcu.part 941 743 -198 nf_confirm 1222 960 -262 ipv6_dev_get_saddr 1321 918 -403 tcp_ao_add_cmd 2643 2211 -432 ipip6_tunnel_lookup 1004 - -1004 Total: Before=33195512, After=33191463, chg -0.01% Signed-off-by: Eric Dumazet Link: https://patch.msgid.link/20260831154129.4048178-1-edumazet@google.com Signed-off-by: Jakub Kicinski --- include/linux/netdevice.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 87cafc932e9e..8454646d6a45 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -5606,12 +5606,12 @@ static inline bool netif_has_l3_rx_handler(const struct net_device *dev) static inline bool netif_is_l3_master(const struct net_device *dev) { - return dev->priv_flags & IFF_L3MDEV_MASTER; + return IS_ENABLED(CONFIG_NET_VRF) && (dev->priv_flags & IFF_L3MDEV_MASTER); } static inline bool netif_is_l3_slave(const struct net_device *dev) { - return dev->priv_flags & IFF_L3MDEV_SLAVE; + return IS_ENABLED(CONFIG_NET_VRF) && (dev->priv_flags & IFF_L3MDEV_SLAVE); } static inline int dev_sdif(const struct net_device *dev) -- cgit v1.2.3 From 4b1d5d51528a2178aa9abeea4881e15f2344285d Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 31 Aug 2026 16:34:31 +0200 Subject: net: phy: add (*notify_phy_attach/detach)() hooks to struct mii_bus Some MDIO buses require programming PHY polling registers depending on the PHY type. RealTek switch SoCs are the most prominent example of a DSA switch which doesn't allow to program MAC speed, duplex and flow-control settings without using PHY polling to do so [1]. Avoid a half-baked solution in the MDIO bus driver because - it must reinvent the bus scanning to determine the PHYs and - it must anticipate the right point in time (e.g. deferred PHYs). Hence there is a need to inform the MDIO bus driver that a PHY is being attached or detached. Provide two hooks in struct mii_bus - notify_phy_attach(): called in phy_attach_direct() after PHY hardware has been initialized and just before PHY is resumed. - notify_phy_detach(): called in phy_detach() right after PHY has been suspended. Worth to notice: As of now phy_detach() is not 100% LIFO symmetric to phy_attach_direct(). E.g. sysfs links are torn down before suspend while being created before resume. Without reordering of the detach function the above mentioned notifier placement is the best possible symmetric implementation. An unconditional call of notify_phy_detach() was favoured [3]. Remark! A slightly different version of this patch was part of a former series [2]. The discussion already showed that an initialization hook should be placed somewhere late during the whole setup. This commit implants it right after phy_init_hw() as suggested. On top of this it adds the detach hook. [1] https://github.com/openwrt/openwrt/pull/21515#discussion_r2714069716 [2] https://lore.kernel.org/netdev/cover.1769053496.git.daniel@makrotopia.org/ [3] https://lore.kernel.org/netdev/9e40f50b-357a-4a93-9f59-94847850835d@lunn.ch/#t Signed-off-by: Daniel Golle Signed-off-by: Markus Stockhausen Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20260831143439.2404484-6-markus.stockhausen@gmx.de Signed-off-by: Jakub Kicinski --- include/linux/phy.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'include/linux') diff --git a/include/linux/phy.h b/include/linux/phy.h index 5f8d65868e0f..3d8afe6b7f1c 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -376,6 +376,24 @@ struct mii_bus { int regnum, u16 val); /** @reset: Perform a reset of the bus */ int (*reset)(struct mii_bus *bus); + /** + * @notify_phy_attach: Perform post-attach handling for MDIO bus + * drivers. Optional and independent of @notify_phy_detach. Called + * in phy_attach_direct() right before phy_resume(). Runs in process + * context, may sleep and may be called with RTNL held. Must not + * acquire or rely on RTNL. Returns 0 on success or negative errno + * on failure. Must unwind its own state on error as attachment is + * aborted. + */ + int (*notify_phy_attach)(struct phy_device *phydev); + /** + * @notify_phy_detach: Perform pre-detach handling for MDIO bus + * drivers. Optional and independent of @notify_phy_attach. Called + * in phy_detach() right after phy_suspend(). Runs in process context, + * may sleep and may be called with RTNL held. Must not acquire or + * rely on RTNL. + */ + void (*notify_phy_detach)(struct phy_device *phydev); /** @stats: Statistic counters per device on the bus */ struct mdio_bus_stats stats[PHY_MAX_ADDR]; -- cgit v1.2.3 From fa01779ff9916b7f3895954185af7c2e519c0435 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 31 Jul 2026 14:02:32 +0200 Subject: wifi: skip DUO params when looking for NPCA If DUO parameters are present, they need to be skipped. This was missed during the D1.3 -> D1.4 transition and causes frames to be mis-parsed for NPCA when DUO is also enabled. Link: https://patch.msgid.link/20260731140351.cb57484a68b1.I229dcd80b8e30c3fdfe8eedb81725dc35d9d9fe1@changeid Signed-off-by: Johannes Berg --- include/linux/ieee80211-uhr.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux') diff --git a/include/linux/ieee80211-uhr.h b/include/linux/ieee80211-uhr.h index 665d4b3a5b41..398ce01fcdee 100644 --- a/include/linux/ieee80211-uhr.h +++ b/include/linux/ieee80211-uhr.h @@ -341,6 +341,9 @@ ieee80211_uhr_npca_info(const struct ieee80211_uhr_operation *oper) if (!(oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_NPCA_ENA))) return NULL; + if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DUO_PRES)) + pos += 1; + if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DPS_PRES)) pos += sizeof(struct ieee80211_uhr_dps_info); @@ -372,6 +375,9 @@ ieee80211_uhr_oper_dbe_info(const struct ieee80211_uhr_operation *oper) if (!(oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DBE_ENA))) return NULL; + if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DUO_PRES)) + pos += 1; + if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DPS_PRES)) pos += sizeof(struct ieee80211_uhr_dps_info); -- cgit v1.2.3 From d25ba7909b2781c827f8b2928f201307c3ad6e44 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 31 Jul 2026 14:02:33 +0200 Subject: wifi: update UHR to Draft_P802.11bn D1.5 Update various definitions and in particular NPCA parsing to D1.5. Link: https://patch.msgid.link/20260731140351.0798bb37908d.I13592341f7f53f7566f9eeb74f0a0b85e73c1fef@changeid Signed-off-by: Johannes Berg --- include/linux/ieee80211-eht.h | 18 +++++++- include/linux/ieee80211-uhr.h | 95 ++++++++++++++++++++++++------------------- 2 files changed, 70 insertions(+), 43 deletions(-) (limited to 'include/linux') diff --git a/include/linux/ieee80211-eht.h b/include/linux/ieee80211-eht.h index b62297a978e7..a699d108eee6 100644 --- a/include/linux/ieee80211-eht.h +++ b/include/linux/ieee80211-eht.h @@ -482,6 +482,7 @@ struct ieee80211_multi_link_elem { #define IEEE80211_MLC_BASIC_PRES_MLD_ID 0x0200 #define IEEE80211_MLC_BASIC_PRES_EXT_MLD_CAPA_OP 0x0400 #define IEEE80211_MLC_BASIC_PRES_ENH_CRIT_UPD 0x0800 +#define IEEE80211_MLC_BASIC_PRES_AGE_OF_BSS_LOAD 0x1000 #define IEEE80211_MED_SYNC_DELAY_DURATION 0x00ff #define IEEE80211_MED_SYNC_DELAY_SYNC_OFDM_ED_THRESH 0x0f00 @@ -550,6 +551,8 @@ struct ieee80211_mle_basic_common_info { } __packed; #define IEEE80211_MLC_PREQ_PRES_MLD_ID 0x0010 +#define IEEE80211_MLC_PREQ_PRES_MLD_MAC_ADDR 0x0020 +#define IEEE80211_MLC_PREQ_PRES_NEIGH_AP_MLD_MAC_ADDR 0x0040 struct ieee80211_mle_preq_common_info { u8 len; @@ -560,6 +563,7 @@ struct ieee80211_mle_preq_common_info { #define IEEE80211_MLC_RECONF_PRES_EML_CAPA 0x0020 #define IEEE80211_MLC_RECONF_PRES_MLD_CAPA_OP 0x0040 #define IEEE80211_MLC_RECONF_PRES_EXT_MLD_CAPA_OP 0x0080 +#define IEEE80211_MLC_RECONF_PRES_TARGET_AP_MLD_ADDR 0x0100 /* no fixed fields in RECONF */ @@ -766,7 +770,7 @@ static inline u16 ieee80211_mle_get_mld_capa_op(const u8 *data) #define IEEE80211_EHT_ML_EXT_MLD_CAPA_NSTR_UPDATE 0x0020 #define IEEE80211_EHT_ML_EXT_MLD_CAPA_EMLSR_ENA_ON_ONE_LINK 0x0040 #define IEEE80211_EHT_ML_EXT_MLD_CAPA_BTM_MLD_RECO_MULTI_AP 0x0080 -/* defined by UHR Draft P802.11bn_D1.3 Figure 9-1147 */ +/* defined by UHR Draft P802.11bn_D1.5 Figure 9-1168 */ #define IEEE80211_UHR_ML_EXT_MLD_CAPA_ML_PM 0x0100 /** @@ -928,11 +932,17 @@ static inline bool ieee80211_mle_size_ok(const u8 *data, size_t len) common += 2; if (control & IEEE80211_MLC_BASIC_PRES_ENH_CRIT_UPD) common += 1; + if (control & IEEE80211_MLC_BASIC_PRES_AGE_OF_BSS_LOAD) + common += 1; break; case IEEE80211_ML_CONTROL_TYPE_PREQ: common += sizeof(struct ieee80211_mle_preq_common_info); if (control & IEEE80211_MLC_PREQ_PRES_MLD_ID) common += 1; + if (control & IEEE80211_MLC_PREQ_PRES_MLD_MAC_ADDR) + common += ETH_ALEN; + if (control & IEEE80211_MLC_PREQ_PRES_NEIGH_AP_MLD_MAC_ADDR) + common += ETH_ALEN; break; case IEEE80211_ML_CONTROL_TYPE_RECONF: common += 1; @@ -944,6 +954,8 @@ static inline bool ieee80211_mle_size_ok(const u8 *data, size_t len) common += 2; if (control & IEEE80211_MLC_RECONF_PRES_EXT_MLD_CAPA_OP) common += 2; + if (control & IEEE80211_MLC_RECONF_PRES_TARGET_AP_MLD_ADDR) + common += ETH_ALEN; break; case IEEE80211_ML_CONTROL_TYPE_TDLS: common += sizeof(struct ieee80211_mle_tdls_common_info); @@ -1003,6 +1015,7 @@ enum ieee80211_mle_subelems { #define IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT 0x0800 #define IEEE80211_MLE_STA_CONTROL_ENH_CRIT_UPD_PRESENT 0x1000 #define IEEE80211_MLE_STA_CONTROL_AP_CONDUCTED_TX_PWR_PRESENT 0x2000 +#define IEEE80211_MLE_STA_CONTROL_AGE_OF_BSS_LOAD_PRESENT 0x4000 struct ieee80211_mle_per_sta_profile { __le16 control; @@ -1054,6 +1067,9 @@ static inline bool ieee80211_mle_basic_sta_prof_size_ok(const u8 *data, if (control & IEEE80211_MLE_STA_CONTROL_AP_CONDUCTED_TX_PWR_PRESENT) info_len += 1; + if (control & IEEE80211_MLE_STA_CONTROL_AGE_OF_BSS_LOAD_PRESENT) + info_len += 1; + return prof->sta_info_len >= info_len && fixed + prof->sta_info_len - 1 <= len; } diff --git a/include/linux/ieee80211-uhr.h b/include/linux/ieee80211-uhr.h index 398ce01fcdee..19e9260d0db8 100644 --- a/include/linux/ieee80211-uhr.h +++ b/include/linux/ieee80211-uhr.h @@ -17,32 +17,32 @@ #define IEEE80211_UHR_OPER_PARAMS_PEDCA_ENA 0x0004 #define IEEE80211_UHR_OPER_PARAMS_DBE_ENA 0x0008 #define IEEE80211_UHR_OPER_PARAMS_DBE_BW 0x0070 -#define IEEE80211_UHR_OPER_PARAMS_DUO_PRES 0x0080 -#define IEEE80211_UHR_OPER_PARAMS_DPS_PRES 0x0100 -#define IEEE80211_UHR_OPER_PARAMS_NPCA_PRES 0x0200 -#define IEEE80211_UHR_OPER_PARAMS_PEDCA_PRES 0x0400 -#define IEEE80211_UHR_OPER_PARAMS_DBE_PRES 0x0800 +#define IEEE80211_UHR_OPER_PARAMS_ELR_RX 0x0080 +#define IEEE80211_UHR_OPER_PARAMS_DUO_PRES 0x0100 +#define IEEE80211_UHR_OPER_PARAMS_DPS_PRES 0x0200 +#define IEEE80211_UHR_OPER_PARAMS_NPCA_PRES 0x0400 +#define IEEE80211_UHR_OPER_PARAMS_PEDCA_PRES 0x0800 +#define IEEE80211_UHR_OPER_PARAMS_DBE_PRES 0x1000 struct ieee80211_uhr_operation { __le16 params; - u8 basic_mcs_nss_set[4]; u8 variable[]; } __packed; -#define IEEE80211_UHR_NPCA_PARAMS_PRIMARY_CHAN_OFFS 0x0000000F -#define IEEE80211_UHR_NPCA_PARAMS_MIN_DUR_THRESH 0x000000F0 -#define IEEE80211_UHR_NPCA_PARAMS_SWITCH_DELAY 0x00003F00 -#define IEEE80211_UHR_NPCA_PARAMS_SWITCH_BACK_DELAY 0x000FC000 -#define IEEE80211_UHR_NPCA_PARAMS_INIT_QSRC 0x00300000 -#define IEEE80211_UHR_NPCA_PARAMS_MOPLEN 0x00400000 -#define IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES 0x00800000 +#define IEEE80211_UHR_NPCA_PARAMS_PRIMARY_CHAN 0x000000FF +#define IEEE80211_UHR_NPCA_PARAMS_MIN_DUR_THRESH 0x00000F00 +#define IEEE80211_UHR_NPCA_PARAMS_SWITCH_DELAY 0x0003F000 +#define IEEE80211_UHR_NPCA_PARAMS_SWITCH_BACK_DELAY 0x00FC0000 +#define IEEE80211_UHR_NPCA_PARAMS_INIT_QSRC 0x03000000 +#define IEEE80211_UHR_NPCA_PARAMS_MOPLEN 0x04000000 +#define IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES 0x08000000 /** * struct ieee80211_uhr_npca_info - npca operation information * * This structure is the "NPCA Operation Parameters field format" of "UHR - * Operation Element" fields as described in P802.11bn_D1.3 - * subclause 9.4.2.353. See Figure 9-aa4. + * Operation Element" fields as described in P802.11bn_D1.5 + * subclause 9.4.2.355.2, see Figure 9-aa6. * * Refer to IEEE80211_UHR_NPCA* * @params: @@ -97,7 +97,7 @@ struct ieee80211_uhr_npca_info { * struct ieee80211_uhr_dps_info - DPS operation information * * This structure is the "DPS Operation Parameter field" of "UHR - * Operation Element" fields as described in P802.11bn_D1.3 + * Operation Element" fields as described in P802.11bn_D1.5 * subclause 9.4.1.87. See Figure 9-207u. * * Refer to IEEE80211_UHR_DPS* @@ -211,8 +211,8 @@ static inline int ieee80211_uhr_dbe_bw_mhz(enum ieee80211_uhr_dbe_oper_bw bw) * struct ieee80211_uhr_dbe_info - DBE operation information * * This structure is the "DBE Operation Parameters field" of - * "UHR Operation Element" fields as described in P802.11bn_D1.3 - * subclause 9.4.2.353. See Figure 9-aa6. + * "UHR Operation Element" fields as described in P802.11bn_D1.5 + * subclause 9.4.2.355.4, see Figure 9-aa9. * * Refer to IEEE80211_UHR_DBE_OPER* * @params: @@ -234,25 +234,23 @@ struct ieee80211_uhr_dbe_info { __le16 dis_subch_bmap[]; } __packed; -#define IEEE80211_UHR_P_EDCA_ECWMIN 0x0F -#define IEEE80211_UHR_P_EDCA_ECWMAX 0xF0 -#define IEEE80211_UHR_P_EDCA_AIFSN 0x000F -#define IEEE80211_UHR_P_EDCA_CW_DS 0x0030 -#define IEEE80211_UHR_P_EDCA_PSRC_THRESHOLD 0x01C0 -#define IEEE80211_UHR_P_EDCA_QSRC_THRESHOLD 0x0600 +#define IEEE80211_UHR_P_EDCA_ECWMIN 0x0007 +#define IEEE80211_UHR_P_EDCA_ECWMAX 0x0038 +#define IEEE80211_UHR_P_EDCA_AIFSN 0x01C0 +#define IEEE80211_UHR_P_EDCA_CW_DS 0x0600 +#define IEEE80211_UHR_P_EDCA_PSRC_THRESHOLD 0x3800 +#define IEEE80211_UHR_P_EDCA_QSRC_THRESHOLD 0xC000 /** * struct ieee80211_uhr_p_edca_info - P-EDCA operation information * * This structure is the "P-EDCA Operation Parameters field" of - * "UHR Operation Element" fields as described in P802.11bn_D1.3 - * subclause 9.4.2.353. See Figure 9-aa5. + * "UHR Operation Element" fields as described in P802.11bn_D1.5 + * subclause 9.4.2.355.3, see Figure 9-aa8. * * Refer to IEEE80211_UHR_P_EDCA* - * @p_edca_ec: P-EDCA ECWmin and ECWmax. - * These fields indicate the CWmin and CWmax values used by a - * P-EDCA STA during P-EDCA contention. - * @params: AIFSN, CW DS, PSRC threshold, and QSRC threshold. + * @params: ECWmin, ECWmax, AIFSN, CW DS, PSRC threshold, and QSRC threshold. + * - CWmin/CWmax values used by a P-EDCA STA during P-EDCA contention. * - The AIFSN field indicates the AIFSN value used by a P-EDCA STA * during P-EDCA contention. * - The CW DS field indicates the value used for randomization of the @@ -266,7 +264,6 @@ struct ieee80211_uhr_dbe_info { * value 0 is reserved. */ struct ieee80211_uhr_p_edca_info { - u8 p_edca_ec; __le16 params; } __packed; @@ -302,7 +299,7 @@ static inline bool ieee80211_uhr_oper_size_ok(const u8 *data, u8 len) } } - /* P-EDCA Operation Parameters (fixed 3 bytes) */ + /* P-EDCA Operation Parameters */ if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_PEDCA_PRES)) { needed += sizeof(struct ieee80211_uhr_p_edca_info); if (len < needed) @@ -421,28 +418,42 @@ ieee80211_uhr_oper_dbe_info(const struct ieee80211_uhr_operation *oper) #define IEEE80211_UHR_MAC_CAP2_UHR_OM_PU_TO_LOW 0xC0 #define IEEE80211_UHR_MAC_CAP3_UHR_OM_PU_TO_HIGH 0x03 -#define IEEE80211_UHR_MAC_CAP3_PARAM_UPD_ADV_NOTIF_INTV 0x1C -#define IEEE80211_UHR_MAC_CAP3_UPD_IND_TIM_INTV_LOW 0xE0 +#define IEEE80211_UHR_MAC_CAP3_PARAM_UPD_ADV_NOTIF_INTV 0x7C +#define IEEE80211_UHR_MAC_CAP3_UPD_IND_TIM_INTV_LOW 0x80 -#define IEEE80211_UHR_MAC_CAP4_UPD_IND_TIM_INTV_HIGH 0x03 -#define IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS 0x04 -#define IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE 0x08 -#define IEEE80211_UHR_MAC_CAP4_CO_BF_SUPP 0x10 +#define IEEE80211_UHR_MAC_CAP4_UPD_IND_TIM_INTV_HIGH 0x0F +#define IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS 0x10 +#define IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE 0x20 +#define IEEE80211_UHR_MAC_CAP4_CO_BF_SUPP 0x40 +#define IEEE80211_UHR_MAC_CAP4_CO_SR_SUPP 0x80 + +#define IEEE80211_UHR_MAC_CAP5_MAPC_ENH_MSRMT_SUPP 0x01 #define IEEE80211_UHR_MAC_CAP_DBE_MAX_BW 0x07 #define IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES 0x08 #define IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES 0x10 +/* struct ieee80211_uhr_cap_dbe::bwcap[].cap */ +#define IEEE80211_UHR_MAC_CAP_DBE_CAP_NUM_SND_DIMS 0x07 +#define IEEE80211_UHR_MAC_CAP_DBE_CAP_NON_OFDMA_UL_MUMIMO 0x08 +#define IEEE80211_UHR_MAC_CAP_DBE_CAP_MU_BEAMFORMER 0x10 +#define IEEE80211_UHR_MAC_CAP_DBE_CAP_BEAMFORMEE_SS 0xe0 + struct ieee80211_uhr_cap_dbe { u8 cap; + u8 max_switch_time_period; + u8 mode_change_intvl; /* present 0, 1 or 2 times depending on _PRES bits */ - struct ieee80211_eht_mcs_nss_supp_bw eht_mcs_map[]; + struct { + struct ieee80211_eht_mcs_nss_supp_bw eht_mcs_map; + u8 cap; + } __packed bwcap[]; } __packed; /** * enum ieee80211_uhr_dbe_max_supported_bw - DBE Maximum Supported Bandwidth * - * As per spec P802.11bn_D1.3 "Table 9-bb5—Encoding of the DBE Maximum + * As per spec P802.11bn_D1.5 Table 9-bb8 "Encoding of the DBE Maximum * Supported Bandwidth field". * * @IEEE80211_UHR_DBE_MAX_BW_40: Indicates 40 MHz DBE max supported bw @@ -526,10 +537,10 @@ static inline bool ieee80211_uhr_capa_size_ok(const u8 *data, u8 len, dbe = (const void *)cap->variable; if (dbe->cap & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES) - needed += sizeof(dbe->eht_mcs_map[0]); + needed += sizeof(dbe->bwcap[0]); if (dbe->cap & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES) - needed += sizeof(dbe->eht_mcs_map[0]); + needed += sizeof(dbe->bwcap[0]); } return len >= needed; -- cgit v1.2.3 From 9f8cb9cbcdc815d7f7b625705924e9c64e54cac4 Mon Sep 17 00:00:00 2001 From: Javen Xu Date: Mon, 31 Aug 2026 13:37:40 +0800 Subject: net: phy: phylink: add helper to modify pause For Realtek nics, when we enable jumbo, pause are not supported. So we must check the pause capabilities from ourself and lp. Reviewed-by: Andrew Lunn Signed-off-by: Javen Xu Link: https://patch.msgid.link/20260831053745.1197-3-javen_xu@realsil.com.cn Signed-off-by: Jakub Kicinski --- include/linux/phylink.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 1dda5c7ed5f1..3a88a69882a6 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -843,4 +843,6 @@ void phylink_replay_link_begin(struct phylink *pl); void phylink_replay_link_end(struct phylink *pl); +void phylink_update_mac_pause_capabilities(struct phylink *pl, unsigned long mac_pause); + #endif -- cgit v1.2.3 From 7f1de03e31033590279e4f8fc01ddf2c5dcfab51 Mon Sep 17 00:00:00 2001 From: Tristan Madani Date: Wed, 2 Sep 2026 12:30:40 +0000 Subject: net: reduce XMIT_RECURSION_LIMIT under KASAN Virtual network devices (ipvlan, macvlan, bonding) can enter legitimate transmit recursion when combined with packet forwarding configurations such as IPVS NAT. The existing XMIT_RECURSION_LIMIT (8) in __dev_queue_xmit() detects and breaks these loops, but the allowed depth is too high for KASAN-instrumented kernels: each recursion level consumes significantly more stack due to KASAN inline instrumentation, and the cumulative usage overflows the kernel stack before the limit fires. On x86_64, CONFIG_KASAN_GENERIC doubles THREAD_SIZE from 16KB to 32KB (KASAN_STACK_ORDER=1), but KASAN per-access checks inflate individual function frames by roughly 2-3x. For an ipvlan L3 + IPVS NAT routing loop, objdump measurements on a non-KASAN kernel show ~1.4KB of stack consumed per recursion level (across 17 functions from __dev_queue_xmit through the full IP output path and back). At KASAN ~2.3x inflation factor that becomes ~3.3KB per level. Eight levels -- the current limit -- consume ~26KB plus the initial call chain (~8KB), which exceeds the 32KB KASAN stack. The overflow hits the VMAP_STACK guard page and causes a non-recoverable kernel panic (BUG: stack guard page was hit). On non-KASAN kernels the same loop is safely caught by the existing limit: the "Dead loop on virtual device" message fires and the packet is dropped without any stack overflow. Reduce XMIT_RECURSION_LIMIT to 4 when CONFIG_KASAN is enabled. The deepest legitimate transmit recursion observed in the kernel selftests is 5 levels of __dev_queue_xmit nesting, in VXLAN symmetric routing topologies with VRF (vxlan_symmetric, vxlan_asymmetric): __dev_queue_xmit(vrf) depth 1 __dev_queue_xmit(vlan-svi) depth 2 __dev_queue_xmit(bridge) depth 3 __dev_queue_xmit(vxlan) depth 4 __dev_queue_xmit(veth) depth 5 Since the recursion check fires when the counter exceeds the limit (strictly greater than), a limit of 4 permits 5 levels of nesting while blocking the 6th. At ~3.3KB per level, five levels consume ~16.5KB; combined with the ~8KB initial call chain, total usage is ~24.5KB -- well within the 32KB KASAN stack with ~7.5KB of margin. A limit of 3 (v2/v3 of this patch) allows only 4 levels, which broke the VXLAN symmetric selftests: the 5th __dev_queue_xmit call was incorrectly dropped, as reported by Jakub Kicinski and the kernel test robot. The recursion path triggering this is: __dev_queue_xmit -> dev_hard_start_xmit -> ipvlan_start_xmit -> ipvlan_queue_xmit -> ipvlan_process_outbound -> ip_local_out -> nf_hook (IPVS) -> ip_vs_in_hook -> ip_vs_nat_xmit -> ip_output -> ip_finish_output2 -> neigh_resolve_output -> __dev_queue_xmit Tested: - KASAN kernel (6.8.12 x86_64): panic before fix, "Dead loop" drop after fix (at recursion level 4 instead of 8). - Non-KASAN kernel (6.8.12 x86_64): "Dead loop" drop both before and after fix (no behavior change for production kernels). - Measured max __dev_queue_xmit nesting depth via bpftrace in a VXLAN symmetric cross-VLAN topology (VRF + VLAN + bridge + VXLAN + veth underlay): 5 levels, confirming limit=4 is sufficient. Cc: stable+noautosel@kernel.org # KASAN is non-production Signed-off-by: Tristan Madani Link: https://patch.msgid.link/20260902123040.2172805-1-tristmd@gmail.com Signed-off-by: Jakub Kicinski --- include/linux/netdevice.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 8454646d6a45..3e184994df4b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3669,7 +3669,11 @@ struct page_pool_bh { }; DECLARE_PER_CPU(struct page_pool_bh, system_page_pool); +#ifdef CONFIG_KASAN +#define XMIT_RECURSION_LIMIT 4 +#else #define XMIT_RECURSION_LIMIT 8 +#endif #ifndef CONFIG_PREEMPT_RT static inline int dev_recursion_level(void) -- cgit v1.2.3 From 31c5ea8a3296e1486ac34bccea452bfe8c0bb1f9 Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Fri, 4 Sep 2026 03:35:29 +0000 Subject: ipv6: Remove IPV6_ADDRFORM. Recently, IPV6_ADDRFORM has received many AI-driven bug reports. Fixing them properly would needlessly churn the fast paths in TCP and UDP. IPV6_ADDRFORM was initially introduced in RFC 2133 in 1997, but only two years later, it was removed from RFC 2553 in 1999. In 2026, modern applications natively support dual-stack sockets; notably, systemd's socket activation does not use IPV6_ADDRFORM. Also, getsockopt(IPV6_ADDRFORM) can be replaced with SO_DOMAIN. Let's remove IPV6_ADDRFORM. Later, we can remove sk->sk_prot_creator and revert commit c26c192c3d48 ("udp: properly deal with xfrm encap and ADDRFORM"). Reported-by: Daehyeon Ko <4ncienth@gmail.com> Closes: https://lore.kernel.org/netdev/20260902010408.1057857-1-4ncienth@gmail.com/ Reported-by: Hyunwoo Kim Closes: https://lore.kernel.org/netdev/20260824033331.1084971-1-imv4bel@gmail.com/ Signed-off-by: Kuniyuki Iwashima Link: https://patch.msgid.link/20260904033543.2635540-3-kuniyu@google.com Signed-off-by: Jakub Kicinski --- include/linux/net.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/net.h b/include/linux/net.h index 3d82966e2243..470100ae7107 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -166,7 +166,7 @@ struct socket { struct file *file; struct sock *sk; - const struct proto_ops *ops; /* Might change with IPV6_ADDRFORM or MPTCP. */ + const struct proto_ops *ops; /* Might change with MPTCP. */ struct socket_wq wq; }; -- cgit v1.2.3 From 32ca12fbcf6bb001a7121112f113ac0380b4af0f Mon Sep 17 00:00:00 2001 From: Hemanth Selam Date: Fri, 4 Sep 2026 16:11:04 +0530 Subject: mdio-mux: fix typo "framwork" in comment Correct "framwork" to "framework", reported by scripts/checkpatch.pl using the misspelling list in scripts/spelling.txt. Only touches comments, no code changes. Signed-off-by: Hemanth Selam Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20260904104107.12832-2-hemanth.selam@gmail.com Signed-off-by: Jakub Kicinski --- include/linux/mdio-mux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/mdio-mux.h b/include/linux/mdio-mux.h index a5d58f221939..e2af9cb8e017 100644 --- a/include/linux/mdio-mux.h +++ b/include/linux/mdio-mux.h @@ -1,5 +1,5 @@ /* - * MDIO bus multiplexer framwork. + * MDIO bus multiplexer framework. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive -- cgit v1.2.3 From f6e96d72f64a83b31655ce504a1029b155c16966 Mon Sep 17 00:00:00 2001 From: Gustavo Luiz Duarte Date: Thu, 3 Sep 2026 17:26:00 +0100 Subject: netconsole: add an address family to struct inet_addr netconsole_target stores a single 'bool ipv6' to denote the target's address family. This makes it hard to detect conditions like "no address set" or ipv4/ipv6 mixup between local_ip and remote_ip. Add a 'family' field to inet_addr so each address stores its own address family: AF_UNSPEC while unset, else AF_INET or AF_INET6. Nothing reads the new field yet. The next patch switches the users over and removes the bool. No functional change. Reviewed-by: Breno Leitao Signed-off-by: Gustavo Luiz Duarte Link: https://patch.msgid.link/20260903-netcons_ipv6-v4-1-bdd183c844d3@gmail.com Signed-off-by: Jakub Kicinski --- include/linux/netpoll.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 1c6b1eec5efd..de97f001a0f9 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -16,9 +16,13 @@ #include #include -union inet_addr { - __be32 ip; - struct in6_addr in6; +struct inet_addr { + /* Address family: AF_UNSPEC when unset, else AF_INET or AF_INET6 */ + u8 family; + union { + __be32 ip; + struct in6_addr in6; + }; }; struct netpoll { -- cgit v1.2.3 From 7be9bfb7689e875fc94b711dcafe27c86413c966 Mon Sep 17 00:00:00 2001 From: Gustavo Luiz Duarte Date: Thu, 3 Sep 2026 17:26:05 +0100 Subject: netconsole: move struct inet_addr into netconsole.c The struct inet_addr lives in netpoll.h, but since commit a1116396476f ("netconsole: move local_ip/remote_ip/ipv6 to netconsole_target") the only user is netconsole. Move the definition into netconsole.c Suggested-by: Breno Leitao Reviewed-by: Breno Leitao Signed-off-by: Gustavo Luiz Duarte Link: https://patch.msgid.link/20260903-netcons_ipv6-v4-6-bdd183c844d3@gmail.com Signed-off-by: Jakub Kicinski --- include/linux/netpoll.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'include/linux') diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index de97f001a0f9..ec0821a5b02d 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -16,15 +16,6 @@ #include #include -struct inet_addr { - /* Address family: AF_UNSPEC when unset, else AF_INET or AF_INET6 */ - u8 family; - union { - __be32 ip; - struct in6_addr in6; - }; -}; - struct netpoll { struct net_device *dev; netdevice_tracker dev_tracker; -- cgit v1.2.3 From 3037c2f6a9de3af9775427059546e705237f6723 Mon Sep 17 00:00:00 2001 From: Tapio Reijonen Date: Fri, 4 Sep 2026 06:03:00 +0000 Subject: net: dsa: microchip: enable the SGMII port of the KSZ9897S The KSZ9897 has an SGMII/1000BASE-X capable port 7, but its chip_info entry never set .sgmii_port. ksz_has_sgmii_port() is therefore false, ksz9477_pcs_create() is never called and ksz9477_phylink_mac_select_pcs() returns NULL for port 7, so a phy-mode = "sgmii" or "1000base-x" link on that port cannot come up. Only the KSZ9897S has that port; the KSZ9897R has a second RGMII port instead. Both report chip ID 0x00989700, so the port cannot be enabled from the chip ID alone, and enabling it unconditionally breaks the KSZ9897R badly: ksz9477_setup() propagates the failure of xpcs_create_pcs_mdiodev() on a part without an XPCS, so the switch as a whole stops probing. The variants do differ in the read-only bit 7 of the port 7 XMII control 0 register, which reads one on the KSZ9897S and zero on the KSZ9897R. Compare the KSZ9897S data sheet DS00002394C section 5.2.4.1 with the KSZ9897R data sheet DS00002330D section 5.2.3.1. Read that bit in ksz_switch_register() and use it to select a KSZ9897S chip_data entry, which is the KSZ9897 one plus .sgmii_port = 7, with port 7 no longer marked as supporting MII, RMII and RGMII. On the KSZ9897S that port is permanently an SGMII port and only its differential pairs are brought out, so advertising the xMII modes on it would let phylink accept a mode the driver never programs: ksz_phylink_need_config() skips the XMII control registers for the SGMII port. The KSZ9477, which also has SGMII on port 7, is described the same way. See DS00002394C section 4.11. KSZ9897S_CHIP_ID selects that chip_data entry and nothing else. dev->chip_id keeps the KSZ9897 chip ID that both parts report, so no other chip ID comparison has to know about the variant, ksz_check_device_id() is unchanged, and a device tree naming the KSZ9897 keeps matching whichever part is fitted. No binding change is needed and existing device trees keep working. Tested on a KSZ9897S with a 1000BASE-LX fibre SFP on port 7: bit 7 of the port 7 XMII control 0 register reads one, the switch is identified as a KSZ9897S and the PCS is created. The port advertises 1000baseX/Full, clause 37 in-band autonegotiation completes against the link partner, and the link comes up at 1Gbps/full duplex and passes traffic. Suggested-by: Nicolai Buchwitz Suggested-by: Jerry Ray Suggested-by: Tristram Ha Signed-off-by: Tapio Reijonen Reviewed-by: Linus Walleij Link: https://patch.msgid.link/20260904-ksz9897-sgmii-port-v5-1-9bd4a0381aa8@vaisala.com Signed-off-by: Jakub Kicinski --- include/linux/platform_data/microchip-ksz.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/platform_data/microchip-ksz.h b/include/linux/platform_data/microchip-ksz.h index 028781ad4059..fe8df1774289 100644 --- a/include/linux/platform_data/microchip-ksz.h +++ b/include/linux/platform_data/microchip-ksz.h @@ -34,6 +34,7 @@ enum ksz_chip_id { KSZ9477_CHIP_ID = 0x00947700, KSZ9896_CHIP_ID = 0x00989600, KSZ9897_CHIP_ID = 0x00989700, + KSZ9897S_CHIP_ID = 0x00989701, KSZ9893_CHIP_ID = 0x00989300, KSZ9563_CHIP_ID = 0x00956300, KSZ8567_CHIP_ID = 0x00856700, -- cgit v1.2.3 From 5a81c72ef9ad6477e03d9d9b0abd794e9e4e639c Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Fri, 4 Sep 2026 11:00:58 -0700 Subject: net: run netdev work under the ops-compat lock netdev_work_proc() took rtnl_lock() for the whole batch, forcing even ops-locked drivers onto rtnl just to run their rx_mode / ndo_work callbacks. Take the per-device ops-compat lock instead: the instance lock for ops-locked drivers, rtnl_lock for the rest. That's what the callbacks already assert (e.g. netif_rx_mode_run() asserts netdev_assert_locked_ops_compat()), and non-ops-locked work such as vlan ndo_work keeps rtnl, since its compat lock resolves to rtnl anyway. Without this adding more uses of ndo_work, for cases which don't need rtnl_lock feels like a step back. We can drop the comment about the extra ref now, with the relocking it's a necessity. Signed-off-by: Jakub Kicinski Link: https://patch.msgid.link/20260904180058.3803849-1-kuba@kernel.org Signed-off-by: Paolo Abeni --- include/linux/netdevice.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 3e184994df4b..707b2e51c2b9 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1135,13 +1135,16 @@ struct netdev_net_notifier { * struct netdev_hw_addr_list *uc, * struct netdev_hw_addr_list *mc); * Async version of ndo_set_rx_mode which runs in process context - * with rtnl_lock and netdev_lock_ops(dev) held. The uc/mc parameters + * under the netdev instance lock for "ops locked" drivers, or + * rtnl_lock for all other drivers. The uc/mc parameters * are snapshots of the address lists - iterate with * netdev_hw_addr_list_for_each(ha, uc). Return 0 on success or a * negative errno to request a retry via the core backoff. * * void (*ndo_work)(struct net_device *dev, unsigned long events); * Run deferred work scheduled with netdev_work_sched(@events). + * Runs in process context under the netdev instance lock for "ops + * locked" drivers, or rtnl_lock for all other drivers. * * int (*ndo_set_mac_address)(struct net_device *dev, void *addr); * This function is called when the Media Access Control address -- cgit v1.2.3 From cc54f9667188904b3a20ebee1f1eac56b947b358 Mon Sep 17 00:00:00 2001 From: Jia Wang Date: Mon, 7 Sep 2026 15:46:50 +0800 Subject: net: stmmac: Add common internal RGMII delay handling Some DWMAC integrations add fixed RGMII clock delays internally. Glue drivers need to account for these delays before passing the interface mode to the PHY. Add TX and RX delay capability flags to the common platform data. Apply phy_fix_phy_mode_for_mac_delays() in stmmac_pltfr_probe() when either capability is present. This lets glue drivers describe the MAC capabilities without duplicating the interface-mode validation and conversion. Signed-off-by: Jia Wang Reviewed-by: Maxime Chevallier Link: https://patch.msgid.link/20260907-dwmac-ultrarisc-v2-1-9a39bf8db313@ultrarisc.com Signed-off-by: Paolo Abeni --- include/linux/stmmac.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 4430b967abde..00be2df63d22 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -242,6 +242,8 @@ struct plat_stmmacenet_data { * that phylink uses. */ phy_interface_t phy_interface; + bool has_internal_tx_delay; + bool has_internal_rx_delay; struct stmmac_mdio_bus_data *mdio_bus_data; struct device_node *phy_node; struct device_node *mdio_node; -- cgit v1.2.3 From f2109e90a5aaedb10b4ac7927ec074820a452d57 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Thu, 10 Sep 2026 13:10:20 -0400 Subject: net: rtnetlink: add pacing_offload attribute to net_device Add a new flag to administratively control pacing offload. The feature is disabled by default. That does not cause regressions, as no driver advertises max_pacing_offload_horizon yet. Also add NLA_REJECT for max_pacing_offload_horizon, in line with other such read-only members of link-attrs. Both fields can be read with ynl --family rt-link --do getlink \ --json '{"ifname": "eth0"}' | grep pacing And pacing offload enabled with ynl --family rt-link --do setlink \ --json '{"ifname": "eth0", "pacing-offload": 1}' Signed-off-by: Willem de Bruijn Link: https://patch.msgid.link/20260910171131.2532487-2-willemdebruijn.kernel@gmail.com Signed-off-by: Jakub Kicinski --- include/linux/netdevice.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 707b2e51c2b9..1f0710eef185 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1840,6 +1840,7 @@ enum netdev_reg_state { * drivers. Mainly used by logical interfaces, such as * bonding and tunnels * @netmem_tx: device netmem TX mode + * @pacing_offload: enable EDT pacing offload. * * @name: This is the first field of the "visible" part of this structure * (i.e. as seen by users in the "Space.c" file). It is the name @@ -2170,6 +2171,7 @@ struct net_device { unsigned long priv_flags:32; unsigned long lltx:1; unsigned long netmem_tx:2; + unsigned long pacing_offload:1; ); const struct net_device_ops *netdev_ops; const struct header_ops *header_ops; -- cgit v1.2.3 From 0093f7db9c47177fd5a269858002c89c6a3fa340 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Mon, 14 Sep 2026 05:20:07 -0700 Subject: net: add sockopt_expand_out() Some getsockopt options size their reply from a count the caller left in optval rather than from optlen, and so write past the optlen the caller declared. Userspace relies on that, so the sockopt_t conversion has to keep doing it. IP_MSFILTER is the first one to convert: its reply covers the imsf_numsrc sources the caller asked for, while optlen only has to cover the fixed header. Add sockopt_expand_out() to grow opt->iter_out mid-air, so the quirk sits in one place instead of each protocol assuming it implicitly. It is a no-op unless the reply outruns optlen. Growing re-anchors the iterator at the head of optval, so it has to be called before anything is written through iter_out. Only a user buffer can be longer than optlen says. A kernel-backed optval keeps the bounded iterator, and a callback that asks to grow one gets a WARN_ON_ONCE() and -EINVAL. Nothing in tree can trip that WARN: the only kernel-backed path into do_ip_getsockopt() is sol_ip_sockopt(), which takes IP_TOS and IP_TRANSPARENT only. It is an assert for the in-kernel callers BPF and io_uring gain once the conversion is done, so they declare an optlen covering the whole buffer instead of repeating the userspace mistake. The conversion in the next patch calls sockptr_to_sockopt() from net/ipv4/, so drop its static and declare it in net.h. Signed-off-by: Breno Leitao Acked-by: Stanislav Fomichev Link: https://patch.msgid.link/20260914-getsockopt_phase6-v2-1-e48befc9602e@debian.org Signed-off-by: Jakub Kicinski --- include/linux/net.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'include/linux') diff --git a/include/linux/net.h b/include/linux/net.h index 470100ae7107..e2a866fbcfa5 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -47,6 +47,9 @@ typedef struct sockopt { int optlen; } sockopt_t; +int sockptr_to_sockopt(sockopt_t *opt, sockptr_t optval, sockptr_t optlen, + struct kvec *kvec); + /* * Initialize a user-backed sockopt_t from the (optval, optlen) __user pair of * a getsockopt() callback. Used by transitional __user getsockopt wrappers @@ -70,6 +73,35 @@ static inline int sockopt_init_user(sockopt_t *opt, char __user *optval, return 0; } +/* + * Grow optval to @size, for the options whose reply is sized by a count the + * caller left in optval rather than by optlen. Those write past optlen today + * and userspace relies on it. + * + * Call it before writing through opt->iter_out: it re-anchors the iterator at + * the head of optval. Only a user buffer can be longer than the optlen the + * caller declared, so a kernel-backed optval is refused with -EINVAL. + */ +static inline int sockopt_expand_out(sockopt_t *opt, size_t size) +{ + if (size <= (size_t)opt->optlen) + return 0; + + if (size > INT_MAX) + return -EINVAL; + + /* Re-anchoring reads iter_out.ubuf, so the iterator has to be a user + * buffer that nothing has written through yet. + */ + if (WARN_ON_ONCE(!iter_is_ubuf(&opt->iter_out) || + iov_iter_count(&opt->iter_out) != (size_t)opt->optlen)) + return -EINVAL; + + iov_iter_ubuf(&opt->iter_out, ITER_DEST, opt->iter_out.ubuf, size); + + return 0; +} + struct poll_table_struct; struct pipe_inode_info; struct inode; -- cgit v1.2.3 From e12e04f5ab54cd6b4c1819b2a8e870245406022a Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Mon, 14 Sep 2026 05:20:08 -0700 Subject: ipv4: igmp: convert ip_mc_msfget() to sockopt_t IP_MSFILTER reads its reply through ip_mc_msfget(), reached from do_ip_getsockopt() and from nowhere else. Convert it, and build the sockopt_t at the call site for as long as the caller still carries a sockptr_t pair. optlen here only has to cover the header, and the real reply size comes from the imsf_numsrc field inside it. This is nasty, but userspace relies on it, so sockopt_expand_out() preserves the same mechanism: it grows optval only for a user address, and assumes the caller left room for the size its own header asked for. The *optlen store moves out of ip_mc_msfget() and into the call site, guarded by !err so the -EINVAL, -ENODEV and -EADDRNOTAVAIL returns still leave the caller's optlen word untouched. The source list also moves from copy_to_sockptr_offset() to a sequential copy_to_iter(). IP_MSFILTER_SIZE(0) and offsetof(struct ip_msfilter, imsf_slist_flex) are both 16, so the bytes land where they did. Signed-off-by: Breno Leitao Acked-by: Stanislav Fomichev Link: https://patch.msgid.link/20260914-getsockopt_phase6-v2-2-e48befc9602e@debian.org Signed-off-by: Jakub Kicinski --- include/linux/igmp.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/igmp.h b/include/linux/igmp.h index a0cf0398519f..e075611344ef 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -273,7 +274,7 @@ extern int ip_mc_source(int add, int omode, struct sock *sk, struct ip_mreq_source *mreqs, int ifindex); extern int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf,int ifindex); extern int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf, - sockptr_t optval, sockptr_t optlen); + sockopt_t *opt); extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf, sockptr_t optval, size_t offset); extern int ip_mc_sf_allow(const struct sock *sk, __be32 local, __be32 rmt, -- cgit v1.2.3 From f619d5003ff4e6e2c1ec456ab3aca5622587b5d7 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 16 Sep 2026 08:05:22 +0200 Subject: net: phy: factor out legacy PHY fixup support and make it always built-in PHY fixup registration is used from platform code in init phase only. Let's move the PHY fixup code from the modular part of phylib to the always built-in part of phylib. This allows to annotate the fixup registration as __init. No caller uses the return code of PHY fixup registration, therefore change related functions to return void. phy_needs_fixup() and phy_scan_fixups() wouldn't have to be moved to the built-in part of phylib. But doing so allows to fully factor out legacy fixup support into its own source code file, and make struct phy_fixup and phy_fixup_list strictly private to phy_fixup.c. phy_scan_fixups() is used after init phase only, then phy_fixup_list is read-only. So we don't need the mutex when accessing the list. Also when registering PHY fixups the mutex isn't needed, because fixup registration is done sequentially from platform init code. Actually there is only one platform with more than one fixup. In addition this change lays the foundation for enabling modular phylib on platforms where the fixup just sets a flag. Last but not least reflect the change in the documentation, and add a hint that fixup's are legacy functionality. Reviewed-by: Andrew Lunn Signed-off-by: Heiner Kallweit Link: https://patch.msgid.link/2d722b84-a263-400b-ac91-bf37125eb85b@gmail.com Signed-off-by: Jakub Kicinski --- include/linux/phy.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/phy.h b/include/linux/phy.h index 3d8afe6b7f1c..257634a543a1 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -2440,10 +2440,10 @@ int phy_get_mac_termination(struct phy_device *phydev, struct device *dev, void phy_resolve_pause(unsigned long *local_adv, unsigned long *partner_adv, bool *tx_pause, bool *rx_pause); -int phy_register_fixup_for_id(const char *bus_id, - int (*run)(struct phy_device *)); -int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask, - int (*run)(struct phy_device *)); +void __init phy_register_fixup_for_id(const char *bus_id, + int (*run)(struct phy_device *)); +void __init phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask, + int (*run)(struct phy_device *)); int phy_eee_tx_clock_stop_capable(struct phy_device *phydev); int phy_eee_rx_clock_stop(struct phy_device *phydev, bool clk_stop_enable); -- cgit v1.2.3 From d4f90143b9ffdac1fae765354b72366ad6c5ce65 Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Thu, 17 Sep 2026 08:30:51 +0200 Subject: net: phy: Fix device_set_wakeup_enable() reference in kernel-doc The phy_may_wakeup() documentation refers to device_set_wakeup_enabled(), but the function is named device_set_wakeup_enable(). Correct the reference. Signed-off-by: Karl Mehltretter Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Link: https://patch.msgid.link/20260917063051.52727-1-kmehltretter@gmail.com Signed-off-by: Jakub Kicinski --- include/linux/phy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/phy.h b/include/linux/phy.h index 257634a543a1..7c5098a0dd6c 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1715,7 +1715,7 @@ static inline bool phy_can_wakeup(struct phy_device *phydev) * phy_may_wakeup() - indicate whether PHY has wakeup enabled * @phydev: The phy_device struct * - * Returns: true/false depending on the PHY driver's device_set_wakeup_enabled() + * Returns: true/false depending on the PHY driver's device_set_wakeup_enable() * setting if using the driver model, otherwise the legacy determination. */ bool phy_may_wakeup(struct phy_device *phydev); -- cgit v1.2.3 From a926dc2352a9bac233baa2aaf7cd6031bbb74842 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 16 Sep 2026 12:21:00 +0200 Subject: net: dsa: microchip: Support Microchip KSZ8995XA / KS8995XA This adds support for the Microchip KSZ8995XA also known as the Micrel KS8995XA switch to the KSZ driver. The KSZ8995XA shares family ID 0x95 and chip-ID nibble 0x0 with the KS8995MA, so hardware detection cannot distinguish them. The legacy "micrel,ks8995" compatible is therefore treated as KSZ8995XA. No KS8995MA users are known, and KS8995E has no documented SPI management interface. Neither MA nor E has been verified with this driver. The helper macros are named ksz_is_ksz8995xa() to make it possible to add E and MA support in the future. Wait for the self-clearing per-port PHY reset bits before continuing with switch setup. Poll each port for up to 600 ms and allow an additional millisecond for the PHYs to settle. The KSZ8995XA has eight global TOS priority registers with one bit per DSCP code point, providing two internal priority levels. The registers are ordered in the opposite direction from the other KSZ8 switches. Describe the two priorities in the chip data, then augment the DCB helpers for this. Practical testing also shows that its packet-size control bits use the same semantics as the other KSZ8 switches. The polarity in the manual appears to be wrong and makes the switch hang on big packets. The legacy KS8995 driver also matches the Micrel compatibles for KSZ8864 and KSZ8795. Add these to the KSZ SPI driver here and use an exact tristate dependency to make the drivers mutually exclusive. This transfers ownership atomically, avoiding module probe races and gaps in driver coverage between patches. Reviewed-by: Nicolai Buchwitz Signed-off-by: Linus Walleij Link: https://patch.msgid.link/20260916-ks8995-to-ksz8-v15-3-8825ff5fd4be@kernel.org Signed-off-by: Jakub Kicinski --- include/linux/platform_data/microchip-ksz.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/platform_data/microchip-ksz.h b/include/linux/platform_data/microchip-ksz.h index fe8df1774289..411d5e164383 100644 --- a/include/linux/platform_data/microchip-ksz.h +++ b/include/linux/platform_data/microchip-ksz.h @@ -31,6 +31,7 @@ enum ksz_chip_id { KSZ88X3_CHIP_ID = 0x8830, KSZ8864_CHIP_ID = 0x8864, KSZ8895_CHIP_ID = 0x8895, + KSZ8995XA_CHIP_ID = 0x8995, KSZ9477_CHIP_ID = 0x00947700, KSZ9896_CHIP_ID = 0x00989600, KSZ9897_CHIP_ID = 0x00989700, -- cgit v1.2.3 From d98a52ae914e9fef700047f1eca486087abb13db Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 15 Sep 2026 23:14:04 +0200 Subject: net: remove ndo_do_ioctl handler All of the references to the callback pointer are gone, so remove the pointer itself before we grow new references to it. Signed-off-by: Arnd Bergmann Link: https://patch.msgid.link/20260915211538.1519815-2-arnd@kernel.org Signed-off-by: Jakub Kicinski --- include/linux/netdevice.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 1f0710eef185..5d16737167ee 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1154,11 +1154,6 @@ struct netdev_net_notifier { * int (*ndo_validate_addr)(struct net_device *dev); * Test if Media Access Control address is valid for the device. * - * int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); - * Old-style ioctl entry point. This is used internally by the - * ieee802154 subsystem but is no longer called by the device - * ioctl handler. - * * int (*ndo_siocbond)(struct net_device *dev, struct ifreq *ifr, int cmd); * Used by the bonding driver for its device specific ioctls: * SIOCBONDENSLAVE, SIOCBONDRELEASE, SIOCBONDSETHWADDR, SIOCBONDCHANGEACTIVE, @@ -1480,8 +1475,6 @@ struct net_device_ops { int (*ndo_set_mac_address)(struct net_device *dev, void *addr); int (*ndo_validate_addr)(struct net_device *dev); - int (*ndo_do_ioctl)(struct net_device *dev, - struct ifreq *ifr, int cmd); int (*ndo_eth_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); int (*ndo_siocbond)(struct net_device *dev, -- cgit v1.2.3 From 94fe252cd763c3e09399dea3fd28e555090599f5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Sep 2026 12:02:32 +0200 Subject: wifi: ieee80211: fix FTM bufferable check The FTM action frames don't have a protected dual, in fact their numbers are assigned otherwise. Remove the wrong check. Link: https://patch.msgid.link/20260916120232.d3c05305173e.I3855653e49311b0752b9fcdf9d5c6373408a14da@changeid Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 26e674038865..7fbc51f873ff 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -2421,8 +2421,7 @@ static inline bool ieee80211_is_bufferable_mmpdu(struct sk_buff *skb) /* action frame - additionally check for non-bufferable FTM */ - if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC && - mgmt->u.action.category != WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION) + if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) return true; if (mgmt->u.action.action_code == WLAN_PUB_ACTION_FTM_REQUEST || -- cgit v1.2.3 From 4c1b44ac2221bfecabf3b772c4c04c1a90048328 Mon Sep 17 00:00:00 2001 From: Vikas Gupta Date: Thu, 17 Sep 2026 12:15:38 +0530 Subject: bnge: update HSI Update HSI to support future patches implementing multi-RSS and NTUPLE-related features. Signed-off-by: Vikas Gupta Reviewed-by: Dharmender Garg Link: https://patch.msgid.link/20260917064548.773334-2-vikas.gupta@broadcom.com Signed-off-by: Jakub Kicinski --- include/linux/bnge/hsi.h | 136 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 135 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/bnge/hsi.h b/include/linux/bnge/hsi.h index 1f7bd96415a5..d4fe662d60b1 100644 --- a/include/linux/bnge/hsi.h +++ b/include/linux/bnge/hsi.h @@ -8607,6 +8607,7 @@ struct hwrm_cfa_l2_filter_alloc_input { #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_MIRROR_VNIC_ID 0x10000UL #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_NUM_VLANS 0x20000UL #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_T_NUM_VLANS 0x40000UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_RFS_RING_TBL_IDX 0x80000UL u8 l2_addr[6]; u8 num_vlans; u8 t_num_vlans; @@ -8663,7 +8664,8 @@ struct hwrm_cfa_l2_filter_alloc_input { #define CFA_L2_FILTER_ALLOC_REQ_PRI_HINT_MIN 0x4UL #define CFA_L2_FILTER_ALLOC_REQ_PRI_HINT_LAST CFA_L2_FILTER_ALLOC_REQ_PRI_HINT_MIN u8 unused_5; - __le32 unused_6; + __le16 rfs_ring_tbl_idx; + __le16 unused_6; __le64 l2_filter_id_hint; }; @@ -8900,6 +8902,95 @@ struct hwrm_cfa_tunnel_filter_free_output { u8 valid; }; +/* hwrm_cfa_ntuple_filter_alloc_input (size:1024b/128B) */ +struct hwrm_cfa_ntuple_filter_alloc_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_LOOPBACK 0x1UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_DROP 0x2UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_METER 0x4UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_DEST_FID 0x8UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_ARP_REPLY 0x10UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_DEST_RFS_RING_IDX 0x20UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_NO_L2_CONTEXT 0x40UL + __le32 enables; + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_L2_FILTER_ID 0x1UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_ETHERTYPE 0x2UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_TUNNEL_TYPE 0x4UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_MACADDR 0x8UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_IPADDR_TYPE 0x10UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_IPADDR 0x20UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_IPADDR_MASK 0x40UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_IPADDR 0x80UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_IPADDR_MASK 0x100UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_IP_PROTOCOL 0x200UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_PORT 0x400UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_PORT_MASK 0x800UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_PORT 0x1000UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_PORT_MASK 0x2000UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_PRI_HINT 0x4000UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_NTUPLE_FILTER_ID 0x8000UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_ID 0x10000UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_MIRROR_VNIC_ID 0x20000UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_MACADDR 0x40000UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_RFS_RING_TBL_IDX 0x80000UL + __le64 l2_filter_id; + u8 src_macaddr[6]; + __be16 ethertype; + u8 ip_addr_type; + #define CFA_NTUPLE_FILTER_ALLOC_REQ_IP_ADDR_TYPE_UNKNOWN 0x0UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_IP_ADDR_TYPE_IPV4 0x4UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_IP_ADDR_TYPE_IPV6 0x6UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_IP_ADDR_TYPE_LAST CFA_NTUPLE_FILTER_ALLOC_REQ_IP_ADDR_TYPE_IPV6 + u8 ip_protocol; + #define CFA_NTUPLE_FILTER_ALLOC_REQ_IP_PROTOCOL_UNKNOWN 0x0UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_IP_PROTOCOL_TCP 0x6UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_IP_PROTOCOL_UDP 0x11UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_IP_PROTOCOL_ICMP 0x1UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_IP_PROTOCOL_ICMPV6 0x3aUL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_IP_PROTOCOL_RSVD 0xffUL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_IP_PROTOCOL_LAST CFA_NTUPLE_FILTER_ALLOC_REQ_IP_PROTOCOL_RSVD + __le16 dst_id; + __le16 rfs_ring_tbl_idx; + u8 tunnel_type; + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_NONTUNNEL 0x0UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN 0x1UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_NVGRE 0x2UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_L2GRE 0x3UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPIP 0x4UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_GENEVE 0x5UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_MPLS 0x6UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_STT 0x7UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPGRE 0x8UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN_V4 0x9UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPGRE_V1 0xaUL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_L2_ETYPE 0xbUL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN_GPE_V6 0xcUL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN_GPE 0x10UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_ANYTUNNEL 0xffUL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_LAST CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_ANYTUNNEL + u8 pri_hint; + #define CFA_NTUPLE_FILTER_ALLOC_REQ_PRI_HINT_NO_PREFER 0x0UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_PRI_HINT_ABOVE 0x1UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_PRI_HINT_BELOW 0x2UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_PRI_HINT_HIGHEST 0x3UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_PRI_HINT_LOWEST 0x4UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_PRI_HINT_LAST CFA_NTUPLE_FILTER_ALLOC_REQ_PRI_HINT_LOWEST + __be32 src_ipaddr[4]; + __be32 src_ipaddr_mask[4]; + __be32 dst_ipaddr[4]; + __be32 dst_ipaddr_mask[4]; + __be16 src_port; + __be16 src_port_mask; + __be16 dst_port; + __be16 dst_port_mask; + __le64 ntuple_filter_id_hint; +}; + /* hwrm_cfa_ntuple_filter_alloc_output (size:192b/24B) */ struct hwrm_cfa_ntuple_filter_alloc_output { __le16 error_code; @@ -9014,6 +9105,49 @@ struct hwrm_cfa_ntuple_filter_cfg_output { u8 valid; }; +/* hwrm_cfa_adv_flow_mgnt_qcaps_input (size:256b/32B) */ +struct hwrm_cfa_adv_flow_mgnt_qcaps_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 unused_0[4]; +}; + +/* hwrm_cfa_adv_flow_mgnt_qcaps_output (size:128b/16B) */ +struct hwrm_cfa_adv_flow_mgnt_qcaps_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 flags; + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_FLOW_HND_16BIT_SUPPORTED 0x1UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_FLOW_HND_64BIT_SUPPORTED 0x2UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_FLOW_BATCH_DELETE_SUPPORTED 0x4UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_FLOW_RESET_ALL_SUPPORTED 0x8UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_NTUPLE_FLOW_DEST_FUNC_SUPPORTED 0x10UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_TX_EEM_FLOW_SUPPORTED 0x20UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_RX_EEM_FLOW_SUPPORTED 0x40UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_FLOW_COUNTER_ALLOC_SUPPORTED 0x80UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_RFS_RING_TBL_IDX_SUPPORTED 0x100UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_UNTAGGED_VLAN_SUPPORTED 0x200UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_XDP_SUPPORTED 0x400UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_L2_HEADER_SOURCE_FIELDS_SUPPORTED 0x800UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_NTUPLE_FLOW_RX_ARP_SUPPORTED 0x1000UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_RFS_RING_TBL_IDX_V2_SUPPORTED 0x2000UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_NTUPLE_FLOW_RX_ETHERTYPE_IP_SUPPORTED 0x4000UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_TRUFLOW_CAPABLE 0x8000UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_L2_FILTER_TRAFFIC_TYPE_L2_ROCE_SUPPORTED 0x10000UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_LAG_SUPPORTED 0x20000UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_NTUPLE_FLOW_NO_L2CTX_SUPPORTED 0x40000UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_NIC_FLOW_STATS_SUPPORTED 0x80000UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_NTUPLE_FLOW_RX_EXT_IP_PROTO_SUPPORTED 0x100000UL + #define CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_RFS_RING_TBL_IDX_V3_SUPPORTED 0x200000UL + u8 unused_0[3]; + u8 valid; +}; + /* hwrm_tunnel_dst_port_alloc_input (size:192b/24B) */ struct hwrm_tunnel_dst_port_alloc_input { __le16 req_type; -- cgit v1.2.3 From 898d431abd2578281bd3bb7db0970bc2de7a24c5 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 22 Sep 2026 16:34:56 +0000 Subject: net: ethtool: generate RSS keys that spread flows over all queues netdev_rss_key_fill() returns a key made of uniformly random bytes. That is not enough, because the Toeplitz hash is linear over GF(2). Walking the hash input MSB first, each set bit contributes a 32-bit sliding window of the key, and hardware indexes the indirection table with the low order bits of the result. Only the tail of each window therefore reaches the queue index: v(i) = key bits [i + 32 - q .. i + 31] with q = log2(number of RX queues). Consecutive input bits give windows overlapping in q - 1 positions, so the q vectors belonging to the q lowest bits of a header field form a Toeplitz matrix built from 2 * q - 1 key bits, rather than q * q independent ones. Over GF(2) a random Toeplitz matrix is singular with probability exactly 1/2, whatever its size. When it is singular, flows differing only in the low order bits of that field cannot reach all the queues. This is not theoretical: a burst of connections draws ephemeral ports from a narrow range, and on one affected host only 4 of the 16 RX queues received any traffic at all, until its key was replaced. Keep drawing the key at random, since it is a secret that stops a remote attacker from steering flows onto a single queue, but force the handful of bits that decide this. Writing d[t] for key bit (lsb + 31 - t), where lsb is the position of the least significant bit of a field in the hash input, the matrices of all the q values up to 8 are non singular if and only if d[2 * i] = 1 ^ d[i] ^ d[i + 1] ^ ... ^ d[2 * i - 1] The odd positions stay free, so this is a one pass fixup rather than a search. It is in fact a bijection from those free positions onto the set of the values having the property, so the key stays uniformly distributed over that set and the whole cost is 8 bits of entropy per position. Searching for such a key by rejection would not have been an option: a freshly drawn one has the property everywhere with probability 2^-1008. Apply this at every 16-bit aligned position of the key, rather than at the offsets of the 2-tuple and 4-tuple layouts only. The core does not get to know what a given NIC hashes. Hardware may select the bytes it feeds to Toeplitz out of a header window with a bitmap, and hash an encapsulated header: for PSP over UDP over IPv6 it can pick the outer addresses and the inner TCP ports, which sit 78 bytes into the frame and read key bits well past the 40 bytes an IPv6 4-tuple needs. Hashed fields are 16 bits wide at the smallest and are not expected to straddle that grid, so covering the grid covers the layouts that were never written down, at no cost in code. This spends 8 bits of entropy per position, 1008 bits out of the 2048 bits of netdev_rss_key, leaving 1040 bits. 8 is also the largest usable bound, as each q constrains 2 * q - 1 bits and anything larger would make the ranges of two adjacent positions overlap. What the fixup leaves behind is visible structure: 8 of every 16 bits are derived from the 8 others, so a 16-bit aligned word of the key takes only 2^8 values and about 27 of the 128 words of netdev_rss_key duplicate another one. That much is forced rather than an artefact of this implementation, 1040 bits spread over 128 words being a little over 8 bits each, but it has one consequence worth removing. Two 32-bit windows a whole number of words apart now collide with probability 2^-16 instead of 2^-32, and two input bits reading the same window are indistinguishable to the hash, since flipping both of them leaves it unchanged. Over 500 keys, 23% of them had such a pair, where a uniformly random key has one with probability 2^-11. So draw another key when that happens. Four out of five pass. Which distances to look at follows from where the structure is: covering the multiples of 16 leaves 1.2e-3 expected colliding pairs per key, still 2.6 times the 4.6e-4 of a plain random key, and almost all of that excess sits at a distance of 8 modulo 16. Covering every multiple of 8 brings the total down to 4.2e-4, below what a plain random key gives over all distances, and within a few percent of the 4.0e-4 it gives over the distances that are left. Two windows a multiple of 8 bits apart are two windows at the same offset modulo 8, so this is a handful of pairwise sweeps rather than one pass over the key per distance. DO_ONCE() runs the generator under a spinlock with hard IRQs disabled, so keep the windows of a class in an array rather than recomputing both sides of every pair: 116 us instead of 254 us for the worst case, a 2048-bit key with no collision anywhere, at a cost of 512 bytes of stack. The shared key is fixed up once and every driver prefix inherits both properties. Move netdev_rss_key and netdev_rss_key_fill() from net/ethtool/ioctl.c to net/ethtool/common.c, and move the netdev_rss_key declaration out of include/linux/netdevice.h into net/core/dev.h. Checked against an independent Toeplitz implementation: for every 16-bit aligned position and every q in 1..8, an aligned block of 2^q consecutive values of a field ending there lands on the 2^q queues exactly once each. Over 20 random keys that is 20160 checks, which 50.1% of plain random keys fail and none of the generated keys do, for an average of 502 rewritten bits out of 2048. Signed-off-by: Eric Dumazet Link: https://patch.msgid.link/20260922163458.3900996-3-edumazet@google.com Signed-off-by: Jakub Kicinski --- include/linux/netdevice.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 5d16737167ee..d037faff7c44 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -5323,7 +5323,6 @@ void netdev_lower_state_changed(struct net_device *lower_dev, void *lower_state_info); #define NETDEV_RSS_KEY_LEN 256 -extern u8 netdev_rss_key[NETDEV_RSS_KEY_LEN] __read_mostly; void netdev_rss_key_fill(void *buffer, size_t len); int skb_checksum_help(struct sk_buff *skb); -- cgit v1.2.3 From fc14cfab631994c872e2ebb65de8c50c49bda38e Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Mon, 21 Sep 2026 14:40:54 +0200 Subject: wifi: mac80211: add helpers to parse/generate CIP Capabilities The Control Integrity Protocol (CIP) Capabilities need to be added to and parsed from the association request and response. Signed-off-by: Benjamin Berg Link: https://patch.msgid.link/20260921144048.a3249c0b78ad.Ia3ea929dd6381cf8b04e3dd0c38e709e335113c2@changeid Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'include/linux') diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 7fbc51f873ff..73ac5336a17a 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1828,6 +1828,7 @@ enum ieee80211_eid_ext { WLAN_EID_EXT_BANDWIDTH_INDICATION = 135, WLAN_EID_EXT_KNOWN_STA_IDENTIFCATION = 136, WLAN_EID_EXT_NON_AP_STA_REG_CON = 137, + WLAN_EID_EXT_CIP_CAPA = 150, WLAN_EID_EXT_UHR_OPER = 151, WLAN_EID_EXT_UHR_CAPA = 152, WLAN_EID_EXT_MACP = 153, @@ -2899,4 +2900,25 @@ static inline bool ieee80211_check_tim(const struct ieee80211_tim_ie *tim, __ieee80211_check_tim(tim, tim_len, aid); } +/** + * enum ieee80211_cip_cap_fields - CIP Capabilities element fields + * @IEEE80211_CIP_CAP_MIC_PADDING: The MIC padding subfield in the CIP + * capabilities + * @IEEE80211_CIP_CAP_PROTECTED_CTRL_FRAME_ONLY: The MIC Padding For Protected + * Control Frames Only bit in CIP capabilities + */ +enum ieee80211_cip_cap_fields { + IEEE80211_CIP_CAP_MIC_PADDING = 0x0F, + IEEE80211_CIP_CAP_PROTECTED_CTRL_FRAME_ONLY = 0x10, +}; + +/** + * struct ieee80211_cip_cap - CIP Capabilities element + * + * @v: The value of the Control Integrity Protocol Capability element + */ +struct ieee80211_cip_cap { + u8 v; +} __packed; + #endif /* LINUX_IEEE80211_H */ -- cgit v1.2.3 From d451adde0203fa62519eb224be87046b27c76b99 Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Wed, 23 Sep 2026 13:38:26 +0300 Subject: net/mlx5: E-switch, derive manager vport from device capability mlx5_eswitch_manager_vport() hardcoded the e-switch manager vport as either the ECPF or the host PF. Read esw_manager_vport_number from the e-switch capability when esw_manager_vport_number_valid is set, so the manager vport can be a VF - a prerequisite for VFs acting as e-switch managers. Keep the previous mapping as fallback when the capability does not report a number. Signed-off-by: Shay Drory Reviewed-by: Moshe Shemesh Reviewed-by: Akiva Goldberger Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20260923103830.1183-10-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- include/linux/mlx5/eswitch.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/linux') diff --git a/include/linux/mlx5/eswitch.h b/include/linux/mlx5/eswitch.h index a0dd162baa78..03d3620141c8 100644 --- a/include/linux/mlx5/eswitch.h +++ b/include/linux/mlx5/eswitch.h @@ -222,6 +222,9 @@ static inline bool is_mdev_switchdev_mode(struct mlx5_core_dev *dev) /* The returned number is valid only when the dev is eswitch manager. */ static inline u16 mlx5_eswitch_manager_vport(struct mlx5_core_dev *dev) { + if (MLX5_CAP_ESW(dev, esw_manager_vport_number_valid)) + return MLX5_CAP_ESW(dev, esw_manager_vport_number); + return mlx5_core_is_ecpf_esw_manager(dev) ? MLX5_VPORT_ECPF : MLX5_VPORT_HOST_PF; } -- cgit v1.2.3 From f817c1894dc12af86d11110df4ab3d70271b627c Mon Sep 17 00:00:00 2001 From: Jeff Chen Date: Tue, 8 Sep 2026 17:37:55 +0800 Subject: mmc: sdio: add NXP IW610 device ID Add SDIO device ID (0x0215) for NXP IW610 to sdio_ids.h. It is used by the nxpwifi driver to probe the IW610 chip over SDIO. Signed-off-by: Jeff Chen Acked-by: Ulf Hansson --- include/linux/mmc/sdio_ids.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index afae93f6f245..5eff5e348eb0 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h @@ -123,6 +123,7 @@ #define SDIO_VENDOR_ID_NXP 0x0471 #define SDIO_DEVICE_ID_NXP_IW61X_BASE 0x0204 #define SDIO_DEVICE_ID_NXP_IW61X 0x0205 +#define SDIO_DEVICE_ID_NXP_IW610 0x0215 #define SDIO_VENDOR_ID_REALTEK 0x024c #define SDIO_DEVICE_ID_REALTEK_RTW8723BS 0xb723 -- cgit v1.2.3 From e477a2aa1ad5a8a911d4b5488adf5943be369216 Mon Sep 17 00:00:00 2001 From: Jeff Chen Date: Tue, 8 Sep 2026 17:37:56 +0800 Subject: mmc: core: add NXP IW610 base ID and block size quirk The NXP IW610 SDIO chipset identifies itself with a base card ID (0x0214) during the initial MMC bus scan, whereas the WLAN function reports a different ID (0x0215). Like the IW61x, the IW610 requires MMC_QUIRK_BLKSZ_FOR_BYTE_MODE for correct byte-mode block size handling. Since SDIO fixups are applied before function devices are enumerated, the quirk must be associated with the base card ID rather than the WLAN function ID. Add the SDIO_DEVICE_ID_NXP_IW610_BASE definition and apply the required fixup in the SDIO quirk table. Signed-off-by: Jeff Chen Acked-by: Ulf Hansson --- include/linux/mmc/sdio_ids.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index 5eff5e348eb0..dfffda3d8002 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h @@ -123,6 +123,7 @@ #define SDIO_VENDOR_ID_NXP 0x0471 #define SDIO_DEVICE_ID_NXP_IW61X_BASE 0x0204 #define SDIO_DEVICE_ID_NXP_IW61X 0x0205 +#define SDIO_DEVICE_ID_NXP_IW610_BASE 0x0214 #define SDIO_DEVICE_ID_NXP_IW610 0x0215 #define SDIO_VENDOR_ID_REALTEK 0x024c -- cgit v1.2.3 From 5c729e6c71f1be48b5afb99326a6b687e3600c67 Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Fri, 25 Sep 2026 13:15:22 -0700 Subject: net: devmem: decode DMA addresses for TX On 32-bit architectures where dma_addr_t is wider than unsigned long, page_pool_set_dma_addr_netmem() stores page-aligned DMA addresses shifted by PAGE_SHIFT. The net_iov branch of __skb_frag_dma_map() adds byte offsets to the encoded value, so the NIC is programmed with an invalid DMA address. This can trigger an IOMMU fault or DMA from unintended memory. Consolidate DMA address encoding, decoding, and representability checks in netmem helpers. Use the common decoder from the page pool and net_iov TX paths so both interpret stored addresses consistently. Reviewed-by: Mina Almasry Signed-off-by: Stanislav Fomichev Link: https://patch.msgid.link/20260925201522.254717-4-sdf@fomichev.me Signed-off-by: Paolo Abeni --- include/linux/skbuff.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 84308498a3a8..38b7d7389452 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -3816,9 +3816,12 @@ static inline dma_addr_t __skb_frag_dma_map(struct device *dev, size_t offset, size_t size, enum dma_data_direction dir) { + dma_addr_t addr; + if (skb_frag_is_net_iov(frag)) { - return netmem_to_net_iov(frag->netmem)->desc.dma_addr + - offset + frag->offset; + addr = netmem_dma_addr_decode( + netmem_get_dma_addr(frag->netmem)); + return addr + offset + frag->offset; } return dma_map_page(dev, skb_frag_page(frag), skb_frag_off(frag) + offset, size, dir); -- cgit v1.2.3 From f092b749e11c18b34b8e793bd3a134357257fa1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= Date: Fri, 25 Sep 2026 12:44:10 +0200 Subject: net: Revalidate queue config for ringparam changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Memory-provider queue configuration is validated when the provider is bound. A later ethtool ring change may invalidate it because drivers can size queue memory from both ring depth and RX page size. The fbnic consumer is added in the following patch. Keep configured RX ring depths in netdev_config and stage proposed values in cfg_pending. Validate every RX queue before calling the driver. Each check validates the device defaults, then any queue memory-provider override. Commit the values only after the driver accepts them. Drivers which consume stored ring depths through queue configuration must initialize every RX depth before registering the netdev. Stored values override callback defaults, including when zero. The callback receives a rendered configuration rather than a queue ID. Validation should depend on the configuration, not queue identity. Checking defaults also covers the case where every queue has a memory-provider override. Drivers may normalize ring depths when applying them. Require the validation callback to use the same normalization. Drivers must report the applied depths through the ethtool_ringparam argument so the core records the result. Use the same transaction for ioctl and netlink. Drivers without ndo_validate_qcfg skip the new validation. Link: https://lore.kernel.org/all/20250421222827.283737-14-kuba@kernel.org/ Signed-off-by: Björn Töpel Reviewed-by: Simon Horman Reviewed-by: Joe Damato Link: https://patch.msgid.link/20260925104417.2325213-4-bjorn@kernel.org Signed-off-by: Jakub Kicinski --- include/linux/ethtool.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index c4c9ce038611..c3a41fbd5426 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -1025,7 +1025,9 @@ struct kernel_ethtool_ts_info { * types should be set in @supported_coalesce_params. * Returns a negative error code or zero. * @get_ringparam: Report ring sizes - * @set_ringparam: Set ring sizes. Returns a negative error code or zero. + * @set_ringparam: Set ring sizes. The &struct ethtool_ringparam argument is + * also an output; drivers which normalize requested sizes must update it + * with the applied sizes. Returns a negative error code or zero. * @get_pause_stats: Report pause frame statistics. Drivers must not zero * statistics which they don't report. The stats structure is initialized * to ETHTOOL_STAT_NOT_SET indicating driver does not report statistics. -- cgit v1.2.3 From a0227fa24e8a2a0397cc4eb669731ff8d9161bbd Mon Sep 17 00:00:00 2001 From: Alexandra Winter Date: Mon, 28 Sep 2026 17:14:20 +0200 Subject: s390/ism: Zerorize dmb at allocation Sashiko reported [1] that 'Missing __GFP_ZERO in folio_alloc() causes uninitialized kernel memory to be exposed in the receive message buffer'. An ism dmb is receive-only, so the data is not leaked to a remote peer. In general the smc kernel module (dibs client) will only push newly received data to userspace. We still should not have uninitialized data in a receive buffer. Since commit 750afb08ca71 ("cross-tree: phase out dma_zalloc_coherent()") dma_alloc_coherent no longer required the __GFP_ZERO flag, but when commit 83781384a96b ("s390/ism: Properly fix receive message buffer allocation") switched to folio_alloc(), it should have added back the __GFP_ZERO flag. Add __GFP_ZERO flag and state in dibs.h that register_dbm() provides a zerorized buffer (dibs_lo already does). Link: https://lore.kernel.org/linux-s390/20260903143746.A5CC41F00A3A@smtp.kernel.org/ [1] Fixes: 83781384a96b ("s390/ism: Properly fix receive message buffer allocation") Signed-off-by: Alexandra Winter Reviewed-by: Julian Ruess Link: https://patch.msgid.link/20260928151420.383105-1-wintera@linux.ibm.com Signed-off-by: Jakub Kicinski --- include/linux/dibs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dibs.h b/include/linux/dibs.h index d3e0777f25ae..0c10c224bcca 100644 --- a/include/linux/dibs.h +++ b/include/linux/dibs.h @@ -261,12 +261,12 @@ struct dibs_dev_ops { * @vlan_id: deprecated, ignored if device does not support vlan * Upon return in addition the following fields will be valid: * @dmb_tok: for usage by remote and local devices and clients - * @cpu_addr: allocated buffer + * @cpu_addr: allocated, zerorized buffer * @idx: dmb index, unique per dibs device * @dma_addr: to be used by device driver,if applicable * - * Allocate a dmb buffer and register it with this device and for this - * client. + * Allocate and zerorize a dmb buffer and register it with this device + * and for this client. * Return: zero on success */ int (*register_dmb)(struct dibs_dev *dev, struct dibs_dmb *dmb, -- cgit v1.2.3 From 003f21868b2b0b4d09eb6b1f4abe0a8fbc03e859 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 28 Sep 2026 12:07:58 -0700 Subject: llc: move the type 2 sockets out of tree 802.2 LLC is only used in tree by protocols which need the connectionless type 1 subset: STP, which carries the bridge's BPDUs, GARP, which sends its own UI PDUs, and SNAP. The llc2 module on top of the core - the type 2 connection state machine, the type 1 SAP state machine, the station component and the PF_LLC socket family - has no in-kernel users and nobody who can test it; what we get instead is a slow trickle of drive-by fixes. There was a recent patch from Ernestas Kulik indicating potential real life use, but it was new/experimental and that person is not responding to off-list pings. Let LLC2 follow AX.25, hamradio and AppleTalk out of the Linux tree. We will maintain the code at: github.com/linux-netdev/mod-orphan for anyone interested in playing with it. PF_LLC goes in full, both the class two SOCK_STREAM and the class one SOCK_DGRAM half, and so do /proc/net/llc/ and /proc/sys/net/llc/. Note that the kernel also stops answering XID and TEST commands, addressed to a SAP or to the station - those are type 1, but they lived in the module, and they got answered whether or not any socket was open. Nothing in tree asks for them; what the core keeps is SAP registration and the UI path the in-tree users need. Retain the uAPI for now, like we did for AppleTalk. Only the socket ABI half of it is vestigial: STP, GARP, the bridge and openvswitch use the SAP numbers it defines. Cleaning up what the core no longer needs follows in the next patch. Signed-off-by: Jakub Kicinski Link: https://patch.msgid.link/20260928190800.2521749-2-kuba@kernel.org Reviewed-by: Nikolay Aleksandrov Signed-off-by: Paolo Abeni --- include/linux/llc.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/llc.h b/include/linux/llc.h index 944e9e213112..c03bb12bcc9c 100644 --- a/include/linux/llc.h +++ b/include/linux/llc.h @@ -9,9 +9,4 @@ #include -#define LLC_SAP_DYN_START 0xC0 -#define LLC_SAP_DYN_STOP 0xDE -#define LLC_SAP_DYN_TRIES 4 - -#define llc_ui_skb_cb(__skb) ((struct sockaddr_llc *)&((__skb)->cb[0])) #endif /* __LINUX_LLC_H */ -- cgit v1.2.3 From 34f93ba0bc9f2bca0fde881b2267bc18bc9ac052 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 28 Sep 2026 19:38:32 +0200 Subject: wifi: ieee80211: type-check (extended) element functions Type-check element finding functions and element iteration macros, so that when constants are given for the (extended) ID they must be from the appropriate enum, otherwise an enum compare compiler warning will trigger. Two places are using element iteration for subelements, but don't have the outer element as a struct element, so they need casts to avoid the warning now, but overall this will flag issues like the one in the previous commit. Link: https://patch.msgid.link/20260928193832.706fb927f309.I0f8702dc218b56470017d2fcf8fff2980946e818@changeid Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 73ac5336a17a..66f9ebe79c61 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -2730,6 +2730,10 @@ struct element { u8 data[]; } __packed; +/* trigger enum comparison warnings if applicable (constant id) */ +#define element_iteration_typecheck(type, id) \ + (((type)0 == (id)) || true) + /* element iteration helpers */ #define for_each_element(_elem, _data, _datalen) \ for (_elem = (const struct element *)(_data); \ @@ -2741,11 +2745,15 @@ struct element { #define for_each_element_id(element, _id, data, datalen) \ for_each_element(element, data, datalen) \ - if (element->id == (_id)) + if (element_iteration_typecheck(enum ieee80211_eid, \ + _id) && \ + element->id == (_id)) #define for_each_element_extid(element, extid, _data, _datalen) \ for_each_element(element, _data, _datalen) \ - if (element->id == WLAN_EID_EXTENSION && \ + if (element_iteration_typecheck(enum ieee80211_eid_ext, \ + extid) && \ + element->id == WLAN_EID_EXTENSION && \ element->datalen > 0 && \ element->data[0] == (extid)) @@ -2753,10 +2761,11 @@ struct element { for_each_element(sub, (element)->data, (element)->datalen) #define for_each_subelement_id(sub, id, element) \ - for_each_element_id(sub, id, (element)->data, (element)->datalen) + for_each_element_id(sub, (u8)id, (element)->data, (element)->datalen) #define for_each_subelement_extid(sub, extid, element) \ - for_each_element_extid(sub, extid, (element)->data, (element)->datalen) + for_each_element_extid(sub, (u8)extid, (element)->data, \ + (element)->datalen) /** * for_each_element_completed - determine if element parsing consumed all data -- cgit v1.2.3 From 41da18108d25fb487c503c9a63b72cc543a9e72a Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Mon, 5 Oct 2026 11:44:51 +0300 Subject: wifi: cfg80211: do not use NAN beacons to update the BSS table As NAN beacons have a different structure compared to beacons defined in the IEEE802.11 specification, e.g., they do not contain a SSID element etc., they cannot be used to update the BSS table. Add a utility function to check if a frame is a NAN beacon and use it do return early in cfg80211_inform_bss_frame_data(). Signed-off-by: Ilan Peer Link: https://patch.msgid.link/20261005084458.3666739-5-ilan.peer@intel.com Signed-off-by: Johannes Berg --- include/linux/ieee80211-nan.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'include/linux') diff --git a/include/linux/ieee80211-nan.h b/include/linux/ieee80211-nan.h index 455033955e54..b332a94671ba 100644 --- a/include/linux/ieee80211-nan.h +++ b/include/linux/ieee80211-nan.h @@ -74,4 +74,30 @@ struct ieee80211_nan_anchor_master_info { _attr = (const struct ieee80211_nan_attr *) \ (_attr->data + le16_to_cpu(_attr->length))) +static inline bool ieee80211_is_nan_beacon(const struct ieee80211_mgmt *mgmt, + size_t len) +{ + const struct element *elem; + + /* The NAN IE is at least 6 octets */ + if (len < offsetofend(struct ieee80211_mgmt, u.beacon) + 6) + return false; + + if (!ieee80211_is_beacon(mgmt->frame_control)) + return false; + + /* NAN Cluster IDs range from 50-6F-9A-01-00-00 to 50-6F-9A-01-FF-FF */ + if (get_unaligned_be32(mgmt->bssid) != ((WLAN_OUI_WFA << 8) | 0x01)) + return false; + + elem = (const struct element *)mgmt->u.beacon.variable; + if (elem->id != WLAN_EID_VENDOR_SPECIFIC || + elem->datalen < 4 || + get_unaligned_be32(elem->data) != + (WLAN_OUI_WFA << 8 | WLAN_OUI_TYPE_WFA_NAN)) + return false; + + return true; +} + #endif /* LINUX_IEEE80211_NAN_H */ -- cgit v1.2.3 From ee0ea8cebd11781c4ae5ea5d050fb15ad12887c9 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Mon, 5 Oct 2026 11:44:54 +0300 Subject: wifi: ieee80211: add NAN service ID list attribute definitions Add the Service ID List and Subscribe Service ID List NAN attribute IDs. These are needed to filter in NAN beacons during Instant Communication. Assisted-by: GitHubCopilot:claude-opus-5 Signed-off-by: Ilan Peer Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20261005084458.3666739-8-ilan.peer@intel.com Signed-off-by: Johannes Berg --- include/linux/ieee80211-nan.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/ieee80211-nan.h b/include/linux/ieee80211-nan.h index b332a94671ba..7815a6cf8160 100644 --- a/include/linux/ieee80211-nan.h +++ b/include/linux/ieee80211-nan.h @@ -40,6 +40,8 @@ /* NAN attributes, as defined in Wi-Fi Aware (TM) specification 4.0 Table 42 */ #define NAN_ATTR_MASTER_INDICATION 0x00 #define NAN_ATTR_CLUSTER_INFO 0x01 +#define NAN_ATTR_SERVICE_ID_LIST 0x02 +#define NAN_ATTR_SUBSCRIBE_SERVICE_ID_LIST 0x28 struct ieee80211_nan_attr { u8 attr; -- cgit v1.2.3 From 4eee6d58ad1497518b59f8f2c0eb42e258d9cc82 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 29 Sep 2026 07:17:43 +0000 Subject: tcp: add tp->tcp_nospace tcp_check_space() runs for every incoming ACK and for every packet we send, and reads SOCK_NOSPACE from sk->sk_socket->flags. struct socket lives in its own cache line, which the TCP fast paths do not otherwise touch, so testing sk->sk_socket->flags pulls in an extra cache line that is cold when the working set is large. Add tp->tcp_nospace, a mirror of SOCK_NOSPACE placed right after tp->chrono_type in the tcp_sock_write_tx group, in a cache line both the transmit and the ACK paths already touch (bytes_sent, data_segs_out, delivered, bytes_acked, chrono_type). It fits in an existing 3-byte hole before chrono_start, so no other field moves and sizeof(struct tcp_sock) is unchanged. The two flags are now only changed from sk_set_nospace() and sk_clear_nospace(), which maintain this invariant: SOCK_NOSPACE set => tp->tcp_nospace set sk_set_nospace() sets SOCK_NOSPACE before tp->tcp_nospace (using smp_mb__after_atomic() and smp_store_mb()), while sk_clear_nospace() clears tp->tcp_nospace before SOCK_NOSPACE (using smp_mb__before_atomic()). If a lockless sk_set_nospace() from tcp_poll() races with sk_clear_nospace() and SOCK_NOSPACE ends up set, set_bit(SOCK_NOSPACE) happened after clear_bit(SOCK_NOSPACE), so tp->tcp_nospace = 1 happens after tp->tcp_nospace = 0 as well. tcp_check_space() can thus test tp->tcp_nospace alone and leave the authoritative SOCK_NOSPACE test to __tcp_check_space(). The invariant is one directional on purpose: a stale tp->tcp_nospace only costs an extra call to __tcp_check_space(), which is what we do unconditionally today, while a stale SOCK_NOSPACE would cost a missed EPOLLOUT. Note the smp_mb() is kept. tcp_poll() sets the flag without the socket lock, and the store-buffer pattern it forms with tcp_check_space() needs a full barrier on both sides. MPTCP subflows share the struct socket of their parent, hence its SOCK_NOSPACE bit, which can not be mirrored in the subflow tcp_sock. Pin their tp->tcp_nospace in subflow_ulp_init(), so that they always reach __tcp_check_space() and keep the current behavior. Microbenchmark on an AMD EPYC 7B13, 64 threads, each thread calling tcp_check_space() in a loop over a private set of sockets. Numbers are cycles per call above a baseline loop that performs the work the callers already did (the cache lines tcp_write_xmit() and tcp_clean_rtx_queue() touched) but not tcp_check_space() itself, so they are the marginal cost of the function. Median of 11 runs. The set size controls whether struct socket is still cached: sockets/thread before after 1 +0.6 +0.7 256 (64 KB) +8.3 +3.9 4096 (1 MB) +22.4 +1.1 262144 (64 MB) +48.4 -0.8 Signed-off-by: Eric Dumazet Link: https://patch.msgid.link/20260929071743.23624-10-edumazet@kernel.org Signed-off-by: Jakub Kicinski --- include/linux/tcp.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/linux') diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 6a8c77719322..e4d1720f49f0 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -269,6 +269,9 @@ struct tcp_sock { */ u32 snd_sml; /* Last byte of the most recently transmitted small packet */ u8 chrono_type; /* current chronograph type */ + u8 tcp_nospace; /* mirrors SOCK_NOSPACE, must be set whenever + * SOCK_NOSPACE is set. + */ u32 chrono_start; /* Start time in jiffies of a TCP chrono */ u32 chrono_stat[3]; /* Time in jiffies for chrono_stat stats */ u32 write_seq; /* Tail(+1) of data held in tcp send buffer */ -- cgit v1.2.3 From 6451576b53961f620de641c0ab3bfa8eabc7184b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 2 Oct 2026 20:55:09 +0200 Subject: net: remove IPX raw 802.3 detection from eth_type_trans() eth_type_trans() and vlan_set_encap_proto() still carry a "magic hack" to spot Novell raw 802.3 frames (IPX directly over 802.3, without an 802.2 LLC header) by looking for 0xFFFF in the first two bytes of the payload, and report them as ETH_P_802_3. IPX was removed in commit 7a2e838d28cf ("staging: ipx: delete it from the tree") and there is no in-kernel packet handler for ETH_P_802_3 on the Ethernet receive path anymore. Simply classify all frames using a length field as ETH_P_802_2, which is what the remaining LLC users (STP, GARP, SNAP) register for. This removes a skb_header_pointer() call (and the skb->dev scratch trick used to avoid a stack canary) from eth_type_trans(), and lets skb_vlan_untag() only pull VLAN_HLEN bytes, as the extra two bytes were only needed for this check since commit 55eff0eb7460 ("net: Fix potential wrong skb->protocol in skb_vlan_untag()"). Note that such frames are now reported to AF_PACKET, tc, BPF and nftables with skb->protocol == ETH_P_802_2 instead of ETH_P_802_3. $ scripts/bloat-o-meter -t vmlinux.old vmlinux.new add/remove: 0/0 grow/shrink: 2/5 up/down: 33/-187 (-154) Function old new delta skb_shift 1736 1768 +32 eth_type_trans.cold 45 46 +1 skb_vlan_untag 690 678 -12 __skb_vlan_pop 489 477 -12 nf_flow_encap_pop 462 449 -13 eth_type_trans 354 220 -134 Total: Before=31212910, After=31212756, chg -0.00% Signed-off-by: Eric Dumazet Link: https://patch.msgid.link/20261002185509.17226-1-edumazet@kernel.org Signed-off-by: Jakub Kicinski --- include/linux/if_vlan.h | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) (limited to 'include/linux') diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 4846032bf4ff..975892367136 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -698,7 +698,6 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb, struct vlan_hdr *vhdr) { __be16 proto; - unsigned short *rawp; /* * Was a VLAN packet, grab the encapsulated protocol, which the layer @@ -711,21 +710,8 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb, return; } - rawp = (unsigned short *)(vhdr + 1); - if (*rawp == 0xFFFF) - /* - * This is a magic hack to spot IPX packets. Older Novell - * breaks the protocol design and runs IPX over 802.3 without - * an 802.2 LLC layer. We look for FFFF which isn't a used - * 802.2 SSAP/DSAP. This won't work for fault tolerant netware - * but does for the rest. - */ - skb->protocol = htons(ETH_P_802_3); - else - /* - * Real 802.2 LLC - */ - skb->protocol = htons(ETH_P_802_2); + /* No ethertype: this is an 802.2 LLC frame (length field). */ + skb->protocol = htons(ETH_P_802_2); } /** -- cgit v1.2.3 From 2e65372a2b64a1d6d1e27dff0579b3a609b2e405 Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Thu, 1 Oct 2026 20:47:15 +0000 Subject: net: Rename dev_isalive() to netif_is_alive(). The next patch needs to use dev_isalive() in xfrm. We should try to avoid using the dev_ prefix on APIs we export via include/linux/. Let's move it to include/linux/netdevice.h and rename to netif_is_alive(). Signed-off-by: Kuniyuki Iwashima Reviewed-by: Ido Schimmel Tested-by: Chris J Arges Link: https://patch.msgid.link/20261001204752.2572265-4-kuniyu@google.com Signed-off-by: Jakub Kicinski --- include/linux/netdevice.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f61c97231309..8cae9b00211e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -5715,6 +5715,12 @@ static inline const char *netdev_name(const struct net_device *dev) return dev->name; } +/* Caller holds RTNL, netdev->lock or RCU */ +static inline bool netif_is_alive(const struct net_device *dev) +{ + return READ_ONCE(dev->reg_state) <= NETREG_REGISTERED; +} + static inline const char *netdev_reg_state(const struct net_device *dev) { u8 reg_state = READ_ONCE(dev->reg_state); -- cgit v1.2.3 From 4e3b56eb2ed879353de392acec7b485b123840a4 Mon Sep 17 00:00:00 2001 From: Naman Gulati Date: Tue, 6 Oct 2026 23:51:13 +0000 Subject: net: gro_cells: prevent enabling threaded NAPI on gro_cells MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gro_cells allocates a per-CPU struct gro_cell with per-CPU queues (cell->napi_skbs), per-CPU local_lock_t (cell->bh_lock), and per-CPU napi_struct (cell->napi). On !CONFIG_PREEMPT_RT, local_lock_t only provides lockdep annotation (and is a complete no-op when CONFIG_DEBUG_LOCK_ALLOC is disabled), relying on per-CPU locality and disabled BH context for mutual exclusion; it does not provide cross-CPU synchronization. When threaded NAPI is enabled on a device backed by gro_cells (e.g. gre0, vxlan, geneve) via sysfs, unbound kernel threads are created for each per-CPU NAPI. When gro_cells_receive() on CPU A enqueues a packet to cell_A and calls napi_schedule(&cell_A->napi) while holding cell_A->bh_lock, the woken kthread can run concurrently on remote CPU B. When CPU B runs gro_cell_poll(&cell_A->napi) and calls __local_lock_nested_bh(&cell_A->bh_lock), lockdep detects that the lock is already held by CPU A's task and triggers a warning: WARNING: CPU: 1 PID: 377 at net/core/gro_cells.c:66 gro_cell_poll DEBUG_LOCKS_WARN_ON(l->owner) CPU: 1 UID: 0 PID: 377 Comm: napi/gre0-0 Not tainted 7.3.0-rc2 Call Trace: __local_lock_nested_bh include/linux/local_lock_internal.h:92 gro_cell_poll+0x5aa/0x6c0 net/core/gro_cells.c:66 napi_threaded_poll+0x39b/0x600 net/core/dev.c:7048 kthread+0x71e/0x870 kernel/kthread.c:464 ret_from_fork+0x5d/0x90 arch/x86/kernel/process.c:167 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:264 On !CONFIG_PREEMPT_RT kernels without lockdep, concurrent execution of __skb_queue_tail() on CPU A and __skb_dequeue() on CPU B without cross-CPU locks leads to silent queue corruption. Virtual per-CPU NAPIs cannot support unbound threaded NAPI. While gro_cells also sets NAPI_STATE_NO_BUSY_POLL (which skips napi_hash_add() and prevents configuring them via Netlink), NAPI_STATE_NO_BUSY_POLL cannot be used to reject threaded NAPI in sysfs because drivers such as WireGuard set NAPI_STATE_NO_BUSY_POLL on per-peer NAPIs while running them in threaded mode by default. Introduce NAPI_STATE_PERCPU to mark per-CPU NAPIs that cannot run in unbound threaded mode. Set NAPI_STATE_PERCPU in gro_cells_init(), and fail early with -EOPNOTSUPP in modify_napi_threaded() and netdev_nl_napi_set_config() when trying to enable threaded NAPI on NAPI_STATE_PERCPU NAPIs, while still allowing disabling (writing 0) as a no-op. Fixes: 25718fdcbdd2 ("net: gro_cells: Use nested-BH locking for gro_cell") Fixes: 29863d41bb6e ("net: implement threaded-able napi poll loop support") Reported-by: syzbot+f0661448aa9511ce744a@syzkaller.appspotmail.com Closes: https://lore.kernel.org/netdev/6aad6d7b.0c43d342.320d00.0001.GAE@google.com Signed-off-by: Naman Gulati Reviewed-by: Björn Töpel Link: https://patch.msgid.link/20261006235113.2394030-1-namangulati@google.com Signed-off-by: Jakub Kicinski --- include/linux/netdevice.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 8cae9b00211e..5b4b92e76b67 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -433,6 +433,7 @@ enum { NAPI_STATE_SCHED_THREADED, /* Napi is currently scheduled in threaded mode */ NAPI_STATE_HAS_NOTIFIER, /* Napi has an IRQ notifier */ NAPI_STATE_THREADED_BUSY_POLL, /* The threaded NAPI poller will busy poll */ + NAPI_STATE_PERCPU, /* NAPI handler is run per-CPU - incompatible with threaded mode */ }; enum { @@ -448,6 +449,7 @@ enum { NAPIF_STATE_SCHED_THREADED = BIT(NAPI_STATE_SCHED_THREADED), NAPIF_STATE_HAS_NOTIFIER = BIT(NAPI_STATE_HAS_NOTIFIER), NAPIF_STATE_THREADED_BUSY_POLL = BIT(NAPI_STATE_THREADED_BUSY_POLL), + NAPIF_STATE_PERCPU = BIT(NAPI_STATE_PERCPU), }; enum gro_result { -- cgit v1.2.3 From 9142c2f8f84bf4eafe23e9d68b6ba016a60300c0 Mon Sep 17 00:00:00 2001 From: Emanuele Rocca Date: Mon, 5 Oct 2026 18:21:37 +0200 Subject: octeontx2: use arch_extension to enable LSE Instead of using ".cpu generic+lse", use ".arch_extension lse" to enable LSE. The ".cpu generic+lse" directive replaces the assembler's current feature set with generic+lse, dropping other previously enabled features. In contrast, ".arch_extension lse" enables LSE while preserving the current feature set. For example, the following code is rejected with "selected processor does not support retaa", because ".cpu generic+lse" drops PAuth even though it was enabled by armv9-a: .arch armv9-a .text .cpu generic+lse retaa We encountered this issue while building the kernel with GCC configured using --with-arch=armv9-a. Since Armv9-A includes pointer authentication, GCC can assume that PAuth instructions are available and may use retaa when generating PAuth-protected returns. Signed-off-by: Emanuele Rocca Link: https://patch.msgid.link/20261005162137.71397-1-emanuele.rocca@arm.com Signed-off-by: Jakub Kicinski --- include/linux/soc/marvell/octeontx2/asm.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/soc/marvell/octeontx2/asm.h b/include/linux/soc/marvell/octeontx2/asm.h index d683251a0b40..8b572d3d741c 100644 --- a/include/linux/soc/marvell/octeontx2/asm.h +++ b/include/linux/soc/marvell/octeontx2/asm.h @@ -17,7 +17,7 @@ #define otx2_lmt_flush(ioaddr) \ ({ \ u64 result = 0; \ - __asm__ volatile(".cpu generic+lse\n" \ + __asm__ volatile(".arch_extension lse\n" \ "ldeor xzr, %x[rf], [%[rs]]" \ : [rf]"=r" (result) \ : [rs]"r" (ioaddr)); \ @@ -30,7 +30,7 @@ */ #define cn10k_lmt_flush(val, addr) \ ({ \ - __asm__ volatile(".cpu generic+lse\n" \ + __asm__ volatile(".arch_extension lse\n" \ "steorl %x[rf],[%[rs]]" \ : [rf] "+r"(val) \ : [rs] "r"(addr)); \ @@ -40,7 +40,7 @@ static inline u64 otx2_atomic64_fetch_add(u64 incr, u64 *ptr) { u64 result; - asm volatile (".cpu generic+lse\n" + asm volatile (".arch_extension lse\n" "ldadda %x[i], %x[r], [%[b]]" : [r] "=r" (result), "+m" (*ptr) : [i] "r" (incr), [b] "r" (ptr) -- cgit v1.2.3 From f688218baa7128a1ef3f8377679fc5fcbc22fa2e Mon Sep 17 00:00:00 2001 From: Rokas Juras Date: Mon, 5 Oct 2026 10:48:52 +0300 Subject: rndis_host: enable RX aggregation for OnePlus Nord CE 2 USB tethering on the OnePlus Nord CE 2 (IV2201, USB ID 22d9:2766) running Android 13 has download speeds of approximately 2mbps with the default 2048-byte receive limit. The phone's published RNDIS code only enables packet batching when the computer reports a receive limit above 2048 bytes. Testing shows that increasing this limit to 2560 bytes restores normal speeds. Add a quirk for USB device 22d9:2766 to use and advertise a receive buffer of at least 16 KiB. This fits the phone code's default batch of ten packets at a 1500-byte MTU. Tested on 7.3.0-rc5 with the affected phone, including reconnecting USB tethering. Download speeds with the change exceed 100mpbs. Link: https://github.com/OnePlusOSS/android_kernel_oneplus_mt6877/blob/3c1e3d432d0c35afa7fded974b50fa6617219e0f/drivers/usb/gadget/function/f_rndis.c#L538-L551 Link: https://github.com/OnePlusOSS/android_kernel_oneplus_mt6877/blob/3c1e3d432d0c35afa7fded974b50fa6617219e0f/drivers/usb/gadget/function/u_ether.c#L869-L874 Signed-off-by: Rokas Juras Link: https://patch.msgid.link/20261005074852.76818-1-asrokasjuras@gmail.com Signed-off-by: Jakub Kicinski --- include/linux/usb/rndis_host.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/usb/rndis_host.h b/include/linux/usb/rndis_host.h index 489cfb1d00f6..3eaf57a9b282 100644 --- a/include/linux/usb/rndis_host.h +++ b/include/linux/usb/rndis_host.h @@ -182,8 +182,9 @@ struct rndis_keepalive_c { /* IN (optionally OUT) */ #define FLAG_RNDIS_PHYM_WIRELESS 0x0002 /* Flags for driver_info::data */ -#define RNDIS_DRIVER_DATA_POLL_STATUS 1 /* poll status before control */ -#define RNDIS_DRIVER_DATA_DST_MAC_FIXUP 2 /* device ignores configured MAC address */ +#define RNDIS_DRIVER_DATA_POLL_STATUS 1 /* poll status before control */ +#define RNDIS_DRIVER_DATA_DST_MAC_FIXUP 2 /* device ignores configured MAC address */ +#define RNDIS_DRIVER_DATA_RX_AGGREGATION 4 /* needs RX limit > 2048 */ extern void rndis_status(struct usbnet *dev, struct urb *urb); extern int -- cgit v1.2.3 From 4c5679222f6b9bb6800d32eb8256b43d164c3e31 Mon Sep 17 00:00:00 2001 From: Or Har-Toov Date: Mon, 5 Oct 2026 11:40:46 +0300 Subject: net/mlx5: Add cap_tx_speed and effective_tx_speed support to IFC Introduce the cap_tx_speed and effective_tx_speed fields to the query and modify_vport_state structures. Add the esw_vport_state_cap_tx_speed and esw_vport_state_effective_tx_speed capability bits, indicating the firmware supports modifying the cap_tx_speed and effective_tx_speed fields, via the MODIFY_VPORT_STATE command. Signed-off-by: Or Har-Toov Reviewed-by: Mark Bloch Reviewed-by: Nimrod Oren Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20261005084047.237081-2-tariqt@nvidia.com Signed-off-by: Leon Romanovsky --- include/linux/mlx5/mlx5_ifc.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index a712463e89b4..989408764e1b 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -1070,7 +1070,9 @@ struct mlx5_ifc_e_switch_cap_bits { u8 root_ft_on_other_esw[0x1]; u8 reserved_at_a[0x1]; u8 esw_vport_state_max_tx_speed[0x1]; - u8 reserved_at_c[0xd]; + u8 esw_vport_state_cap_tx_speed[0x1]; + u8 esw_vport_state_effective_tx_speed[0x1]; + u8 reserved_at_e[0xb]; u8 esw_functions_changed[0x1]; u8 reserved_at_1a[0x1]; u8 ecpf_vport_exists[0x1]; @@ -5492,6 +5494,9 @@ struct mlx5_ifc_query_vport_state_out_bits { u8 reserved_at_70[0x8]; u8 admin_state[0x4]; u8 state[0x4]; + + u8 cap_tx_speed[0x10]; + u8 effective_tx_speed[0x10]; }; struct mlx5_ifc_array1024_auto_bits { @@ -7840,6 +7845,9 @@ struct mlx5_ifc_modify_vport_state_in_bits { u8 reserved_at_74[0x4]; u8 admin_state[0x4]; u8 reserved_at_7c[0x4]; + + u8 cap_tx_speed[0x10]; + u8 effective_tx_speed[0x10]; }; struct mlx5_ifc_modify_tis_out_bits { -- cgit v1.2.3 From 41de84543574f2923776790f608c56389aed972e Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Mon, 5 Oct 2026 11:40:47 +0300 Subject: net/mlx5: IFC, Add capability bits for virtual LAG Virtual LAG can also be built over virtual uplinks rather than physical ports. The support for this virtual LAG is indicated by multi_uplink_eswitch and port_select_eswitch caps bit. Signed-off-by: Shay Drory Reviewed-by: Mark Bloch Reviewed-by: Moshe Shemesh Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20261005084047.237081-3-tariqt@nvidia.com Signed-off-by: Leon Romanovsky --- include/linux/mlx5/mlx5_ifc.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 989408764e1b..f1ee35aa884a 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -929,7 +929,7 @@ struct mlx5_ifc_flow_table_nic_cap_bits { struct mlx5_ifc_port_selection_cap_bits { u8 reserved_at_0[0x10]; u8 port_select_flow_table[0x1]; - u8 reserved_at_11[0x1]; + u8 port_select_eswitch[0x1]; u8 port_select_flow_table_bypass[0x1]; u8 reserved_at_13[0xd]; @@ -2010,7 +2010,9 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 reserved_at_3b0[0x2]; u8 qp_latency_sensitive_disable[0x1]; u8 log_max_stride_sz_sq[0x5]; - u8 reserved_at_3b8[0x3]; + u8 reserved_at_3b8[0x1]; + u8 multi_uplink_eswitch[0x1]; + u8 reserved_at_3ba[0x1]; u8 log_min_stride_sz_sq[0x5]; u8 hairpin[0x1]; -- cgit v1.2.3 From cc9dcb0e7a428ca43259bbee3350d786681265a3 Mon Sep 17 00:00:00 2001 From: Wang Zhan Date: Thu, 8 Oct 2026 18:06:46 +0800 Subject: net: core: use the packet's L3 protocol for the GSO size limit gso_features_check() compares the frame length against netif_get_gso_max_size(), which picks the IPv4 or the IPv6 limit from skb->protocol. A tag which is already inside the frame replaces that field with the VLAN ethertype, as skb_vlan_push() does, and an IPv6 packet is then measured against the IPv4 limit and segmented although the device could send it as one TSO frame. The lookup moves from netdevice.h into dev.c: vlan_get_protocol() reads the L3 protocol from behind an in-frame tag, while if_vlan.h includes netdevice.h, so an inline in that header cannot call it. dev.c is the only file which calls the lookup, so it becomes a static helper there. Reviewed-by: Willem de Bruijn Assisted-by: LLM Signed-off-by: Wang Zhan Link: https://patch.msgid.link/20261008100651.2534957-2-wang.zhan@smartx.com Signed-off-by: Paolo Abeni --- include/linux/netdevice.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 5b4b92e76b67..1743dcd02d5b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -5566,15 +5566,6 @@ netif_get_gro_max_size(const struct net_device *dev, const struct sk_buff *skb) READ_ONCE(dev->gro_ipv4_max_size); } -static inline unsigned int -netif_get_gso_max_size(const struct net_device *dev, const struct sk_buff *skb) -{ - /* pairs with WRITE_ONCE() in netif_set_gso(_ipv4)_max_size() */ - return skb->protocol == htons(ETH_P_IPV6) ? - READ_ONCE(dev->gso_max_size) : - READ_ONCE(dev->gso_ipv4_max_size); -} - static inline bool netif_is_macsec(const struct net_device *dev) { return dev->priv_flags & IFF_MACSEC; -- cgit v1.2.3 From 0bba48256b0aa86e84a08d69b4410018bd8ffc67 Mon Sep 17 00:00:00 2001 From: Wang Zhan Date: Thu, 8 Oct 2026 18:06:47 +0800 Subject: net: core: factor out the GSO device limit check gso_features_check() decides whether an egress device can offload a GSO skb as a single TSO frame by comparing the segment count and the frame length against the device limits. The resegmentation path added by a later patch caps the MSS segments per output skb and needs the same features computed without those limits, so put the two tests in a helper and gate them with one flag. __netif_skb_features() takes that flag and takes the place of netif_skb_features(), which becomes an inline wrapper in netdevice.h and passes the flag set. Existing callers keep their call, and the resegmentation path asks for the features without the limit checks. No functional changes. Reviewed-by: Willem de Bruijn Assisted-by: LLM Signed-off-by: Wang Zhan Link: https://patch.msgid.link/20261008100651.2534957-3-wang.zhan@smartx.com Signed-off-by: Paolo Abeni --- include/linux/netdevice.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 1743dcd02d5b..8fbe3a5d8169 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -5500,7 +5500,14 @@ void netif_stacked_transfer_operstate(const struct net_device *rootdev, netdev_features_t passthru_features_check(struct sk_buff *skb, struct net_device *dev, netdev_features_t features); -netdev_features_t netif_skb_features(struct sk_buff *skb); +netdev_features_t __netif_skb_features(struct sk_buff *skb, + bool check_gso_limits); + +static inline netdev_features_t netif_skb_features(struct sk_buff *skb) +{ + return __netif_skb_features(skb, true); +} + void skb_warn_bad_offload(const struct sk_buff *skb); static inline bool net_gso_ok(netdev_features_t features, int gso_type) -- cgit v1.2.3 From 72ebc685bca99f466ef35600b5263d1c21c790d9 Mon Sep 17 00:00:00 2001 From: Mina Almasry Date: Sat, 10 Oct 2026 03:36:08 +0000 Subject: net: netmem: document netmem and memory provider design in comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clarify the netmem, memory provider, page_pool, and skb fragment design principles in header and code comments: - Memory providers allocate struct net_iov or struct page, cast them to netmem_ref, and pass them to page_pool; page_pool, drivers, and the core stack operate on netmem_ref and must not downcast to page or net_iov outside dedicated netmem helpers. - While current memory providers supply struct net_iov, they are not architecturally restricted to net_iov and may supply page-backed netmems. - While current net_iov types are CPU-unreadable, net_iov has no inherent restrictions and may be readable or unreadable. - New code should generalize existing limitations as much as possible to match these design principles. - Per-provider logic belongs in memory_provider_ops, and per-netmem-type logic belongs in netmem helpers. - All frags in an skb must either all be struct page-backed or all belong to the same memory provider instance; mixing them (including via coalescing) is not allowed. Cc: Luigi Rizzo Cc: Pavel Begunkov Signed-off-by: Mina Almasry Acked-by: Jesper Dangaard Brouer Reviewed-by: Björn Töpel Acked-by: Stanislav Fomichev Link: https://patch.msgid.link/20261010033630.1171692-2-almasrymina@google.com Signed-off-by: Jakub Kicinski --- include/linux/skbuff.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 27ec1e38c828..af1cbc2799b7 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -358,6 +358,12 @@ struct sk_buff; */ #define GSO_BY_FRAGS 0xFFFF +/* All frags in an skb must either all be struct page-backed or all belong to + * the same memory provider instance (e.g. the same devmem binding or io_uring + * area). Mixing page and memory-provider frags, or mixing frags from different + * memory providers within a single skb (including via coalescing), is not + * allowed. + */ typedef struct skb_frag { netmem_ref netmem; unsigned int len; -- cgit v1.2.3 From 7151b86654fa635101cabe7f55511f54c3adcf84 Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Tue, 13 Oct 2026 18:12:00 +0300 Subject: net: phy: put the driver module the attach took phy_attach_direct() pins the PHY driver module through d->driver, and phy_detach() releases it by reading d->driver again. Unbinding the PHY driver while the PHY is attached clears that pointer, so a detach that runs while the driver is still unbound skips the put and the module can no longer be unloaded; if a different driver binds in between, the put lands on a module that was never pinned. The NULL test added by commit c2b727df7caa ("net: phy: Avoid NPD upon phy_detach() when driver is unbound") avoids the oops but skips the put. Found by reading phy_detach() while chasing a PHY driver unbind race on a Keenetic KN-1012 (MT7981, air_en8811h built as a module). The leak itself was not observed there: unbinding air_en8811h under the attached lan4 DSA port and then unbinding the switch faults earlier on that board, in phy_free_interrupt() or under phy_stop(), before phy_detach() gets to the put. Remember which module was pinned and release that one. Reviewed-by: Andrew Lunn Signed-off-by: Aleksei Sviridkin Link: https://patch.msgid.link/20261013151200.2473464-3-f@lex.la Signed-off-by: Jakub Kicinski --- include/linux/phy.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/phy.h b/include/linux/phy.h index 7c5098a0dd6c..a5a419bc400e 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -578,6 +578,7 @@ struct phy_oatc14_sqi_capability { * * @mdio: MDIO bus this PHY is on * @drv: Pointer to the driver for this PHY instance + * @drv_owner: Driver module phy_attach_direct() took a reference on * @devlink: Create a link between phy dev and mac dev, if the external phy * used by current mac interface is managed by another mac interface. * @phyindex: Unique id across the phy's parent tree of phys to address the PHY @@ -689,6 +690,7 @@ struct phy_device { /* Information about the PHY type */ /* And management functions */ const struct phy_driver *drv; + struct module *drv_owner; struct device_link *devlink; -- cgit v1.2.3 From 3dcafe6cb5e1b467a25fde347c8c3949a2866adc Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 11 Oct 2026 23:59:43 +0200 Subject: netfilter: flowtable: add encap_proto to flow_offload_tunnel Add encap_proto (AF_INET or AF_INET6) to struct flow_offload_tunnel to allow its use as part of the hash table key during flowtable entry lookup. This is a preliminary change to support IPv4 over IPv6 tunneling via the flowtable infrastructure for software acceleration. Signed-off-by: Lorenzo Bianconi Signed-off-by: Pablo Neira Ayuso --- include/linux/netdevice.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f61c97231309..fee3728ad666 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -911,6 +911,7 @@ struct net_device_path { }; u8 inner_proto; + u8 encap_proto; } tun; struct { enum { -- cgit v1.2.3 From 729a47b803b5c95659e32d9014ba10c727995d1c Mon Sep 17 00:00:00 2001 From: Mina Almasry Date: Wed, 14 Oct 2026 17:37:16 +0000 Subject: net: skbuff: add napi_pp_get_page() and use it in tcp_recvmsg_dmabuf() While napi_pp_put_page() releases a page_pool pp_ref_count reference on a netmem, no symmetric helper existed to acquire one, forcing callers like tcp_recvmsg_dmabuf() to open-code atomic_long_inc() on niov->desc.pp_ref_count. Add napi_pp_get_page() to pair symmetrically with napi_pp_put_page(), and use WARN_ON_ONCE(!napi_pp_get_page(netmem)) in tcp_recvmsg_dmabuf() to match WARN_ON_ONCE(!napi_pp_put_page(netmem)) in tcp_release_user_frags(). Assisted-by: LLM Signed-off-by: Mina Almasry Link: https://patch.msgid.link/20261014173945.373295-3-almasrymina@google.com Acked-by: Stanislav Fomichev Signed-off-by: Paolo Abeni --- include/linux/skbuff_ref.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/skbuff_ref.h b/include/linux/skbuff_ref.h index 05c8486bafac..0441c220fdbd 100644 --- a/include/linux/skbuff_ref.h +++ b/include/linux/skbuff_ref.h @@ -9,6 +9,8 @@ #include +bool napi_pp_get_page(netmem_ref netmem); + /** * __skb_frag_ref - take an addition reference on a paged fragment. * @frag: the paged fragment -- cgit v1.2.3 From 4d688084070e72d66090f3bb739218278d3e889b Mon Sep 17 00:00:00 2001 From: Mina Almasry Date: Wed, 14 Oct 2026 17:37:17 +0000 Subject: net: skbuff: replace skb_page_unref() and __skb_frag_unref() with skb_netmem_unref() Unreferencing a page_pool fragment with recycle=false decrements the non-pp backing refcount instead of pp_ref_count, underflowing the page refcount when the fragment was owned via page_pool (as on mlx4's RX error path). Having both skb_page_unref() and __skb_frag_unref(frag, recycle) made it easy for callers to pass hardcoded recycle=false on SKB-owned fragments. Replace skb_page_unref() and __skb_frag_unref() with skb_netmem_unref(netmem, recycle), which dispatches to napi_pp_put_page() when recycle is true and put_netmem() otherwise: - Use skb_frag_unref(skb, ...) on SKB-owned fragments in mlx4, sky2, tls_strp, and skb_shift() so unrefs always match skb->pp_recycle. - Use put_netmem() directly in tls_device's destroy_record(), which releases raw non-pp page references outside an SKB. Found by code inspection and confirmed with the KUnit tests added later in this series; not observed in production. The mlx4, sky2, and TLS call-site changes are compile-tested only. Assisted-by: LLM Signed-off-by: Mina Almasry Link: https://patch.msgid.link/20261014173945.373295-4-almasrymina@google.com Acked-by: Stanislav Fomichev Signed-off-by: Paolo Abeni --- include/linux/skbuff_ref.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'include/linux') diff --git a/include/linux/skbuff_ref.h b/include/linux/skbuff_ref.h index 0441c220fdbd..04114c64dad9 100644 --- a/include/linux/skbuff_ref.h +++ b/include/linux/skbuff_ref.h @@ -36,7 +36,16 @@ static __always_inline void skb_frag_ref(struct sk_buff *skb, int f) bool napi_pp_put_page(netmem_ref netmem); -static __always_inline void skb_page_unref(netmem_ref netmem, bool recycle) +/** + * skb_netmem_unref - release a fragment reference on a netmem + * @netmem: netmem to unreference + * @recycle: whether page_pool recycling is enabled (e.g. skb->pp_recycle) + * + * Drops pp_ref_count via napi_pp_put_page() if @recycle is true and @netmem + * belongs to a page_pool; otherwise drops a non-pp backing reference via + * put_netmem(). Counterpart to skb_netmem_ref(). + */ +static __always_inline void skb_netmem_unref(netmem_ref netmem, bool recycle) { #ifdef CONFIG_PAGE_POOL if (recycle && napi_pp_put_page(netmem)) @@ -46,31 +55,22 @@ static __always_inline void skb_page_unref(netmem_ref netmem, bool recycle) } /** - * __skb_frag_unref - release a reference on a paged fragment. - * @frag: the paged fragment - * @recycle: recycle the page if allocated via page_pool - * - * Releases a reference on the paged fragment @frag - * or recycles the page via the page_pool API. - */ -static __always_inline void __skb_frag_unref(skb_frag_t *frag, bool recycle) -{ - skb_page_unref(skb_frag_netmem(frag), recycle); -} - -/** - * skb_frag_unref - release a reference on a paged fragment of an skb. + * skb_frag_unref - release a reference on a paged fragment of an skb * @skb: the buffer * @f: the fragment offset * - * Releases a reference on the @f'th paged fragment of @skb. + * Drops a reference on the @f'th fragment of @skb via skb_netmem_unref() + * (pp_ref_count if skb->pp_recycle and page_pool-backed, else non-pp + * backing refcount), skipping managed zerocopy fragments. Counterpart to + * skb_frag_ref(). */ static __always_inline void skb_frag_unref(struct sk_buff *skb, int f) { struct skb_shared_info *shinfo = skb_shinfo(skb); if (!skb_zcopy_managed(skb)) - __skb_frag_unref(&shinfo->frags[f], skb->pp_recycle); + skb_netmem_unref(skb_frag_netmem(&shinfo->frags[f]), + skb->pp_recycle); } #endif /* _LINUX_SKBUFF_REF_H */ -- cgit v1.2.3 From 1f6f88105e1da95954bca63475796ee09afd8ba1 Mon Sep 17 00:00:00 2001 From: Mina Almasry Date: Wed, 14 Oct 2026 17:37:18 +0000 Subject: net: skbuff: replace __skb_frag_ref() with symmetric skb_netmem_ref() Previously, __skb_frag_ref() and skb_frag_ref() unconditionally incremented the non-pp backing refcount via get_netmem(), while skb_frag_unref() decremented pp_ref_count whenever skb->pp_recycle was set. Ref-ing a page_pool fragment into a pp_recycle=1 SKB (or clearing pp_recycle=0 on an uncloned SKB while clones still held pp_recycle=1) leaked the backing non-pp refcount and underflowed pp_ref_count across IP-TFS, skb_split(), skb_shift(), and cloned unclone paths. Replace __skb_frag_ref() with skb_netmem_ref(netmem, recycle) as the exact counterpart to skb_netmem_unref(netmem, recycle): - Keep skb->pp_recycle intact in skb_release_data() so uncloning paths (pskb_expand_head() and pskb_carve_inside_{header,nonlinear}()) keep trading pp_ref_count references symmetrically across clones. - Propagate pp_recycle and call skb_frag_ref() on the destination SKB in __pskb_copy_fclone(), skb_zerocopy(), skb_split(), skb_shift(), and skb_segment(). - Linearize an output segment's existing frags in skb_segment() before attaching frags from a frag_list SKB with a different pp_recycle bit, since each output segment carries a single pp_recycle bit. - Use skb_frag_ref() in xfrm_iptfs, chcr_ktls, and cassini, and call get_netmem() directly in veth and tls_device_fallback where callers explicitly take a raw non-pp reference. Found by code inspection while reviewing the IP-TFS pp_ref_count fix [1] and confirmed with the KUnit tests added later in this series; not observed in production. The xfrm_iptfs, chcr_ktls, cassini, veth, and tls_device_fallback changes are compile-tested only. Link: https://lore.kernel.org/netdev/xfrm-iptfs-pp_ref_count-underflow-v4-1-912fa72106f0@secunet.com/ [1] Cc: Antony Antony Cc: Stanislav Fomichev Cc: Daniel Borkmann Cc: Alexei Starovoitov Cc: Jesper Dangaard Brouer Cc: bpf@vger.kernel.org Assisted-by: LLM Signed-off-by: Mina Almasry Tested-by: Antony Antony Link: https://patch.msgid.link/20261014173945.373295-5-almasrymina@google.com Acked-by: Stanislav Fomichev Signed-off-by: Paolo Abeni --- include/linux/skbuff_ref.h | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'include/linux') diff --git a/include/linux/skbuff_ref.h b/include/linux/skbuff_ref.h index 04114c64dad9..f768a3fa1d60 100644 --- a/include/linux/skbuff_ref.h +++ b/include/linux/skbuff_ref.h @@ -12,26 +12,36 @@ bool napi_pp_get_page(netmem_ref netmem); /** - * __skb_frag_ref - take an addition reference on a paged fragment. - * @frag: the paged fragment + * skb_netmem_ref - acquire a fragment reference on a netmem + * @netmem: netmem to reference + * @recycle: whether page_pool recycling is enabled (e.g. skb->pp_recycle) * - * Takes an additional reference on the paged fragment @frag. + * Acquires pp_ref_count via napi_pp_get_page() if @recycle is true and + * @netmem belongs to a page_pool; otherwise acquires a non-pp backing + * reference via get_netmem(). Counterpart to skb_netmem_unref(). */ -static __always_inline void __skb_frag_ref(skb_frag_t *frag) +static __always_inline void skb_netmem_ref(netmem_ref netmem, bool recycle) { - get_netmem(skb_frag_netmem(frag)); +#ifdef CONFIG_PAGE_POOL + if (recycle && napi_pp_get_page(netmem)) + return; +#endif + get_netmem(netmem); } /** - * skb_frag_ref - take an addition reference on a paged fragment of an skb. + * skb_frag_ref - acquire a reference on a paged fragment of an skb * @skb: the buffer - * @f: the fragment offset. + * @f: the fragment offset * - * Takes an additional reference on the @f'th paged fragment of @skb. + * Acquires a reference on the @f'th fragment of @skb via skb_netmem_ref() + * (pp_ref_count if skb->pp_recycle and page_pool-backed, else non-pp + * backing refcount). Counterpart to skb_frag_unref(). */ static __always_inline void skb_frag_ref(struct sk_buff *skb, int f) { - __skb_frag_ref(&skb_shinfo(skb)->frags[f]); + skb_netmem_ref(skb_frag_netmem(&skb_shinfo(skb)->frags[f]), + skb->pp_recycle); } bool napi_pp_put_page(netmem_ref netmem); -- cgit v1.2.3 From fece8420e76fe53ee84f0439f18d026b4c7641da Mon Sep 17 00:00:00 2001 From: James Hilliard Date: Wed, 14 Oct 2026 12:33:48 -0600 Subject: xsk: freeze deferred pool teardown without blocking unregister MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deferred pool destruction calls ndo_bpf() under RTNL. system_wq is not frozen during system sleep, so that callback can run after a device has suspended and gated its clocks. Use system_freezable_wq so running destruction finishes before device suspend and new work waits until process thaw. Keep assigned pools visible to NETDEV_UNREGISTER independently of the socket list. A released socket has already left that list, but its final pool put can queue destruction after workqueues freeze. A resume-time unregister would then wait for a device reference whose release cannot run until the resume completes. Track assigned pools per netdev with netdev operations locking and detach remaining pools after the notifier socket walk, including copy-mode pools. This also covers leased queues without scanning pools from unrelated devices or network namespaces. Remove the entry on assignment failure and normal teardown. The deferred worker still owns the pool and later observes the cleared device pointer, avoiding a second driver detach or put. The lifetime problem was identified by code inspection of the deferred release and system-sleep paths. Fixes: 1c1efc2af158 ("xsk: Create and free buffer pool independently from umem") Signed-off-by: James Hilliard Reviewed-by: Björn Töpel Reviewed-by: Jason Xing Acked-by: Stanislav Fomichev Link: https://patch.msgid.link/20261014-xsk-suspend-teardown-v4-1-27795582e4a3@gmail.com Signed-off-by: Paolo Abeni --- include/linux/netdevice.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 3cff2174dc03..ac257221c7c5 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2545,6 +2545,11 @@ struct net_device { /* protected by rtnl_lock */ struct bpf_xdp_entity xdp_state[__MAX_XDP_MODE]; +#ifdef CONFIG_XDP_SOCKETS + /** @xsk_pools: assigned AF_XDP pools, ops protected */ + struct hlist_head xsk_pools; +#endif + u8 dev_addr_shadow[MAX_ADDR_LEN]; netdevice_tracker linkwatch_dev_tracker; netdevice_tracker watchdog_dev_tracker; -- cgit v1.2.3 From 258c3ae4a4af0c7948a3d99e7262701aaa350d31 Mon Sep 17 00:00:00 2001 From: Nicolai Buchwitz Date: Thu, 15 Oct 2026 10:16:38 +0200 Subject: net: rename skb_unshare() to skb_unclone_full() skb_unshare() only copies cloned skbs. A shared skb that is not a clone comes back unchanged, which the name doesn't suggest. The loopback selftest hooks got caught by this and hit BUG_ON(skb_shared()). Rename it to skb_unclone_full(). Like skb_unclone() it only acts on clones, but it copies the whole skb, not just the head. Suggested-by: Jakub Kicinski Signed-off-by: Nicolai Buchwitz Reviewed-by: Ioana Ciornei # dpaa2 Link: https://patch.msgid.link/20261015-nb-skb-unclone-full-v1-1-0dfbf01f60f2@tipi-net.de Signed-off-by: Jakub Kicinski --- include/linux/if_vlan.h | 16 ++++++++-------- include/linux/skbuff.h | 11 +++++++---- 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 975892367136..c863cdf60f01 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -427,8 +427,8 @@ static inline int __vlan_insert_tag(struct sk_buff *skb, * Inserts the VLAN tag into @skb as part of the payload at offset mac_len * Returns a VLAN tagged skb. This might change skb->head. * - * Following the skb_unshare() example, in case of error, the calling function - * doesn't have to worry about freeing the original skb. + * Following the skb_unclone_full() example, in case of error, the calling + * function doesn't have to worry about freeing the original skb. * * Does not change skb->protocol so this function can be used during receive. * @@ -458,8 +458,8 @@ static inline struct sk_buff *vlan_insert_inner_tag(struct sk_buff *skb, * Inserts the VLAN tag into @skb as part of the payload * Returns a VLAN tagged skb. This might change skb->head. * - * Following the skb_unshare() example, in case of error, the calling function - * doesn't have to worry about freeing the original skb. + * Following the skb_unclone_full() example, in case of error, the calling + * function doesn't have to worry about freeing the original skb. * * Does not change skb->protocol so this function can be used during receive. * @@ -480,8 +480,8 @@ static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb, * Inserts the VLAN tag into @skb as part of the payload * Returns a VLAN tagged skb. This might change skb->head. * - * Following the skb_unshare() example, in case of error, the calling function - * doesn't have to worry about freeing the original skb. + * Following the skb_unclone_full() example, in case of error, the calling + * function doesn't have to worry about freeing the original skb. * * Return: modified @skb on success, NULL on error (@skb is freed). */ @@ -524,8 +524,8 @@ static inline void __vlan_hwaccel_copy_tag(struct sk_buff *dst, const struct sk_ * * Pushes the VLAN tag from @skb->vlan_tci inside to the payload. * - * Following the skb_unshare() example, in case of error, the calling function - * doesn't have to worry about freeing the original skb. + * Following the skb_unclone_full() example, in case of error, the calling + * function doesn't have to worry about freeing the original skb. */ static inline struct sk_buff *__vlan_hwaccel_push_inside(struct sk_buff *skb) { diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index af1cbc2799b7..5079335f7aae 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2131,14 +2131,14 @@ static inline struct sk_buff *skb_share_check(struct sk_buff *skb, gfp_t pri) } /* - * Copy shared buffers into a new sk_buff. We effectively do COW on + * Copy cloned buffers into a new sk_buff. We effectively do COW on * packets to handle cases where we have a local reader and forward * and a couple of other messy ones. The normal one is tcpdumping * a packet that's being forwarded. */ /** - * skb_unshare - make a copy of a shared buffer + * skb_unclone_full - make a private copy of a cloned buffer * @skb: buffer to check * @pri: priority for memory allocation * @@ -2148,10 +2148,13 @@ static inline struct sk_buff *skb_share_check(struct sk_buff *skb, gfp_t pri) * the original buffer is returned. When called with a spinlock held or * from interrupt state @pri must be %GFP_ATOMIC * + * Unlike skb_unclone(), the paged data is copied as well. A buffer with + * skb->users > 1 that is not a clone is returned as is, use + * skb_share_check() for that case. + * * %NULL is returned on a memory allocation failure. */ -static inline struct sk_buff *skb_unshare(struct sk_buff *skb, - gfp_t pri) +static inline struct sk_buff *skb_unclone_full(struct sk_buff *skb, gfp_t pri) { might_sleep_if(gfpflags_allow_blocking(pri)); if (skb_cloned(skb)) { -- cgit v1.2.3 From 241c9ed785d0f6e5e3f5981d5652f6e1727e5f6d Mon Sep 17 00:00:00 2001 From: Peter Hunt Date: Tue, 13 Oct 2026 12:34:59 -0600 Subject: net: wwan: core: propagate modem control signals to port drivers The WWAN character device emulates the TTY modem-control ioctls (TIOCMGET/TIOCMSET/TIOCMBIC/TIOCMBIS) for AT and QCDM ports, but the result is only stored in port->at_data.mdmbits and never reaches the port driver. A driver therefore cannot act on the host raising or dropping DTR/RTS, even though some modems depend on it (e.g. they withhold unsolicited AT result codes until the host asserts DTR). Add an optional ->dtr_rts(port, mdmbits) operation to struct wwan_port_ops. Drivers that implement it receive the TIOCM output bitmask so they can assert or de-assert DTR and RTS independently. As in tty_tiocmset(), the wwan core keeps only the output bits (DTR, RTS, OUT1, OUT2, LOOP) of the TIOCMSET/TIOCMBIS/TIOCMBIC value in port->at_data.mdmbits, and calls ->dtr_rts when DTR or RTS actually changes, gated on WWAN_PORT_AT to match the open/close raise/drop behaviour. Also raise DTR/RTS in wwan_port_op_start on first open of an AT port when the driver implements ->dtr_rts, and drop them in wwan_port_op_stop on last close if HUPCL is set in the port's termios. This follows TTY open/close semantics, although the termios baud rate is not used, and means individual drivers do not need to implement this themselves. As on a TTY, HUPCL defaults to on for AT ports, and userspace can clear it with TCSETS to keep DTR asserted across close, for example so that closing the port does not end a call on a modem set to AT&D1/AT&D2. TCSETS and TCSETS2 now only commit the new termios when the copy from userspace succeeds, so a faulting call cannot silently clear HUPCL. ->dtr_rts must be called under ops_lock, which serialises port ops and protects against port removal (removal clears port->ops under it). So that updates to the TIOCM state and the ->dtr_rts calls are serialised together, the termios/TIOCM state now also lives under ops_lock and the separate data_lock is removed. The AT/QCDM ioctl handler only holds ops_lock while it reads or updates that state, never across a user-memory copy, and takes it interruptibly since a driver's blocking write holds it while it waits. Ioctls that do not touch that state, such as TCFLSH, TIOCEXCL and the FIONREAD fallback, do not take it. wwan_remove_port() also drops DTR/RTS before ->stop() when a port is removed while still open, regardless of HUPCL since the device is going away. The raise and drop paths go through two small helpers, which do the AT port and ->dtr_rts checks and pass the driver the resulting bitmask. Signed-off-by: Peter Hunt Reviewed-by: Loic Poulain Link: https://patch.msgid.link/20261013183500.261229-2-peter.hunt@opengear.com Signed-off-by: Jakub Kicinski --- include/linux/wwan.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include/linux') diff --git a/include/linux/wwan.h b/include/linux/wwan.h index 1e0e2cb53579..23a8a8ee473d 100644 --- a/include/linux/wwan.h +++ b/include/linux/wwan.h @@ -57,6 +57,14 @@ struct wwan_port; * @tx_blocking: Optional blocking routine that sends WWAN port protocol data * to the device. * @tx_poll: Optional routine that sets additional TX poll flags. + * @dtr_rts: Optional routine that updates the modem control lines to match + * @mdmbits, the TIOCM_* output bits (DTR, RTS, OUT1, OUT2, LOOP) + * currently set for the port. Called when the port is first opened + * and ->start() has succeeded, on last close if HUPCL is set, when + * the port is removed while still open, and when TIOCMSET, TIOCMBIS + * or TIOCMBIC changes DTR or RTS. Only called for WWAN_PORT_AT ports, + * as only the AT (DUN) port carries the modem's virtual RS-232 + * control signals. * * The wwan_port_ops structure contains a list of low-level operations * that control a WWAN port device. All functions are mandatory unless specified. @@ -70,6 +78,7 @@ struct wwan_port_ops { int (*tx_blocking)(struct wwan_port *port, struct sk_buff *skb); __poll_t (*tx_poll)(struct wwan_port *port, struct file *filp, poll_table *wait); + void (*dtr_rts)(struct wwan_port *port, unsigned int mdmbits); }; /** struct wwan_port_caps - The WWAN port capbilities -- cgit v1.2.3 From 56f8d919739b588e2ad8cb9fb9eff704f32afaab Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 15 Oct 2026 10:00:03 -0700 Subject: netdev: Hide the netdev_priv() origin from GCC in netdev_from_priv() GCC 15.1 and later can compute an object size of 0 for a pointer that container_of() derives from a pointer into a __counted_by flexible array member[1]; Clang gets it right. netdev_from_priv() does this with struct net_device's "priv" array, so when GCC can see that its argument came from netdev_priv(), FORTIFY_SOURCE sees a zero-sized net_device. Since commit 9027497a25e3c ("team: use netdev_from_priv()"), adding a port of another type to a team device can then fail the memcpy() to "dev->broadcast" in team_setup_by_port(), which GCC sees through after inlining team_port_add() into team_add_slave(): memcpy: detected buffer overflow: 4 byte write of buffer size 0 ... kernel BUG at lib/string_helpers.c:1044! ... Call Trace: team_add_slave.cold+0x88/0x201 do_set_master+0x11c/0x180 do_setlink.isra.0+0x3a4/0x1410 Whether GCC inlines that far depends on the architecture and the configuration. It does on ppc64le, where this was reported, and on x86_64 with defconfig plus hardening.config or with Debian's configuration, but not with allmodconfig. Hide where "priv" came from with OPTIMIZER_HIDE_VAR(), so GCC sees a net_device of unknown size whose members have their declared sizes. (An "unknown" size is considered uncheckable by FORTIFY.) FORTIFY still bounds writes to members; only the whole-object size becomes unknown, as it already is for any net_device pointer GCC can't trace to its allocation. In an extracted PoC, the __builtin_dynamic_object_size() of "dev->broadcast" for the two types FORTIFY sees, before and after this patch: GCC 16.2.0 Clang 22 and 24 before after plain pointer, whole object unknown unknown 44 container_of(), whole object 0 unknown 44 container_of(), member 0 32 32 In addition to getting the bogus "0" fixed in GCC, I'll be following up to solve the whole-object visiblity disparity as well. Build tested with GCC 16.2.0: ARCH=x86_64 defconfig with hardening.config, CONFIG_NET_TEAM=y, and CONFIG_NET_IPGRE=y; ARCH=arm64 defconfig with hardening.config, CONFIG_NET_TEAM=y, CONFIG_PPP=y, and CONFIG_NET_AIROHA=m; and drivers/net/team/, drivers/net/ppp/, and drivers/net/ethernet/airoha/ in ARCH=x86_64 allmodconfig. Under QEMU, the x86_64 kernel hits the BUG above when adding the GRE fallback device "gre0" as a port of a new team device without this patch, and adds it with the patch. Reported-by: Yeswanth Krishna Tellakula Closes: https://lore.kernel.org/all/3ad19e86-234c-408f-896e-0d6c774fea49@linux.ibm.com/ Fixes: 9027497a25e3c ("team: use netdev_from_priv()") Cc: stable@vger.kernel.org Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127875 [1] Signed-off-by: Kees Cook Link: https://patch.msgid.link/20261015165959.i.798-kees@kernel.org Signed-off-by: Jakub Kicinski --- include/linux/netdevice.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 8fbe3a5d8169..f064c9c989ee 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2841,6 +2841,13 @@ static inline void *netdev_priv(const struct net_device *dev) */ static inline struct net_device *netdev_from_priv(const void *priv) { + /* + * When GCC can see that @priv came from netdev_priv(), it can + * compute an object size of 0 for the net_device and its members, + * which makes FORTIFY_SOURCE fail valid accesses through the result: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127875 + */ + OPTIMIZER_HIDE_VAR(priv); return container_of(priv, struct net_device, priv); } -- cgit v1.2.3 From 78d4bd22ec9df490135303c00e190ac43d5c334a Mon Sep 17 00:00:00 2001 From: Carolina Jubran Date: Mon, 19 Oct 2026 20:41:52 +0300 Subject: net: skbuff: don't copy alloc_cpu in skb header copies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 68822bdf76f1 ("net: generalize skb freeing deferral to per-cpu lists") added alloc_cpu to struct sk_buff and placed it in the headers group copied by __copy_skb_header(). This is wrong for newly allocated skbs. For example, skb_segment() allocates a new skb and records the current CPU in alloc_cpu, but __copy_skb_header() overwrites it with the value from the original skb. If the original skb was allocated on another CPU, the segment may later be treated as remotely allocated and unnecessarily deferred there when it is freed. Move alloc_cpu out of the headers group so it is preserved across header copies. Copy it explicitly in skb_clone(), which allocates the skb object directly instead of going through __alloc_skb(). This was discovered while investigating a throughput regression with software IPsec. The load used 512 IPsec tunnels carrying traffic over VXLAN, with 512 parallel iperf3 flows and an MTU of 4500. Before the fix: 16.09% queued_spin_lock_slowpath | --15.90%--_raw_spin_lock_irqsave | --9.37%--__slab_free kfree skb_release_data napi_consume_skb mlx5e_poll_tx_cq After the fix: 6.84% queued_spin_lock_slowpath | --6.57%--_raw_spin_lock_irqsave | --5.00%--__slab_free kfree skb_release_data napi_consume_skb mlx5e_poll_tx_cq Fixes: 68822bdf76f1 ("net: generalize skb freeing deferral to per-cpu lists") Signed-off-by: Carolina Jubran Reviewed-by: Dragos Tatulea Reviewed-by: Björn Töpel Reviewed-by: Jason Xing Reviewed-by: Eric Dumazet Reviewed-by: Kuniyuki Iwashima Link: https://patch.msgid.link/20261019174152.2932829-1-cjubran@nvidia.com Signed-off-by: Jakub Kicinski --- include/linux/skbuff.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index a3ff380d43f0..d6894f463bf4 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1036,8 +1036,6 @@ struct sk_buff { __u16 tc_index; /* traffic control index */ #endif - u16 alloc_cpu; - union { __wsum csum; struct { @@ -1088,6 +1086,8 @@ struct sk_buff { ); /* end headers group */ + u16 alloc_cpu; + /* These elements must be at the end, see alloc_skb() for details. */ sk_buff_data_t tail; sk_buff_data_t end; -- cgit v1.2.3 From 778a262a6c690621a5c37d2a1cebc88e4585a870 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Mon, 12 Oct 2026 10:17:03 +0900 Subject: net: change netdev_hw_addr_list count through helpers The count of a netdev_hw_addr_list is changed in several places of dev_addr_lists.c and a few drivers read it directly. The next patch needs to account every change of the count of dev->mc. Add __hw_addr_count_add(), __hw_addr_count_inc(), __hw_addr_count_dec() and __hw_addr_count_reset(), use them for every change of the count and rename the field to _count so that a direct write stands out. Readers keep using netdev_hw_addr_list_count() and the netdev_uc_count() and netdev_mc_count() helpers, the few that read the field directly are converted. No functional change. Signed-off-by: Yuyang Huang Reviewed-by: Nicolas Dichtel Link: https://patch.msgid.link/20261012011707.3378-3-sigefriedhyy@gmail.com Signed-off-by: Paolo Abeni --- include/linux/netdevice.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 53d5e9c9a674..cf25c16bdba8 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -252,13 +252,16 @@ struct netdev_hw_addr { struct netdev_hw_addr_list { struct list_head list; - int count; + /* Only changed through the __hw_addr_count_* helpers after + * __hw_addr_init() + */ + int _count; /* Auxiliary tree for faster lookup on addition and deletion */ struct rb_root tree; }; -#define netdev_hw_addr_list_count(l) ((l)->count) +#define netdev_hw_addr_list_count(l) ((l)->_count) #define netdev_hw_addr_list_empty(l) (netdev_hw_addr_list_count(l) == 0) #define netdev_hw_addr_list_for_each(ha, l) \ list_for_each_entry(ha, &(l)->list, list) -- cgit v1.2.3 From 646cb8868bd29646b79e11fc0d574b8e25801a23 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Mon, 12 Oct 2026 10:17:04 +0900 Subject: net: add a generation counter for dev->mc changes A multi-part RTM_GETMULTICAST dump of dev->mc resumes by position, so entries added or removed between two dump rounds can be skipped or repeated. The IPv4 and IPv6 dumps report that with NLM_F_DUMP_INTR by stamping cb->seq from a per netns generation counter combined with dev_base_seq, see inet_base_seq(). Add the equivalent for the device multicast lists: a per netns counter bumped whenever an entry is added to or removed from any dev->mc. The list helpers do not know which device a list belongs to, so give netdev_hw_addr_list an mc_dev pointer, set for dev->mc only, and bump the counter of dev_net(mc_dev) from the count helpers. That covers the dev_mc_* helpers, both lists of a sync, the hardware sync helpers drivers call from their rx mode callbacks or their own workers and the reconciliation after an asynchronous rx mode update. It is atomic since the writers only hold the address lock of their own device. Used by the following patch for the AF_PACKET multicast dump. Signed-off-by: Yuyang Huang Reviewed-by: Nicolas Dichtel Link: https://patch.msgid.link/20261012011707.3378-4-sigefriedhyy@gmail.com Signed-off-by: Paolo Abeni --- include/linux/netdevice.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index cf25c16bdba8..f52c46e28e3a 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -259,6 +259,9 @@ struct netdev_hw_addr_list { /* Auxiliary tree for faster lookup on addition and deletion */ struct rb_root tree; + + /* Set for dev->mc only, the device the list belongs to */ + struct net_device *mc_dev; }; #define netdev_hw_addr_list_count(l) ((l)->_count) -- cgit v1.2.3 From ebff14be20c3f2c0fbfa2da3321e3043a0ff8650 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Mon, 12 Oct 2026 10:17:05 +0900 Subject: net: add AF_PACKET multicast dumps RTM_GETMULTICAST dumps IPv4 and IPv6 multicast group memberships, but the device multicast list (dev->mc) is only available through /proc/net/dev_mcast, so "ip maddr show" still has to parse procfs for its link-layer entries. Handle RTM_GETMULTICAST dumps with ifa_family set to AF_PACKET next to the dev->mc helpers in dev_addr_lists.c and report every entry of dev->mc in the existing ifaddrmsg format: - IFA_MULTICAST carries the raw link-layer address - IFA_MC_USERS carries the entry reference count - IFA_F_GLOBAL in IFA_FLAGS reports netdev_hw_addr::global_use, set by dev_mc_add_global() (SIOCADDMULTI) and dev_mc_add_excl() ("bridge fdb add ... self"), i.e. entries added explicitly rather than by a protocol join. This is the static column of /proc/net/dev_mcast - ifa_scope is RT_SCOPE_LINK This covers every column of /proc/net/dev_mcast. AF_PACKET is the family iproute2 already uses for link-layer addresses ("ip -0"). The default FDB dump also walks dev->mc, but only for Ethernet devices and only if the driver uses it, vxlan for example does not, and it has no users count or global_use bit. Extending it would change "bridge fdb show" output and add NDA_* attributes. Requests are always validated, there are no legacy users: prefixlen, flags and scope must be zero, ifa_index selects one device and IFA_TARGET_NETNSID is the only attribute accepted. The dump runs under RCU and netif_addr_lock_bh() without RTNL. cb->seq is set from the dev->mc generation counter and dev_base_seq before each round and checked after it, so an entry added or removed since the previous round sets NLM_F_DUMP_INTR. A round without a message skips the check and cb->seq is set once more after the round, so the NLMSG_DONE check reports a change made during the last round or before an empty one. Signed-off-by: Yuyang Huang Reviewed-by: Nicolas Dichtel Link: https://patch.msgid.link/20261012011707.3378-5-sigefriedhyy@gmail.com Signed-off-by: Paolo Abeni --- include/linux/netdevice.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f52c46e28e3a..79f9ee0cf799 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -5181,6 +5181,7 @@ int dev_mc_sync_multiple(struct net_device *to, struct net_device *from); void dev_mc_unsync(struct net_device *to, struct net_device *from); void dev_mc_flush(struct net_device *dev); void dev_mc_init(struct net_device *dev); +int dev_mc_dump(struct sk_buff *skb, struct netlink_callback *cb); /** * __dev_mc_sync - Synchronize device's multicast list -- cgit v1.2.3 From 9fd93893b6fa0f22d9fd186d5b3467538d5f16f4 Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Fri, 16 Oct 2026 15:30:57 +0200 Subject: net: phy: phy_link_topology: Track ports in phy_link_topology phy_port is aimed at representing the various physical interfaces of a net_device. They can be controlled by various components in the link, such as the Ethernet PHY, the Ethernet MAC, and SFP module, etc. Let's therefore make so we keep track of all the ports connected to a netdev in phy_link_topology. The only ports added for now are phy-driven ports. Reviewed-by: Andrew Lunn Tested-by: Aleksei Sviridkin Reviewed-by: Christophe Leroy (CS GROUP) Tested-by: Christophe Leroy (CS GROUP) Signed-off-by: Maxime Chevallier Link: https://patch.msgid.link/20261016133107.54054-3-maxime.chevallier@bootlin.com Signed-off-by: Jakub Kicinski --- include/linux/phy_link_topology.h | 18 ++++++++++++++++++ include/linux/phy_port.h | 2 ++ 2 files changed, 20 insertions(+) (limited to 'include/linux') diff --git a/include/linux/phy_link_topology.h b/include/linux/phy_link_topology.h index 95575f68d5bc..296ee514ba46 100644 --- a/include/linux/phy_link_topology.h +++ b/include/linux/phy_link_topology.h @@ -16,11 +16,15 @@ struct xarray; struct phy_device; +struct phy_port; struct sfp_bus; struct phy_link_topology { struct xarray phys; u32 next_phy_index; + + struct xarray ports; + u32 next_port_index; }; struct phy_device_node { @@ -48,6 +52,9 @@ int phy_link_topo_add_phy(struct net_device *dev, void phy_link_topo_del_phy(struct net_device *dev, struct phy_device *phy); +int phy_link_topo_add_port(struct net_device *dev, struct phy_port *port); +void phy_link_topo_del_port(struct net_device *dev, struct phy_port *port); + static inline struct phy_device * phy_link_topo_get_phy(struct net_device *dev, u32 phyindex) { @@ -77,6 +84,17 @@ static inline void phy_link_topo_del_phy(struct net_device *dev, { } +static inline int phy_link_topo_add_port(struct net_device *dev, + struct phy_port *port) +{ + return 0; +} + +static inline void phy_link_topo_del_port(struct net_device *dev, + struct phy_port *port) +{ +} + static inline struct phy_device * phy_link_topo_get_phy(struct net_device *dev, u32 phyindex) { diff --git a/include/linux/phy_port.h b/include/linux/phy_port.h index 0ef0f5ce4709..4e2a3fdd2f2e 100644 --- a/include/linux/phy_port.h +++ b/include/linux/phy_port.h @@ -36,6 +36,7 @@ struct phy_port_ops { /** * struct phy_port - A representation of a network device physical interface * + * @id: Unique identifier for the port within the topology * @head: Used by the port's parent to list ports * @parent_type: The type of device this port is directly connected to * @phy: If the parent is PHY_PORT_PHYDEV, the PHY controlling that port @@ -52,6 +53,7 @@ struct phy_port_ops { * @is_sfp: Indicates if this port drives an SFP cage. */ struct phy_port { + u32 id; struct list_head head; enum phy_port_parent parent_type; union { -- cgit v1.2.3 From 51ebb13c1d9658328b66b8f67e7992f708567807 Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Fri, 16 Oct 2026 15:31:00 +0200 Subject: net: phy: Represent PHY-less SFP modules with phy_port Now that the SFP bus infrastructure notifies when PHY-less modules are connected, we can create a phy_port to represent it. Instead of letting the SFP subsystem handle that, the Bus' upstream is in charge of maintaining that phy_port and register it to the topology, as the upstream (in this case a phy device) is directly interacting with the underlying net_device. Add a phy_caps helper to get the achievable modes on this module based on what the phy_port representing the bus supports. Reviewed-by: Andrew Lunn Tested-by: Aleksei Sviridkin Reviewed-by: Christophe Leroy (CS GROUP) Tested-by: Christophe Leroy (CS GROUP) Signed-off-by: Maxime Chevallier Link: https://patch.msgid.link/20261016133107.54054-6-maxime.chevallier@bootlin.com Signed-off-by: Jakub Kicinski --- include/linux/phy.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux') diff --git a/include/linux/phy.h b/include/linux/phy.h index a5a419bc400e..782d3ea2964e 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -612,7 +612,10 @@ struct phy_oatc14_sqi_capability { * @irq: IRQ number of the PHY's interrupt (-1 if none) * @phylink: Pointer to phylink instance for this PHY * @sfp_bus_attached: Flag indicating whether the SFP bus has been attached + * @has_sfp_mod_phy: Set true if downstream SFP bus's module contains a PHY * @sfp_bus: SFP bus attached to this PHY's fiber port + * @sfp_cage_port: The phy_port connected to the downstream SFP cage + * @mod_port: phy_port representing the SFP module, if it is phy-less * @attached_dev: The attached enet driver's device instance ptr * @adjust_link: Callback for the enet controller to respond to changes: in the * link state. @@ -804,7 +807,10 @@ struct phy_device { /* This may be modified under the rtnl lock */ bool sfp_bus_attached; + bool has_sfp_mod_phy; struct sfp_bus *sfp_bus; + struct phy_port *sfp_cage_port; + struct phy_port *mod_port; struct phylink *phylink; struct net_device *attached_dev; struct mii_timestamper *mii_ts; -- cgit v1.2.3 From 9e7cd33fafb2ce1fd6cf19fd20f486ea341e6c0c Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Fri, 16 Oct 2026 15:31:01 +0200 Subject: net: phy: phy_port: Store information about a port's upstream MII phy_ports are not meant to be connected directly to a link partner. They are meant to feed into some media converter devices that will expose an MDI phy_port, so far we only support SFP modules for that. In the case an MDI phy_port is backed by an MII port (e.g. a SFP module's port, backed by the SFP cage port), let's keep track of the port id of the MII port backing it. Reviewed-by: Andrew Lunn Tested-by: Aleksei Sviridkin Reviewed-by: Christophe Leroy (CS GROUP) Tested-by: Christophe Leroy (CS GROUP) Signed-off-by: Maxime Chevallier Link: https://patch.msgid.link/20261016133107.54054-7-maxime.chevallier@bootlin.com Signed-off-by: Jakub Kicinski --- include/linux/phy.h | 4 ++++ include/linux/phy_port.h | 3 +++ 2 files changed, 7 insertions(+) (limited to 'include/linux') diff --git a/include/linux/phy.h b/include/linux/phy.h index 782d3ea2964e..21afc2082b17 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -616,6 +616,7 @@ struct phy_oatc14_sqi_capability { * @sfp_bus: SFP bus attached to this PHY's fiber port * @sfp_cage_port: The phy_port connected to the downstream SFP cage * @mod_port: phy_port representing the SFP module, if it is phy-less + * @upstream_port: phy_port this PHY's MII attaches to, if any * @attached_dev: The attached enet driver's device instance ptr * @adjust_link: Callback for the enet controller to respond to changes: in the * link state. @@ -811,6 +812,7 @@ struct phy_device { struct sfp_bus *sfp_bus; struct phy_port *sfp_cage_port; struct phy_port *mod_port; + struct phy_port *upstream_port; struct phylink *phylink; struct net_device *attached_dev; struct mii_timestamper *mii_ts; @@ -2495,6 +2497,8 @@ int __phy_hwtstamp_set(struct phy_device *phydev, struct phy_port *phy_get_sfp_port(struct phy_device *phydev); +void phy_set_upstream_port(struct phy_device *phydev, struct phy_port *port); + /** * phy_module_driver() - Helper macro for registering PHY drivers * @__phy_drivers: array of PHY drivers to register diff --git a/include/linux/phy_port.h b/include/linux/phy_port.h index 4e2a3fdd2f2e..8f45c031cbc1 100644 --- a/include/linux/phy_port.h +++ b/include/linux/phy_port.h @@ -40,6 +40,8 @@ struct phy_port_ops { * @head: Used by the port's parent to list ports * @parent_type: The type of device this port is directly connected to * @phy: If the parent is PHY_PORT_PHYDEV, the PHY controlling that port + * @upstream_port: Indicates the MII port that feeds this port, if any, + * e.g. the SFP cage port for a SFP module port. * @ops: Callback ops implemented by the port controller * @pairs: The number of pairs this port has, 0 if not applicable * @mediums: Bitmask of the physical mediums this port provides access to @@ -59,6 +61,7 @@ struct phy_port { union { struct phy_device *phy; }; + struct phy_port *upstream_port; const struct phy_port_ops *ops; -- cgit v1.2.3 From b06f1e6c85ba9c7c42ef7161ae35e3b2f2dbdc6c Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Fri, 16 Oct 2026 15:31:02 +0200 Subject: net: phy: phy_link_topology: Add a helper to retrieve ports In order to allow netlink access to phy_ports, let's add a helper to retrieve them. When handling a port coming from phy_link_topology, the caller must hold rtnl until it's done with it. We don't really support PHY and phy_port operation on ops-locked devices yet, warn when we try to do so on such an interface. Reviewed-by: Andrew Lunn Tested-by: Aleksei Sviridkin Reviewed-by: Christophe Leroy (CS GROUP) Tested-by: Christophe Leroy (CS GROUP) Signed-off-by: Maxime Chevallier Link: https://patch.msgid.link/20261016133107.54054-8-maxime.chevallier@bootlin.com Signed-off-by: Jakub Kicinski --- include/linux/phy_link_topology.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'include/linux') diff --git a/include/linux/phy_link_topology.h b/include/linux/phy_link_topology.h index 296ee514ba46..f2e493c433ff 100644 --- a/include/linux/phy_link_topology.h +++ b/include/linux/phy_link_topology.h @@ -13,6 +13,7 @@ #include #include +#include struct xarray; struct phy_device; @@ -71,6 +72,24 @@ phy_link_topo_get_phy(struct net_device *dev, u32 phyindex) return NULL; } +static inline struct phy_port * +phy_link_topo_get_port(struct net_device *dev, u32 port_id) +{ + struct phy_link_topology *topo = dev->link_topo; + + if (!topo) + return NULL; + + /* ports in the topo are RTNL protected, but may be accessed under + * netdev_lock for ops-locked devices. For now keep them under rtnl + * protection, as no ops-locked devices have phy_port capabilities + * yet. + */ + ASSERT_RTNL(); + + return xa_load(&topo->ports, port_id); +} + #else static inline int phy_link_topo_add_phy(struct net_device *dev, struct phy_device *phy, @@ -100,6 +119,12 @@ phy_link_topo_get_phy(struct net_device *dev, u32 phyindex) { return NULL; } + +static inline struct phy_port * +phy_link_topo_get_port(struct net_device *dev, u32 port_id) +{ + return NULL; +} #endif #endif /* __PHY_LINK_TOPOLOGY_H */ -- cgit v1.2.3 From b9e7cb89aac8c073f29d897dbf5bda078237ca5e Mon Sep 17 00:00:00 2001 From: Coia Prant Date: Sat, 17 Oct 2026 13:44:01 +0800 Subject: net: pcs: xpcs: add Rockchip RK3568 platform glue driver The RK3568 SoC integrates a Synopsys DesignWare XPCS that is accessed via APB3 memory-mapped registers. This driver provides the glue logic to make the XPCS accessible to the generic pcs-xpcs core. The XPCS block contains four MII ports (0..3). On RK3568 the MII port used by SGMII follows the MAC it is routed to: GMAC0 maps to port 0 and GMAC1 maps to port 1. The glue driver receives the port index from the MAC side and passes it to xpcs_create_mdiodev(). The hardware maps these ports to different MMDs: - port 0: MMD 7 (ROCKCHIP_MMD_MII) - port 1: MMD 2 (ROCKCHIP_MMD_MII1) - port 2: MMD 3 (ROCKCHIP_MMD_MII2) - port 3: MMD 4 (ROCKCHIP_MMD_MII3) This driver creates a virtual MDIO bus that translates MDIO operations to APB3 register accesses, with proper address remapping for each port. The generic xpcs driver then creates a phylink_pcs instance on top of this bus, allowing the MAC to use the PCS via the standard phylink API. The generic XPCS platform glue (pcs-xpcs-plat.o) is split out of the pcs_xpcs composite object into its own module, gated behind the new PCS_XPCS_PLATFORM symbol. There is no in-tree user of the generic snps,dw-xpcs glue that would need it selected by default, so the symbol has no default and platforms that need it select it explicitly. PCS_XPCS_ROCKCHIP selects GENERIC_PHY and PM_GENERIC_DOMAINS. ARCH_ROCKCHIP already selects PM, so the dependency of PM_GENERIC_DOMAINS on PM is satisfied on the target platform. The EEE multiplier is derived at runtime from the EEE clock rate instead of being hardcoded, because the clock is muxed between gpll200 (200 MHz) and cpll125 (125 MHz) and can be changed by the board or firmware. A 64-bit intermediate avoids overflow on 32-bit builds, and the result is clamped to the 4-bit DW_VR_MII_EEE_MULT_FACT_100NS field. Power management ================ The XPCS, its SerDes PHY and the SATA/PCIe controllers share the PD_PIPE power domain on RK3568. genpd powers the domain down during system suspend once every consumer is suspended, which also kills the SerDes and the XPCS. Boards that rely on MAC WoL need the PCS and SerDes alive to receive magic packets, so PD_PIPE must stay powered across system suspend. Keep it on by marking the XPCS as part of the wakeup path via device_set_wakeup_path(). genpd then leaves the domain powered, because the Rockchip power domain driver sets GENPD_FLAG_ACTIVE_WAKEUP on PD_PIPE, which makes genpd check the wakeup path of its consumers during system suspend. This is unconditional because the XPCS core currently has no platform callback through which a consumer could convey the MAC WoL state, and the state itself is dynamic: WoL is toggled at runtime via ethtool, so a static DT property cannot express it either. The affected hardware is limited to RK3568 boards using SGMII, which are always-on routers where system suspend is not a realistic use case; the extra power draw is therefore acceptable. Runtime PM is unaffected: the runtime callbacks only gate the CSR clock, and dev_pm_genpd_rpm_always_on() already keeps PD_PIPE on at runtime. Link: https://dl.radxa.com/rock3/docs/hw/datasheet/Rockchip%20RK3568%20TRM%20Part1%20V1.1-20210301.pdf (Page 59, CRU_CLKSEL_CON29) Link: https://dl.radxa.com/rock3/docs/hw/datasheet/Rockchip%20RK3568%20TRM%20Part2%20V1.1-20210301.pdf (Page 2078) Signed-off-by: Coia Prant Link: https://patch.msgid.link/20261017054406.1828061-4-coiaprant@gmail.com Signed-off-by: Jakub Kicinski --- include/linux/pcs/pcs-xpcs-rk.h | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 include/linux/pcs/pcs-xpcs-rk.h (limited to 'include/linux') diff --git a/include/linux/pcs/pcs-xpcs-rk.h b/include/linux/pcs/pcs-xpcs-rk.h new file mode 100644 index 000000000000..e3ca3d51f7c7 --- /dev/null +++ b/include/linux/pcs/pcs-xpcs-rk.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_PCS_XPCS_ROCKCHIP_H +#define __LINUX_PCS_XPCS_ROCKCHIP_H + +#include +#include +#include + +struct dw_xpcs *xpcs_rk_create(struct device *dev, struct device_node *pcs, int port); + +#endif /* __LINUX_PCS_XPCS_ROCKCHIP_H */ -- cgit v1.2.3 From 2620efb2cec11628ff419dc876981e1f8fed664a Mon Sep 17 00:00:00 2001 From: Mina Almasry Date: Wed, 21 Oct 2026 01:55:58 +0000 Subject: netmem: rename get/put_netmem() to netmem_inc/dec_ref() Follow the object_action() naming convention for netmem non-page_pool reference helpers by renaming get_netmem() and put_netmem() to netmem_inc_ref() and netmem_dec_ref(). Use netmem_inc_ref() and netmem_dec_ref() rather than netmem_ref() and netmem_unref() because netmem_ref is already a typedef (typedef unsigned long __bitwise netmem_ref). Suggested-by: Jakub Kicinski Signed-off-by: Mina Almasry Link: https://patch.msgid.link/20261021015558.4124825-3-almasrymina@google.com Signed-off-by: Jakub Kicinski --- include/linux/skbuff_ref.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/skbuff_ref.h b/include/linux/skbuff_ref.h index f768a3fa1d60..b6f6da556ee9 100644 --- a/include/linux/skbuff_ref.h +++ b/include/linux/skbuff_ref.h @@ -18,7 +18,7 @@ bool napi_pp_get_page(netmem_ref netmem); * * Acquires pp_ref_count via napi_pp_get_page() if @recycle is true and * @netmem belongs to a page_pool; otherwise acquires a non-pp backing - * reference via get_netmem(). Counterpart to skb_netmem_unref(). + * reference via netmem_inc_ref(). Counterpart to skb_netmem_unref(). */ static __always_inline void skb_netmem_ref(netmem_ref netmem, bool recycle) { @@ -26,7 +26,7 @@ static __always_inline void skb_netmem_ref(netmem_ref netmem, bool recycle) if (recycle && napi_pp_get_page(netmem)) return; #endif - get_netmem(netmem); + netmem_inc_ref(netmem); } /** @@ -53,7 +53,7 @@ bool napi_pp_put_page(netmem_ref netmem); * * Drops pp_ref_count via napi_pp_put_page() if @recycle is true and @netmem * belongs to a page_pool; otherwise drops a non-pp backing reference via - * put_netmem(). Counterpart to skb_netmem_ref(). + * netmem_dec_ref(). Counterpart to skb_netmem_ref(). */ static __always_inline void skb_netmem_unref(netmem_ref netmem, bool recycle) { @@ -61,7 +61,7 @@ static __always_inline void skb_netmem_unref(netmem_ref netmem, bool recycle) if (recycle && napi_pp_put_page(netmem)) return; #endif - put_netmem(netmem); + netmem_dec_ref(netmem); } /** -- cgit v1.2.3 From 4957ea03bf2696f5da12c09144f48d040696ecc2 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 20 Oct 2026 17:19:54 +0200 Subject: net: shrink the payload-only part of skb dataref to one bit skb_shinfo(skb)->dataref is split in two 16-bit halves: the lower one counts all references, the upper one the payload-only (nohdr) references. __skb_clone() increments dataref without bound, and skb_cloned() only checks the low 16 bits. With 65,537 references the low half reads 1, the head looks private, and pskb_expand_head() (or skb_unclone(), skb_cow(), ...) frees it while clones still point to it. An unprivileged user can reach this from a user and network namespace: about 32,770 AF_PACKET sockets on lo bring dataref to 0x10001, then any pskb_expand_head() on the receive path (here a pull of a large IPv6 Hop-by-Hop header) frees the shared head: BUG: KASAN: slab-use-after-free in _copy_to_iter+0x187/0x1330 Read of size 1590 at addr ff110001104a9002 by task dataref_wrap/87 skb_copy_datagram_iter+0x60/0x190 packet_recvmsg+0x1f5/0x12b0 __sys_recvfrom+0x18d/0x290 Freed by task 87: kfree+0xf3/0x3b0 pskb_expand_head+0x344/0xeb0 __pskb_pull_tail+0xf9/0x1bf0 ipv6_parse_hopopts+0x377/0x4f0 ip6_rcv_core+0xc67/0x1620 The upper half never holds more than 1. It is only set by __skb_header_release(), with atomic_set() on an skb owning its head (TCP/SCTP output, and GRO which never sees cloned skbs). __skb_clone() clears nohdr, and __copy_skb_header() does not copy it. Move SKB_DATAREF_SHIFT to 30, so that the reference count gets 30 bits, and dataref stays positive. Wrapping it would need 2^30 live clones of a single skb, which socket buffer limits and memory make unreachable. This issue was found by Anthropic using Claude, and validated by Ada Logics. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: Stephan Lipp Signed-off-by: Eric Dumazet Link: https://patch.msgid.link/20261020151954.22953-1-edumazet@kernel.org Signed-off-by: Jakub Kicinski --- include/linux/skbuff.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index d6894f463bf4..707082f68f21 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -633,9 +633,9 @@ struct skb_shared_info { * * Transport layers send out clones of payload skbs they hold for * retransmissions. To allow lower layers of the stack to prepend their headers - * we split &skb_shared_info.dataref into two halves. - * The lower 16 bits count the overall number of references. - * The higher 16 bits indicate how many of the references are payload-only. + * we split &skb_shared_info.dataref into two parts. + * The lower 30 bits count the overall number of references. + * Bit 30 indicates whether one of the references is payload-only. * skb_header_cloned() checks if skb is allowed to add / write the headers. * * The creator of the skb (e.g. TCP) marks its skb as &sk_buff.nohdr @@ -655,7 +655,7 @@ struct skb_shared_info { * Having multiple payload-only skbs with different lengths of hdr_len is not * possible. The payload-only skbs should never leave their owner. */ -#define SKB_DATAREF_SHIFT 16 +#define SKB_DATAREF_SHIFT 30 #define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1) -- cgit v1.2.3