AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/06/30 04:06 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch modifies the Wangxun Ethernet drivers (ngbe, txgbe) to add PCI error recovery, TX timeout handling, and TX hang detection. These are drivers for specific physical PCI hardware. Since there is no software emulator for Wangxun devices in the kernel, the probe functions will not succeed and the netdevs will not be registered in virtualized environments like GCE or QEMU. Therefore, the modified code is unreachable during fuzzing.",
  "WorthFuzzing": false
}

1/1 2026/06/30 04:06 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 2160a414d246ac3fdf36d26f7f1dd756ae874054\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Tue Jun 30 04:06:50 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/ethernet/wangxun/libwx/Makefile b/drivers/net/ethernet/wangxun/libwx/Makefile\nindex a71b0ad77de3f7..c8724bb129aa06 100644\n--- a/drivers/net/ethernet/wangxun/libwx/Makefile\n+++ b/drivers/net/ethernet/wangxun/libwx/Makefile\n@@ -4,5 +4,5 @@\n \n obj-$(CONFIG_LIBWX) += libwx.o\n \n-libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o wx_ptp.o wx_mbx.o wx_sriov.o\n+libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o wx_ptp.o wx_mbx.o wx_sriov.o wx_err.o\n libwx-objs += wx_vf.o wx_vf_lib.o wx_vf_common.o\ndiff --git a/drivers/net/ethernet/wangxun/libwx/wx_err.c b/drivers/net/ethernet/wangxun/libwx/wx_err.c\nnew file mode 100644\nindex 00000000000000..c34c9406a5aedf\n--- /dev/null\n+++ b/drivers/net/ethernet/wangxun/libwx/wx_err.c\n@@ -0,0 +1,321 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/* Copyright (c) 2015 - 2026 Beijing WangXun Technology Co., Ltd. */\n+/* Copyright (c) 1999 - 2026 Intel Corporation. */\n+\n+#include \u003clinux/netdevice.h\u003e\n+#include \u003clinux/pci.h\u003e\n+#include \u003clinux/aer.h\u003e\n+\n+#include \"wx_type.h\"\n+#include \"wx_lib.h\"\n+#include \"wx_err.h\"\n+\n+/**\n+ * wx_io_error_detected - called when PCI error is detected\n+ * @pdev: Pointer to PCI device\n+ * @state: The current pci connection state\n+ *\n+ * Return: pci_ers_result_t.\n+ *\n+ * This function is called after a PCI bus error affecting\n+ * this device has been detected.\n+ */\n+static pci_ers_result_t wx_io_error_detected(struct pci_dev *pdev,\n+\t\t\t\t\t     pci_channel_state_t state)\n+{\n+\tstruct wx *wx = pci_get_drvdata(pdev);\n+\tstruct net_device *netdev;\n+\n+\tif (!wx)\n+\t\treturn PCI_ERS_RESULT_DISCONNECT;\n+\n+\tnetdev = wx-\u003enetdev;\n+\tif (!netif_device_present(netdev))\n+\t\treturn PCI_ERS_RESULT_DISCONNECT;\n+\n+\tif (state == pci_channel_io_perm_failure)\n+\t\treturn PCI_ERS_RESULT_DISCONNECT;\n+\n+\trtnl_lock();\n+\tnetif_device_detach(netdev);\n+\tset_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx-\u003eflags);\n+\twx_soft_quiesce(wx);\n+\n+\tif (!test_and_set_bit(WX_STATE_DISABLED, wx-\u003estate))\n+\t\tpci_disable_device(pdev);\n+\trtnl_unlock();\n+\n+\t/* Request a slot reset. */\n+\treturn PCI_ERS_RESULT_NEED_RESET;\n+}\n+\n+/**\n+ * wx_io_slot_reset - called after the pci bus has been reset.\n+ * @pdev: Pointer to PCI device\n+ *\n+ * Return: pci_ers_result_t.\n+ *\n+ * Restart the card from scratch, as if from a cold-boot.\n+ */\n+static pci_ers_result_t wx_io_slot_reset(struct pci_dev *pdev)\n+{\n+\tstruct wx *wx = pci_get_drvdata(pdev);\n+\tpci_ers_result_t result;\n+\n+\tif (pci_enable_device_mem(pdev)) {\n+\t\twx_err(wx, \"Cannot re-enable PCI device after reset.\\n\");\n+\t\tresult = PCI_ERS_RESULT_DISCONNECT;\n+\t} else {\n+\t\t/* make all memory operations done before clearing the flag */\n+\t\tsmp_mb__before_atomic();\n+\t\tclear_bit(WX_STATE_DISABLED, wx-\u003estate);\n+\t\tclear_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx-\u003eflags);\n+\t\tpci_set_master(pdev);\n+\t\tpci_restore_state(pdev);\n+\t\tpci_wake_from_d3(pdev, false);\n+\n+\t\trtnl_lock();\n+\t\tif (netif_running(wx-\u003enetdev) \u0026\u0026 wx-\u003edown_suspend)\n+\t\t\twx-\u003edown_suspend(wx);\n+\t\tif (wx-\u003edo_reset)\n+\t\t\twx-\u003edo_reset(wx-\u003enetdev, false);\n+\t\trtnl_unlock();\n+\t\tresult = PCI_ERS_RESULT_RECOVERED;\n+\t}\n+\n+\tpci_aer_clear_nonfatal_status(pdev);\n+\n+\treturn result;\n+}\n+\n+/**\n+ * wx_io_resume - called when traffic can start flowing again.\n+ * @pdev: Pointer to PCI device\n+ *\n+ * This callback is called when the error recovery driver tells us that\n+ * its OK to resume normal operation.\n+ */\n+static void wx_io_resume(struct pci_dev *pdev)\n+{\n+\tstruct wx *wx = pci_get_drvdata(pdev);\n+\tstruct net_device *netdev;\n+\tint err;\n+\n+\tnetdev = wx-\u003enetdev;\n+\trtnl_lock();\n+\tif (netif_running(netdev)) {\n+\t\terr = netdev-\u003enetdev_ops-\u003endo_open(netdev);\n+\t\tif (err) {\n+\t\t\twx_err(wx, \"Failed to open netdev after reset\\n\");\n+\t\t\tgoto out;\n+\t\t}\n+\t}\n+\tnetif_device_attach(netdev);\n+out:\n+\trtnl_unlock();\n+}\n+\n+const struct pci_error_handlers wx_err_handler = {\n+\t.error_detected = wx_io_error_detected,\n+\t.slot_reset = wx_io_slot_reset,\n+\t.resume = wx_io_resume,\n+};\n+EXPORT_SYMBOL(wx_err_handler);\n+\n+static void wx_pf_reset_subtask(struct wx *wx)\n+{\n+\tif (!test_and_clear_bit(WX_FLAG_NEED_PF_RESET, wx-\u003eflags))\n+\t\treturn;\n+\n+\twx_warn(wx, \"Reset adapter.\\n\");\n+\tif (wx-\u003edo_reset)\n+\t\twx-\u003edo_reset(wx-\u003enetdev, true);\n+}\n+\n+static void wx_reset_task(struct work_struct *work)\n+{\n+\tstruct wx *wx = container_of(work, struct wx, reset_task);\n+\n+\trtnl_lock();\n+\n+\tif (test_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx-\u003eflags))\n+\t\twx_soft_quiesce(wx);\n+\n+\tif (test_bit(WX_STATE_DOWN, wx-\u003estate) ||\n+\t    test_bit(WX_STATE_RESETTING, wx-\u003estate))\n+\t\tgoto out;\n+\n+\twx_pf_reset_subtask(wx);\n+\n+out:\n+\trtnl_unlock();\n+}\n+\n+void wx_check_err_subtask(struct wx *wx)\n+{\n+\tif (test_bit(WX_FLAG_NEED_PF_RESET, wx-\u003eflags))\n+\t\tqueue_work(wx-\u003ereset_wq, \u0026wx-\u003ereset_task);\n+}\n+EXPORT_SYMBOL(wx_check_err_subtask);\n+\n+int wx_init_err_task(struct wx *wx)\n+{\n+\twx-\u003ereset_wq = alloc_workqueue(\"%s_reset_wq_%x\", WQ_UNBOUND | WQ_HIGHPRI,\n+\t\t\t\t       1, wx-\u003edriver_name, pci_dev_id(wx-\u003epdev));\n+\tif (!wx-\u003ereset_wq) {\n+\t\twx_err(wx, \"Failed to create wx_reset_wq workqueue\\n\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tINIT_WORK(\u0026wx-\u003ereset_task, wx_reset_task);\n+\treturn 0;\n+}\n+EXPORT_SYMBOL(wx_init_err_task);\n+\n+static bool wx_ring_tx_pending(struct wx *wx)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i \u003c wx-\u003enum_tx_queues; i++) {\n+\t\tstruct wx_ring *tx_ring = wx-\u003etx_ring[i];\n+\n+\t\tif (tx_ring-\u003enext_to_use != tx_ring-\u003enext_to_clean)\n+\t\t\treturn true;\n+\t}\n+\n+\treturn false;\n+}\n+\n+static bool wx_vf_tx_pending(struct wx *wx)\n+{\n+\tstruct wx_ring_feature *vmdq = \u0026wx-\u003ering_feature[RING_F_VMDQ];\n+\tu32 q_per_pool = __ALIGN_MASK(1, ~vmdq-\u003emask);\n+\tu32 i, j;\n+\n+\tif (!wx-\u003enum_vfs)\n+\t\treturn false;\n+\n+\tfor (i = 0; i \u003c wx-\u003enum_vfs; i++) {\n+\t\tfor (j = 0; j \u003c q_per_pool; j++) {\n+\t\t\tu32 h, t;\n+\n+\t\t\th = rd32(wx, WX_PX_TR_RP_PV(q_per_pool, i, j));\n+\t\t\tt = rd32(wx, WX_PX_TR_WP_PV(q_per_pool, i, j));\n+\n+\t\t\tif (h != t)\n+\t\t\t\treturn true;\n+\t\t}\n+\t}\n+\n+\treturn false;\n+}\n+\n+static void wx_watchdog_flush_tx(struct wx *wx)\n+{\n+\tif (!netif_running(wx-\u003enetdev))\n+\t\treturn;\n+\tif (netif_carrier_ok(wx-\u003enetdev))\n+\t\treturn;\n+\n+\tif (wx_ring_tx_pending(wx) || wx_vf_tx_pending(wx)) {\n+\t\t/* We've lost link, so the controller stops DMA,\n+\t\t * but we've got queued Tx work that's never going\n+\t\t * to get done, so reset controller to flush Tx.\n+\t\t * (Do the reset outside of interrupt context).\n+\t\t */\n+\t\twx_warn(wx, \"initiating reset due to lost link with pending Tx work\\n\");\n+\t\tset_bit(WX_FLAG_NEED_PF_RESET, wx-\u003eflags);\n+\t}\n+}\n+\n+static void wx_detect_tx_hang(struct wx *wx)\n+{\n+\tint i;\n+\n+\t/* If we're down or resetting, just bail */\n+\tif (!netif_running(wx-\u003enetdev) ||\n+\t    test_bit(WX_STATE_RESETTING, wx-\u003estate))\n+\t\treturn;\n+\n+\t/* Force detection of hung controller */\n+\tif (netif_carrier_ok(wx-\u003enetdev)) {\n+\t\tfor (i = 0; i \u003c wx-\u003enum_tx_queues; i++)\n+\t\t\tset_bit(WX_TX_DETECT_HANG, wx-\u003etx_ring[i]-\u003estate);\n+\t}\n+}\n+\n+void wx_check_hang_subtask(struct wx *wx)\n+{\n+\tif (test_bit(WX_STATE_DOWN, wx-\u003estate) ||\n+\t    test_bit(WX_STATE_RESETTING, wx-\u003estate))\n+\t\treturn;\n+\n+\twx_watchdog_flush_tx(wx);\n+\twx_detect_tx_hang(wx);\n+}\n+EXPORT_SYMBOL(wx_check_hang_subtask);\n+\n+static bool wx_check_pcie_error(struct wx *wx)\n+{\n+\tu16 vid, pci_cmd;\n+\n+\tpci_read_config_word(wx-\u003epdev, PCI_VENDOR_ID, \u0026vid);\n+\tpci_read_config_word(wx-\u003epdev, PCI_COMMAND, \u0026pci_cmd);\n+\n+\t/* PCIe link loss or memory space can't access */\n+\tif (vid == U16_MAX || !(pci_cmd \u0026 PCI_COMMAND_MEMORY))\n+\t\treturn true;\n+\n+\treturn false;\n+}\n+\n+static void wx_tx_timeout_recovery(struct wx *wx)\n+{\n+\t/*\n+\t * When a PCIe hardware error occurs, the driver should initiate a PCIe\n+\t * recovery mechanism. However, this recovery flow relies on the AER\n+\t * driver for current kernel policy. Therefore, a self-contained\n+\t * recovery mechanism is not implemented yet.\n+\t */\n+\tset_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx-\u003eflags);\n+\twx_err(wx, \"PCIe error detected during tx timeout\\n\");\n+\tqueue_work(wx-\u003ereset_wq, \u0026wx-\u003ereset_task);\n+}\n+\n+static void wx_tx_timeout_reset(struct wx *wx)\n+{\n+\tif (test_bit(WX_STATE_DOWN, wx-\u003estate))\n+\t\treturn;\n+\n+\tset_bit(WX_FLAG_NEED_PF_RESET, wx-\u003eflags);\n+\twx_warn(wx, \"initiating reset due to tx timeout\\n\");\n+\twx_service_event_schedule(wx);\n+}\n+\n+void wx_tx_timeout(struct net_device *netdev, unsigned int __always_unused txqueue)\n+{\n+\tstruct wx *wx = netdev_priv(netdev);\n+\n+\tif (wx_check_pcie_error(wx))\n+\t\twx_tx_timeout_recovery(wx);\n+\telse\n+\t\twx_tx_timeout_reset(wx);\n+}\n+EXPORT_SYMBOL(wx_tx_timeout);\n+\n+void wx_handle_tx_hang(struct wx_ring *tx_ring, unsigned int next)\n+{\n+\tstruct wx *wx = netdev_priv(tx_ring-\u003enetdev);\n+\n+\twx_warn(wx,\n+\t\t\"Detected Tx Unit Hang: Queue %d, TDH %x, TDT %x, ntu %x, ntc %x, ntc.time_stamp %lx, jiffies %lx\\n\",\n+\t\ttx_ring-\u003equeue_index,\n+\t\trd32(wx, WX_PX_TR_RP(tx_ring-\u003ereg_idx)),\n+\t\trd32(wx, WX_PX_TR_WP(tx_ring-\u003ereg_idx)),\n+\t\ttx_ring-\u003enext_to_use, next,\n+\t\ttx_ring-\u003etx_buffer_info[next].time_stamp, jiffies);\n+\n+\tnetif_stop_subqueue(tx_ring-\u003enetdev, tx_ring-\u003equeue_index);\n+\n+\twx_tx_timeout_reset(wx);\n+}\ndiff --git a/drivers/net/ethernet/wangxun/libwx/wx_err.h b/drivers/net/ethernet/wangxun/libwx/wx_err.h\nnew file mode 100644\nindex 00000000000000..a6a82a26352849\n--- /dev/null\n+++ b/drivers/net/ethernet/wangxun/libwx/wx_err.h\n@@ -0,0 +1,18 @@\n+/* SPDX-License-Identifier: GPL-2.0 */\n+/*\n+ * WangXun Gigabit PCI Express Linux driver\n+ * Copyright (c) 2015 - 2026 Beijing WangXun Technology Co., Ltd.\n+ */\n+\n+#ifndef _WX_ERR_H_\n+#define _WX_ERR_H_\n+\n+extern const struct pci_error_handlers wx_err_handler;\n+\n+void wx_check_err_subtask(struct wx *wx);\n+int wx_init_err_task(struct wx *wx);\n+void wx_check_hang_subtask(struct wx *wx);\n+void wx_tx_timeout(struct net_device *netdev, unsigned int txqueue);\n+void wx_handle_tx_hang(struct wx_ring *tx_ring, unsigned int next);\n+\n+#endif /* _WX_ERR_H_ */\ndiff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c\nindex 5df971aca9e35f..d1356ff5d69b54 100644\n--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c\n+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c\n@@ -395,7 +395,7 @@ static void wx_update_rsc(struct wx *wx)\n \n \t/* reset the device to apply the new RSC setting */\n \tif (need_reset \u0026\u0026 wx-\u003edo_reset)\n-\t\twx-\u003edo_reset(netdev);\n+\t\twx-\u003edo_reset(netdev, true);\n }\n \n int wx_set_coalesce(struct net_device *netdev,\ndiff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c\nindex 260e14d5d54121..122c4952d203f0 100644\n--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c\n+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c\n@@ -1932,6 +1932,7 @@ static void wx_configure_tx_ring(struct wx *wx,\n \telse\n \t\tring-\u003eatr_sample_rate = 0;\n \n+\tbitmap_zero(ring-\u003estate, WX_RING_STATE_NBITS);\n \t/* reinitialize tx_buffer_info */\n \tmemset(ring-\u003etx_buffer_info, 0,\n \t       sizeof(struct wx_tx_buffer) * ring-\u003ecount);\n@@ -2851,16 +2852,26 @@ EXPORT_SYMBOL(wx_fc_enable);\n static void wx_update_xoff_rx_lfc(struct wx *wx)\n {\n \tstruct wx_hw_stats *hwstats = \u0026wx-\u003estats;\n+\tu64 data;\n+\tint i;\n \n \tif (wx-\u003efc.mode != wx_fc_full \u0026\u0026\n \t    wx-\u003efc.mode != wx_fc_rx_pause)\n \t\treturn;\n \n \tif (wx-\u003emac.type \u003e= wx_mac_aml)\n-\t\thwstats-\u003elxoffrxc += rd32_wrap(wx, WX_MAC_LXOFFRXC_AML,\n-\t\t\t\t\t       \u0026wx-\u003elast_stats.lxoffrxc);\n+\t\tdata = rd32_wrap(wx, WX_MAC_LXOFFRXC_AML,\n+\t\t\t\t \u0026wx-\u003elast_stats.lxoffrxc);\n \telse\n-\t\thwstats-\u003elxoffrxc += rd64(wx, WX_MAC_LXOFFRXC);\n+\t\tdata = rd64(wx, WX_MAC_LXOFFRXC);\n+\thwstats-\u003elxoffrxc += data;\n+\n+\t/* refill credits (no tx hang) if we received xoff */\n+\tif (!data)\n+\t\treturn;\n+\n+\tfor (i = 0; i \u003c wx-\u003enum_tx_queues; i++)\n+\t\tclear_bit(WX_HANG_CHECK_ARMED, wx-\u003etx_ring[i]-\u003estate);\n }\n \n /**\ndiff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c\nindex d042567b81284b..d3340b2b068243 100644\n--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c\n+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c\n@@ -14,6 +14,7 @@\n \n #include \"wx_type.h\"\n #include \"wx_lib.h\"\n+#include \"wx_err.h\"\n #include \"wx_ptp.h\"\n #include \"wx_hw.h\"\n #include \"wx_vf_lib.h\"\n@@ -742,6 +743,37 @@ static struct netdev_queue *wx_txring_txq(const struct wx_ring *ring)\n \treturn netdev_get_tx_queue(ring-\u003enetdev, ring-\u003equeue_index);\n }\n \n+static u32 wx_get_tx_pending(struct wx_ring *ring)\n+{\n+\tunsigned int head, tail;\n+\n+\thead = ring-\u003enext_to_clean;\n+\ttail = ring-\u003enext_to_use;\n+\n+\treturn ((head \u003c= tail) ? tail : tail + ring-\u003ecount) - head;\n+}\n+\n+static bool wx_check_tx_hang(struct wx_ring *ring)\n+{\n+\tu32 tx_done_old = ring-\u003etx_stats.tx_done_old;\n+\tu32 tx_pending = wx_get_tx_pending(ring);\n+\tu32 tx_done = ring-\u003estats.packets;\n+\n+\tif (!test_and_clear_bit(WX_TX_DETECT_HANG, ring-\u003estate))\n+\t\treturn false;\n+\n+\tif (tx_done_old == tx_done \u0026\u0026 tx_pending)\n+\t\t/* make sure it is true for two checks in a row */\n+\t\treturn test_and_set_bit(WX_HANG_CHECK_ARMED, ring-\u003estate);\n+\n+\t/* update completed stats and continue */\n+\tring-\u003etx_stats.tx_done_old = tx_done;\n+\t/* reset the countdown */\n+\tclear_bit(WX_HANG_CHECK_ARMED, ring-\u003estate);\n+\n+\treturn false;\n+}\n+\n /**\n  * wx_clean_tx_irq - Reclaim resources after transmit completes\n  * @q_vector: structure containing interrupt and ring information\n@@ -866,6 +898,11 @@ static bool wx_clean_tx_irq(struct wx_q_vector *q_vector,\n \tnetdev_tx_completed_queue(wx_txring_txq(tx_ring),\n \t\t\t\t  total_packets, total_bytes);\n \n+\tif (wx_check_tx_hang(tx_ring)) {\n+\t\twx_handle_tx_hang(tx_ring, i);\n+\t\treturn true;\n+\t}\n+\n #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)\n \tif (unlikely(total_packets \u0026\u0026 netif_carrier_ok(tx_ring-\u003enetdev) \u0026\u0026\n \t\t     (wx_desc_unused(tx_ring) \u003e= TX_WAKE_THRESHOLD))) {\n@@ -3111,7 +3148,7 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features)\n \tnetdev-\u003efeatures = features;\n \n \tif (changed \u0026 NETIF_F_HW_VLAN_CTAG_RX \u0026\u0026 wx-\u003edo_reset)\n-\t\twx-\u003edo_reset(netdev);\n+\t\twx-\u003edo_reset(netdev, true);\n \telse if (changed \u0026 (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER))\n \t\twx_set_rx_mode(netdev);\n \n@@ -3161,7 +3198,7 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features)\n \n out:\n \tif (need_reset \u0026\u0026 wx-\u003edo_reset)\n-\t\twx-\u003edo_reset(netdev);\n+\t\twx-\u003edo_reset(netdev, true);\n \n \treturn 0;\n }\n@@ -3345,5 +3382,23 @@ void wx_service_timer(struct timer_list *t)\n }\n EXPORT_SYMBOL(wx_service_timer);\n \n+void wx_soft_quiesce(struct wx *wx)\n+{\n+\tif (!netif_running(wx-\u003enetdev) ||\n+\t    test_and_set_bit(WX_STATE_DOWN, wx-\u003estate))\n+\t\treturn;\n+\n+\tpci_clear_master(wx-\u003epdev);\n+\tnetif_tx_stop_all_queues(wx-\u003enetdev);\n+\tnetif_carrier_off(wx-\u003enetdev);\n+\tnetif_tx_disable(wx-\u003enetdev);\n+\twx_napi_disable_all(wx);\n+\twx_ptp_quiesce(wx);\n+\n+\tclear_bit(WX_FLAG_NEED_PF_RESET, wx-\u003eflags);\n+\ttimer_delete_sync(\u0026wx-\u003eservice_timer);\n+}\n+EXPORT_SYMBOL(wx_soft_quiesce);\n+\n MODULE_DESCRIPTION(\"Common library for Wangxun(R) Ethernet drivers.\");\n MODULE_LICENSE(\"GPL\");\ndiff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.h b/drivers/net/ethernet/wangxun/libwx/wx_lib.h\nindex aed6ea8cf0d64a..11bd79985e1710 100644\n--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h\n+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h\n@@ -41,5 +41,6 @@ void wx_set_ring(struct wx *wx, u32 new_tx_count,\n void wx_service_event_schedule(struct wx *wx);\n void wx_service_event_complete(struct wx *wx);\n void wx_service_timer(struct timer_list *t);\n+void wx_soft_quiesce(struct wx *wx);\n \n #endif /* _WX_LIB_H_ */\ndiff --git a/drivers/net/ethernet/wangxun/libwx/wx_ptp.c b/drivers/net/ethernet/wangxun/libwx/wx_ptp.c\nindex 44f3e65052468f..7068c6845b6245 100644\n--- a/drivers/net/ethernet/wangxun/libwx/wx_ptp.c\n+++ b/drivers/net/ethernet/wangxun/libwx/wx_ptp.c\n@@ -321,6 +321,9 @@ static long wx_ptp_do_aux_work(struct ptp_clock_info *ptp)\n \tstruct wx *wx = container_of(ptp, struct wx, ptp_caps);\n \tint ts_done;\n \n+\tif (!test_bit(WX_STATE_PTP_RUNNING, wx-\u003estate))\n+\t\treturn HZ;\n+\n \tts_done = wx_ptp_tx_hwtstamp_work(wx);\n \n \twx_ptp_overflow_check(wx);\n@@ -842,6 +845,21 @@ void wx_ptp_stop(struct wx *wx)\n }\n EXPORT_SYMBOL(wx_ptp_stop);\n \n+void wx_ptp_quiesce(struct wx *wx)\n+{\n+\tif (!test_and_clear_bit(WX_STATE_PTP_RUNNING, wx-\u003estate))\n+\t\treturn;\n+\n+\tclear_bit(WX_FLAG_PTP_PPS_ENABLED, wx-\u003eflags);\n+\n+\tif (wx-\u003eptp_tx_skb) {\n+\t\tdev_kfree_skb_any(wx-\u003eptp_tx_skb);\n+\t\twx-\u003eptp_tx_skb = NULL;\n+\t}\n+\tclear_bit_unlock(WX_STATE_PTP_TX_IN_PROGRESS, wx-\u003estate);\n+}\n+EXPORT_SYMBOL(wx_ptp_quiesce);\n+\n /**\n  * wx_ptp_rx_hwtstamp - utility function which checks for RX time stamp\n  * @wx: pointer to wx struct\ndiff --git a/drivers/net/ethernet/wangxun/libwx/wx_ptp.h b/drivers/net/ethernet/wangxun/libwx/wx_ptp.h\nindex 50db90a6e3ee66..ad2f824875d51b 100644\n--- a/drivers/net/ethernet/wangxun/libwx/wx_ptp.h\n+++ b/drivers/net/ethernet/wangxun/libwx/wx_ptp.h\n@@ -10,6 +10,7 @@ void wx_ptp_reset(struct wx *wx);\n void wx_ptp_init(struct wx *wx);\n void wx_ptp_suspend(struct wx *wx);\n void wx_ptp_stop(struct wx *wx);\n+void wx_ptp_quiesce(struct wx *wx);\n void wx_ptp_rx_hwtstamp(struct wx *wx, struct sk_buff *skb);\n int wx_hwtstamp_get(struct net_device *dev,\n \t\t    struct kernel_hwtstamp_config *cfg);\ndiff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h\nindex c7befe4cdfe908..c2edb74881f2b7 100644\n--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h\n+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h\n@@ -450,6 +450,11 @@ enum WX_MSCA_CMD_value {\n #define WX_PX_TR_CFG_THRE_SHIFT      8\n #define WX_PX_TR_CFG_HEAD_WB         BIT(27)\n \n+#define WX_PX_TR_RP_PV(q_per_pool, vf_number, vf_q_index) \\\n+\t\t(WX_PX_TR_RP((q_per_pool) * (vf_number) + (vf_q_index)))\n+#define WX_PX_TR_WP_PV(q_per_pool, vf_number, vf_q_index) \\\n+\t\t(WX_PX_TR_WP((q_per_pool) * (vf_number) + (vf_q_index)))\n+\n /* Receive DMA Registers */\n #define WX_PX_RR_BAL(_i)             (0x01000 + ((_i) * 0x40))\n #define WX_PX_RR_BAH(_i)             (0x01004 + ((_i) * 0x40))\n@@ -1039,6 +1044,7 @@ struct wx_queue_stats {\n struct wx_tx_queue_stats {\n \tu64 restart_queue;\n \tu64 tx_busy;\n+\tu32 tx_done_old;\n };\n \n struct wx_rx_queue_stats {\n@@ -1054,6 +1060,12 @@ struct wx_rx_queue_stats {\n #define wx_for_each_ring(posm, headm) \\\n \tfor (posm = (headm).ring; posm; posm = posm-\u003enext)\n \n+enum wx_ring_state {\n+\tWX_TX_DETECT_HANG,\n+\tWX_HANG_CHECK_ARMED,\n+\tWX_RING_STATE_NBITS\n+};\n+\n struct wx_ring_container {\n \tstruct wx_ring *ring;           /* pointer to linked list of rings */\n \tunsigned int total_bytes;       /* total bytes processed this int */\n@@ -1073,6 +1085,7 @@ struct wx_ring {\n \t\tstruct wx_tx_buffer *tx_buffer_info;\n \t\tstruct wx_rx_buffer *rx_buffer_info;\n \t};\n+\tDECLARE_BITMAP(state, WX_RING_STATE_NBITS);\n \tu8 __iomem *tail;\n \tdma_addr_t dma;                 /* phys. address of descriptor ring */\n \tdma_addr_t headwb_dma;\n@@ -1208,6 +1221,8 @@ enum wx_state {\n \tWX_STATE_PTP_RUNNING,\n \tWX_STATE_PTP_TX_IN_PROGRESS,\n \tWX_STATE_SERVICE_SCHED,\n+\tWX_STATE_DISABLED,\n+\tWX_STATE_RES_FREED,\n \tWX_STATE_NBITS\t\t/* must be last */\n };\n \n@@ -1274,6 +1289,8 @@ enum wx_pf_flags {\n \tWX_FLAG_NEED_DO_RESET,\n \tWX_FLAG_RX_MERGE_ENABLED,\n \tWX_FLAG_TXHEAD_WB_ENABLED,\n+\tWX_FLAG_NEED_PF_RESET,\n+\tWX_FLAG_NEED_PCIE_RECOVERY,\n \tWX_PF_FLAGS_NBITS               /* must be last */\n };\n \n@@ -1394,7 +1411,8 @@ struct wx {\n \tvoid (*atr)(struct wx_ring *ring, struct wx_tx_buffer *first, u8 ptype);\n \tvoid (*configure_fdir)(struct wx *wx);\n \tint (*setup_tc)(struct net_device *netdev, u8 tc);\n-\tvoid (*do_reset)(struct net_device *netdev);\n+\tvoid (*do_reset)(struct net_device *netdev, bool reinit);\n+\tvoid (*down_suspend)(struct wx *wx);\n \tint (*ptp_setup_sdp)(struct wx *wx);\n \tvoid (*set_num_queues)(struct wx *wx);\n \n@@ -1422,6 +1440,8 @@ struct wx {\n \n \tstruct timer_list service_timer;\n \tstruct work_struct service_task;\n+\tstruct work_struct reset_task;\n+\tstruct workqueue_struct *reset_wq;\n \tstruct mutex reset_lock; /* mutex for reset */\n };\n \n@@ -1504,7 +1524,8 @@ rd32_wrap(struct wx *wx, u32 reg, u32 *last)\n \n #define wx_err(wx, fmt, arg...) \\\n \tdev_err(\u0026(wx)-\u003epdev-\u003edev, fmt, ##arg)\n-\n+#define wx_warn(wx, fmt, arg...) \\\n+\tdev_warn(\u0026(wx)-\u003epdev-\u003edev, fmt, ##arg)\n #define wx_dbg(wx, fmt, arg...) \\\n \tdev_dbg(\u0026(wx)-\u003epdev-\u003edev, fmt, ##arg)\n \ndiff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c\nindex b2e19198280326..1960f7154151df 100644\n--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c\n+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c\n@@ -59,7 +59,6 @@ static int ngbe_set_ringparam(struct net_device *netdev,\n \twx_set_ring(wx, new_tx_count, new_rx_count, temp_ring);\n \tkvfree(temp_ring);\n \n-\twx_configure(wx);\n \tngbe_up(wx);\n \n clear_reset:\ndiff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c\nindex a16221995909f9..cda223101ced72 100644\n--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c\n+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c\n@@ -14,6 +14,7 @@\n #include \"../libwx/wx_type.h\"\n #include \"../libwx/wx_hw.h\"\n #include \"../libwx/wx_lib.h\"\n+#include \"../libwx/wx_err.h\"\n #include \"../libwx/wx_ptp.h\"\n #include \"../libwx/wx_mbx.h\"\n #include \"../libwx/wx_sriov.h\"\n@@ -46,6 +47,20 @@ static const struct pci_device_id ngbe_pci_tbl[] = {\n \t{ }\n };\n \n+static void ngbe_down_suspend(struct wx *wx)\n+{\n+\tif (test_and_set_bit(WX_STATE_RES_FREED, wx-\u003estate))\n+\t\treturn;\n+\n+\tphylink_stop(wx-\u003ephylink);\n+\tphylink_disconnect_phy(wx-\u003ephylink);\n+\twx_clean_all_tx_rings(wx);\n+\twx_clean_all_rx_rings(wx);\n+\twx_free_irq(wx);\n+\twx_free_isb_resources(wx);\n+\twx_free_resources(wx);\n+}\n+\n /**\n  *  ngbe_init_type_code - Initialize the shared code\n  *  @wx: pointer to hardware structure\n@@ -133,6 +148,8 @@ static int ngbe_sw_init(struct wx *wx)\n \n \twx-\u003embx.size = WX_VXMAILBOX_SIZE;\n \twx-\u003esetup_tc = ngbe_setup_tc;\n+\twx-\u003edo_reset = ngbe_do_reset;\n+\twx-\u003edown_suspend = ngbe_down_suspend;\n \tset_bit(0, \u0026wx-\u003efwd_bitmask);\n \n \treturn 0;\n@@ -147,6 +164,8 @@ static void ngbe_service_task(struct work_struct *work)\n \tstruct wx *wx = container_of(work, struct wx, service_task);\n \n \twx_update_stats(wx);\n+\twx_check_hang_subtask(wx);\n+\twx_check_err_subtask(wx);\n \n \twx_service_event_complete(wx);\n }\n@@ -392,6 +411,7 @@ static void ngbe_disable_device(struct wx *wx)\n \tnetif_tx_stop_all_queues(netdev);\n \tnetif_tx_disable(netdev);\n \n+\tclear_bit(WX_FLAG_NEED_PF_RESET, wx-\u003eflags);\n \ttimer_delete_sync(\u0026wx-\u003eservice_timer);\n \tcancel_work_sync(\u0026wx-\u003eservice_task);\n \n@@ -408,6 +428,9 @@ static void ngbe_disable_device(struct wx *wx)\n \n static void ngbe_reset(struct wx *wx)\n {\n+\tif (test_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx-\u003eflags))\n+\t\treturn;\n+\n \twx_flush_sw_mac_table(wx);\n \twx_mac_set_default_filter(wx, wx-\u003emac.addr);\n \tif (test_bit(WX_STATE_PTP_RUNNING, wx-\u003estate))\n@@ -423,13 +446,14 @@ void ngbe_down(struct wx *wx)\n \twx_clean_all_rx_rings(wx);\n }\n \n-void ngbe_up(struct wx *wx)\n+static void ngbe_up_complete(struct wx *wx)\n {\n \twx_configure_vectors(wx);\n \n \t/* make sure to complete pre-operations */\n \tsmp_mb__before_atomic();\n \tclear_bit(WX_STATE_DOWN, wx-\u003estate);\n+\tclear_bit(WX_STATE_RES_FREED, wx-\u003estate);\n \twx_napi_enable_all(wx);\n \t/* enable transmits */\n \tnetif_tx_start_all_queues(wx-\u003enetdev);\n@@ -490,7 +514,7 @@ static int ngbe_open(struct net_device *netdev)\n \n \twx_ptp_init(wx);\n \n-\tngbe_up(wx);\n+\tngbe_up_complete(wx);\n \n \treturn 0;\n err_dis_phy:\n@@ -503,6 +527,12 @@ static int ngbe_open(struct net_device *netdev)\n \treturn err;\n }\n \n+void ngbe_up(struct wx *wx)\n+{\n+\twx_configure(wx);\n+\tngbe_up_complete(wx);\n+}\n+\n /**\n  * ngbe_close - Disables a network interface\n  * @netdev: network interface device structure\n@@ -518,6 +548,9 @@ static int ngbe_close(struct net_device *netdev)\n {\n \tstruct wx *wx = netdev_priv(netdev);\n \n+\tif (test_bit(WX_STATE_RES_FREED, wx-\u003estate))\n+\t\tgoto out;\n+\n \twx_ptp_stop(wx);\n \tngbe_down(wx);\n \twx_free_irq(wx);\n@@ -525,7 +558,7 @@ static int ngbe_close(struct net_device *netdev)\n \twx_free_resources(wx);\n \tphylink_disconnect_phy(wx-\u003ephylink);\n \twx_control_hw(wx, false);\n-\n+out:\n \treturn 0;\n }\n \n@@ -555,7 +588,8 @@ static void ngbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake)\n \t*enable_wake = !!wufc;\n \twx_control_hw(wx, false);\n \n-\tpci_disable_device(pdev);\n+\tif (!test_and_set_bit(WX_STATE_DISABLED, wx-\u003estate))\n+\t\tpci_disable_device(pdev);\n }\n \n static void ngbe_shutdown(struct pci_dev *pdev)\n@@ -590,6 +624,8 @@ int ngbe_setup_tc(struct net_device *dev, u8 tc)\n \t */\n \tif (netif_running(dev))\n \t\tngbe_close(dev);\n+\telse\n+\t\tngbe_reset(wx);\n \n \twx_clear_interrupt_scheme(wx);\n \n@@ -606,11 +642,36 @@ int ngbe_setup_tc(struct net_device *dev, u8 tc)\n \treturn 0;\n }\n \n+static void ngbe_reinit_locked(struct wx *wx)\n+{\n+\tnetif_trans_update(wx-\u003enetdev);\n+\n+\tmutex_lock(\u0026wx-\u003ereset_lock);\n+\tset_bit(WX_STATE_RESETTING, wx-\u003estate);\n+\n+\tngbe_down(wx);\n+\tngbe_up(wx);\n+\n+\tclear_bit(WX_STATE_RESETTING, wx-\u003estate);\n+\tmutex_unlock(\u0026wx-\u003ereset_lock);\n+}\n+\n+void ngbe_do_reset(struct net_device *netdev, bool reinit)\n+{\n+\tstruct wx *wx = netdev_priv(netdev);\n+\n+\tif (netif_running(netdev) \u0026\u0026 reinit)\n+\t\tngbe_reinit_locked(wx);\n+\telse\n+\t\tngbe_reset(wx);\n+}\n+\n static const struct net_device_ops ngbe_netdev_ops = {\n \t.ndo_open               = ngbe_open,\n \t.ndo_stop               = ngbe_close,\n \t.ndo_change_mtu         = wx_change_mtu,\n \t.ndo_start_xmit         = wx_xmit_frame,\n+\t.ndo_tx_timeout         = wx_tx_timeout,\n \t.ndo_set_rx_mode        = wx_set_rx_mode,\n \t.ndo_set_features       = wx_set_features,\n \t.ndo_fix_features       = wx_fix_features,\n@@ -700,6 +761,7 @@ static int ngbe_probe(struct pci_dev *pdev,\n \twx-\u003edriver_name = ngbe_driver_name;\n \tngbe_set_ethtool_ops(netdev);\n \tnetdev-\u003enetdev_ops = \u0026ngbe_netdev_ops;\n+\tnetdev-\u003ewatchdog_timeo = 5 * HZ;\n \n \tnetdev-\u003efeatures = NETIF_F_SG | NETIF_F_IP_CSUM |\n \t\t\t   NETIF_F_TSO | NETIF_F_TSO6 |\n@@ -796,6 +858,10 @@ static int ngbe_probe(struct pci_dev *pdev,\n \teth_hw_addr_set(netdev, wx-\u003emac.perm_addr);\n \twx_mac_set_default_filter(wx, wx-\u003emac.perm_addr);\n \n+\terr = wx_init_err_task(wx);\n+\tif (err)\n+\t\tgoto err_free_mac_table;\n+\n \tngbe_init_service(wx);\n \n \terr = wx_init_interrupt_scheme(wx);\n@@ -812,6 +878,7 @@ static int ngbe_probe(struct pci_dev *pdev,\n \t\tgoto err_register;\n \n \tpci_set_drvdata(pdev, wx);\n+\tpci_save_state(pdev);\n \n \treturn 0;\n \n@@ -823,6 +890,8 @@ static int ngbe_probe(struct pci_dev *pdev,\n err_cancel_service:\n \ttimer_delete_sync(\u0026wx-\u003eservice_timer);\n \tcancel_work_sync(\u0026wx-\u003eservice_task);\n+\tcancel_work_sync(\u0026wx-\u003ereset_task);\n+\tdestroy_workqueue(wx-\u003ereset_wq);\n err_free_mac_table:\n \tkfree(wx-\u003erss_key);\n \tkfree(wx-\u003emac_table);\n@@ -854,6 +923,8 @@ static void ngbe_remove(struct pci_dev *pdev)\n \n \ttimer_shutdown_sync(\u0026wx-\u003eservice_timer);\n \tcancel_work_sync(\u0026wx-\u003eservice_task);\n+\tcancel_work_sync(\u0026wx-\u003ereset_task);\n+\tdestroy_workqueue(wx-\u003ereset_wq);\n \n \tphylink_destroy(wx-\u003ephylink);\n \tpci_release_selected_regions(pdev,\n@@ -863,7 +934,8 @@ static void ngbe_remove(struct pci_dev *pdev)\n \tkfree(wx-\u003emac_table);\n \twx_clear_interrupt_scheme(wx);\n \n-\tpci_disable_device(pdev);\n+\tif (!test_and_set_bit(WX_STATE_DISABLED, wx-\u003estate))\n+\t\tpci_disable_device(pdev);\n }\n \n static int ngbe_suspend(struct pci_dev *pdev, pm_message_t state)\n@@ -890,6 +962,7 @@ static int ngbe_resume(struct pci_dev *pdev)\n \t\twx_err(wx, \"Cannot enable PCI device from suspend\\n\");\n \t\treturn err;\n \t}\n+\tclear_bit(WX_STATE_DISABLED, wx-\u003estate);\n \tpci_set_master(pdev);\n \tdevice_wakeup_disable(\u0026pdev-\u003edev);\n \n@@ -914,6 +987,7 @@ static struct pci_driver ngbe_driver = {\n \t.resume   = ngbe_resume,\n \t.shutdown = ngbe_shutdown,\n \t.sriov_configure = wx_pci_sriov_configure,\n+\t.err_handler = \u0026wx_err_handler,\n };\n \n module_pci_driver(ngbe_driver);\ndiff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h\nindex 7077a0da4c986a..c9233dc7ae5052 100644\n--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h\n+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h\n@@ -125,5 +125,6 @@ extern char ngbe_driver_name[];\n void ngbe_down(struct wx *wx);\n void ngbe_up(struct wx *wx);\n int ngbe_setup_tc(struct net_device *dev, u8 tc);\n+void ngbe_do_reset(struct net_device *netdev, bool reinit);\n \n #endif /* _NGBE_TYPE_H_ */\ndiff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c\nindex 20c5a295c6c296..d85ee83192e4fa 100644\n--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c\n+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c\n@@ -14,6 +14,7 @@\n \n #include \"../libwx/wx_type.h\"\n #include \"../libwx/wx_lib.h\"\n+#include \"../libwx/wx_err.h\"\n #include \"../libwx/wx_ptp.h\"\n #include \"../libwx/wx_hw.h\"\n #include \"../libwx/wx_mbx.h\"\n@@ -93,6 +94,10 @@ static void txgbe_module_detection_subtask(struct wx *wx)\n {\n \tint err;\n \n+\tif (test_bit(WX_STATE_DOWN, wx-\u003estate) ||\n+\t    test_bit(WX_STATE_RESETTING, wx-\u003estate))\n+\t\treturn;\n+\n \tif (!test_and_clear_bit(WX_FLAG_NEED_MODULE_RESET, wx-\u003eflags))\n \t\treturn;\n \n@@ -106,6 +111,10 @@ static void txgbe_module_detection_subtask(struct wx *wx)\n \n static void txgbe_link_config_subtask(struct wx *wx)\n {\n+\tif (test_bit(WX_STATE_DOWN, wx-\u003estate) ||\n+\t    test_bit(WX_STATE_RESETTING, wx-\u003estate))\n+\t\treturn;\n+\n \tif (!test_and_clear_bit(WX_FLAG_NEED_LINK_CONFIG, wx-\u003eflags))\n \t\treturn;\n \n@@ -123,6 +132,8 @@ static void txgbe_service_task(struct work_struct *work)\n \ttxgbe_module_detection_subtask(wx);\n \ttxgbe_link_config_subtask(wx);\n \twx_update_stats(wx);\n+\twx_check_hang_subtask(wx);\n+\twx_check_err_subtask(wx);\n \n \twx_service_event_complete(wx);\n }\n@@ -144,6 +155,7 @@ static void txgbe_up_complete(struct wx *wx)\n \t/* make sure to complete pre-operations */\n \tsmp_mb__before_atomic();\n \tclear_bit(WX_STATE_DOWN, wx-\u003estate);\n+\tclear_bit(WX_STATE_RES_FREED, wx-\u003estate);\n \twx_napi_enable_all(wx);\n \n \tswitch (wx-\u003emac.type) {\n@@ -187,6 +199,9 @@ static void txgbe_reset(struct wx *wx)\n \tu8 old_addr[ETH_ALEN];\n \tint err;\n \n+\tif (test_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx-\u003eflags))\n+\t\treturn;\n+\n \terr = txgbe_reset_hw(wx);\n \tif (err != 0)\n \t\twx_err(wx, \"Hardware Error: %d\\n\", err);\n@@ -224,6 +239,7 @@ static void txgbe_disable_device(struct wx *wx)\n \twx_irq_disable(wx);\n \twx_napi_disable_all(wx);\n \n+\tclear_bit(WX_FLAG_NEED_PF_RESET, wx-\u003eflags);\n \ttimer_delete_sync(\u0026wx-\u003eservice_timer);\n \tcancel_work_sync(\u0026wx-\u003eservice_task);\n \n@@ -292,6 +308,20 @@ void txgbe_up(struct wx *wx)\n \ttxgbe_up_complete(wx);\n }\n \n+static void txgbe_down_suspend(struct wx *wx)\n+{\n+\tif (test_and_set_bit(WX_STATE_RES_FREED, wx-\u003estate))\n+\t\treturn;\n+\n+\tphylink_stop(wx-\u003ephylink);\n+\twx_clean_all_tx_rings(wx);\n+\twx_clean_all_rx_rings(wx);\n+\twx_free_irq(wx);\n+\ttxgbe_free_misc_irq(wx-\u003epriv);\n+\twx_free_resources(wx);\n+\ttxgbe_fdir_filter_exit(wx);\n+}\n+\n /**\n  *  txgbe_init_type_code - Initialize the shared code\n  *  @wx: pointer to hardware structure\n@@ -408,6 +438,7 @@ static int txgbe_sw_init(struct wx *wx)\n \n \twx-\u003esetup_tc = txgbe_setup_tc;\n \twx-\u003edo_reset = txgbe_do_reset;\n+\twx-\u003edown_suspend = txgbe_down_suspend;\n \tset_bit(0, \u0026wx-\u003efwd_bitmask);\n \n \tswitch (wx-\u003emac.type) {\n@@ -518,12 +549,16 @@ static int txgbe_close(struct net_device *netdev)\n {\n \tstruct wx *wx = netdev_priv(netdev);\n \n+\tif (test_bit(WX_STATE_RES_FREED, wx-\u003estate))\n+\t\tgoto out;\n+\n \twx_ptp_stop(wx);\n \ttxgbe_down(wx);\n \twx_free_irq(wx);\n \ttxgbe_free_misc_irq(wx-\u003epriv);\n \twx_free_resources(wx);\n \ttxgbe_fdir_filter_exit(wx);\n+out:\n \twx_control_hw(wx, false);\n \n \treturn 0;\n@@ -544,7 +579,8 @@ static void txgbe_dev_shutdown(struct pci_dev *pdev)\n \n \twx_control_hw(wx, false);\n \n-\tpci_disable_device(pdev);\n+\tif (!test_and_set_bit(WX_STATE_DISABLED, wx-\u003estate))\n+\t\tpci_disable_device(pdev);\n }\n \n static void txgbe_shutdown(struct pci_dev *pdev)\n@@ -606,11 +642,11 @@ static void txgbe_reinit_locked(struct wx *wx)\n \tmutex_unlock(\u0026wx-\u003ereset_lock);\n }\n \n-void txgbe_do_reset(struct net_device *netdev)\n+void txgbe_do_reset(struct net_device *netdev, bool reinit)\n {\n \tstruct wx *wx = netdev_priv(netdev);\n \n-\tif (netif_running(netdev))\n+\tif (netif_running(netdev) \u0026\u0026 reinit)\n \t\ttxgbe_reinit_locked(wx);\n \telse\n \t\ttxgbe_reset(wx);\n@@ -654,6 +690,7 @@ static const struct net_device_ops txgbe_netdev_ops = {\n \t.ndo_stop               = txgbe_close,\n \t.ndo_change_mtu         = wx_change_mtu,\n \t.ndo_start_xmit         = wx_xmit_frame,\n+\t.ndo_tx_timeout         = wx_tx_timeout,\n \t.ndo_set_rx_mode        = wx_set_rx_mode,\n \t.ndo_set_features       = wx_set_features,\n \t.ndo_fix_features       = wx_fix_features,\n@@ -745,6 +782,7 @@ static int txgbe_probe(struct pci_dev *pdev,\n \twx-\u003edriver_name = txgbe_driver_name;\n \ttxgbe_set_ethtool_ops(netdev);\n \tnetdev-\u003enetdev_ops = \u0026txgbe_netdev_ops;\n+\tnetdev-\u003ewatchdog_timeo = 5 * HZ;\n \tnetdev-\u003eudp_tunnel_nic_info = \u0026txgbe_udp_tunnels;\n \n \t/* setup the private structure */\n@@ -814,6 +852,10 @@ static int txgbe_probe(struct pci_dev *pdev,\n \teth_hw_addr_set(netdev, wx-\u003emac.perm_addr);\n \twx_mac_set_default_filter(wx, wx-\u003emac.perm_addr);\n \n+\terr = wx_init_err_task(wx);\n+\tif (err)\n+\t\tgoto err_free_mac_table;\n+\n \ttxgbe_init_service(wx);\n \n \terr = wx_init_interrupt_scheme(wx);\n@@ -889,6 +931,7 @@ static int txgbe_probe(struct pci_dev *pdev,\n \t\tgoto err_remove_phy;\n \n \tpci_set_drvdata(pdev, wx);\n+\tpci_save_state(pdev);\n \n \tnetif_tx_stop_all_queues(netdev);\n \n@@ -916,6 +959,8 @@ static int txgbe_probe(struct pci_dev *pdev,\n err_cancel_service:\n \ttimer_delete_sync(\u0026wx-\u003eservice_timer);\n \tcancel_work_sync(\u0026wx-\u003eservice_task);\n+\tcancel_work_sync(\u0026wx-\u003ereset_task);\n+\tdestroy_workqueue(wx-\u003ereset_wq);\n err_free_mac_table:\n \tkfree(wx-\u003erss_key);\n \tkfree(wx-\u003emac_table);\n@@ -948,6 +993,8 @@ static void txgbe_remove(struct pci_dev *pdev)\n \n \ttimer_shutdown_sync(\u0026wx-\u003eservice_timer);\n \tcancel_work_sync(\u0026wx-\u003eservice_task);\n+\tcancel_work_sync(\u0026wx-\u003ereset_task);\n+\tdestroy_workqueue(wx-\u003ereset_wq);\n \n \ttxgbe_remove_phy(txgbe);\n \twx_free_isb_resources(wx);\n@@ -959,7 +1006,8 @@ static void txgbe_remove(struct pci_dev *pdev)\n \tkfree(wx-\u003emac_table);\n \twx_clear_interrupt_scheme(wx);\n \n-\tpci_disable_device(pdev);\n+\tif (!test_and_set_bit(WX_STATE_DISABLED, wx-\u003estate))\n+\t\tpci_disable_device(pdev);\n }\n \n static struct pci_driver txgbe_driver = {\n@@ -969,6 +1017,7 @@ static struct pci_driver txgbe_driver = {\n \t.remove   = txgbe_remove,\n \t.shutdown = txgbe_shutdown,\n \t.sriov_configure = wx_pci_sriov_configure,\n+\t.err_handler = \u0026wx_err_handler,\n };\n \n module_pci_driver(txgbe_driver);\ndiff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h\nindex 877234e3fdc2b6..3e93a3f309c166 100644\n--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h\n+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h\n@@ -313,7 +313,7 @@ extern char txgbe_driver_name[];\n void txgbe_down(struct wx *wx);\n void txgbe_up(struct wx *wx);\n int txgbe_setup_tc(struct net_device *dev, u8 tc);\n-void txgbe_do_reset(struct net_device *netdev);\n+void txgbe_do_reset(struct net_device *netdev, bool reinit);\n \n #define DECLARE_PHY_INTERFACE_MASK_ZERO(name) \\\n \tunsigned long name[PHY_INTERFACE_MODE_MAX] = { 0, }\n"
}

