xref: /linux/drivers/net/ethernet/wangxun/libwx/wx_err.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
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