hv_netvsc: Switch the data path at the right time during hibernation
When netvsc_resume() is called, the mlx5 VF NIC has not been resumed yet,
so in the future the host might sliently fail the call netvsc_vf_changed()
-> netvsc_switch_datapath() there, even if the call works now.
Call netvsc_vf_changed() in the NETDEV_CHANGE event handler: at that time
the mlx5 VF NIC has been resumed.
Fixes: 19162fd406 ("hv_netvsc: Fix hibernation for mlx5 VF driver")
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
2fb541c862
commit
de214e52de
@@ -2619,7 +2619,6 @@ static int netvsc_resume(struct hv_device *dev)
|
|||||||
struct net_device *net = hv_get_drvdata(dev);
|
struct net_device *net = hv_get_drvdata(dev);
|
||||||
struct net_device_context *net_device_ctx;
|
struct net_device_context *net_device_ctx;
|
||||||
struct netvsc_device_info *device_info;
|
struct netvsc_device_info *device_info;
|
||||||
struct net_device *vf_netdev;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
@@ -2632,15 +2631,6 @@ static int netvsc_resume(struct hv_device *dev)
|
|||||||
netvsc_devinfo_put(device_info);
|
netvsc_devinfo_put(device_info);
|
||||||
net_device_ctx->saved_netvsc_dev_info = NULL;
|
net_device_ctx->saved_netvsc_dev_info = NULL;
|
||||||
|
|
||||||
/* A NIC driver (e.g. mlx5) may keep the VF network interface across
|
|
||||||
* hibernation, but here the data path is implicitly switched to the
|
|
||||||
* netvsc NIC since the vmbus channel is closed and re-opened, so
|
|
||||||
* netvsc_vf_changed() must be used to switch the data path to the VF.
|
|
||||||
*/
|
|
||||||
vf_netdev = rtnl_dereference(net_device_ctx->vf_netdev);
|
|
||||||
if (vf_netdev && netvsc_vf_changed(vf_netdev) != NOTIFY_OK)
|
|
||||||
ret = -EINVAL;
|
|
||||||
|
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -2701,6 +2691,7 @@ static int netvsc_netdev_event(struct notifier_block *this,
|
|||||||
return netvsc_unregister_vf(event_dev);
|
return netvsc_unregister_vf(event_dev);
|
||||||
case NETDEV_UP:
|
case NETDEV_UP:
|
||||||
case NETDEV_DOWN:
|
case NETDEV_DOWN:
|
||||||
|
case NETDEV_CHANGE:
|
||||||
return netvsc_vf_changed(event_dev);
|
return netvsc_vf_changed(event_dev);
|
||||||
default:
|
default:
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
|
|||||||
Reference in New Issue
Block a user