2/1 2026/06/30 04:06 agent patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch modifies the Wangxun Ethernet drivers (ngbe, txgbe) to add PCI error recovery, TX timeout handling, and TX hang detection. These are drivers for specific physical PCI hardware. Since there is no software emulator for Wangxun devices in the kernel, the probe functions will not succeed and the netdevs will not be registered in virtualized environments like GCE or QEMU. Therefore, the modified code is unreachable during fuzzing.",
  "WorthFuzzing": false
}

Instruction:
You are an expert Linux kernel maintainer.
Your job is to review a provided patch series and determine
if it makes functional changes to the kernel that should be fuzzed.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively
use your code access tools to examine the actual source code and confirm any assumptions.

Return WorthFuzzing=false if the patch only contains:
- Modifications to Documentation/, Kconfig files, or code comments.
- Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints.
- Changes to numeric constants or macros that do not functionally alter execution flow.
- Code paths that are impossible to reach in virtualized environments like GCE or QEMU,
even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim).

If it modifies reachable core kernel logic, drivers, or architectures, use your code search
tools to verify the code can be executed, then return WorthFuzzing=true.

When returning WorthFuzzing=true, you MUST ALSO:
1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols.
   Avoid listing generic hot-path functions to prevent skewed test distributions.
2. Identify any specific CONFIG_ options required to properly test this new/modified feature.
   Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions.
   Do not list too generic configs (we already have them enabled). Only list those that
   specifically cover the modified code. List them in the EnableConfigs output array,
   and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
