1 // SPDX-License-Identifier: GPL-2.0
3 * This file implements the error recovery as a core part of PCIe error
4 * reporting. When a PCIe error is delivered, an error message will be
5 * collected and printed to console, then, an error recovery procedure
6 * will be executed by following the PCI error recovery rules.
8 * Copyright (C) 2006 Intel Corp.
9 * Tom Long Nguyen (tom.l.nguyen@intel.com)
10 * Zhang Yanmin (yanmin.zhang@intel.com)
13 #define dev_fmt(fmt) "AER: " fmt
15 #include <linux/pci.h>
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/errno.h>
19 #include <linux/aer.h>
23 static pci_ers_result_t
merge_result(enum pci_ers_result orig
,
24 enum pci_ers_result
new)
26 if (new == PCI_ERS_RESULT_NO_AER_DRIVER
)
27 return PCI_ERS_RESULT_NO_AER_DRIVER
;
29 if (new == PCI_ERS_RESULT_NONE
)
33 case PCI_ERS_RESULT_CAN_RECOVER
:
34 case PCI_ERS_RESULT_RECOVERED
:
37 case PCI_ERS_RESULT_DISCONNECT
:
38 if (new == PCI_ERS_RESULT_NEED_RESET
)
39 orig
= PCI_ERS_RESULT_NEED_RESET
;
48 static int report_error_detected(struct pci_dev
*dev
,
49 enum pci_channel_state state
,
50 enum pci_ers_result
*result
)
52 pci_ers_result_t vote
;
53 const struct pci_error_handlers
*err_handler
;
55 device_lock(&dev
->dev
);
56 if (!pci_dev_set_io_state(dev
, state
) ||
58 !dev
->driver
->err_handler
||
59 !dev
->driver
->err_handler
->error_detected
) {
61 * If any device in the subtree does not have an error_detected
62 * callback, PCI_ERS_RESULT_NO_AER_DRIVER prevents subsequent
63 * error callbacks of "any" device in the subtree, and will
64 * exit in the disconnected error state.
66 if (dev
->hdr_type
!= PCI_HEADER_TYPE_BRIDGE
) {
67 vote
= PCI_ERS_RESULT_NO_AER_DRIVER
;
68 pci_info(dev
, "can't recover (no error_detected callback)\n");
70 vote
= PCI_ERS_RESULT_NONE
;
73 err_handler
= dev
->driver
->err_handler
;
74 vote
= err_handler
->error_detected(dev
, state
);
76 pci_uevent_ers(dev
, vote
);
77 *result
= merge_result(*result
, vote
);
78 device_unlock(&dev
->dev
);
82 static int report_frozen_detected(struct pci_dev
*dev
, void *data
)
84 return report_error_detected(dev
, pci_channel_io_frozen
, data
);
87 static int report_normal_detected(struct pci_dev
*dev
, void *data
)
89 return report_error_detected(dev
, pci_channel_io_normal
, data
);
92 static int report_mmio_enabled(struct pci_dev
*dev
, void *data
)
94 pci_ers_result_t vote
, *result
= data
;
95 const struct pci_error_handlers
*err_handler
;
97 device_lock(&dev
->dev
);
99 !dev
->driver
->err_handler
||
100 !dev
->driver
->err_handler
->mmio_enabled
)
103 err_handler
= dev
->driver
->err_handler
;
104 vote
= err_handler
->mmio_enabled(dev
);
105 *result
= merge_result(*result
, vote
);
107 device_unlock(&dev
->dev
);
111 static int report_slot_reset(struct pci_dev
*dev
, void *data
)
113 pci_ers_result_t vote
, *result
= data
;
114 const struct pci_error_handlers
*err_handler
;
116 device_lock(&dev
->dev
);
118 !dev
->driver
->err_handler
||
119 !dev
->driver
->err_handler
->slot_reset
)
122 err_handler
= dev
->driver
->err_handler
;
123 vote
= err_handler
->slot_reset(dev
);
124 *result
= merge_result(*result
, vote
);
126 device_unlock(&dev
->dev
);
130 static int report_resume(struct pci_dev
*dev
, void *data
)
132 const struct pci_error_handlers
*err_handler
;
134 device_lock(&dev
->dev
);
135 if (!pci_dev_set_io_state(dev
, pci_channel_io_normal
) ||
137 !dev
->driver
->err_handler
||
138 !dev
->driver
->err_handler
->resume
)
141 err_handler
= dev
->driver
->err_handler
;
142 err_handler
->resume(dev
);
144 pci_uevent_ers(dev
, PCI_ERS_RESULT_RECOVERED
);
145 device_unlock(&dev
->dev
);
150 * default_reset_link - default reset function
151 * @dev: pointer to pci_dev data structure
153 * Invoked when performing link reset on a Downstream Port or a
154 * Root Port with no aer driver.
156 static pci_ers_result_t
default_reset_link(struct pci_dev
*dev
)
160 rc
= pci_bus_error_reset(dev
);
161 pci_printk(KERN_DEBUG
, dev
, "downstream link has been reset\n");
162 return rc
? PCI_ERS_RESULT_DISCONNECT
: PCI_ERS_RESULT_RECOVERED
;
165 static pci_ers_result_t
reset_link(struct pci_dev
*dev
, u32 service
)
167 pci_ers_result_t status
;
168 struct pcie_port_service_driver
*driver
= NULL
;
170 driver
= pcie_port_find_service(dev
, service
);
171 if (driver
&& driver
->reset_link
) {
172 status
= driver
->reset_link(dev
);
173 } else if (pcie_downstream_port(dev
)) {
174 status
= default_reset_link(dev
);
176 pci_printk(KERN_DEBUG
, dev
, "no link-reset support at upstream device %s\n",
178 return PCI_ERS_RESULT_DISCONNECT
;
181 if (status
!= PCI_ERS_RESULT_RECOVERED
) {
182 pci_printk(KERN_DEBUG
, dev
, "link reset at upstream device %s failed\n",
184 return PCI_ERS_RESULT_DISCONNECT
;
190 void pcie_do_recovery(struct pci_dev
*dev
, enum pci_channel_state state
,
193 pci_ers_result_t status
= PCI_ERS_RESULT_CAN_RECOVER
;
197 * Error recovery runs on all subordinates of the first downstream port.
198 * If the downstream port detected the error, it is cleared at the end.
200 if (!(pci_pcie_type(dev
) == PCI_EXP_TYPE_ROOT_PORT
||
201 pci_pcie_type(dev
) == PCI_EXP_TYPE_DOWNSTREAM
))
202 dev
= dev
->bus
->self
;
203 bus
= dev
->subordinate
;
205 pci_dbg(dev
, "broadcast error_detected message\n");
206 if (state
== pci_channel_io_frozen
)
207 pci_walk_bus(bus
, report_frozen_detected
, &status
);
209 pci_walk_bus(bus
, report_normal_detected
, &status
);
211 if (state
== pci_channel_io_frozen
&&
212 reset_link(dev
, service
) != PCI_ERS_RESULT_RECOVERED
)
215 if (status
== PCI_ERS_RESULT_CAN_RECOVER
) {
216 status
= PCI_ERS_RESULT_RECOVERED
;
217 pci_dbg(dev
, "broadcast mmio_enabled message\n");
218 pci_walk_bus(bus
, report_mmio_enabled
, &status
);
221 if (status
== PCI_ERS_RESULT_NEED_RESET
) {
223 * TODO: Should call platform-specific
224 * functions to reset slot before calling
225 * drivers' slot_reset callbacks?
227 status
= PCI_ERS_RESULT_RECOVERED
;
228 pci_dbg(dev
, "broadcast slot_reset message\n");
229 pci_walk_bus(bus
, report_slot_reset
, &status
);
232 if (status
!= PCI_ERS_RESULT_RECOVERED
)
235 pci_dbg(dev
, "broadcast resume message\n");
236 pci_walk_bus(bus
, report_resume
, &status
);
238 pci_aer_clear_device_status(dev
);
239 pci_cleanup_aer_uncorrect_error_status(dev
);
240 pci_info(dev
, "device recovery successful\n");
244 pci_uevent_ers(dev
, PCI_ERS_RESULT_DISCONNECT
);
246 /* TODO: Should kernel panic here? */
247 pci_info(dev
, "device recovery failed\n");