Add function pointer wx->close_suspend() and adjust wx->do_reset(), so that PCI driver ops such as .shutdown can be called in libwx. Signed-off-by: Jiawen Wu --- .../net/ethernet/wangxun/libwx/wx_ethtool.c | 2 +- drivers/net/ethernet/wangxun/libwx/wx_lib.c | 89 +++++++++++++- drivers/net/ethernet/wangxun/libwx/wx_lib.h | 3 + drivers/net/ethernet/wangxun/libwx/wx_type.h | 3 +- drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 113 ++++-------------- drivers/net/ethernet/wangxun/ngbe/ngbe_type.h | 3 +- .../net/ethernet/wangxun/txgbe/txgbe_main.c | 17 +-- .../net/ethernet/wangxun/txgbe/txgbe_type.h | 3 +- 8 files changed, 126 insertions(+), 107 deletions(-) diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c index 9e940ea9cb8b..9fd8cbe62f0c 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c @@ -396,7 +396,7 @@ static void wx_update_rsc(struct wx *wx) /* reset the device to apply the new RSC setting */ if (need_reset && wx->do_reset) - wx->do_reset(netdev); + wx->do_reset(netdev, true); } int wx_set_coalesce(struct net_device *netdev, diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c index 746623fa59b4..c65240ca3c28 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c @@ -3109,7 +3109,7 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features) netdev->features = features; if (changed & NETIF_F_HW_VLAN_CTAG_RX && wx->do_reset) - wx->do_reset(netdev); + wx->do_reset(netdev, true); else if (changed & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER)) wx_set_rx_mode(netdev); @@ -3159,7 +3159,7 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features) out: if (need_reset && wx->do_reset) - wx->do_reset(netdev); + wx->do_reset(netdev, true); return 0; } @@ -3342,5 +3342,90 @@ void wx_service_timer(struct timer_list *t) } EXPORT_SYMBOL(wx_service_timer); +static void wx_dev_shutdown(struct pci_dev *pdev, bool *enable_wake) +{ + struct wx *wx = pci_get_drvdata(pdev); + struct net_device *netdev; + u32 wufc = wx->wol; + + netdev = wx->netdev; + rtnl_lock(); + netif_device_detach(netdev); + + if (netif_running(netdev)) + wx->close_suspend(wx); + + wx_clear_interrupt_scheme(wx); + rtnl_unlock(); + + if (wufc) { + wx_set_rx_mode(netdev); + wx_configure_rx(wx); + wr32(wx, WX_PSR_WKUP_CTL, wufc); + } else { + wr32(wx, WX_PSR_WKUP_CTL, 0); + } + pci_wake_from_d3(pdev, !!wufc); + *enable_wake = !!wufc; + wx_control_hw(wx, false); + + pci_disable_device(pdev); +} + +int wx_suspend(struct pci_dev *pdev, pm_message_t state) +{ + bool wake; + + wx_dev_shutdown(pdev, &wake); + device_set_wakeup_enable(&pdev->dev, wake); + + return 0; +} +EXPORT_SYMBOL(wx_suspend); + +int wx_resume(struct pci_dev *pdev) +{ + struct net_device *netdev; + struct wx *wx; + u32 err; + + wx = pci_get_drvdata(pdev); + netdev = wx->netdev; + + err = pci_enable_device_mem(pdev); + if (err) { + wx_err(wx, "Cannot enable PCI device from suspend\n"); + return err; + } + pci_set_master(pdev); + device_wakeup_disable(&pdev->dev); + + wx->do_reset(netdev, false); + rtnl_lock(); + + err = wx_init_interrupt_scheme(wx); + if (!err && netif_running(netdev)) + err = netdev->netdev_ops->ndo_open(netdev); + if (!err) + netif_device_attach(netdev); + rtnl_unlock(); + + return err; +} +EXPORT_SYMBOL(wx_resume); + +void wx_shutdown(struct pci_dev *pdev) +{ + bool wake; + + wx_dev_shutdown(pdev, &wake); + + if (system_state == SYSTEM_POWER_OFF) { + pci_wake_from_d3(pdev, wake); + pci_set_power_state(pdev, PCI_D3hot); + } +} +EXPORT_SYMBOL(wx_shutdown); + MODULE_DESCRIPTION("Common library for Wangxun(R) Ethernet drivers."); MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.h b/drivers/net/ethernet/wangxun/libwx/wx_lib.h index aed6ea8cf0d6..42461723a400 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h @@ -41,5 +41,8 @@ void wx_set_ring(struct wx *wx, u32 new_tx_count, void wx_service_event_schedule(struct wx *wx); void wx_service_event_complete(struct wx *wx); void wx_service_timer(struct timer_list *t); +int wx_suspend(struct pci_dev *pdev, pm_message_t state); +int wx_resume(struct pci_dev *pdev); +void wx_shutdown(struct pci_dev *pdev); #endif /* _WX_LIB_H_ */ diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index 29e5c5470c94..e013f05d2cfe 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -1372,7 +1372,8 @@ struct wx { void (*atr)(struct wx_ring *ring, struct wx_tx_buffer *first, u8 ptype); void (*configure_fdir)(struct wx *wx); int (*setup_tc)(struct net_device *netdev, u8 tc); - void (*do_reset)(struct net_device *netdev); + void (*do_reset)(struct net_device *netdev, bool reinit); + void (*close_suspend)(struct wx *wx); int (*ptp_setup_sdp)(struct wx *wx); void (*set_num_queues)(struct wx *wx); diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c index f25a5fcab319..4dd7de79431c 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c @@ -134,6 +134,7 @@ static int ngbe_sw_init(struct wx *wx) wx->mbx.size = WX_VXMAILBOX_SIZE; wx->setup_tc = ngbe_setup_tc; wx->do_reset = ngbe_do_reset; + wx->close_suspend = ngbe_close_suspend; set_bit(0, &wx->fwd_bitmask); return 0; @@ -483,6 +484,16 @@ static int ngbe_open(struct net_device *netdev) return err; } +void ngbe_close_suspend(struct wx *wx) +{ + wx_ptp_suspend(wx); + ngbe_down(wx); + wx_free_irq(wx); + wx_free_isb_resources(wx); + wx_free_resources(wx); + phylink_disconnect_phy(wx->phylink); +} + /** * ngbe_close - Disables a network interface * @netdev: network interface device structure @@ -499,11 +510,10 @@ static int ngbe_close(struct net_device *netdev) struct wx *wx = netdev_priv(netdev); wx_ptp_stop(wx); - ngbe_down(wx); - wx_free_irq(wx); - wx_free_isb_resources(wx); - wx_free_resources(wx); - phylink_disconnect_phy(wx->phylink); + + if (netif_device_present(netdev)) + ngbe_close_suspend(wx); + wx_control_hw(wx, false); return 0; @@ -515,50 +525,6 @@ void ngbe_up(struct wx *wx) ngbe_up_complete(wx); } -static void ngbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake) -{ - struct wx *wx = pci_get_drvdata(pdev); - struct net_device *netdev; - u32 wufc = wx->wol; - - netdev = wx->netdev; - rtnl_lock(); - netif_device_detach(netdev); - - if (netif_running(netdev)) - ngbe_close(netdev); - wx_clear_interrupt_scheme(wx); - rtnl_unlock(); - - if (wufc) { - wx_set_rx_mode(netdev); - wx_configure_rx(wx); - wr32(wx, WX_PSR_WKUP_CTL, wufc); - } else { - wr32(wx, WX_PSR_WKUP_CTL, 0); - } - pci_wake_from_d3(pdev, !!wufc); - *enable_wake = !!wufc; - wx_control_hw(wx, false); - - pci_disable_device(pdev); -} - -static void ngbe_shutdown(struct pci_dev *pdev) -{ - struct wx *wx = pci_get_drvdata(pdev); - bool wake; - - wake = !!wx->wol; - - ngbe_dev_shutdown(pdev, &wake); - - if (system_state == SYSTEM_POWER_OFF) { - pci_wake_from_d3(pdev, wake); - pci_set_power_state(pdev, PCI_D3hot); - } -} - /** * ngbe_setup_tc - routine to configure net_device for multiple traffic * classes. @@ -612,11 +578,11 @@ static void ngbe_reinit_locked(struct wx *wx) clear_bit(WX_STATE_RESETTING, wx->state); } -void ngbe_do_reset(struct net_device *netdev) +void ngbe_do_reset(struct net_device *netdev, bool reinit) { struct wx *wx = netdev_priv(netdev); - if (netif_running(netdev)) + if (netif_running(netdev) && reinit) ngbe_reinit_locked(wx); else ngbe_reset(wx); @@ -874,53 +840,14 @@ static void ngbe_remove(struct pci_dev *pdev) pci_disable_device(pdev); } -static int ngbe_suspend(struct pci_dev *pdev, pm_message_t state) -{ - bool wake; - - ngbe_dev_shutdown(pdev, &wake); - device_set_wakeup_enable(&pdev->dev, wake); - - return 0; -} - -static int ngbe_resume(struct pci_dev *pdev) -{ - struct net_device *netdev; - struct wx *wx; - u32 err; - - wx = pci_get_drvdata(pdev); - netdev = wx->netdev; - - err = pci_enable_device_mem(pdev); - if (err) { - wx_err(wx, "Cannot enable PCI device from suspend\n"); - return err; - } - pci_set_master(pdev); - device_wakeup_disable(&pdev->dev); - - ngbe_reset(wx); - rtnl_lock(); - err = wx_init_interrupt_scheme(wx); - if (!err && netif_running(netdev)) - err = ngbe_open(netdev); - if (!err) - netif_device_attach(netdev); - rtnl_unlock(); - - return 0; -} - static struct pci_driver ngbe_driver = { .name = ngbe_driver_name, .id_table = ngbe_pci_tbl, .probe = ngbe_probe, .remove = ngbe_remove, - .suspend = ngbe_suspend, - .resume = ngbe_resume, - .shutdown = ngbe_shutdown, + .suspend = wx_suspend, + .resume = wx_resume, + .shutdown = wx_shutdown, .sriov_configure = wx_pci_sriov_configure, }; diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h index 4f648f272c08..eb5c92edae06 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h @@ -125,6 +125,7 @@ extern char ngbe_driver_name[]; void ngbe_down(struct wx *wx); void ngbe_up(struct wx *wx); int ngbe_setup_tc(struct net_device *dev, u8 tc); -void ngbe_do_reset(struct net_device *netdev); +void ngbe_do_reset(struct net_device *netdev, bool reinit); +void ngbe_close_suspend(struct wx *wx); #endif /* _NGBE_TYPE_H_ */ diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index 0de051450a82..30f66507809b 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -412,6 +412,7 @@ static int txgbe_sw_init(struct wx *wx) wx->setup_tc = txgbe_setup_tc; wx->do_reset = txgbe_do_reset; + wx->close_suspend = txgbe_close_suspend; set_bit(0, &wx->fwd_bitmask); switch (wx->mac.type) { @@ -500,10 +501,12 @@ static int txgbe_open(struct net_device *netdev) * This function should contain the necessary work common to both suspending * and closing of the device. */ -static void txgbe_close_suspend(struct wx *wx) +void txgbe_close_suspend(struct wx *wx) { wx_ptp_suspend(wx); - txgbe_disable_device(wx); + txgbe_down(wx); + wx_free_irq(wx); + txgbe_free_misc_irq(wx->priv); wx_free_resources(wx); } @@ -523,10 +526,8 @@ static int txgbe_close(struct net_device *netdev) struct wx *wx = netdev_priv(netdev); wx_ptp_stop(wx); - txgbe_down(wx); - wx_free_irq(wx); - txgbe_free_misc_irq(wx->priv); - wx_free_resources(wx); + if (netif_device_present(netdev)) + txgbe_close_suspend(wx); txgbe_fdir_filter_exit(wx); wx_control_hw(wx, false); @@ -614,11 +615,11 @@ static void txgbe_reinit_locked(struct wx *wx) clear_bit(WX_STATE_RESETTING, wx->state); } -void txgbe_do_reset(struct net_device *netdev) +void txgbe_do_reset(struct net_device *netdev, bool reinit) { struct wx *wx = netdev_priv(netdev); - if (netif_running(netdev)) + if (netif_running(netdev) && reinit) txgbe_reinit_locked(wx); else txgbe_reset(wx); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index 82433e9cb0e3..e9360e935682 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -313,7 +313,8 @@ extern char txgbe_driver_name[]; void txgbe_down(struct wx *wx); void txgbe_up(struct wx *wx); int txgbe_setup_tc(struct net_device *dev, u8 tc); -void txgbe_do_reset(struct net_device *netdev); +void txgbe_do_reset(struct net_device *netdev, bool reinit); +void txgbe_close_suspend(struct wx *wx); #define TXGBE_LINK_SPEED_UNKNOWN 0 #define TXGBE_LINK_SPEED_10GB_FULL 4 -- 2.48.1