For your convenience, here is the diff of the changes:
commit 2160a414d246ac3fdf36d26f7f1dd756ae874054
Author: syz-cluster <triage@syzkaller.com>
Date:   Tue Jun 30 04:06:50 2026 +0000

    syz-cluster: applied patch under review

diff --git a/drivers/net/ethernet/wangxun/libwx/Makefile b/drivers/net/ethernet/wangxun/libwx/Makefile
index a71b0ad77de3f7..c8724bb129aa06 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 00000000000000..c34c9406a5aedf
--- /dev/null
+++ b/drivers/net/ethernet/wangxun/libwx/wx_err.c
@@ -0,0 +1,321 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2015 - 2026 Beijing WangXun Technology Co., Ltd. */
+/* Copyright (c) 1999 - 2026 Intel Corporation. */
+
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/aer.h>
+
+#include "wx_type.h"
+#include "wx_lib.h"
+#include "wx_err.h"
+
+/**
+ * wx_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci connection state
+ *
+ * Return: pci_ers_result_t.
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t wx_io_error_detected(struct pci_dev *pdev,
+					     pci_channel_state_t state)
+{
+	struct wx *wx = pci_get_drvdata(pdev);
+	struct net_device *netdev;
+
+	if (!wx)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	netdev = wx->netdev;
+	if (!netif_device_present(netdev))
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	if (state == pci_channel_io_perm_failure)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	rtnl_lock();
+	netif_device_detach(netdev);
+	set_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx->flags);
+	wx_soft_quiesce(wx);
+
+	if (!test_and_set_bit(WX_STATE_DISABLED, wx->state))
+		pci_disable_device(pdev);
+	rtnl_unlock();
+
+	/* Request a slot reset. */
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * wx_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Return: pci_ers_result_t.
+ *
+ * Restart the card from scratch, as if from a cold-boot.
+ */
+static pci_ers_result_t wx_io_slot_reset(struct pci_dev *pdev)
+{
+	struct wx *wx = pci_get_drvdata(pdev);
+	pci_ers_result_t result;
+
+	if (pci_enable_device_mem(pdev)) {
+		wx_err(wx, "Cannot re-enable PCI device after reset.\n");
+		result = PCI_ERS_RESULT_DISCONNECT;
+	} else {
+		/* make all memory operations done before clearing the flag */
+		smp_mb__before_atomic();
+		clear_bit(WX_STATE_DISABLED, wx->state);
+		clear_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx->flags);
+		pci_set_master(pdev);
+		pci_restore_state(pdev);
+		pci_wake_from_d3(pdev, false);
+
+		rtnl_lock();
+		if (netif_running(wx->netdev) && wx->down_suspend)
+			wx->down_suspend(wx);
+		if (wx->do_reset)
+			wx->do_reset(wx->netdev, false);
+		rtnl_unlock();
+		result = PCI_ERS_RESULT_RECOVERED;
+	}
+
+	pci_aer_clear_nonfatal_status(pdev);
+
+	return result;
+}
+
+/**
+ * wx_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells us that
+ * its OK to resume normal operation.
+ */
+static void wx_io_resume(struct pci_dev *pdev)
+{
+	struct wx *wx = pci_get_drvdata(pdev);
+	struct net_device *netdev;
+	int err;
+
+	netdev = wx->netdev;
+	rtnl_lock();
+	if (netif_running(netdev)) {
+		err = netdev->netdev_ops->ndo_open(netdev);
+		if (err) {
+			wx_err(wx, "Failed to open netdev after reset\n");
+			goto out;
+		}
+	}
+	netif_device_attach(netdev);
+out:
+	rtnl_unlock();
+}
+
+const struct pci_error_handlers wx_err_handler = {
+	.error_detected = wx_io_error_detected,
+	.slot_reset = wx_io_slot_reset,
+	.resume = wx_io_resume,
+};
+EXPORT_SYMBOL(wx_err_handler);
+
+static void wx_pf_reset_subtask(struct wx *wx)
+{
+	if (!test_and_clear_bit(WX_FLAG_NEED_PF_RESET, wx->flags))
+		return;
+
+	wx_warn(wx, "Reset adapter.\n");
+	if (wx->do_reset)
+		wx->do_reset(wx->netdev, true);
+}
+
+static void wx_reset_task(struct work_struct *work)
+{
+	struct wx *wx = container_of(work, struct wx, reset_task);
+
+	rtnl_lock();
+
+	if (test_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx->flags))
+		wx_soft_quiesce(wx);
+
+	if (test_bit(WX_STATE_DOWN, wx->state) ||
+	    test_bit(WX_STATE_RESETTING, wx->state))
+		goto out;
+
+	wx_pf_reset_subtask(wx);
+
+out:
+	rtnl_unlock();
+}
+
+void wx_check_err_subtask(struct wx *wx)
+{
+	if (test_bit(WX_FLAG_NEED_PF_RESET, wx->flags))
+		queue_work(wx->reset_wq, &wx->reset_task);
+}
+EXPORT_SYMBOL(wx_check_err_subtask);
+
+int wx_init_err_task(struct wx *wx)
+{
+	wx->reset_wq = alloc_workqueue("%s_reset_wq_%x", WQ_UNBOUND | WQ_HIGHPRI,
+				       1, wx->driver_name, pci_dev_id(wx->pdev));
+	if (!wx->reset_wq) {
+		wx_err(wx, "Failed to create wx_reset_wq workqueue\n");
+		return -ENOMEM;
+	}
+
+	INIT_WORK(&wx->reset_task, wx_reset_task);
+	return 0;
+}
+EXPORT_SYMBOL(wx_init_err_task);
+
+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_running(wx->netdev))
+		return;
+	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);
+	}
+}
+
+static void wx_detect_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_hang_subtask(struct wx *wx)
+{
+	if (test_bit(WX_STATE_DOWN, wx->state) ||
+	    test_bit(WX_STATE_RESETTING, wx->state))
+		return;
+
+	wx_watchdog_flush_tx(wx);
+	wx_detect_tx_hang(wx);
+}
+EXPORT_SYMBOL(wx_check_hang_subtask);
+
+static bool wx_check_pcie_error(struct wx *wx)
+{
+	u16 vid, pci_cmd;
+
+	pci_read_config_word(wx->pdev, PCI_VENDOR_ID, &vid);
+	pci_read_config_word(wx->pdev, PCI_COMMAND, &pci_cmd);
+
+	/* PCIe link loss or memory space can't access */
+	if (vid == U16_MAX || !(pci_cmd & PCI_COMMAND_MEMORY))
+		return true;
+
+	return false;
+}
+
+static void wx_tx_timeout_recovery(struct wx *wx)
+{
+	/*
+	 * When a PCIe hardware error occurs, the driver should initiate a PCIe
+	 * recovery mechanism. However, this recovery flow relies on the AER
+	 * driver for current kernel policy. Therefore, a self-contained
+	 * recovery mechanism is not implemented yet.
+	 */
+	set_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx->flags);
+	wx_err(wx, "PCIe error detected during tx timeout\n");
+	queue_work(wx->reset_wq, &wx->reset_task);
+}
+
+static void wx_tx_timeout_reset(struct wx *wx)
+{
+	if (test_bit(WX_STATE_DOWN, wx->state))
+		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);
+
+	if (wx_check_pcie_error(wx))
+		wx_tx_timeout_recovery(wx);
+	else
+		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 00000000000000..a6a82a26352849
--- /dev/null
+++ b/drivers/net/ethernet/wangxun/libwx/wx_err.h
@@ -0,0 +1,18 @@
+/* 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_
+
+extern const struct pci_error_handlers wx_err_handler;
+
+void wx_check_err_subtask(struct wx *wx);
+int wx_init_err_task(struct wx *wx);
+void wx_check_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_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index 5df971aca9e35f..d1356ff5d69b54 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -395,7 +395,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_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index 260e14d5d54121..122c4952d203f0 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);
@@ -2851,16 +2852,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 d042567b81284b..d3340b2b068243 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))) {
@@ -3111,7 +3148,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);
 
@@ -3161,7 +3198,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;
 }
@@ -3345,5 +3382,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_PF_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 aed6ea8cf0d64a..11bd79985e1710 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
@@ -41,5 +41,6 @@ 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);
+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 44f3e65052468f..7068c6845b6245 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,21 @@ 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_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);
+}
+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 50db90a6e3ee66..ad2f824875d51b 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/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index c7befe4cdfe908..c2edb74881f2b7 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;
@@ -1208,6 +1221,8 @@ enum wx_state {
 	WX_STATE_PTP_RUNNING,
 	WX_STATE_PTP_TX_IN_PROGRESS,
 	WX_STATE_SERVICE_SCHED,
+	WX_STATE_DISABLED,
+	WX_STATE_RES_FREED,
 	WX_STATE_NBITS		/* must be last */
 };
 
