Fix the suspend/resume sequence by: * protecting the open/close path with RTNL, * closing the netdev before releasing interrupt resources, * re-enabling the PCI device and restoring bus mastering during resume, * rebuilding the interrupt scheme, and * reopening the interface when it was running before suspend. Signed-off-by: Mengyuan Lou --- .../net/ethernet/wangxun/libwx/wx_vf_common.c | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c index 26de78e9a69e..e8448783df3e 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c @@ -16,9 +16,13 @@ int wxvf_suspend(struct device *dev_d) struct pci_dev *pdev = to_pci_dev(dev_d); struct wx *wx = pci_get_drvdata(pdev); + rtnl_lock(); netif_device_detach(wx->netdev); + if (netif_running(wx->netdev)) + wxvf_close(wx->netdev); wx_clear_interrupt_scheme(wx); pci_disable_device(pdev); + rtnl_unlock(); return 0; } @@ -34,12 +38,25 @@ int wxvf_resume(struct device *dev_d) { struct pci_dev *pdev = to_pci_dev(dev_d); struct wx *wx = pci_get_drvdata(pdev); + int err = 0; + + err = pci_enable_device_mem(pdev); + if (err) { + dev_err(&pdev->dev, "Cannot enable PCI device from suspend\n"); + return err; + } pci_set_master(pdev); - wx_init_interrupt_scheme(wx); + rtnl_lock(); + err = wx_init_interrupt_scheme(wx); + if (!err && netif_running(wx->netdev)) + err = wxvf_open(wx->netdev); + rtnl_unlock(); + if (err) + return err; netif_device_attach(wx->netdev); - return 0; + return err; } EXPORT_SYMBOL(wxvf_resume); -- 2.30.1