diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c index 67af8640a49e..ed5aad7857bd 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c @@ -3410,5 +3410,23 @@ void wx_service_timer(struct timer_list *t) } EXPORT_SYMBOL(wx_service_timer); +void wx_soft_quiesce(struct wx *wx) +{ + if (!netif_running(wx->netdev) || + test_and_set_bit(WX_STATE_DOWN, wx->state)) + return; + + pci_clear_master(wx->pdev); + netif_tx_stop_all_queues(wx->netdev); + netif_carrier_off(wx->netdev); + netif_tx_disable(wx->netdev); + wx_napi_disable_all(wx); + wx_ptp_quiesce(wx); + + clear_bit(WX_FLAG_NEED_DO_RESET, wx->flags); + timer_delete_sync(&wx->service_timer); +} +EXPORT_SYMBOL(wx_soft_quiesce); + 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 bc671786978e..9d85d399e17f 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h @@ -41,5 +41,6 @@ int 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); +void wx_soft_quiesce(struct wx *wx); #endif /* _WX_LIB_H_ */ diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ptp.c b/drivers/net/ethernet/wangxun/libwx/wx_ptp.c index 44f3e6505246..3eea647c4742 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_ptp.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_ptp.c @@ -321,6 +321,9 @@ static long wx_ptp_do_aux_work(struct ptp_clock_info *ptp) struct wx *wx = container_of(ptp, struct wx, ptp_caps); int ts_done; + if (!test_bit(WX_STATE_PTP_RUNNING, wx->state)) + return HZ; + ts_done = wx_ptp_tx_hwtstamp_work(wx); wx_ptp_overflow_check(wx); @@ -842,6 +845,30 @@ void wx_ptp_stop(struct wx *wx) } EXPORT_SYMBOL(wx_ptp_stop); +void wx_ptp_quiesce(struct wx *wx) +{ + if (!test_and_clear_bit(WX_STATE_PTP_RUNNING, wx->state)) + return; + + clear_bit(WX_FLAG_PTP_PPS_ENABLED, wx->flags); + + if (wx->ptp_clock) + ptp_cancel_worker_sync(wx->ptp_clock); + + if (wx->ptp_tx_skb) { + dev_kfree_skb_any(wx->ptp_tx_skb); + wx->ptp_tx_skb = NULL; + } + clear_bit_unlock(WX_STATE_PTP_TX_IN_PROGRESS, wx->state); + + if (wx->ptp_clock) { + ptp_clock_unregister(wx->ptp_clock); + wx->ptp_clock = NULL; + dev_info(&wx->pdev->dev, "removed PHC on %s\n", wx->netdev->name); + } +} +EXPORT_SYMBOL(wx_ptp_quiesce); + /** * wx_ptp_rx_hwtstamp - utility function which checks for RX time stamp * @wx: pointer to wx struct diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ptp.h b/drivers/net/ethernet/wangxun/libwx/wx_ptp.h index 50db90a6e3ee..ad2f824875d5 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_ptp.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_ptp.h @@ -10,6 +10,7 @@ void wx_ptp_reset(struct wx *wx); void wx_ptp_init(struct wx *wx); void wx_ptp_suspend(struct wx *wx); void wx_ptp_stop(struct wx *wx); +void wx_ptp_quiesce(struct wx *wx); void wx_ptp_rx_hwtstamp(struct wx *wx, struct sk_buff *skb); int wx_hwtstamp_get(struct net_device *dev, struct kernel_hwtstamp_config *cfg); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index f25249ddf2c6..414b2ba8dfc4 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -94,12 +94,24 @@ static void txgbe_module_detection_subtask(struct wx *wx) { int err; + if (test_bit(WX_STATE_DOWN, wx->state) || + test_bit(WX_STATE_RESETTING, wx->state)) + return; + if (!test_and_clear_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags)) return; /* wait for SFF module ready */ msleep(200); + /* Re-check state to avoid racing with down/reset paths. + * Module identification is deferred to the next up event, + * so it is safe to bail out here. + */ + if (test_bit(WX_STATE_DOWN, wx->state) || + test_bit(WX_STATE_RESETTING, wx->state)) + return; + err = txgbe_identify_module(wx); if (err == -ENODEV) set_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags); @@ -107,6 +119,10 @@ static void txgbe_module_detection_subtask(struct wx *wx) static void txgbe_link_config_subtask(struct wx *wx) { + if (test_bit(WX_STATE_DOWN, wx->state) || + test_bit(WX_STATE_RESETTING, wx->state)) + return; + if (!test_and_clear_bit(WX_FLAG_NEED_LINK_CONFIG, wx->flags)) return;