@@ -1274,6 +1289,8 @@ 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_FLAG_NEED_PCIE_RECOVERY,
 	WX_PF_FLAGS_NBITS               /* must be last */
 };
 
@@ -1394,7 +1411,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 (*down_suspend)(struct wx *wx);
 	int (*ptp_setup_sdp)(struct wx *wx);
 	void (*set_num_queues)(struct wx *wx);
 
@@ -1422,6 +1440,8 @@ struct wx {
 
 	struct timer_list service_timer;
 	struct work_struct service_task;
+	struct work_struct reset_task;
+	struct workqueue_struct *reset_wq;
 	struct mutex reset_lock; /* mutex for reset */
 };
 
@@ -1504,7 +1524,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_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
index b2e19198280326..1960f7154151df 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
@@ -59,7 +59,6 @@ static int ngbe_set_ringparam(struct net_device *netdev,
 	wx_set_ring(wx, new_tx_count, new_rx_count, temp_ring);
 	kvfree(temp_ring);
 
-	wx_configure(wx);
 	ngbe_up(wx);
 
 clear_reset:
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index a16221995909f9..cda223101ced72 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"
@@ -46,6 +47,20 @@ static const struct pci_device_id ngbe_pci_tbl[] = {
 	{ }
 };
 
+static void ngbe_down_suspend(struct wx *wx)
+{
+	if (test_and_set_bit(WX_STATE_RES_FREED, wx->state))
+		return;
+
+	phylink_stop(wx->phylink);
+	phylink_disconnect_phy(wx->phylink);
+	wx_clean_all_tx_rings(wx);
+	wx_clean_all_rx_rings(wx);
+	wx_free_irq(wx);
+	wx_free_isb_resources(wx);
+	wx_free_resources(wx);
+}
+
 /**
  *  ngbe_init_type_code - Initialize the shared code
  *  @wx: pointer to hardware structure
@@ -133,6 +148,8 @@ 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->down_suspend = ngbe_down_suspend;
 	set_bit(0, &wx->fwd_bitmask);
 
 	return 0;
@@ -147,6 +164,8 @@ static void ngbe_service_task(struct work_struct *work)
 	struct wx *wx = container_of(work, struct wx, service_task);
 
 	wx_update_stats(wx);
+	wx_check_hang_subtask(wx);
+	wx_check_err_subtask(wx);
 
 	wx_service_event_complete(wx);
 }
@@ -392,6 +411,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);
 
@@ -408,6 +428,9 @@ static void ngbe_disable_device(struct wx *wx)
 
 static void ngbe_reset(struct wx *wx)
 {
+	if (test_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx->flags))
+		return;
+
 	wx_flush_sw_mac_table(wx);
 	wx_mac_set_default_filter(wx, wx->mac.addr);
 	if (test_bit(WX_STATE_PTP_RUNNING, wx->state))
@@ -423,13 +446,14 @@ void ngbe_down(struct wx *wx)
 	wx_clean_all_rx_rings(wx);
 }
 
-void ngbe_up(struct wx *wx)
+static void ngbe_up_complete(struct wx *wx)
 {
 	wx_configure_vectors(wx);
 
 	/* make sure to complete pre-operations */
 	smp_mb__before_atomic();
 	clear_bit(WX_STATE_DOWN, wx->state);
+	clear_bit(WX_STATE_RES_FREED, wx->state);
 	wx_napi_enable_all(wx);
 	/* enable transmits */
 	netif_tx_start_all_queues(wx->netdev);
@@ -490,7 +514,7 @@ static int ngbe_open(struct net_device *netdev)
 
 	wx_ptp_init(wx);
 
-	ngbe_up(wx);
+	ngbe_up_complete(wx);
 
 	return 0;
 err_dis_phy:
@@ -503,6 +527,12 @@ static int ngbe_open(struct net_device *netdev)
 	return err;
 }
 
