122d95e93SJiawen Wu // SPDX-License-Identifier: GPL-2.0
222d95e93SJiawen Wu /* Copyright (c) 2015 - 2026 Beijing WangXun Technology Co., Ltd. */
322d95e93SJiawen Wu /* Copyright (c) 1999 - 2026 Intel Corporation. */
422d95e93SJiawen Wu
522d95e93SJiawen Wu #include <linux/netdevice.h>
622d95e93SJiawen Wu #include <linux/pci.h>
7*e73e4d18SJiawen Wu #include <linux/aer.h>
822d95e93SJiawen Wu
922d95e93SJiawen Wu #include "wx_type.h"
1022d95e93SJiawen Wu #include "wx_lib.h"
1122d95e93SJiawen Wu #include "wx_err.h"
1222d95e93SJiawen Wu
13*e73e4d18SJiawen Wu /**
14*e73e4d18SJiawen Wu * wx_io_error_detected - called when PCI error is detected
15*e73e4d18SJiawen Wu * @pdev: Pointer to PCI device
16*e73e4d18SJiawen Wu * @state: The current pci connection state
17*e73e4d18SJiawen Wu *
18*e73e4d18SJiawen Wu * Return: pci_ers_result_t.
19*e73e4d18SJiawen Wu *
20*e73e4d18SJiawen Wu * This function is called after a PCI bus error affecting
21*e73e4d18SJiawen Wu * this device has been detected.
22*e73e4d18SJiawen Wu */
wx_io_error_detected(struct pci_dev * pdev,pci_channel_state_t state)23*e73e4d18SJiawen Wu static pci_ers_result_t wx_io_error_detected(struct pci_dev *pdev,
24*e73e4d18SJiawen Wu pci_channel_state_t state)
25*e73e4d18SJiawen Wu {
26*e73e4d18SJiawen Wu struct wx *wx = pci_get_drvdata(pdev);
27*e73e4d18SJiawen Wu struct net_device *netdev;
28*e73e4d18SJiawen Wu
29*e73e4d18SJiawen Wu if (!wx)
30*e73e4d18SJiawen Wu return PCI_ERS_RESULT_DISCONNECT;
31*e73e4d18SJiawen Wu
32*e73e4d18SJiawen Wu netdev = wx->netdev;
33*e73e4d18SJiawen Wu if (!netif_device_present(netdev))
34*e73e4d18SJiawen Wu return PCI_ERS_RESULT_DISCONNECT;
35*e73e4d18SJiawen Wu
36*e73e4d18SJiawen Wu rtnl_lock();
37*e73e4d18SJiawen Wu netif_device_detach(netdev);
38*e73e4d18SJiawen Wu set_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx->flags);
39*e73e4d18SJiawen Wu wx_soft_quiesce(wx);
40*e73e4d18SJiawen Wu
41*e73e4d18SJiawen Wu if (state == pci_channel_io_perm_failure) {
42*e73e4d18SJiawen Wu rtnl_unlock();
43*e73e4d18SJiawen Wu return PCI_ERS_RESULT_DISCONNECT;
44*e73e4d18SJiawen Wu }
45*e73e4d18SJiawen Wu
46*e73e4d18SJiawen Wu if (!test_and_set_bit(WX_STATE_DISABLED, wx->state))
47*e73e4d18SJiawen Wu pci_disable_device(pdev);
48*e73e4d18SJiawen Wu rtnl_unlock();
49*e73e4d18SJiawen Wu
50*e73e4d18SJiawen Wu /* Request a slot reset. */
51*e73e4d18SJiawen Wu return PCI_ERS_RESULT_NEED_RESET;
52*e73e4d18SJiawen Wu }
53*e73e4d18SJiawen Wu
54*e73e4d18SJiawen Wu /**
55*e73e4d18SJiawen Wu * wx_io_slot_reset - called after the pci bus has been reset.
56*e73e4d18SJiawen Wu * @pdev: Pointer to PCI device
57*e73e4d18SJiawen Wu *
58*e73e4d18SJiawen Wu * Return: pci_ers_result_t.
59*e73e4d18SJiawen Wu *
60*e73e4d18SJiawen Wu * Restart the card from scratch, as if from a cold-boot.
61*e73e4d18SJiawen Wu */
wx_io_slot_reset(struct pci_dev * pdev)62*e73e4d18SJiawen Wu static pci_ers_result_t wx_io_slot_reset(struct pci_dev *pdev)
63*e73e4d18SJiawen Wu {
64*e73e4d18SJiawen Wu struct wx *wx = pci_get_drvdata(pdev);
65*e73e4d18SJiawen Wu
66*e73e4d18SJiawen Wu if (pci_enable_device_mem(pdev)) {
67*e73e4d18SJiawen Wu wx_err(wx, "Cannot re-enable PCI device after reset.\n");
68*e73e4d18SJiawen Wu return PCI_ERS_RESULT_DISCONNECT;
69*e73e4d18SJiawen Wu }
70*e73e4d18SJiawen Wu
71*e73e4d18SJiawen Wu /* make all memory operations done before clearing the flag */
72*e73e4d18SJiawen Wu smp_mb__before_atomic();
73*e73e4d18SJiawen Wu clear_bit(WX_STATE_DISABLED, wx->state);
74*e73e4d18SJiawen Wu clear_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx->flags);
75*e73e4d18SJiawen Wu pci_set_master(pdev);
76*e73e4d18SJiawen Wu pci_restore_state(pdev);
77*e73e4d18SJiawen Wu pci_wake_from_d3(pdev, false);
78*e73e4d18SJiawen Wu
79*e73e4d18SJiawen Wu rtnl_lock();
80*e73e4d18SJiawen Wu if (netif_running(wx->netdev) && wx->down_suspend)
81*e73e4d18SJiawen Wu wx->down_suspend(wx);
82*e73e4d18SJiawen Wu if (wx->do_reset)
83*e73e4d18SJiawen Wu wx->do_reset(wx->netdev, false);
84*e73e4d18SJiawen Wu rtnl_unlock();
85*e73e4d18SJiawen Wu
86*e73e4d18SJiawen Wu return PCI_ERS_RESULT_RECOVERED;
87*e73e4d18SJiawen Wu }
88*e73e4d18SJiawen Wu
89*e73e4d18SJiawen Wu /**
90*e73e4d18SJiawen Wu * wx_io_resume - called when traffic can start flowing again.
91*e73e4d18SJiawen Wu * @pdev: Pointer to PCI device
92*e73e4d18SJiawen Wu *
93*e73e4d18SJiawen Wu * This callback is called when the error recovery driver tells us that
94*e73e4d18SJiawen Wu * its OK to resume normal operation.
95*e73e4d18SJiawen Wu */
wx_io_resume(struct pci_dev * pdev)96*e73e4d18SJiawen Wu static void wx_io_resume(struct pci_dev *pdev)
97*e73e4d18SJiawen Wu {
98*e73e4d18SJiawen Wu struct wx *wx = pci_get_drvdata(pdev);
99*e73e4d18SJiawen Wu struct net_device *netdev;
100*e73e4d18SJiawen Wu int err;
101*e73e4d18SJiawen Wu
102*e73e4d18SJiawen Wu netdev = wx->netdev;
103*e73e4d18SJiawen Wu rtnl_lock();
104*e73e4d18SJiawen Wu if (netif_running(netdev)) {
105*e73e4d18SJiawen Wu err = netdev->netdev_ops->ndo_open(netdev);
106*e73e4d18SJiawen Wu if (err) {
107*e73e4d18SJiawen Wu wx_err(wx, "Failed to open netdev after reset\n");
108*e73e4d18SJiawen Wu goto out;
109*e73e4d18SJiawen Wu }
110*e73e4d18SJiawen Wu }
111*e73e4d18SJiawen Wu netif_device_attach(netdev);
112*e73e4d18SJiawen Wu out:
113*e73e4d18SJiawen Wu rtnl_unlock();
114*e73e4d18SJiawen Wu }
115*e73e4d18SJiawen Wu
116*e73e4d18SJiawen Wu const struct pci_error_handlers wx_err_handler = {
117*e73e4d18SJiawen Wu .error_detected = wx_io_error_detected,
118*e73e4d18SJiawen Wu .slot_reset = wx_io_slot_reset,
119*e73e4d18SJiawen Wu .resume = wx_io_resume,
120*e73e4d18SJiawen Wu };
121*e73e4d18SJiawen Wu EXPORT_SYMBOL(wx_err_handler);
122*e73e4d18SJiawen Wu
wx_check_pcie_error(struct wx * wx)123*e73e4d18SJiawen Wu static bool wx_check_pcie_error(struct wx *wx)
124*e73e4d18SJiawen Wu {
125*e73e4d18SJiawen Wu u16 vid, pci_cmd;
126*e73e4d18SJiawen Wu
127*e73e4d18SJiawen Wu pci_read_config_word(wx->pdev, PCI_VENDOR_ID, &vid);
128*e73e4d18SJiawen Wu pci_read_config_word(wx->pdev, PCI_COMMAND, &pci_cmd);
129*e73e4d18SJiawen Wu
130*e73e4d18SJiawen Wu /* PCIe link loss or memory space can't access */
131*e73e4d18SJiawen Wu if (vid == U16_MAX || !(pci_cmd & PCI_COMMAND_MEMORY))
132*e73e4d18SJiawen Wu return true;
133*e73e4d18SJiawen Wu
134*e73e4d18SJiawen Wu return false;
135*e73e4d18SJiawen Wu }
136*e73e4d18SJiawen Wu
wx_pf_reset_subtask(struct wx * wx)13722d95e93SJiawen Wu static void wx_pf_reset_subtask(struct wx *wx)
13822d95e93SJiawen Wu {
13922d95e93SJiawen Wu if (!test_and_clear_bit(WX_FLAG_NEED_DO_RESET, wx->flags))
14022d95e93SJiawen Wu return;
14122d95e93SJiawen Wu
14222d95e93SJiawen Wu wx_warn(wx, "Reset adapter.\n");
14322d95e93SJiawen Wu if (wx->do_reset)
144c656a3b7SJiawen Wu wx->do_reset(wx->netdev, true);
14522d95e93SJiawen Wu }
14622d95e93SJiawen Wu
wx_reset_task(struct work_struct * work)14722d95e93SJiawen Wu static void wx_reset_task(struct work_struct *work)
14822d95e93SJiawen Wu {
14922d95e93SJiawen Wu struct wx *wx = container_of(work, struct wx, reset_task);
15022d95e93SJiawen Wu
15122d95e93SJiawen Wu rtnl_lock();
15222d95e93SJiawen Wu
153*e73e4d18SJiawen Wu /* If the device has been detached (e.g., due to AER error handling),
154*e73e4d18SJiawen Wu * abort the reset task to prevent operating on a dead or unmanaged
155*e73e4d18SJiawen Wu * hardware.
156*e73e4d18SJiawen Wu */
157*e73e4d18SJiawen Wu if (!netif_device_present(wx->netdev))
158*e73e4d18SJiawen Wu goto out;
159*e73e4d18SJiawen Wu
160*e73e4d18SJiawen Wu if (test_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx->flags)) {
161*e73e4d18SJiawen Wu /* Double check: Verify if the PCIe error is still present. */
162*e73e4d18SJiawen Wu if (wx_check_pcie_error(wx))
163*e73e4d18SJiawen Wu wx_soft_quiesce(wx);
164*e73e4d18SJiawen Wu else
165*e73e4d18SJiawen Wu clear_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx->flags);
166*e73e4d18SJiawen Wu goto out;
167*e73e4d18SJiawen Wu }
168*e73e4d18SJiawen Wu
16922d95e93SJiawen Wu if (test_bit(WX_STATE_DOWN, wx->state) ||
17022d95e93SJiawen Wu test_bit(WX_STATE_RESETTING, wx->state))
17122d95e93SJiawen Wu goto out;
17222d95e93SJiawen Wu
17322d95e93SJiawen Wu wx_pf_reset_subtask(wx);
17422d95e93SJiawen Wu
17522d95e93SJiawen Wu out:
17622d95e93SJiawen Wu rtnl_unlock();
17722d95e93SJiawen Wu }
17822d95e93SJiawen Wu
wx_check_err_subtask(struct wx * wx)17922d95e93SJiawen Wu void wx_check_err_subtask(struct wx *wx)
18022d95e93SJiawen Wu {
18122d95e93SJiawen Wu if (test_bit(WX_FLAG_NEED_DO_RESET, wx->flags))
18222d95e93SJiawen Wu queue_work(wx->reset_wq, &wx->reset_task);
18322d95e93SJiawen Wu }
18422d95e93SJiawen Wu EXPORT_SYMBOL(wx_check_err_subtask);
18522d95e93SJiawen Wu
wx_init_err_task(struct wx * wx)18622d95e93SJiawen Wu int wx_init_err_task(struct wx *wx)
18722d95e93SJiawen Wu {
18822d95e93SJiawen Wu wx->reset_wq = alloc_workqueue("%s_reset_wq_%x", WQ_UNBOUND | WQ_HIGHPRI,
18922d95e93SJiawen Wu 1, wx->driver_name, pci_dev_id(wx->pdev));
19022d95e93SJiawen Wu if (!wx->reset_wq) {
19122d95e93SJiawen Wu wx_err(wx, "Failed to create wx_reset_wq workqueue\n");
19222d95e93SJiawen Wu return -ENOMEM;
19322d95e93SJiawen Wu }
19422d95e93SJiawen Wu
19522d95e93SJiawen Wu INIT_WORK(&wx->reset_task, wx_reset_task);
19622d95e93SJiawen Wu return 0;
19722d95e93SJiawen Wu }
19822d95e93SJiawen Wu EXPORT_SYMBOL(wx_init_err_task);
19922d95e93SJiawen Wu
wx_ring_tx_pending(struct wx * wx)20022d95e93SJiawen Wu static bool wx_ring_tx_pending(struct wx *wx)
20122d95e93SJiawen Wu {
20222d95e93SJiawen Wu int i;
20322d95e93SJiawen Wu
20422d95e93SJiawen Wu for (i = 0; i < wx->num_tx_queues; i++) {
20522d95e93SJiawen Wu struct wx_ring *tx_ring = wx->tx_ring[i];
20622d95e93SJiawen Wu
20722d95e93SJiawen Wu if (tx_ring->next_to_use != tx_ring->next_to_clean)
20822d95e93SJiawen Wu return true;
20922d95e93SJiawen Wu }
21022d95e93SJiawen Wu
21122d95e93SJiawen Wu return false;
21222d95e93SJiawen Wu }
21322d95e93SJiawen Wu
wx_vf_tx_pending(struct wx * wx)21422d95e93SJiawen Wu static bool wx_vf_tx_pending(struct wx *wx)
21522d95e93SJiawen Wu {
21622d95e93SJiawen Wu struct wx_ring_feature *vmdq = &wx->ring_feature[RING_F_VMDQ];
21722d95e93SJiawen Wu u32 q_per_pool = __ALIGN_MASK(1, ~vmdq->mask);
21822d95e93SJiawen Wu u32 i, j;
21922d95e93SJiawen Wu
22022d95e93SJiawen Wu if (!wx->num_vfs)
22122d95e93SJiawen Wu return false;
22222d95e93SJiawen Wu
22322d95e93SJiawen Wu for (i = 0; i < wx->num_vfs; i++) {
22422d95e93SJiawen Wu for (j = 0; j < q_per_pool; j++) {
22522d95e93SJiawen Wu u32 h, t;
22622d95e93SJiawen Wu
22722d95e93SJiawen Wu h = rd32(wx, WX_PX_TR_RP_PV(q_per_pool, i, j));
22822d95e93SJiawen Wu t = rd32(wx, WX_PX_TR_WP_PV(q_per_pool, i, j));
22922d95e93SJiawen Wu
23022d95e93SJiawen Wu if (h != t)
23122d95e93SJiawen Wu return true;
23222d95e93SJiawen Wu }
23322d95e93SJiawen Wu }
23422d95e93SJiawen Wu
23522d95e93SJiawen Wu return false;
23622d95e93SJiawen Wu }
23722d95e93SJiawen Wu
wx_watchdog_flush_tx(struct wx * wx)23822d95e93SJiawen Wu static void wx_watchdog_flush_tx(struct wx *wx)
23922d95e93SJiawen Wu {
24022d95e93SJiawen Wu if (!netif_running(wx->netdev))
24122d95e93SJiawen Wu return;
24222d95e93SJiawen Wu if (netif_carrier_ok(wx->netdev))
24322d95e93SJiawen Wu return;
24422d95e93SJiawen Wu
24522d95e93SJiawen Wu if (wx_ring_tx_pending(wx) || wx_vf_tx_pending(wx)) {
24622d95e93SJiawen Wu /* We've lost link, so the controller stops DMA,
24722d95e93SJiawen Wu * but we've got queued Tx work that's never going
24822d95e93SJiawen Wu * to get done, so reset controller to flush Tx.
24922d95e93SJiawen Wu * (Do the reset outside of interrupt context).
25022d95e93SJiawen Wu */
25122d95e93SJiawen Wu wx_warn(wx, "initiating reset due to lost link with pending Tx work\n");
25222d95e93SJiawen Wu set_bit(WX_FLAG_NEED_DO_RESET, wx->flags);
25322d95e93SJiawen Wu }
25422d95e93SJiawen Wu }
25522d95e93SJiawen Wu
wx_detect_tx_hang(struct wx * wx)25622d95e93SJiawen Wu static void wx_detect_tx_hang(struct wx *wx)
25722d95e93SJiawen Wu {
25822d95e93SJiawen Wu int i;
25922d95e93SJiawen Wu
26022d95e93SJiawen Wu /* If we're down or resetting, just bail */
26122d95e93SJiawen Wu if (!netif_running(wx->netdev) ||
26222d95e93SJiawen Wu test_bit(WX_STATE_RESETTING, wx->state))
26322d95e93SJiawen Wu return;
26422d95e93SJiawen Wu
26522d95e93SJiawen Wu /* Force detection of hung controller */
26622d95e93SJiawen Wu if (netif_carrier_ok(wx->netdev)) {
26722d95e93SJiawen Wu for (i = 0; i < wx->num_tx_queues; i++)
26822d95e93SJiawen Wu set_bit(WX_TX_DETECT_HANG, wx->tx_ring[i]->state);
26922d95e93SJiawen Wu }
27022d95e93SJiawen Wu }
27122d95e93SJiawen Wu
wx_check_hang_subtask(struct wx * wx)27222d95e93SJiawen Wu void wx_check_hang_subtask(struct wx *wx)
27322d95e93SJiawen Wu {
27422d95e93SJiawen Wu if (test_bit(WX_STATE_DOWN, wx->state) ||
27522d95e93SJiawen Wu test_bit(WX_STATE_RESETTING, wx->state))
27622d95e93SJiawen Wu return;
27722d95e93SJiawen Wu
27822d95e93SJiawen Wu wx_watchdog_flush_tx(wx);
27922d95e93SJiawen Wu wx_detect_tx_hang(wx);
28022d95e93SJiawen Wu }
28122d95e93SJiawen Wu EXPORT_SYMBOL(wx_check_hang_subtask);
28222d95e93SJiawen Wu
wx_tx_timeout_recovery(struct wx * wx)283*e73e4d18SJiawen Wu static void wx_tx_timeout_recovery(struct wx *wx)
284*e73e4d18SJiawen Wu {
285*e73e4d18SJiawen Wu /*
286*e73e4d18SJiawen Wu * When a PCIe hardware error occurs, the driver should initiate a PCIe
287*e73e4d18SJiawen Wu * recovery mechanism. However, this recovery flow relies on the AER
288*e73e4d18SJiawen Wu * driver for current kernel policy. Therefore, a self-contained
289*e73e4d18SJiawen Wu * recovery mechanism is not implemented yet.
290*e73e4d18SJiawen Wu */
291*e73e4d18SJiawen Wu set_bit(WX_FLAG_NEED_PCIE_RECOVERY, wx->flags);
292*e73e4d18SJiawen Wu wx_err(wx, "PCIe error detected during tx timeout\n");
293*e73e4d18SJiawen Wu queue_work(wx->reset_wq, &wx->reset_task);
294*e73e4d18SJiawen Wu }
295*e73e4d18SJiawen Wu
wx_tx_timeout_reset(struct wx * wx)29622d95e93SJiawen Wu static void wx_tx_timeout_reset(struct wx *wx)
29722d95e93SJiawen Wu {
29822d95e93SJiawen Wu if (test_bit(WX_STATE_DOWN, wx->state))
29922d95e93SJiawen Wu return;
30022d95e93SJiawen Wu
30122d95e93SJiawen Wu set_bit(WX_FLAG_NEED_DO_RESET, wx->flags);
30222d95e93SJiawen Wu wx_warn(wx, "initiating reset due to tx timeout\n");
30322d95e93SJiawen Wu wx_service_event_schedule(wx);
30422d95e93SJiawen Wu }
30522d95e93SJiawen Wu
wx_tx_timeout(struct net_device * netdev,unsigned int __always_unused txqueue)30622d95e93SJiawen Wu void wx_tx_timeout(struct net_device *netdev, unsigned int __always_unused txqueue)
30722d95e93SJiawen Wu {
30822d95e93SJiawen Wu struct wx *wx = netdev_priv(netdev);
30922d95e93SJiawen Wu
310*e73e4d18SJiawen Wu if (wx_check_pcie_error(wx))
311*e73e4d18SJiawen Wu wx_tx_timeout_recovery(wx);
312*e73e4d18SJiawen Wu else
31322d95e93SJiawen Wu wx_tx_timeout_reset(wx);
31422d95e93SJiawen Wu }
31522d95e93SJiawen Wu EXPORT_SYMBOL(wx_tx_timeout);
31622d95e93SJiawen Wu
wx_handle_tx_hang(struct wx_ring * tx_ring,unsigned int next)31722d95e93SJiawen Wu void wx_handle_tx_hang(struct wx_ring *tx_ring, unsigned int next)
31822d95e93SJiawen Wu {
31922d95e93SJiawen Wu struct wx *wx = netdev_priv(tx_ring->netdev);
32022d95e93SJiawen Wu
32122d95e93SJiawen Wu wx_warn(wx,
32222d95e93SJiawen Wu "Detected Tx Unit Hang: Queue %d, TDH %x, TDT %x, ntu %x, ntc %x, ntc.time_stamp %lx, jiffies %lx\n",
32322d95e93SJiawen Wu tx_ring->queue_index,
32422d95e93SJiawen Wu rd32(wx, WX_PX_TR_RP(tx_ring->reg_idx)),
32522d95e93SJiawen Wu rd32(wx, WX_PX_TR_WP(tx_ring->reg_idx)),
32622d95e93SJiawen Wu tx_ring->next_to_use, next,
32722d95e93SJiawen Wu tx_ring->tx_buffer_info[next].time_stamp, jiffies);
32822d95e93SJiawen Wu
32922d95e93SJiawen Wu netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
33022d95e93SJiawen Wu
33122d95e93SJiawen Wu wx_tx_timeout_reset(wx);
33222d95e93SJiawen Wu }
333