xref: /openbmc/linux/drivers/pci/pcie/err.c (revision 20e2fc42)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
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.
7  *
8  * Copyright (C) 2006 Intel Corp.
9  *	Tom Long Nguyen (tom.l.nguyen@intel.com)
10  *	Zhang Yanmin (yanmin.zhang@intel.com)
11  */
12 
13 #include <linux/pci.h>
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/aer.h>
18 #include "portdrv.h"
19 #include "../pci.h"
20 
21 static pci_ers_result_t merge_result(enum pci_ers_result orig,
22 				  enum pci_ers_result new)
23 {
24 	if (new == PCI_ERS_RESULT_NO_AER_DRIVER)
25 		return PCI_ERS_RESULT_NO_AER_DRIVER;
26 
27 	if (new == PCI_ERS_RESULT_NONE)
28 		return orig;
29 
30 	switch (orig) {
31 	case PCI_ERS_RESULT_CAN_RECOVER:
32 	case PCI_ERS_RESULT_RECOVERED:
33 		orig = new;
34 		break;
35 	case PCI_ERS_RESULT_DISCONNECT:
36 		if (new == PCI_ERS_RESULT_NEED_RESET)
37 			orig = PCI_ERS_RESULT_NEED_RESET;
38 		break;
39 	default:
40 		break;
41 	}
42 
43 	return orig;
44 }
45 
46 static int report_error_detected(struct pci_dev *dev,
47 				 enum pci_channel_state state,
48 				 enum pci_ers_result *result)
49 {
50 	pci_ers_result_t vote;
51 	const struct pci_error_handlers *err_handler;
52 
53 	device_lock(&dev->dev);
54 	if (!pci_dev_set_io_state(dev, state) ||
55 		!dev->driver ||
56 		!dev->driver->err_handler ||
57 		!dev->driver->err_handler->error_detected) {
58 		/*
59 		 * If any device in the subtree does not have an error_detected
60 		 * callback, PCI_ERS_RESULT_NO_AER_DRIVER prevents subsequent
61 		 * error callbacks of "any" device in the subtree, and will
62 		 * exit in the disconnected error state.
63 		 */
64 		if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE)
65 			vote = PCI_ERS_RESULT_NO_AER_DRIVER;
66 		else
67 			vote = PCI_ERS_RESULT_NONE;
68 	} else {
69 		err_handler = dev->driver->err_handler;
70 		vote = err_handler->error_detected(dev, state);
71 	}
72 	pci_uevent_ers(dev, vote);
73 	*result = merge_result(*result, vote);
74 	device_unlock(&dev->dev);
75 	return 0;
76 }
77 
78 static int report_frozen_detected(struct pci_dev *dev, void *data)
79 {
80 	return report_error_detected(dev, pci_channel_io_frozen, data);
81 }
82 
83 static int report_normal_detected(struct pci_dev *dev, void *data)
84 {
85 	return report_error_detected(dev, pci_channel_io_normal, data);
86 }
87 
88 static int report_mmio_enabled(struct pci_dev *dev, void *data)
89 {
90 	pci_ers_result_t vote, *result = data;
91 	const struct pci_error_handlers *err_handler;
92 
93 	device_lock(&dev->dev);
94 	if (!dev->driver ||
95 		!dev->driver->err_handler ||
96 		!dev->driver->err_handler->mmio_enabled)
97 		goto out;
98 
99 	err_handler = dev->driver->err_handler;
100 	vote = err_handler->mmio_enabled(dev);
101 	*result = merge_result(*result, vote);
102 out:
103 	device_unlock(&dev->dev);
104 	return 0;
105 }
106 
107 static int report_slot_reset(struct pci_dev *dev, void *data)
108 {
109 	pci_ers_result_t vote, *result = data;
110 	const struct pci_error_handlers *err_handler;
111 
112 	device_lock(&dev->dev);
113 	if (!dev->driver ||
114 		!dev->driver->err_handler ||
115 		!dev->driver->err_handler->slot_reset)
116 		goto out;
117 
118 	err_handler = dev->driver->err_handler;
119 	vote = err_handler->slot_reset(dev);
120 	*result = merge_result(*result, vote);
121 out:
122 	device_unlock(&dev->dev);
123 	return 0;
124 }
125 
126 static int report_resume(struct pci_dev *dev, void *data)
127 {
128 	const struct pci_error_handlers *err_handler;
129 
130 	device_lock(&dev->dev);
131 	if (!pci_dev_set_io_state(dev, pci_channel_io_normal) ||
132 		!dev->driver ||
133 		!dev->driver->err_handler ||
134 		!dev->driver->err_handler->resume)
135 		goto out;
136 
137 	err_handler = dev->driver->err_handler;
138 	err_handler->resume(dev);
139 out:
140 	pci_uevent_ers(dev, PCI_ERS_RESULT_RECOVERED);
141 	device_unlock(&dev->dev);
142 	return 0;
143 }
144 
145 /**
146  * default_reset_link - default reset function
147  * @dev: pointer to pci_dev data structure
148  *
149  * Invoked when performing link reset on a Downstream Port or a
150  * Root Port with no aer driver.
151  */
152 static pci_ers_result_t default_reset_link(struct pci_dev *dev)
153 {
154 	int rc;
155 
156 	rc = pci_bus_error_reset(dev);
157 	pci_printk(KERN_DEBUG, dev, "downstream link has been reset\n");
158 	return rc ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
159 }
160 
161 static pci_ers_result_t reset_link(struct pci_dev *dev, u32 service)
162 {
163 	pci_ers_result_t status;
164 	struct pcie_port_service_driver *driver = NULL;
165 
166 	driver = pcie_port_find_service(dev, service);
167 	if (driver && driver->reset_link) {
168 		status = driver->reset_link(dev);
169 	} else if (pcie_downstream_port(dev)) {
170 		status = default_reset_link(dev);
171 	} else {
172 		pci_printk(KERN_DEBUG, dev, "no link-reset support at upstream device %s\n",
173 			pci_name(dev));
174 		return PCI_ERS_RESULT_DISCONNECT;
175 	}
176 
177 	if (status != PCI_ERS_RESULT_RECOVERED) {
178 		pci_printk(KERN_DEBUG, dev, "link reset at upstream device %s failed\n",
179 			pci_name(dev));
180 		return PCI_ERS_RESULT_DISCONNECT;
181 	}
182 
183 	return status;
184 }
185 
186 void pcie_do_recovery(struct pci_dev *dev, enum pci_channel_state state,
187 		      u32 service)
188 {
189 	pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
190 	struct pci_bus *bus;
191 
192 	/*
193 	 * Error recovery runs on all subordinates of the first downstream port.
194 	 * If the downstream port detected the error, it is cleared at the end.
195 	 */
196 	if (!(pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT ||
197 	      pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM))
198 		dev = dev->bus->self;
199 	bus = dev->subordinate;
200 
201 	pci_dbg(dev, "broadcast error_detected message\n");
202 	if (state == pci_channel_io_frozen)
203 		pci_walk_bus(bus, report_frozen_detected, &status);
204 	else
205 		pci_walk_bus(bus, report_normal_detected, &status);
206 
207 	if (state == pci_channel_io_frozen &&
208 	    reset_link(dev, service) != PCI_ERS_RESULT_RECOVERED)
209 		goto failed;
210 
211 	if (status == PCI_ERS_RESULT_CAN_RECOVER) {
212 		status = PCI_ERS_RESULT_RECOVERED;
213 		pci_dbg(dev, "broadcast mmio_enabled message\n");
214 		pci_walk_bus(bus, report_mmio_enabled, &status);
215 	}
216 
217 	if (status == PCI_ERS_RESULT_NEED_RESET) {
218 		/*
219 		 * TODO: Should call platform-specific
220 		 * functions to reset slot before calling
221 		 * drivers' slot_reset callbacks?
222 		 */
223 		status = PCI_ERS_RESULT_RECOVERED;
224 		pci_dbg(dev, "broadcast slot_reset message\n");
225 		pci_walk_bus(bus, report_slot_reset, &status);
226 	}
227 
228 	if (status != PCI_ERS_RESULT_RECOVERED)
229 		goto failed;
230 
231 	pci_dbg(dev, "broadcast resume message\n");
232 	pci_walk_bus(bus, report_resume, &status);
233 
234 	pci_aer_clear_device_status(dev);
235 	pci_cleanup_aer_uncorrect_error_status(dev);
236 	pci_info(dev, "AER: Device recovery successful\n");
237 	return;
238 
239 failed:
240 	pci_uevent_ers(dev, PCI_ERS_RESULT_DISCONNECT);
241 
242 	/* TODO: Should kernel panic here? */
243 	pci_info(dev, "AER: Device recovery failed\n");
244 }
245