+void ngbe_up(struct wx *wx)
+{
+	wx_configure(wx);
+	ngbe_up_complete(wx);
+}
+
 /**
  * ngbe_close - Disables a network interface
  * @netdev: network interface device structure
@@ -518,6 +548,9 @@ static int ngbe_close(struct net_device *netdev)
 {
 	struct wx *wx = netdev_priv(netdev);
 
+	if (test_bit(WX_STATE_RES_FREED, wx->state))
+		goto out;
+
 	wx_ptp_stop(wx);
 	ngbe_down(wx);
 	wx_free_irq(wx);
@@ -525,7 +558,7 @@ static int ngbe_close(struct net_device *netdev)
 	wx_free_resources(wx);
 	phylink_disconnect_phy(wx->phylink);
 	wx_control_hw(wx, false);
-
+out:
 	return 0;
 }
 
@@ -555,7 +588,8 @@ static void ngbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake)
 	*enable_wake = !!wufc;
 	wx_control_hw(wx, false);
 
-	pci_disable_device(pdev);
+	if (!test_and_set_bit(WX_STATE_DISABLED, wx->state))
+		pci_disable_device(pdev);
 }
 
 static void ngbe_shutdown(struct pci_dev *pdev)
@@ -590,6 +624,8 @@ int ngbe_setup_tc(struct net_device *dev, u8 tc)
 	 */
 	if (netif_running(dev))
 		ngbe_close(dev);
