hv_netvsc: Add the support of hibernation
The existing netvsc_detach() and netvsc_attach() APIs make it easy to implement the suspend/resume callbacks. Signed-off-by: Dexuan Cui <decui@microsoft.com> Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
2194c2eb67
commit
0efeea5fb1
|
@ -952,6 +952,9 @@ struct net_device_context {
|
|||
u32 vf_alloc;
|
||||
/* Serial number of the VF to team with */
|
||||
u32 vf_serial;
|
||||
|
||||
/* Used to temporarily save the config info across hibernation */
|
||||
struct netvsc_device_info *saved_netvsc_dev_info;
|
||||
};
|
||||
|
||||
/* Per channel data */
|
||||
|
|
|
@ -2421,6 +2421,61 @@ static int netvsc_remove(struct hv_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int netvsc_suspend(struct hv_device *dev)
|
||||
{
|
||||
struct net_device_context *ndev_ctx;
|
||||
struct net_device *vf_netdev, *net;
|
||||
struct netvsc_device *nvdev;
|
||||
int ret;
|
||||
|
||||
net = hv_get_drvdata(dev);
|
||||
|
||||
ndev_ctx = netdev_priv(net);
|
||||
cancel_delayed_work_sync(&ndev_ctx->dwork);
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
nvdev = rtnl_dereference(ndev_ctx->nvdev);
|
||||
if (nvdev == NULL) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
|
||||
if (vf_netdev)
|
||||
netvsc_unregister_vf(vf_netdev);
|
||||
|
||||
/* Save the current config info */
|
||||
ndev_ctx->saved_netvsc_dev_info = netvsc_devinfo_get(nvdev);
|
||||
|
||||
ret = netvsc_detach(net, nvdev);
|
||||
out:
|
||||
rtnl_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int netvsc_resume(struct hv_device *dev)
|
||||
{
|
||||
struct net_device *net = hv_get_drvdata(dev);
|
||||
struct net_device_context *net_device_ctx;
|
||||
struct netvsc_device_info *device_info;
|
||||
int ret;
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
net_device_ctx = netdev_priv(net);
|
||||
device_info = net_device_ctx->saved_netvsc_dev_info;
|
||||
|
||||
ret = netvsc_attach(net, device_info);
|
||||
|
||||
rtnl_unlock();
|
||||
|
||||
kfree(device_info);
|
||||
net_device_ctx->saved_netvsc_dev_info = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
static const struct hv_vmbus_device_id id_table[] = {
|
||||
/* Network guid */
|
||||
{ HV_NIC_GUID, },
|
||||
|
@ -2435,6 +2490,8 @@ static struct hv_driver netvsc_drv = {
|
|||
.id_table = id_table,
|
||||
.probe = netvsc_probe,
|
||||
.remove = netvsc_remove,
|
||||
.suspend = netvsc_suspend,
|
||||
.resume = netvsc_resume,
|
||||
.driver = {
|
||||
.probe_type = PROBE_FORCE_SYNCHRONOUS,
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue