FAILED: patch "[PATCH] hv_netvsc: Register VF in netvsc_probe if NET_DEVICE_REGISTER" failed to apply to 5.15-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 9cae43da9867412f8bd09aee5c8a8dc5e8dc3dc2
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2024021937-trace-hardly-10d8@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..
Possible dependencies:
9cae43da9867 ("hv_netvsc: Register VF in netvsc_probe if NET_DEVICE_REGISTER missed") c807d6cd089d ("hv_netvsc: Mark VF as slave before exposing it to user-mode") 365e1ececb29 ("hv_netvsc: Fix race between VF offering and VF association message from host") c60882a4566a ("hv_netvsc: use netif_is_bond_master() instead of open code")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 9cae43da9867412f8bd09aee5c8a8dc5e8dc3dc2 Mon Sep 17 00:00:00 2001
From: Shradha Gupta <[email protected]>
Date: Thu, 1 Feb 2024 20:40:38 -0800
Subject: [PATCH] hv_netvsc: Register VF in netvsc_probe if NET_DEVICE_REGISTER
missed
If hv_netvsc driver is unloaded and reloaded, the NET_DEVICE_REGISTER handler cannot perform VF register successfully as the register call is received before netvsc_probe is finished. This is because we register register_netdevice_notifier() very early( even before vmbus_driver_register()).
To fix this, we try to register each such matching VF( if it is visible as a netdevice) at the end of netvsc_probe.
drivers/net/hyperv/netvsc_drv.c +62 -20
@@ -42,6 +42,10 @@#define LINKCHANGE_INT (2 * HZ)#define VF_TAKEOVER_INT (HZ / 10) +/* Macros to define the context of vf registration */ +#define VF_REG_IN_PROBE 1 +#define VF_REG_IN_NOTIFIER 2 +static unsigned int ring_size__ro_after_init =128 ;module_param (ring_size, uint,0444 );MODULE_PARM_DESC (ring_size,"Ring buffer size (# of 4K pages)" );
@@ -2185,7 +2189,7 @@ static rx_handler_result_t netvsc_vf_handle_frame(struct sk_buff **pskb) }static int netvsc_vf_join (struct net_device *vf_netdev, -struct net_device *ndev) +struct net_device *ndev,int context) {struct net_device_context *ndev_ctx =netdev_priv (ndev);int ret;
@@ -2208,7 +2212,11 @@ static int netvsc_vf_join(struct net_device *vf_netdev, goto upper_link_failed; } -schedule_delayed_work (&ndev_ctx->vf_takeover,VF_TAKEOVER_INT ); +/* If this registration is called from probe context vf_takeover +* is taken care of later in probe itself. +*/ +if (context ==VF_REG_IN_NOTIFIER ) +schedule_delayed_work (&ndev_ctx->vf_takeover,VF_TAKEOVER_INT );call_netdevice_notifiers (NETDEV_JOIN , vf_netdev);
@@ -2346,7 +2354,7 @@ static int netvsc_prepare_bonding(struct net_device *vf_netdev)return NOTIFY_DONE ; } -static int netvsc_register_vf (struct net_device *vf_netdev) +static int netvsc_register_vf (struct net_device *vf_netdev,int context) {struct net_device_context *net_device_ctx;struct netvsc_device *netvsc_dev;
@@ -2386,7 +2394,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev)netdev_info (ndev,"VF registering: %s\n" , vf_netdev->name); -if (netvsc_vf_join (vf_netdev, ndev) !=0 ) +if (netvsc_vf_join (vf_netdev, ndev, context) !=0 )return NOTIFY_DONE ;dev_hold (vf_netdev);
@@ -2484,10 +2492,31 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev)return NOTIFY_OK ; } +static int check_dev_is_matching_vf (struct net_device *event_ndev) +{ +/* Skip NetVSC interfaces */ +if (event_ndev->netdev_ops == &device_ops) +return -ENODEV ; + +/* Avoid non-Ethernet type devices */ +if (event_ndev->type !=ARPHRD_ETHER ) +return -ENODEV ; + +/* Avoid Vlan dev with same MAC registering as VF */ +if (is_vlan_dev (event_ndev)) +return -ENODEV ; + +/* Avoid Bonding master dev with same MAC registering as VF */ +if (netif_is_bond_master (event_ndev)) +return -ENODEV ; + +return 0 ; +} +static int netvsc_probe (struct hv_device *dev,const struct hv_vmbus_device_id *dev_id) { -struct net_device *net =NULL ; +struct net_device *net =NULL , *vf_netdev;struct net_device_context *net_device_ctx;struct netvsc_device_info *device_info =NULL ;struct netvsc_device *nvdev;
@@ -2599,6 +2628,30 @@ static int netvsc_probe(struct hv_device *dev, }list_add (&net_device_ctx->list, &netvsc_dev_list); + +/* When the hv_netvsc driver is unloaded and reloaded, the +* NET_DEVICE_REGISTER for the vf device is replayed before probe +* is complete. This is because register_netdevice_notifier() gets +* registered before vmbus_driver_register() so that callback func +* is set before probe and we don't miss events like NETDEV_POST_INIT +* So, in this section we try to register the matching vf device that +* is present as a netdevice, knowing that its register call is not +* processed in the netvsc_netdev_notifier(as probing is progress and +* get_netvsc_byslot fails). +*/ +for_each_netdev (dev_net (net), vf_netdev) { + ret =check_dev_is_matching_vf (vf_netdev); +if (ret !=0 ) +continue ; + +if (net !=get_netvsc_byslot (vf_netdev)) +continue ; + +netvsc_prepare_bonding (vf_netdev); +netvsc_register_vf (vf_netdev,VF_REG_IN_PROBE ); +__netvsc_vf_setup (net, vf_netdev); +break ; + }rtnl_unlock ();netvsc_devinfo_put (device_info);
@@ -2754,28 +2807,17 @@ static int netvsc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { struct net_device *event_dev = netdev_notifier_info_to_dev(ptr); +int ret =0 ; -/* Skip our own events */ -if (event_dev->netdev_ops == &device_ops) -return NOTIFY_DONE ; - -/* Avoid non-Ethernet type devices */ -if (event_dev->type !=ARPHRD_ETHER ) -return NOTIFY_DONE ; - -/* Avoid Vlan dev with same MAC registering as VF */ -if (is_vlan_dev (event_dev)) -return NOTIFY_DONE ; - -/* Avoid Bonding master dev with same MAC registering as VF */ -if (netif_is_bond_master (event_dev)) + ret =check_dev_is_matching_vf (event_dev); +if (ret !=0 )return NOTIFY_DONE ;switch (event) {case NETDEV_POST_INIT :return netvsc_prepare_bonding (event_dev);case NETDEV_REGISTER : -return netvsc_register_vf (event_dev); +return netvsc_register_vf (event_dev,VF_REG_IN_NOTIFIER );case NETDEV_UNREGISTER :return netvsc_unregister_vf (event_dev);case NETDEV_UP :