+	else
+		ngbe_reset(wx);
 
 	wx_clear_interrupt_scheme(wx);
 
@@ -606,11 +642,36 @@ int ngbe_setup_tc(struct net_device *dev, u8 tc)
 	return 0;
 }
 
+static void ngbe_reinit_locked(struct wx *wx)
+{
+	netif_trans_update(wx->netdev);
+
+	mutex_lock(&wx->reset_lock);
+	set_bit(WX_STATE_RESETTING, wx->state);
+
+	ngbe_down(wx);
+	ngbe_up(wx);
+
+	clear_bit(WX_STATE_RESETTING, wx->state);
+	mutex_unlock(&wx->reset_lock);
+}
+
+void ngbe_do_reset(struct net_device *netdev, bool reinit)
+{
+	struct wx *wx = netdev_priv(netdev);
+
+	if (netif_running(netdev) && reinit)
+		ngbe_reinit_locked(wx);
+	else
+		ngbe_reset(wx);
+}
+
 static const struct net_device_ops ngbe_netdev_ops = {
 	.ndo_open               = ngbe_open,
 	.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,
@@ -700,6 +761,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 |
@@ -796,6 +858,10 @@ static int ngbe_probe(struct pci_dev *pdev,
 	eth_hw_addr_set(netdev, wx->mac.perm_addr);
 	wx_mac_set_default_filter(wx, wx->mac.perm_addr);
 
+	err = wx_init_err_task(wx);
+	if (err)
+		goto err_free_mac_table;
+
 	ngbe_init_service(wx);
 
 	err = wx_init_interrupt_scheme(wx);
@@ -812,6 +878,7 @@ static int ngbe_probe(struct pci_dev *pdev,
 		goto err_register;
 
 	pci_set_drvdata(pdev, wx);
+	pci_save_state(pdev);
 
 	return 0;
 
@@ -823,6 +890,8 @@ static int ngbe_probe(struct pci_dev *pdev,
 err_cancel_service:
 	timer_delete_sync(&wx->service_timer);
 	cancel_work_sync(&wx->service_task);
+	cancel_work_sync(&wx->reset_task);
+	destroy_workqueue(wx->reset_wq);
 err_free_mac_table:
 	kfree(wx->rss_key);
 	kfree(wx->mac_table);
@@ -854,6 +923,8 @@ static void ngbe_remove(struct pci_dev *pdev)
 
 	timer_shutdown_sync(&wx->service_timer);
 	cancel_work_sync(&wx->service_task);
+	cancel_work_sync(&wx->reset_task);
+	destroy_workqueue(wx->reset_wq);
 
 	phylink_destroy(wx->phylink);
 	pci_release_selected_regions(pdev,
@@ -863,7 +934,8 @@ static void ngbe_remove(struct pci_dev *pdev)
 	kfree(wx->mac_table);
 	wx_clear_interrupt_scheme(wx);
 
-	pci_disable_device(pdev);
+	if (!test_and_set_bit(WX_STATE_DISABLED, wx->state))
+		pci_disable_device(pdev);
 }
 
 static int ngbe_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -890,6 +962,7 @@ static int ngbe_resume(struct pci_dev *pdev)
 		wx_err(wx, "Cannot enable PCI device from suspend\n");
 		return err;
 	}
+	clear_bit(WX_STATE_DISABLED, wx->state);
 	pci_set_master(pdev);
 	device_wakeup_disable(&pdev->dev);
 
@@ -914,6 +987,7 @@ static struct pci_driver ngbe_driver = {
 	.resume   = ngbe_resume,
 	.shutdown = ngbe_shutdown,
 	.sriov_configure = wx_pci_sriov_configure,
+	.err_handler = &wx_err_handler,
 };
 
 module_pci_driver(ngbe_driver);
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
index 7077a0da4c986a..c9233dc7ae5052 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
@@ -125,5 +125,6 @@ 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, bool reinit);
 
 #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 20c5a295c6c296..d85ee83192e4fa 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"
@@ -93,6 +94,10 @@ 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;
 
@@ -106,6 +111,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;
 
@@ -123,6 +132,8 @@ static void txgbe_service_task(struct work_struct *work)
 	txgbe_module_detection_subtask(wx);
 	txgbe_link_config_subtask(wx);
 	wx_update_stats(wx);
+	wx_check_hang_subtask(wx);
+	wx_check_err_subtask(wx);
 
 	wx_service_event_complete(wx);
 }
@@ -144,6 +155,7 @@ static void txgbe_up_complete(struct wx *wx)
 	/* make sure to complete pre-operations */
 	smp_mb__before_atomic();
 	clear_bit(WX_STATE_DOWN, wx->state);
+	clear_bit(WX_STATE_RES_FREED, wx->state);
 	wx_napi_enable_all(wx);
 
 	switch (wx->mac.type) {
@@ -187,6 +199,9 @@ static void txgbe_reset(struct wx *wx)
 	u8 old_addr[ETH_ALEN];
 	int err;
 
+	if (test_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx->flags))
+		return;
+
 	err = txgbe_reset_hw(wx);
 	if (err != 0)
 		wx_err(wx, "Hardware Error: %d\n", err);
@@ -224,6 +239,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);
 	cancel_work_sync(&wx->service_task);
 
@@ -292,6 +308,20 @@ void txgbe_up(struct wx *wx)
 	txgbe_up_complete(wx);
 }
 
