From d11706b56a3f738a93bb2af8e94d6fab506e81b6 Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Mon, 8 Jun 2026 08:40:12 -0700 Subject: net: change ndo_set_rx_mode_async return type to int Change the return type of ndo_set_rx_mode_async from void to int to allow drivers to report failures back to the core stack. This is a prerequisite for adding retry logic in the core when drivers fail to program RX filters (e.g. bnxt VF when PF is unavailable). All existing implementations return 0 for now, maintaining current behavior. Signed-off-by: Stanislav Fomichev Link: https://patch.msgid.link/20260608154014.227538-2-sdf@fomichev.me Signed-off-by: Jakub Kicinski --- include/linux/netdevice.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 9b876cd930d7..51ec2df02094 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1122,13 +1122,14 @@ struct netdev_net_notifier { * Cannot sleep, called with netif_addr_lock_bh held. * Deprecated in favor of ndo_set_rx_mode_async. * - * void (*ndo_set_rx_mode_async)(struct net_device *dev, - * struct netdev_hw_addr_list *uc, - * struct netdev_hw_addr_list *mc); + * int (*ndo_set_rx_mode_async)(struct net_device *dev, + * 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 * are snapshots of the address lists - iterate with - * netdev_hw_addr_list_for_each(ha, uc). + * netdev_hw_addr_list_for_each(ha, uc). Return 0 on success or a + * negative errno to request a retry via the core backoff. * * int (*ndo_set_mac_address)(struct net_device *dev, void *addr); * This function is called when the Media Access Control address @@ -1455,7 +1456,7 @@ struct net_device_ops { void (*ndo_change_rx_flags)(struct net_device *dev, int flags); void (*ndo_set_rx_mode)(struct net_device *dev); - void (*ndo_set_rx_mode_async)( + int (*ndo_set_rx_mode_async)( struct net_device *dev, struct netdev_hw_addr_list *uc, struct netdev_hw_addr_list *mc); -- cgit v1.2.3 From d90b85c23b3d64cc58a2bc59ceda6f6aa4df9ea3 Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Mon, 8 Jun 2026 08:40:13 -0700 Subject: net: add retry mechanism to ndo_set_rx_mode_async When ndo_set_rx_mode_async returns an error, schedule a retry with exponential backoff (1s, 2s, 4s, 8s -- 15s total). Give up after the 4th retry and log an error via netdev_err(). This moves retry logic from individual drivers into the core stack. Timer callback does not hold a ref on dev. Safe because the timer can only be armed when dev is IFF_UP, and __dev_close_many runs timer_delete_sync before clearing IFF_UP. Unregister always closes IFF_UP devices first, so by the time dev can be freed the timer is dead and cannot be re-armed. Reviewed-by: Jakub Kicinski Signed-off-by: Stanislav Fomichev Link: https://patch.msgid.link/20260608154014.227538-3-sdf@fomichev.me Signed-off-by: Jakub Kicinski --- include/linux/netdevice.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 51ec2df02094..7f4f0837c09f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1933,6 +1933,8 @@ enum netdev_reg_state { * @rx_mode_node: List entry for rx_mode work processing * @rx_mode_tracker: Refcount tracker for rx_mode work * @rx_mode_addr_cache: Recycled snapshot entries for rx_mode work + * @rx_mode_retry_timer: Timer that re-queues rx_mode work after failure + * @rx_mode_retry_count: Number of consecutive retries already scheduled * @uc: unicast mac addresses * @mc: multicast mac addresses * @dev_addrs: list of device hw addresses @@ -2326,6 +2328,8 @@ struct net_device { struct list_head rx_mode_node; netdevice_tracker rx_mode_tracker; struct netdev_hw_addr_list rx_mode_addr_cache; + struct timer_list rx_mode_retry_timer; + unsigned int rx_mode_retry_count; #ifdef CONFIG_LOCKDEP unsigned char nested_level; #endif @@ -5152,6 +5156,7 @@ static inline void __dev_mc_unsync(struct net_device *dev, /* Functions used for secondary unicast and multicast support */ void dev_set_rx_mode(struct net_device *dev); +void netif_rx_mode_schedule_retry(struct net_device *dev); int netif_set_promiscuity(struct net_device *dev, int inc); int dev_set_promiscuity(struct net_device *dev, int inc); int netif_set_allmulti(struct net_device *dev, int inc, bool notify); -- cgit v1.2.3