From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtpbguseast2.qq.com (smtpbguseast2.qq.com [54.204.34.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 79A3E208D0 for ; Sat, 9 May 2026 10:06:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.204.34.130 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778321200; cv=none; b=KyEiWyWJruYZidsPfgIXOkHQIM1jeEETZpAxWIaraPSaMNGpbmFD7f3Wji8tlQw+rDoGTCQZpYRmegEnfOsZHPg2gnag9+Bj4R5Lo2L+1NJz/QMd89sK8meQuHH4NMkmBFFvCRpwlH+VgiwLX478jwXJ+bLRS/oJgZ8vSWONEEQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778321200; c=relaxed/simple; bh=ZLnIgCUx9Piw/lJDtsCOeYoiPGzfCL7rhO9IEb5CWwA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=lQ1PjZSMN3UvrLcJE2dbQDsp5sayXakkqssgR32gUFPRJ2OqEiahGdFe7+seKldHNO0lv4XuA448QwxuoH3vgQ0vJJqqTpBUpws9frqu0r6IF6Nw8DFpEEGOCkVZxBW76bdFsbT7dB32ZOu2IRH2NBjquqHgp0pmqYh5/khvIoE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=trustnetic.com; spf=pass smtp.mailfrom=trustnetic.com; arc=none smtp.client-ip=54.204.34.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=trustnetic.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=trustnetic.com X-QQ-mid: esmtpsz17t1778321152t60769a04 X-QQ-Originating-IP: BrPZXB+Y3uCBFAAYf1lVEWMWLdTihyTbhFvD0TShHQg= Received: from lap-jiawenwu.trustnetic.com ( [115.204.251.157]) by bizesmtp.qq.com (ESMTP) with id ; Sat, 09 May 2026 18:05:50 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 15497190481867195217 EX-QQ-RecipientCnt: 17 From: Jiawen Wu To: netdev@vger.kernel.org Cc: Mengyuan Lou , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Richard Cochran , Russell King , Simon Horman , Kees Cook , Larysa Zaremba , Breno Leitao , Joe Damato , Jacob Keller , Fabio Baltieri , Jiawen Wu Subject: [PATCH net-next v3 2/5] net: wangxun: add Tx timeout process Date: Sat, 9 May 2026 18:05:37 +0800 Message-Id: <20260509100540.32612-3-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.21.0.windows.1 In-Reply-To: <20260509100540.32612-1-jiawenwu@trustnetic.com> References: <20260509100540.32612-1-jiawenwu@trustnetic.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:trustnetic.com:qybglogicsvrgz:qybglogicsvrgz6b-0 X-QQ-XMAILINFO: Ncpnai4dwVTHEI2zJfHo1+3qyIAOJWDBY0lJ5D0BA/5dy1VmTGL+ovsg WLnYSnjsjYi66+NEyxIhGVtPyScYJkxbp2PxPt5iVR0S7XmUD4ZRh7J7zEw/79Tm3YXV4EX L/DgAJV/ra03OgqVallbkSckxmD5TjqWwge0etuCABfC7uJIk2rlVHwhB4RKK01drPlCj7E ewbEfXOWeFxPI1qYevkevmBVnEGuM9YuI1JhgaVtDYjy/JQt0ZF7z4GaKjrUigWSTZoynli G9OUOaV87+xwDA5BrPRgwVAO4VZVzNoc45l0Mxtaf4ZbcKaAPmGjB8rnvSH3KMUR3734Djr emkVRkrrHq6oz07arlSCDZf2A81n5CBKMhy+YF19sku2GLmZfothh+lUEE2tJRuo4GA5wa0 lyNJ/C6fGJf4DAfCeyj8NNH0SDDOqUE6OOki1E68YkF0YmmWC27N/cguum1WrOFDUWpULeH HeHSC5cENTPdEeouosnbBXqIPJtgaCPNPNNgAJwACHtqM9dSVHZYbmguDTlEIXYXy0od/dY LZIOu9F8Dvo6L7UuBfGitykDLXwSPgyxyynKsVyn5GQw7nVwDuZ2OInked7tpZ2JYRiWcNj EleQACH8p44YcoWiiFR0GKDVaYcn7hvh5MHJ4dbzcTssdGOyXd7uNyQcGUZoahVYPpF8GF8 XftkbRQPHNJOdRDqn7vfaQgUkPpYtT07pcg14BsDWIyMaxobXLhnCL8x1MBRITqLI37g3sB eONvELBoY8D1P3Cp6eyrFrAwWA4UNmAfNESIFUl29oZzWg9N5HINhQ7dFTABZbf8h7A6hND 0683O+tdTlksWpxfA9KjKPf2zPr111zd5ZLR98+S/+9/FQYsVn1zONdCUAdOZLGyIPxno1s KqgEsSnZ5CwPklPzqAQjqgDoYMlvxqPyjjpntRMATabkiZXpT+deZY1RX3s9qRkaCGdec3I WQoNvJOlk0VPH5ex69F+VRVkhjgcWO4XimPY5TCbErzPH4z1acfdNxbVIFWdUxVDMzih9eU VvxTNI0hq1nRbVYnXS9WE9hFvF8H8UAvVkU5QWMlkIthX0hI7VPJSnEreT2dM= X-QQ-XMRINFO: M/715EihBoGS47X28/vv4NpnfpeBLnr4Qg== X-QQ-RECHKSPAM: 0 Implement .ndo_tx_timeout to handle Tx side timeout event. When Tx timeout event occur, it will triger driver into reset process. The WX_HANG_CHECK_ARMED bit is set to indicate a potential hang. It will be cleared if a pause frame is received to remove false hang detection due to 802.3 frames. Signed-off-by: Jiawen Wu --- drivers/net/ethernet/wangxun/libwx/Makefile | 2 +- drivers/net/ethernet/wangxun/libwx/wx_err.c | 154 ++++++++++++++++++ drivers/net/ethernet/wangxun/libwx/wx_err.h | 15 ++ drivers/net/ethernet/wangxun/libwx/wx_hw.c | 17 +- drivers/net/ethernet/wangxun/libwx/wx_lib.c | 37 +++++ drivers/net/ethernet/wangxun/libwx/wx_type.h | 17 +- drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 6 + .../net/ethernet/wangxun/txgbe/txgbe_main.c | 6 + 8 files changed, 249 insertions(+), 5 deletions(-) create mode 100644 drivers/net/ethernet/wangxun/libwx/wx_err.c create mode 100644 drivers/net/ethernet/wangxun/libwx/wx_err.h diff --git a/drivers/net/ethernet/wangxun/libwx/Makefile b/drivers/net/ethernet/wangxun/libwx/Makefile index a71b0ad77de3..c8724bb129aa 100644 --- a/drivers/net/ethernet/wangxun/libwx/Makefile +++ b/drivers/net/ethernet/wangxun/libwx/Makefile @@ -4,5 +4,5 @@ obj-$(CONFIG_LIBWX) += libwx.o -libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o wx_ptp.o wx_mbx.o wx_sriov.o +libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o wx_ptp.o wx_mbx.o wx_sriov.o wx_err.o libwx-objs += wx_vf.o wx_vf_lib.o wx_vf_common.o diff --git a/drivers/net/ethernet/wangxun/libwx/wx_err.c b/drivers/net/ethernet/wangxun/libwx/wx_err.c new file mode 100644 index 000000000000..bb61355447a8 --- /dev/null +++ b/drivers/net/ethernet/wangxun/libwx/wx_err.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2015 - 2026 Beijing WangXun Technology Co., Ltd. */ +/* Copyright (c) 1999 - 2026 Intel Corporation. */ + +#include +#include + +#include "wx_type.h" +#include "wx_lib.h" +#include "wx_err.h" + +void wx_reset_subtask(struct wx *wx) +{ + if (!test_bit(WX_FLAG_NEED_PF_RESET, wx->flags)) + return; + + rtnl_lock(); + + if (!netif_running(wx->netdev) || + test_bit(WX_STATE_RESETTING, wx->state)) + goto out; + + wx_warn(wx, "Reset adapter.\n"); + + if (test_and_clear_bit(WX_FLAG_NEED_PF_RESET, wx->flags)) { + if (wx->do_reset) + wx->do_reset(wx->netdev); + } + +out: + rtnl_unlock(); +} +EXPORT_SYMBOL(wx_reset_subtask); + +static bool wx_ring_tx_pending(struct wx *wx) +{ + int i; + + for (i = 0; i < wx->num_tx_queues; i++) { + struct wx_ring *tx_ring = wx->tx_ring[i]; + + if (tx_ring->next_to_use != tx_ring->next_to_clean) + return true; + } + + return false; +} + +static bool wx_vf_tx_pending(struct wx *wx) +{ + struct wx_ring_feature *vmdq = &wx->ring_feature[RING_F_VMDQ]; + u32 q_per_pool = __ALIGN_MASK(1, ~vmdq->mask); + u32 i, j; + + if (!wx->num_vfs) + return false; + + for (i = 0; i < wx->num_vfs; i++) { + for (j = 0; j < q_per_pool; j++) { + u32 h, t; + + h = rd32(wx, WX_PX_TR_RP_PV(q_per_pool, i, j)); + t = rd32(wx, WX_PX_TR_WP_PV(q_per_pool, i, j)); + + if (h != t) + return true; + } + } + + return false; +} + +static void wx_watchdog_flush_tx(struct wx *wx) +{ + if (netif_carrier_ok(wx->netdev)) + return; + + if (wx_ring_tx_pending(wx) || wx_vf_tx_pending(wx)) { + /* We've lost link, so the controller stops DMA, + * but we've got queued Tx work that's never going + * to get done, so reset controller to flush Tx. + * (Do the reset outside of interrupt context). + */ + wx_warn(wx, "initiating reset due to lost link with pending Tx work\n"); + set_bit(WX_FLAG_NEED_PF_RESET, wx->flags); + } +} + +/* + * wx_check_tx_hang - check for hung queues and dropped interrupts + * @wx - pointer to the device wx structure + * + * This function serves two purposes. First it strobes the interrupt lines + * in order to make certain interrupts are occurring. Secondly it sets the + * bits needed to check for TX hangs. As a result we should immediately + * determine if a hang has occurred. + */ +static void wx_check_tx_hang(struct wx *wx) +{ + int i; + + /* If we're down or resetting, just bail */ + if (!netif_running(wx->netdev) || + test_bit(WX_STATE_RESETTING, wx->state)) + return; + + /* Force detection of hung controller */ + if (netif_carrier_ok(wx->netdev)) { + for (i = 0; i < wx->num_tx_queues; i++) + set_bit(WX_TX_DETECT_HANG, wx->tx_ring[i]->state); + } +} + +void wx_check_tx_hang_subtask(struct wx *wx) +{ + wx_watchdog_flush_tx(wx); + wx_check_tx_hang(wx); +} +EXPORT_SYMBOL(wx_check_tx_hang_subtask); + +static void wx_tx_timeout_reset(struct wx *wx) +{ + if (!netif_running(wx->netdev)) + return; + + set_bit(WX_FLAG_NEED_PF_RESET, wx->flags); + wx_warn(wx, "initiating reset due to tx timeout\n"); + wx_service_event_schedule(wx); +} + +void wx_tx_timeout(struct net_device *netdev, unsigned int __always_unused txqueue) +{ + struct wx *wx = netdev_priv(netdev); + + wx_tx_timeout_reset(wx); +} +EXPORT_SYMBOL(wx_tx_timeout); + +void wx_handle_tx_hang(struct wx_ring *tx_ring, unsigned int next) +{ + struct wx *wx = netdev_priv(tx_ring->netdev); + + wx_warn(wx, + "Detected Tx Unit Hang: Queue %d, TDH %x, TDT %x, ntu %x, ntc %x, ntc.time_stamp %lx, jiffies %lx\n", + tx_ring->queue_index, + rd32(wx, WX_PX_TR_RP(tx_ring->reg_idx)), + rd32(wx, WX_PX_TR_WP(tx_ring->reg_idx)), + tx_ring->next_to_use, next, + tx_ring->tx_buffer_info[next].time_stamp, jiffies); + + netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); + + wx_tx_timeout_reset(wx); +} diff --git a/drivers/net/ethernet/wangxun/libwx/wx_err.h b/drivers/net/ethernet/wangxun/libwx/wx_err.h new file mode 100644 index 000000000000..594e70bce229 --- /dev/null +++ b/drivers/net/ethernet/wangxun/libwx/wx_err.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * WangXun Gigabit PCI Express Linux driver + * Copyright (c) 2015 - 2026 Beijing WangXun Technology Co., Ltd. + */ + +#ifndef _WX_ERR_H_ +#define _WX_ERR_H_ + +void wx_reset_subtask(struct wx *wx); +void wx_check_tx_hang_subtask(struct wx *wx); +void wx_tx_timeout(struct net_device *netdev, unsigned int txqueue); +void wx_handle_tx_hang(struct wx_ring *tx_ring, unsigned int next); + +#endif /* _WX_ERR_H_ */ diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c index 2451f6b20b11..5ef5590c0664 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c @@ -1932,6 +1932,7 @@ static void wx_configure_tx_ring(struct wx *wx, else ring->atr_sample_rate = 0; + bitmap_zero(ring->state, WX_RING_STATE_NBITS); /* reinitialize tx_buffer_info */ memset(ring->tx_buffer_info, 0, sizeof(struct wx_tx_buffer) * ring->count); @@ -2850,16 +2851,26 @@ EXPORT_SYMBOL(wx_fc_enable); static void wx_update_xoff_rx_lfc(struct wx *wx) { struct wx_hw_stats *hwstats = &wx->stats; + u64 data; + int i; if (wx->fc.mode != wx_fc_full && wx->fc.mode != wx_fc_rx_pause) return; if (wx->mac.type >= wx_mac_aml) - hwstats->lxoffrxc += rd32_wrap(wx, WX_MAC_LXOFFRXC_AML, - &wx->last_stats.lxoffrxc); + data = rd32_wrap(wx, WX_MAC_LXOFFRXC_AML, + &wx->last_stats.lxoffrxc); else - hwstats->lxoffrxc += rd64(wx, WX_MAC_LXOFFRXC); + data = rd64(wx, WX_MAC_LXOFFRXC); + hwstats->lxoffrxc += data; + + /* refill credits (no tx hang) if we received xoff */ + if (!data) + return; + + for (i = 0; i < wx->num_tx_queues; i++) + clear_bit(WX_HANG_CHECK_ARMED, wx->tx_ring[i]->state); } /** diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c index 746623fa59b4..610183496632 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c @@ -14,6 +14,7 @@ #include "wx_type.h" #include "wx_lib.h" +#include "wx_err.h" #include "wx_ptp.h" #include "wx_hw.h" #include "wx_vf_lib.h" @@ -742,6 +743,37 @@ static struct netdev_queue *wx_txring_txq(const struct wx_ring *ring) return netdev_get_tx_queue(ring->netdev, ring->queue_index); } +static u32 wx_get_tx_pending(struct wx_ring *ring) +{ + unsigned int head, tail; + + head = ring->next_to_clean; + tail = ring->next_to_use; + + return ((head <= tail) ? tail : tail + ring->count) - head; +} + +static bool wx_check_tx_hang(struct wx_ring *ring) +{ + u32 tx_done_old = ring->tx_stats.tx_done_old; + u32 tx_pending = wx_get_tx_pending(ring); + u32 tx_done = ring->stats.packets; + + if (!test_and_clear_bit(WX_TX_DETECT_HANG, ring->state)) + return false; + + if (tx_done_old == tx_done && tx_pending) + /* make sure it is true for two checks in a row */ + return test_and_set_bit(WX_HANG_CHECK_ARMED, ring->state); + + /* update completed stats and continue */ + ring->tx_stats.tx_done_old = tx_done; + /* reset the countdown */ + clear_bit(WX_HANG_CHECK_ARMED, ring->state); + + return false; +} + /** * wx_clean_tx_irq - Reclaim resources after transmit completes * @q_vector: structure containing interrupt and ring information @@ -866,6 +898,11 @@ static bool wx_clean_tx_irq(struct wx_q_vector *q_vector, netdev_tx_completed_queue(wx_txring_txq(tx_ring), total_packets, total_bytes); + if (wx_check_tx_hang(tx_ring)) { + wx_handle_tx_hang(tx_ring, i); + return true; + } + #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) if (unlikely(total_packets && netif_carrier_ok(tx_ring->netdev) && (wx_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD))) { diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index 0da5565ee4ff..91c6db7e8e40 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -450,6 +450,11 @@ enum WX_MSCA_CMD_value { #define WX_PX_TR_CFG_THRE_SHIFT 8 #define WX_PX_TR_CFG_HEAD_WB BIT(27) +#define WX_PX_TR_RP_PV(q_per_pool, vf_number, vf_q_index) \ + (WX_PX_TR_RP((q_per_pool) * (vf_number) + (vf_q_index))) +#define WX_PX_TR_WP_PV(q_per_pool, vf_number, vf_q_index) \ + (WX_PX_TR_WP((q_per_pool) * (vf_number) + (vf_q_index))) + /* Receive DMA Registers */ #define WX_PX_RR_BAL(_i) (0x01000 + ((_i) * 0x40)) #define WX_PX_RR_BAH(_i) (0x01004 + ((_i) * 0x40)) @@ -1039,6 +1044,7 @@ struct wx_queue_stats { struct wx_tx_queue_stats { u64 restart_queue; u64 tx_busy; + u32 tx_done_old; }; struct wx_rx_queue_stats { @@ -1054,6 +1060,12 @@ struct wx_rx_queue_stats { #define wx_for_each_ring(posm, headm) \ for (posm = (headm).ring; posm; posm = posm->next) +enum wx_ring_state { + WX_TX_DETECT_HANG, + WX_HANG_CHECK_ARMED, + WX_RING_STATE_NBITS +}; + struct wx_ring_container { struct wx_ring *ring; /* pointer to linked list of rings */ unsigned int total_bytes; /* total bytes processed this int */ @@ -1073,6 +1085,7 @@ struct wx_ring { struct wx_tx_buffer *tx_buffer_info; struct wx_rx_buffer *rx_buffer_info; }; + DECLARE_BITMAP(state, WX_RING_STATE_NBITS); u8 __iomem *tail; dma_addr_t dma; /* phys. address of descriptor ring */ dma_addr_t headwb_dma; @@ -1273,6 +1286,7 @@ enum wx_pf_flags { WX_FLAG_NEED_DO_RESET, WX_FLAG_RX_MERGE_ENABLED, WX_FLAG_TXHEAD_WB_ENABLED, + WX_FLAG_NEED_PF_RESET, WX_PF_FLAGS_NBITS /* must be last */ }; @@ -1503,7 +1517,8 @@ rd32_wrap(struct wx *wx, u32 reg, u32 *last) #define wx_err(wx, fmt, arg...) \ dev_err(&(wx)->pdev->dev, fmt, ##arg) - +#define wx_warn(wx, fmt, arg...) \ + dev_warn(&(wx)->pdev->dev, fmt, ##arg) #define wx_dbg(wx, fmt, arg...) \ dev_dbg(&(wx)->pdev->dev, fmt, ##arg) diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c index bd905e267575..c45f5770b722 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c @@ -14,6 +14,7 @@ #include "../libwx/wx_type.h" #include "../libwx/wx_hw.h" #include "../libwx/wx_lib.h" +#include "../libwx/wx_err.h" #include "../libwx/wx_ptp.h" #include "../libwx/wx_mbx.h" #include "../libwx/wx_sriov.h" @@ -147,7 +148,9 @@ static void ngbe_service_task(struct work_struct *work) { struct wx *wx = container_of(work, struct wx, service_task); + wx_reset_subtask(wx); wx_update_stats(wx); + wx_check_tx_hang_subtask(wx); wx_service_event_complete(wx); } @@ -390,6 +393,7 @@ static void ngbe_disable_device(struct wx *wx) netif_tx_stop_all_queues(netdev); netif_tx_disable(netdev); + clear_bit(WX_FLAG_NEED_PF_RESET, wx->flags); timer_delete_sync(&wx->service_timer); cancel_work_sync(&wx->service_task); @@ -642,6 +646,7 @@ static const struct net_device_ops ngbe_netdev_ops = { .ndo_stop = ngbe_close, .ndo_change_mtu = wx_change_mtu, .ndo_start_xmit = wx_xmit_frame, + .ndo_tx_timeout = wx_tx_timeout, .ndo_set_rx_mode = wx_set_rx_mode, .ndo_set_features = wx_set_features, .ndo_fix_features = wx_fix_features, @@ -731,6 +736,7 @@ static int ngbe_probe(struct pci_dev *pdev, wx->driver_name = ngbe_driver_name; ngbe_set_ethtool_ops(netdev); netdev->netdev_ops = &ngbe_netdev_ops; + netdev->watchdog_timeo = 5 * HZ; netdev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | NETIF_F_TSO6 | diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index 8b7c3753bb6a..ba55a17da3b8 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -14,6 +14,7 @@ #include "../libwx/wx_type.h" #include "../libwx/wx_lib.h" +#include "../libwx/wx_err.h" #include "../libwx/wx_ptp.h" #include "../libwx/wx_hw.h" #include "../libwx/wx_mbx.h" @@ -128,9 +129,11 @@ static void txgbe_service_task(struct work_struct *work) { struct wx *wx = container_of(work, struct wx, service_task); + wx_reset_subtask(wx); txgbe_module_detection_subtask(wx); txgbe_link_config_subtask(wx); wx_update_stats(wx); + wx_check_tx_hang_subtask(wx); wx_service_event_complete(wx); } @@ -228,6 +231,7 @@ static void txgbe_disable_device(struct wx *wx) wx_irq_disable(wx); wx_napi_disable_all(wx); + clear_bit(WX_FLAG_NEED_PF_RESET, wx->flags); timer_delete_sync(&wx->service_timer); if (wx->bus.func < 2) @@ -659,6 +663,7 @@ static const struct net_device_ops txgbe_netdev_ops = { .ndo_stop = txgbe_close, .ndo_change_mtu = wx_change_mtu, .ndo_start_xmit = wx_xmit_frame, + .ndo_tx_timeout = wx_tx_timeout, .ndo_set_rx_mode = wx_set_rx_mode, .ndo_set_features = wx_set_features, .ndo_fix_features = wx_fix_features, @@ -750,6 +755,7 @@ static int txgbe_probe(struct pci_dev *pdev, wx->driver_name = txgbe_driver_name; txgbe_set_ethtool_ops(netdev); netdev->netdev_ops = &txgbe_netdev_ops; + netdev->watchdog_timeo = 5 * HZ; netdev->udp_tunnel_nic_info = &txgbe_udp_tunnels; /* setup the private structure */ -- 2.51.0