+static void txgbe_down_suspend(struct wx *wx)
+{
+	if (test_and_set_bit(WX_STATE_RES_FREED, wx->state))
+		return;
+
+	phylink_stop(wx->phylink);
+	wx_clean_all_tx_rings(wx);
+	wx_clean_all_rx_rings(wx);
+	wx_free_irq(wx);
+	txgbe_free_misc_irq(wx->priv);
+	wx_free_resources(wx);
+	txgbe_fdir_filter_exit(wx);
+}
+
 /**
  *  txgbe_init_type_code - Initialize the shared code
  *  @wx: pointer to hardware structure
@@ -408,6 +438,7 @@ static int txgbe_sw_init(struct wx *wx)
 
 	wx->setup_tc = txgbe_setup_tc;
 	wx->do_reset = txgbe_do_reset;
+	wx->down_suspend = txgbe_down_suspend;
 	set_bit(0, &wx->fwd_bitmask);
 
 	switch (wx->mac.type) {
@@ -518,12 +549,16 @@ static int txgbe_close(struct net_device *netdev)
 {
 	struct wx *wx = netdev_priv(netdev);
 
+	if (test_bit(WX_STATE_RES_FREED, wx->state))
+		goto out;
+
 	wx_ptp_stop(wx);
 	txgbe_down(wx);
 	wx_free_irq(wx);
 	txgbe_free_misc_irq(wx->priv);
 	wx_free_resources(wx);
 	txgbe_fdir_filter_exit(wx);
+out:
 	wx_control_hw(wx, false);
 
 	return 0;
@@ -544,7 +579,8 @@ static void txgbe_dev_shutdown(struct pci_dev *pdev)
 
 	wx_control_hw(wx, false);
 
-	pci_disable_device(pdev);
+	if (!test_and_set_bit(WX_STATE_DISABLED, wx->state))
+		pci_disable_device(pdev);
 }
 
 static void txgbe_shutdown(struct pci_dev *pdev)
@@ -606,11 +642,11 @@ static void txgbe_reinit_locked(struct wx *wx)
 	mutex_unlock(&wx->reset_lock);
 }
 
-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);
@@ -654,6 +690,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,
@@ -745,6 +782,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 */
@@ -814,6 +852,10 @@ static int txgbe_probe(struct pci_dev *pdev,
 	eth_hw_addr_set(netdev, wx->mac.perm_addr);
 	wx_mac_set_default_filter(wx, wx->mac.perm_addr);
 
+	err = wx_init_err_task(wx);
+	if (err)
+		goto err_free_mac_table;
+
 	txgbe_init_service(wx);
 
 	err = wx_init_interrupt_scheme(wx);
@@ -889,6 +931,7 @@ static int txgbe_probe(struct pci_dev *pdev,
 		goto err_remove_phy;
 
 	pci_set_drvdata(pdev, wx);
+	pci_save_state(pdev);
 
 	netif_tx_stop_all_queues(netdev);
 
@@ -916,6 +959,8 @@ static int txgbe_probe(struct pci_dev *pdev,
 err_cancel_service:
 	timer_delete_sync(&wx->service_timer);
 	cancel_work_sync(&wx->service_task);
+	cancel_work_sync(&wx->reset_task);
+	destroy_workqueue(wx->reset_wq);
 err_free_mac_table:
 	kfree(wx->rss_key);
 	kfree(wx->mac_table);
@@ -948,6 +993,8 @@ static void txgbe_remove(struct pci_dev *pdev)
 
 	timer_shutdown_sync(&wx->service_timer);
 	cancel_work_sync(&wx->service_task);
+	cancel_work_sync(&wx->reset_task);
+	destroy_workqueue(wx->reset_wq);
 
 	txgbe_remove_phy(txgbe);
 	wx_free_isb_resources(wx);
@@ -959,7 +1006,8 @@ static void txgbe_remove(struct pci_dev *pdev)
 	kfree(wx->mac_table);
 	wx_clear_interrupt_scheme(wx);
 
-	pci_disable_device(pdev);
+	if (!test_and_set_bit(WX_STATE_DISABLED, wx->state))
+		pci_disable_device(pdev);
 }
 
 static struct pci_driver txgbe_driver = {
@@ -969,6 +1017,7 @@ static struct pci_driver txgbe_driver = {
 	.remove   = txgbe_remove,
 	.shutdown = txgbe_shutdown,
 	.sriov_configure = wx_pci_sriov_configure,
+	.err_handler = &wx_err_handler,
 };
 
 module_pci_driver(txgbe_driver);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
index 877234e3fdc2b6..3e93a3f309c166 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
@@ -313,7 +313,7 @@ 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);
 
 #define DECLARE_PHY_INTERFACE_MASK_ZERO(name) \
 	unsigned long name[PHY_INTERFACE_MODE_MAX] = { 0, }

3/2 2026/06/30 04:06 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 17247
							output: 35
							thoughts: 353
						

Thoughts:
**Analyzing the Wangxun Ethernet Driver Patch**

Okay, so I'm looking at this patch for the Wangxun ethernet drivers, specifically the `ngbe` and `txgbe` drivers in `drivers/net/ethernet/wangxun/libwx/`. This is adding some crucial error handling and timeout recovery functionality – basically, robustifying the drivers. We're seeing changes across `wx_err.c`, `wx_err.h`, and modifications to several core files: `wx_hw.c`, `wx_lib.c`, `wx_ptp.c`, `wx_type.h`, `ngbe_main.c`, and `txgbe_main.c`. This is definitely a functional change, adding PCI error recovery, handling TX timeouts, and implementing TX hang detection.

My immediate question, as always, is about reachability, especially in a virtualized environment. These are PCI drivers, and Wangxun Gigabit PCI Express specifically. Typically, without a specific hardware emulator, or a way to inject errors or timeouts through generic netdev interfaces, these paths aren't directly reachable.

But wait, syzkaller! It can fuzz netdevs, creating or using existing ones. But, for PCI drivers, we're still stuck unless there's a virtual device representing the hardware. Can syzkaller register a Wangxun netdev without the physical hardware present?

No, that's not going to work. `ngbe_probe` and `txgbe_probe` both rely on the PCI device being present. They're going to fail if the hardware is not there.

Alright, let's explore if there's any software emulation for Wangxun devices. I'll search through the `drivers/net/ethernet/wangxun/` directory for any references to `ngbe` or `txgbe` within the codebase, hoping for a hint of virtualization or emulation support. That's the key to effective testing of this patch.



4/2 2026/06/30 04:07 tool grepper
0m Args:
{
  "Expression": "ngbe_probe",
  "PathPrefix": "drivers/net/ethernet/wangxun/"
}

Results:
{
  "Output": "drivers/net/ethernet/wangxun/ngbe/ngbe_main.c=669=static const struct net_device_ops ngbe_netdev_ops = {\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-688-/**\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:689: * ngbe_probe - Device Initialization Routine\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-690- * @pdev: PCI device information struct\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-694- *\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:695: * ngbe_probe initializes an wx identified by a pci_dev structure.\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-696- * The OS initialization, configuring of the wx private structure,\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-698- **/\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:699:static int ngbe_probe(struct pci_dev *pdev,\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-700-\t\t      const struct pci_device_id __always_unused *ent)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c=981=static struct pci_driver ngbe_driver = {\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-983-\t.id_table = ngbe_pci_tbl,\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:984:\t.probe    = ngbe_probe,\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-985-\t.remove   = ngbe_remove,\n"
}

5/2 2026/06/30 04:07 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 18593
							output: 34
							thoughts: 133
						

Thoughts:
**My Assessment of the Wangxun PCI Driver's Virtualization Limitations**

Okay, so this Wangxun driver is *definitely* a PCI-specific creature. It's built to interface with actual physical hardware, which means the whole probe function, the critical entry point, won't even *fire* unless that hardware is present. That immediately screams "unreachable code" in any virtualized environment – GCE, QEMU, the whole lot – unless you're doing full PCI passthrough of the Wangxun device. Which, let's be honest, is a pain.

Wait a second, though... I need to be thorough. My experience tells me that there are emulators for other kinds of devices, so maybe I'm missing something. I know syzkaller has `vhci` for USB, `mac80211_hwsim` for wifi, and `netdevsim` provides some netdev features. Perhaps there's some obscure corner of the kernel, some hidden gem, that emulates Wangxun PCI devices? It's unlikely, but I'll double check to ensure there isn't some PCI emulation for Wangxun that I've overlooked. I need to make sure I am fully aware of the facts before dismissing the possibility of virtualized testing.



6/2 2026/06/30 04:07 tool grepper
0m Args:
{
  "Expression": "NGBE",
  "PathPrefix": "drivers/net/ethernet/wangxun/"
}

Results:
{
  "Output": "drivers/net/ethernet/wangxun/Kconfig=19=config LIBWX\n--\ndrivers/net/ethernet/wangxun/Kconfig-27-\ndrivers/net/ethernet/wangxun/Kconfig:28:config NGBE\ndrivers/net/ethernet/wangxun/Kconfig-29-\ttristate \"Wangxun(R) GbE PCI Express adapters support\"\n--\ndrivers/net/ethernet/wangxun/Kconfig=67=config TXGBEVF\n--\ndrivers/net/ethernet/wangxun/Kconfig-84-\ndrivers/net/ethernet/wangxun/Kconfig:85:config NGBEVF\ndrivers/net/ethernet/wangxun/Kconfig-86-\ttristate \"Wangxun(R) GbE Virtual Function Ethernet support\"\n--\ndrivers/net/ethernet/wangxun/Makefile=8=obj-$(CONFIG_TXGBEVF) += txgbevf/\ndrivers/net/ethernet/wangxun/Makefile:9:obj-$(CONFIG_NGBE) += ngbe/\ndrivers/net/ethernet/wangxun/Makefile:10:obj-$(CONFIG_NGBEVF) += ngbevf/\n--\ndrivers/net/ethernet/wangxun/ngbe/Makefile-6-\ndrivers/net/ethernet/wangxun/ngbe/Makefile:7:obj-$(CONFIG_NGBE) += ngbe.o\ndrivers/net/ethernet/wangxun/ngbe/Makefile-8-\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.h-3-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.h:4:#ifndef _NGBE_ETHTOOL_H_\ndrivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.h:5:#define _NGBE_ETHTOOL_H_\ndrivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.h-6-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.h=7=void ngbe_set_ethtool_ops(struct net_device *netdev);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.h-8-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.h:9:#endif /* _NGBE_ETHTOOL_H_ */\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c=13=int ngbe_eeprom_chksum_hostif(struct wx *wx)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c-18-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c:19:\tbuffer.hdr.req.cmd = NGBE_FW_EEPROM_CHECKSUM_CMD;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c-20-\tbuffer.hdr.req.buf_lenh = 0;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c-21-\tbuffer.hdr.req.buf_lenl = 0;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c:22:\tbuffer.hdr.req.checksum = NGBE_FW_CMD_DEFAULT_CHECKSUM;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c-23-\t/* convert offset from words to bytes */\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c-33-\ttmp = rd32a(wx, WX_MNG_MBOX, 1);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c:34:\tif (tmp == NGBE_FW_CMD_ST_PASS)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c-35-\t\treturn 0;\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c=39=static int ngbe_reset_misc(struct wx *wx)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c-43-\t\t/* gpio0 is used to power on/off control*/\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c:44:\t\twr32(wx, NGBE_GPIO_DDR, 0x1);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c-45-\t\tngbe_sfp_modules_txrx_powerctl(wx, false);\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c=50=void ngbe_sfp_modules_txrx_powerctl(struct wx *wx, bool swi)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c-52-\t/* gpio0 is used to power on control . 0 is on */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c:53:\twr32(wx, NGBE_GPIO_DR, swi ? 0 : NGBE_GPIO_DR_0);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c-54-}\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c=64=int ngbe_reset_hw(struct wx *wx)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c-93-\t/* reset num_rar_entries to 128 */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c:94:\twx-\u003emac.num_rar_entries = NGBE_RAR_ENTRIES;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.c-95-\twx_init_rx_addrs(wx);\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.h-6-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.h:7:#ifndef _NGBE_HW_H_\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.h:8:#define _NGBE_HW_H_\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.h-9-\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.h=12=int ngbe_reset_hw(struct wx *wx);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_hw.h:13:#endif /* _NGBE_HW_H_ */\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c=33=static const struct pci_device_id ngbe_pci_tbl[] = {\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:34:\t{ PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL_W) },\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:35:\t{ PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A2) },\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:36:\t{ PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A2S) },\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:37:\t{ PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A4) },\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:38:\t{ PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A4S) },\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:39:\t{ PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL2) },\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:40:\t{ PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL2S) },\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:41:\t{ PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL4) },\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:42:\t{ PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL4S) },\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:43:\t{ PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860LC) },\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:44:\t{ PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A1) },\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:45:\t{ PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A1L) },\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-46-\t/* required last entry */\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c=68=static void ngbe_init_type_code(struct wx *wx)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-73-\twx-\u003emac.type = wx_mac_em;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:74:\ttype_mask = (u16)(wx-\u003esubsystem_device_id \u0026 NGBE_OEM_MASK);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-75-\tncsi_mask = wx-\u003esubsystem_device_id \u0026 WX_NCSI_MASK;\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-84-\twx-\u003encsi_enabled = (ncsi_mask == WX_NCSI_SUP ||\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:85:\t\t\t   type_mask == NGBE_SUBID_OCP_CARD) ? 1 : 0;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-86-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-87-\tswitch (type_mask) {\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:88:\tcase NGBE_SUBID_LY_YT8521S_SFP:\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:89:\tcase NGBE_SUBID_LY_M88E1512_SFP:\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:90:\tcase NGBE_SUBID_YT8521S_SFP_GPIO:\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:91:\tcase NGBE_SUBID_INTERNAL_YT8521S_SFP_GPIO:\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-92-\t\twx-\u003egpio_ctrl = 1;\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c=104=static int ngbe_sw_init(struct wx *wx)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-109-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:110:\twx-\u003emac.num_rar_entries = NGBE_RAR_ENTRIES;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:111:\twx-\u003emac.max_rx_queues = NGBE_MAX_RX_QUEUES;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:112:\twx-\u003emac.max_tx_queues = NGBE_MAX_TX_QUEUES;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:113:\twx-\u003emac.mcft_size = NGBE_MC_TBL_SIZE;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:114:\twx-\u003emac.vft_size = NGBE_SP_VFT_TBL_SIZE;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:115:\twx-\u003emac.rx_pb_size = NGBE_RX_PB_SIZE;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:116:\twx-\u003emac.tx_pb_size = NGBE_TDB_PB_SZ;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-117-\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-126-\t/* Set common capability flags and settings */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:127:\twx-\u003emax_q_vectors = NGBE_MAX_MSIX_VECTORS;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:128:\terr = wx_get_pcie_msix_counts(wx, \u0026msix_count, NGBE_MAX_MSIX_VECTORS);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-129-\tif (err)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-132-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:133:\twx-\u003ering_feature[RING_F_RSS].limit = min_t(int, NGBE_MAX_RSS_INDICES,\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-134-\t\t\t\t\t\t   num_online_cpus());\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-141-\t/* set default ring sizes */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:142:\twx-\u003etx_ring_count = NGBE_DEFAULT_TXD;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:143:\twx-\u003erx_ring_count = NGBE_DEFAULT_RXD;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-144-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-145-\t/* set default work limits */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:146:\twx-\u003etx_work_limit = NGBE_DEFAULT_TX_WORK;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:147:\twx-\u003erx_work_limit = NGBE_DEFAULT_RX_WORK;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-148-\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c=185=static void ngbe_irq_enable(struct wx *wx, bool queues)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-189-\t/* enable misc interrupt */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:190:\tmask = NGBE_PX_MISC_IEN_MASK;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-191-\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-200-\tif (queues)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:201:\t\twx_intr_enable(wx, NGBE_INTR_ALL);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-202-\telse\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:203:\t\twx_intr_enable(wx, NGBE_INTR_MISC(wx));\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-204-}\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c=211=static irqreturn_t ngbe_intr(int __always_unused irq, void *data)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-234-\teicr_misc = wx_misc_isb(wx, WX_ISB_MISC);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:235:\tif (unlikely(eicr_misc \u0026 NGBE_PX_MISC_IC_TIMESYNC))\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-236-\t\twx_ptp_check_pps_event(wx);\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c=248=static irqreturn_t __ngbe_msix_misc(struct wx *wx, u32 eicr)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-249-{\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:250:\tif (eicr \u0026 NGBE_PX_MISC_IC_VF_MBOX)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-251-\t\twx_msg_task(wx);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-252-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:253:\tif (unlikely(eicr \u0026 NGBE_PX_MISC_IC_TIMESYNC))\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-254-\t\twx_ptp_check_pps_event(wx);\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c=699=static int ngbe_probe(struct pci_dev *pdev,\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-734-\t\t\t\t\t sizeof(struct wx),\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:735:\t\t\t\t\t NGBE_MAX_TX_QUEUES,\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:736:\t\t\t\t\t NGBE_MAX_RX_QUEUES);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-737-\tif (!netdev) {\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-759-\t */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:760:\tpci_sriov_set_totalvfs(pdev, NGBE_MAX_VFS_DRV_LIMIT);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-761-\twx-\u003edriver_name = ngbe_driver_name;\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-792-\t/* check if flash load is done after hw power up */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:793:\terr = wx_check_flash_load(wx, NGBE_SPI_ILDR_STATUS_PERST);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-794-\tif (err)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-795-\t\tgoto err_free_mac_table;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:796:\terr = wx_check_flash_load(wx, NGBE_SPI_ILDR_STATUS_PWRRST);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-797-\tif (err)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-812-\tif (wx-\u003ebus.func == 0) {\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:813:\t\twr32(wx, NGBE_CALSUM_CAP_STATUS, 0x0);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:814:\t\twr32(wx, NGBE_EEPROM_VERSION_STORE_REG, 0x0);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-815-\t} else {\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:816:\t\te2rom_cksum_cap = rd32(wx, NGBE_CALSUM_CAP_STATUS);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:817:\t\tsaved_ver = rd32(wx, NGBE_EEPROM_VERSION_STORE_REG);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-818-\t}\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-845-\t\twx_read_ee_hostif(wx,\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:846:\t\t\t\t  wx-\u003eeeprom.sw_region_offset + NGBE_EEPROM_VERSION_H,\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-847-\t\t\t\t  \u0026e2rom_ver);\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-849-\t\twx_read_ee_hostif(wx,\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:850:\t\t\t\t  wx-\u003eeeprom.sw_region_offset + NGBE_EEPROM_VERSION_L,\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-851-\t\t\t\t  \u0026e2rom_ver);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-852-\t\tetrack_id |= e2rom_ver;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:853:\t\twr32(wx, NGBE_EEPROM_VERSION_STORE_REG, etrack_id);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-854-\t}\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c=16=static int ngbe_phy_read_reg_internal(struct mii_bus *bus, int phy_addr, int regnum)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c-21-\t\treturn 0xffff;\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c:22:\treturn (u16)rd32(wx, NGBE_PHY_CONFIG(regnum));\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c-23-}\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c=25=static int ngbe_phy_write_reg_internal(struct mii_bus *bus, int phy_addr, int regnum, u16 value)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c-29-\tif (phy_addr == 0)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c:30:\t\twr32(wx, NGBE_PHY_CONFIG(regnum), value);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c-31-\treturn 0;\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c=78=static void ngbe_mac_link_up(struct phylink_config *config,\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c-101-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c:102:\twr32m(wx, NGBE_CFG_LAN_SPEED, 0x3, lan_speed);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c-103-\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.h-6-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.h:7:#ifndef _NGBE_MDIO_H_\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.h:8:#define _NGBE_MDIO_H_\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.h-9-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.h=10=int ngbe_mdio_init(struct wx *wx);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_mdio.h:11:#endif /* _NGBE_MDIO_H_ */\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-3-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:4:#ifndef _NGBE_TYPE_H_\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:5:#define _NGBE_TYPE_H_\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-6-\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-9-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:10:/************ NGBE_register.h ************/\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-11-/* Device IDs */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:12:#define NGBE_DEV_ID_EM_WX1860AL_W\t\t0x0100\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:13:#define NGBE_DEV_ID_EM_WX1860A2\t\t\t0x0101\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:14:#define NGBE_DEV_ID_EM_WX1860A2S\t\t0x0102\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:15:#define NGBE_DEV_ID_EM_WX1860A4\t\t\t0x0103\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:16:#define NGBE_DEV_ID_EM_WX1860A4S\t\t0x0104\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:17:#define NGBE_DEV_ID_EM_WX1860AL2\t\t0x0105\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:18:#define NGBE_DEV_ID_EM_WX1860AL2S\t\t0x0106\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:19:#define NGBE_DEV_ID_EM_WX1860AL4\t\t0x0107\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:20:#define NGBE_DEV_ID_EM_WX1860AL4S\t\t0x0108\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:21:#define NGBE_DEV_ID_EM_WX1860LC\t\t\t0x0109\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:22:#define NGBE_DEV_ID_EM_WX1860A1\t\t\t0x010a\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:23:#define NGBE_DEV_ID_EM_WX1860A1L\t\t0x010b\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-24-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-25-/* Subsystem ID */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:26:#define NGBE_SUBID_M88E1512_SFP\t\t\t0x0003\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:27:#define NGBE_SUBID_OCP_CARD\t\t\t0x0040\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:28:#define NGBE_SUBID_LY_M88E1512_SFP\t\t0x0050\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:29:#define NGBE_SUBID_M88E1512_RJ45\t\t0x0051\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:30:#define NGBE_SUBID_M88E1512_MIX\t\t\t0x0052\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:31:#define NGBE_SUBID_YT8521S_SFP\t\t\t0x0060\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:32:#define NGBE_SUBID_INTERNAL_YT8521S_SFP\t\t0x0061\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:33:#define NGBE_SUBID_YT8521S_SFP_GPIO\t\t0x0062\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:34:#define NGBE_SUBID_INTERNAL_YT8521S_SFP_GPIO\t0x0064\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:35:#define NGBE_SUBID_LY_YT8521S_SFP\t\t0x0070\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:36:#define NGBE_SUBID_RGMII_FPGA\t\t\t0x0080\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-37-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:38:#define NGBE_OEM_MASK\t\t\t\t0x00FF\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-39-\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-41-/* chip control Registers */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:42:#define NGBE_MIS_PRB_CTL\t\t\t0x10010\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-43-/* FMGR Registers */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:44:#define NGBE_SPI_ILDR_STATUS\t\t\t0x10120\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:45:#define NGBE_SPI_ILDR_STATUS_PERST\t\tBIT(0) /* PCIE_PERST is done */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:46:#define NGBE_SPI_ILDR_STATUS_PWRRST\t\tBIT(1) /* Power on reset is done */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-47-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-48-/* Checksum and EEPROM pointers */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:49:#define NGBE_CALSUM_COMMAND\t\t\t0xE9\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:50:#define NGBE_CALSUM_CAP_STATUS\t\t\t0x10224\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:51:#define NGBE_EEPROM_VERSION_STORE_REG\t\t0x1022C\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:52:#define NGBE_SAN_MAC_ADDR_PTR\t\t\t0x18\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:53:#define NGBE_DEVICE_CAPS\t\t\t0x1C\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:54:#define NGBE_EEPROM_VERSION_L\t\t\t0x1D\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:55:#define NGBE_EEPROM_VERSION_H\t\t\t0x1E\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-56-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-57-/* GPIO Registers */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:58:#define NGBE_GPIO_DR\t\t\t\t0x14800\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:59:#define NGBE_GPIO_DDR\t\t\t\t0x14804\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-60-/*GPIO bit */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:61:#define NGBE_GPIO_DR_0\t\t\t\tBIT(0) /* SDP0 Data Value */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:62:#define NGBE_GPIO_DR_1\t\t\t\tBIT(1) /* SDP1 Data Value */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:63:#define NGBE_GPIO_DDR_0\t\t\t\tBIT(0) /* SDP0 IO direction */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:64:#define NGBE_GPIO_DDR_1\t\t\t\tBIT(1) /* SDP1 IO direction */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-65-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-66-/* Extended Interrupt Enable Set */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:67:#define NGBE_PX_MISC_IEN_DEV_RST\t\tBIT(10)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:68:#define NGBE_PX_MISC_IEN_TIMESYNC\t\tBIT(11)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:69:#define NGBE_PX_MISC_IEN_ETH_LK\t\t\tBIT(18)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:70:#define NGBE_PX_MISC_IEN_INT_ERR\t\tBIT(20)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:71:#define NGBE_PX_MISC_IC_VF_MBOX\t\t\tBIT(23)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:72:#define NGBE_PX_MISC_IEN_GPIO\t\t\tBIT(26)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:73:#define NGBE_PX_MISC_IEN_MASK ( \\\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:74:\t\t\t\tNGBE_PX_MISC_IEN_DEV_RST | \\\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:75:\t\t\t\tNGBE_PX_MISC_IEN_TIMESYNC | \\\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:76:\t\t\t\tNGBE_PX_MISC_IEN_ETH_LK | \\\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:77:\t\t\t\tNGBE_PX_MISC_IEN_INT_ERR | \\\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:78:\t\t\t\tNGBE_PX_MISC_IC_VF_MBOX | \\\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:79:\t\t\t\tNGBE_PX_MISC_IEN_GPIO)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-80-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-81-/* Extended Interrupt Cause Read */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:82:#define NGBE_PX_MISC_IC_TIMESYNC\t\tBIT(11) /* time sync */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-83-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:84:#define NGBE_INTR_ALL\t\t\t\t0x1FF\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:85:#define NGBE_INTR_MISC(A)\t\t\tBIT((A)-\u003emsix_entry-\u003eentry)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-86-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:87:#define NGBE_PHY_CONFIG(reg_offset)\t\t(0x14000 + ((reg_offset) * 4))\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:88:#define NGBE_CFG_LAN_SPEED\t\t\t0x14440\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:89:#define NGBE_CFG_PORT_ST\t\t\t0x14404\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-90-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:91:#define NGBE_FW_EEPROM_CHECKSUM_CMD\t\t0xE9\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:92:#define NGBE_FW_NVM_DATA_OFFSET\t\t\t3\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:93:#define NGBE_FW_CMD_DEFAULT_CHECKSUM\t\t0xFF /* checksum always 0xFF */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:94:#define NGBE_FW_CMD_ST_PASS\t\t\t0x80658383\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:95:#define NGBE_FW_CMD_ST_FAIL\t\t\t0x70657376\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-96-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:97:#define NGBE_MAX_FDIR_INDICES\t\t\t7\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:98:#define NGBE_MAX_RSS_INDICES\t\t\t8\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-99-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:100:#define NGBE_MAX_RX_QUEUES\t\t\t(NGBE_MAX_FDIR_INDICES + 1)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:101:#define NGBE_MAX_TX_QUEUES\t\t\t(NGBE_MAX_FDIR_INDICES + 1)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-102-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:103:#define NGBE_ETH_LENGTH_OF_ADDRESS\t\t6\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:104:#define NGBE_MAX_MSIX_VECTORS\t\t\t0x09\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:105:#define NGBE_RAR_ENTRIES\t\t\t32\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:106:#define NGBE_RX_PB_SIZE\t\t\t\t42\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:107:#define NGBE_MC_TBL_SIZE\t\t\t128\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:108:#define NGBE_SP_VFT_TBL_SIZE\t\t\t128\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:109:#define NGBE_TDB_PB_SZ\t\t\t\t(20 * 1024) /* 160KB Packet Buffer */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-110-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-111-/* TX/RX descriptor defines */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:112:#define NGBE_DEFAULT_TXD\t\t\t512 /* default ring size */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:113:#define NGBE_DEFAULT_TX_WORK\t\t\t256\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:114:#define NGBE_MAX_TXD\t\t\t\t8192\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:115:#define NGBE_MIN_TXD\t\t\t\t128\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-116-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:117:#define NGBE_DEFAULT_RXD\t\t\t512 /* default ring size */\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:118:#define NGBE_DEFAULT_RX_WORK\t\t\t256\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:119:#define NGBE_MAX_RXD\t\t\t\t8192\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:120:#define NGBE_MIN_RXD\t\t\t\t128\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-121-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:122:#define NGBE_MAX_VFS_DRV_LIMIT\t\t\t7\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-123-extern char ngbe_driver_name[];\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h=128=void ngbe_do_reset(struct net_device *netdev, bool reinit);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h-129-\ndrivers/net/ethernet/wangxun/ngbe/ngbe_type.h:130:#endif /* _NGBE_TYPE_H_ */\n--\ndrivers/net/ethernet/wangxun/ngbevf/Makefile-6-\ndrivers/net/ethernet/wangxun/ngbevf/Makefile:7:obj-$(CONFIG_NGBE) += ngbevf.o\ndrivers/net/ethernet/wangxun/ngbevf/Makefile-8-\n--\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c=28=static const struct pci_device_id ngbevf_pci_tbl[] = {\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:29:\t{ PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860AL_W) },\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:30:\t{ PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860A2) },\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:31:\t{ PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860A2S) },\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:32:\t{ PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860A4) },\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:33:\t{ PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860A4S) },\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:34:\t{ PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860AL2) },\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:35:\t{ PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860AL2S) },\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:36:\t{ PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860AL4) },\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:37:\t{ PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860AL4S) },\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:38:\t{ PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860NCSI) },\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:39:\t{ PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860A1) },\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:40:\t{ PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860AL1) },\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c-41-\t/* required last entry */\n--\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c=60=static int ngbevf_sw_init(struct wx *wx)\n--\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c-77-\twx-\u003emac.type = wx_mac_em;\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:78:\twx-\u003emac.max_msix_vectors = NGBEVF_MAX_MSIX_VECTORS;\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c-79-\t/* lock to protect mailbox accesses */\n--\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c-100-\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:101:\twx-\u003emac.max_tx_queues = NGBEVF_MAX_TX_QUEUES;\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:102:\twx-\u003emac.max_rx_queues = NGBEVF_MAX_RX_QUEUES;\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c-103-\t/* Enable dynamic interrupt throttling rates */\n--\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c-107-\t/* set default ring sizes */\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:108:\twx-\u003etx_ring_count = NGBEVF_DEFAULT_TXD;\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:109:\twx-\u003erx_ring_count = NGBEVF_DEFAULT_RXD;\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c-110-\t/* set default work limits */\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:111:\twx-\u003etx_work_limit = NGBEVF_DEFAULT_TX_WORK;\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:112:\twx-\u003erx_work_limit = NGBEVF_DEFAULT_RX_WORK;\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c-113-\twx-\u003eset_num_queues = ngbevf_set_num_queues;\n--\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c=136=static int ngbevf_probe(struct pci_dev *pdev,\n--\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c-166-\t\t\t\t\t sizeof(struct wx),\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:167:\t\t\t\t\t NGBEVF_MAX_TX_QUEUES,\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c:168:\t\t\t\t\t NGBEVF_MAX_RX_QUEUES);\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c-169-\tif (!netdev) {\n--\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h-3-\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:4:#ifndef _NGBEVF_TYPE_H_\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:5:#define _NGBEVF_TYPE_H_\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h-6-\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h-7-/* Device IDs */\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:8:#define NGBEVF_DEV_ID_EM_WX1860AL_W             0x0110\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:9:#define NGBEVF_DEV_ID_EM_WX1860A2               0x0111\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:10:#define NGBEVF_DEV_ID_EM_WX1860A2S              0x0112\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:11:#define NGBEVF_DEV_ID_EM_WX1860A4               0x0113\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:12:#define NGBEVF_DEV_ID_EM_WX1860A4S              0x0114\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:13:#define NGBEVF_DEV_ID_EM_WX1860AL2              0x0115\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:14:#define NGBEVF_DEV_ID_EM_WX1860AL2S             0x0116\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:15:#define NGBEVF_DEV_ID_EM_WX1860AL4              0x0117\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:16:#define NGBEVF_DEV_ID_EM_WX1860AL4S             0x0118\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:17:#define NGBEVF_DEV_ID_EM_WX1860NCSI             0x0119\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:18:#define NGBEVF_DEV_ID_EM_WX1860A1               0x011a\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:19:#define NGBEVF_DEV_ID_EM_WX1860AL1              0x011b\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h-20-\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:21:#define NGBEVF_MAX_MSIX_VECTORS               1\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:22:#define NGBEVF_MAX_RX_QUEUES                  1\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:23:#define NGBEVF_MAX_TX_QUEUES                  1\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:24:#define NGBEVF_DEFAULT_TXD                    128\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:25:#define NGBEVF_DEFAULT_RXD                    128\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:26:#define NGBEVF_DEFAULT_TX_WORK                256\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:27:#define NGBEVF_DEFAULT_RX_WORK                256\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h-28-\ndrivers/net/ethernet/wangxun/ngbevf/ngbevf_type.h:29:#endif /* _NGBEVF_TYPE_H_ */\n"
}

7/2 2026/06/30 04:07 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 33680
							output: 125
							thoughts: 312
						

Thoughts:
**Unreachable Code in a Virtualized World**

Okay, so I've looked at this patch targeting the Wangxun drivers – specifically the `ngbe` and `txgbe` drivers. These are, as I suspected, designed for physical hardware. There's no virtual device emulation or anything like that built into the kernel for them. This means the code being modified in this patch – the error handling, the TX timeout recovery, and the TX hang detection – is simply unreachable within a virtualized environment like GCE or even QEMU.

My initial gut feeling was right; this is not worth fuzzing. But I needed to be absolutely sure. Let me trace how this code gets called. It's nestled in `drivers/net/ethernet/wangxun/libwx/wx_err.c`. Specifically, it appears the `wx_tx_timeout` function is the point of entry and it's hooked up as the `.ndo_tx_timeout` handler. Now, to get that registered, either `ngbe_probe` or `txgbe_probe` has to succeed. And those probe functions are *very* specific. They're tied to the PCI device's presence and involve actual hardware initialization: reading EEPROM, resetting the MAC, all that stuff.

So, without the real hardware, those probes will either fail early on or won't even be invoked. No probe = no netdev = no registration of `.ndo_tx_timeout`. That's that. The PCI error handlers like `wx_err_handler` have the same dependency on the physical PCI device existing. The whole setup is reliant on the real hardware.

Therefore, this code path is completely unreachable in a standard virtualized environment. Time to set `WorthFuzzing=false`.



8/2 2026/06/30 04:07 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch modifies the Wangxun Ethernet drivers (ngbe, txgbe) to add PCI error recovery, TX timeout handling, and TX hang detection. These are drivers for specific physical PCI hardware. Since there is no software emulator for Wangxun devices in the kernel, the probe functions will not succeed and the netdevs will not be registered in virtualized environments like GCE or QEMU. Therefore, the modified code is unreachable during fuzzing.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch modifies the Wangxun Ethernet drivers (ngbe, txgbe) to add PCI error recovery, TX timeout handling, and TX hang detection. These are drivers for specific physical PCI hardware. Since there is no software emulator for Wangxun devices in the kernel, the probe functions will not succeed and the netdevs will not be registered in virtualized environments like GCE or QEMU. Therefore, the modified code is unreachable during fuzzing.",
  "WorthFuzzing": false
}

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)