Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
cbc0dd1f JG |
2 | /* |
3 | * Copyright IBM Corp. 2012 | |
4 | * | |
5 | * Author(s): | |
6 | * Jan Glauber <jang@linux.vnet.ibm.com> | |
7 | */ | |
8 | ||
896cb7e6 GS |
9 | #define KMSG_COMPONENT "zpci" |
10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | |
cbc0dd1f JG |
11 | |
12 | #include <linux/kernel.h> | |
13 | #include <linux/pci.h> | |
1f1dcbd4 | 14 | #include <asm/pci_debug.h> |
652d40b2 | 15 | #include <asm/pci_dma.h> |
d795ddad | 16 | #include <asm/sclp.h> |
cbc0dd1f | 17 | |
05bc1be6 PM |
18 | #include "pci_bus.h" |
19 | ||
cbc0dd1f JG |
20 | /* Content Code Description for PCI Function Error */ |
21 | struct zpci_ccdf_err { | |
22 | u32 reserved1; | |
23 | u32 fh; /* function handle */ | |
24 | u32 fid; /* function id */ | |
25 | u32 ett : 4; /* expected table type */ | |
26 | u32 mvn : 12; /* MSI vector number */ | |
27 | u32 dmaas : 8; /* DMA address space */ | |
28 | u32 : 6; | |
29 | u32 q : 1; /* event qualifier */ | |
30 | u32 rw : 1; /* read/write */ | |
31 | u64 faddr; /* failing address */ | |
32 | u32 reserved3; | |
33 | u16 reserved4; | |
34 | u16 pec; /* PCI event code */ | |
35 | } __packed; | |
36 | ||
37 | /* Content Code Description for PCI Function Availability */ | |
38 | struct zpci_ccdf_avail { | |
39 | u32 reserved1; | |
40 | u32 fh; /* function handle */ | |
41 | u32 fid; /* function id */ | |
42 | u32 reserved2; | |
43 | u32 reserved3; | |
44 | u32 reserved4; | |
45 | u32 reserved5; | |
46 | u16 reserved6; | |
47 | u16 pec; /* PCI event code */ | |
48 | } __packed; | |
49 | ||
4cdf2f4e NS |
50 | static inline bool ers_result_indicates_abort(pci_ers_result_t ers_res) |
51 | { | |
52 | switch (ers_res) { | |
53 | case PCI_ERS_RESULT_CAN_RECOVER: | |
54 | case PCI_ERS_RESULT_RECOVERED: | |
55 | case PCI_ERS_RESULT_NEED_RESET: | |
56 | return false; | |
57 | default: | |
58 | return true; | |
59 | } | |
60 | } | |
61 | ||
b6f88870 | 62 | static bool is_passed_through(struct pci_dev *pdev) |
4cdf2f4e | 63 | { |
b6f88870 NS |
64 | struct zpci_dev *zdev = to_zpci(pdev); |
65 | bool ret; | |
66 | ||
67 | mutex_lock(&zdev->kzdev_lock); | |
68 | ret = !!zdev->kzdev; | |
69 | mutex_unlock(&zdev->kzdev_lock); | |
70 | ||
71 | return ret; | |
4cdf2f4e NS |
72 | } |
73 | ||
74 | static bool is_driver_supported(struct pci_driver *driver) | |
75 | { | |
76 | if (!driver || !driver->err_handler) | |
77 | return false; | |
78 | if (!driver->err_handler->error_detected) | |
79 | return false; | |
80 | if (!driver->err_handler->slot_reset) | |
81 | return false; | |
82 | if (!driver->err_handler->resume) | |
83 | return false; | |
84 | return true; | |
85 | } | |
86 | ||
87 | static pci_ers_result_t zpci_event_notify_error_detected(struct pci_dev *pdev, | |
88 | struct pci_driver *driver) | |
89 | { | |
90 | pci_ers_result_t ers_res = PCI_ERS_RESULT_DISCONNECT; | |
91 | ||
92 | ers_res = driver->err_handler->error_detected(pdev, pdev->error_state); | |
93 | if (ers_result_indicates_abort(ers_res)) | |
94 | pr_info("%s: Automatic recovery failed after initial reporting\n", pci_name(pdev)); | |
95 | else if (ers_res == PCI_ERS_RESULT_NEED_RESET) | |
96 | pr_debug("%s: Driver needs reset to recover\n", pci_name(pdev)); | |
97 | ||
98 | return ers_res; | |
99 | } | |
100 | ||
101 | static pci_ers_result_t zpci_event_do_error_state_clear(struct pci_dev *pdev, | |
102 | struct pci_driver *driver) | |
103 | { | |
104 | pci_ers_result_t ers_res = PCI_ERS_RESULT_DISCONNECT; | |
105 | struct zpci_dev *zdev = to_zpci(pdev); | |
106 | int rc; | |
107 | ||
108 | pr_info("%s: Unblocking device access for examination\n", pci_name(pdev)); | |
109 | rc = zpci_reset_load_store_blocked(zdev); | |
110 | if (rc) { | |
111 | pr_err("%s: Unblocking device access failed\n", pci_name(pdev)); | |
112 | /* Let's try a full reset instead */ | |
113 | return PCI_ERS_RESULT_NEED_RESET; | |
114 | } | |
115 | ||
116 | if (driver->err_handler->mmio_enabled) { | |
117 | ers_res = driver->err_handler->mmio_enabled(pdev); | |
118 | if (ers_result_indicates_abort(ers_res)) { | |
119 | pr_info("%s: Automatic recovery failed after MMIO re-enable\n", | |
120 | pci_name(pdev)); | |
121 | return ers_res; | |
122 | } else if (ers_res == PCI_ERS_RESULT_NEED_RESET) { | |
123 | pr_debug("%s: Driver needs reset to recover\n", pci_name(pdev)); | |
124 | return ers_res; | |
125 | } | |
126 | } | |
127 | ||
128 | pr_debug("%s: Unblocking DMA\n", pci_name(pdev)); | |
129 | rc = zpci_clear_error_state(zdev); | |
130 | if (!rc) { | |
131 | pdev->error_state = pci_channel_io_normal; | |
132 | } else { | |
133 | pr_err("%s: Unblocking DMA failed\n", pci_name(pdev)); | |
134 | /* Let's try a full reset instead */ | |
135 | return PCI_ERS_RESULT_NEED_RESET; | |
136 | } | |
137 | ||
138 | return ers_res; | |
139 | } | |
140 | ||
141 | static pci_ers_result_t zpci_event_do_reset(struct pci_dev *pdev, | |
142 | struct pci_driver *driver) | |
143 | { | |
144 | pci_ers_result_t ers_res = PCI_ERS_RESULT_DISCONNECT; | |
145 | ||
146 | pr_info("%s: Initiating reset\n", pci_name(pdev)); | |
147 | if (zpci_hot_reset_device(to_zpci(pdev))) { | |
148 | pr_err("%s: The reset request failed\n", pci_name(pdev)); | |
149 | return ers_res; | |
150 | } | |
151 | pdev->error_state = pci_channel_io_normal; | |
152 | ers_res = driver->err_handler->slot_reset(pdev); | |
153 | if (ers_result_indicates_abort(ers_res)) { | |
154 | pr_info("%s: Automatic recovery failed after slot reset\n", pci_name(pdev)); | |
155 | return ers_res; | |
156 | } | |
157 | ||
158 | return ers_res; | |
159 | } | |
160 | ||
161 | /* zpci_event_attempt_error_recovery - Try to recover the given PCI function | |
162 | * @pdev: PCI function to recover currently in the error state | |
163 | * | |
164 | * We follow the scheme outlined in Documentation/PCI/pci-error-recovery.rst. | |
165 | * With the simplification that recovery always happens per function | |
166 | * and the platform determines which functions are affected for | |
167 | * multi-function devices. | |
168 | */ | |
169 | static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev) | |
170 | { | |
171 | pci_ers_result_t ers_res = PCI_ERS_RESULT_DISCONNECT; | |
172 | struct pci_driver *driver; | |
173 | ||
174 | /* | |
175 | * Ensure that the PCI function is not removed concurrently, no driver | |
176 | * is unbound or probed and that userspace can't access its | |
177 | * configuration space while we perform recovery. | |
178 | */ | |
179 | pci_dev_lock(pdev); | |
180 | if (pdev->error_state == pci_channel_io_perm_failure) { | |
181 | ers_res = PCI_ERS_RESULT_DISCONNECT; | |
182 | goto out_unlock; | |
183 | } | |
184 | pdev->error_state = pci_channel_io_frozen; | |
185 | ||
b6f88870 | 186 | if (is_passed_through(pdev)) { |
4cdf2f4e NS |
187 | pr_info("%s: Cannot be recovered in the host because it is a pass-through device\n", |
188 | pci_name(pdev)); | |
189 | goto out_unlock; | |
190 | } | |
191 | ||
192 | driver = to_pci_driver(pdev->dev.driver); | |
193 | if (!is_driver_supported(driver)) { | |
194 | if (!driver) | |
195 | pr_info("%s: Cannot be recovered because no driver is bound to the device\n", | |
196 | pci_name(pdev)); | |
197 | else | |
198 | pr_info("%s: The %s driver bound to the device does not support error recovery\n", | |
199 | pci_name(pdev), | |
200 | driver->name); | |
201 | goto out_unlock; | |
202 | } | |
203 | ||
204 | ers_res = zpci_event_notify_error_detected(pdev, driver); | |
205 | if (ers_result_indicates_abort(ers_res)) | |
206 | goto out_unlock; | |
207 | ||
208 | if (ers_res == PCI_ERS_RESULT_CAN_RECOVER) { | |
209 | ers_res = zpci_event_do_error_state_clear(pdev, driver); | |
210 | if (ers_result_indicates_abort(ers_res)) | |
211 | goto out_unlock; | |
212 | } | |
213 | ||
214 | if (ers_res == PCI_ERS_RESULT_NEED_RESET) | |
215 | ers_res = zpci_event_do_reset(pdev, driver); | |
216 | ||
217 | if (ers_res != PCI_ERS_RESULT_RECOVERED) { | |
218 | pr_err("%s: Automatic recovery failed; operator intervention is required\n", | |
219 | pci_name(pdev)); | |
220 | goto out_unlock; | |
221 | } | |
222 | ||
223 | pr_info("%s: The device is ready to resume operations\n", pci_name(pdev)); | |
224 | if (driver->err_handler->resume) | |
225 | driver->err_handler->resume(pdev); | |
226 | out_unlock: | |
227 | pci_dev_unlock(pdev); | |
228 | ||
229 | return ers_res; | |
230 | } | |
231 | ||
232 | /* zpci_event_io_failure - Report PCI channel failure state to driver | |
233 | * @pdev: PCI function for which to report | |
234 | * @es: PCI channel failure state to report | |
235 | */ | |
236 | static void zpci_event_io_failure(struct pci_dev *pdev, pci_channel_state_t es) | |
237 | { | |
238 | struct pci_driver *driver; | |
239 | ||
240 | pci_dev_lock(pdev); | |
241 | pdev->error_state = es; | |
242 | /** | |
243 | * While vfio-pci's error_detected callback notifies user-space QEMU | |
244 | * reacts to this by freezing the guest. In an s390 environment PCI | |
245 | * errors are rarely fatal so this is overkill. Instead in the future | |
246 | * we will inject the error event and let the guest recover the device | |
247 | * itself. | |
248 | */ | |
b6f88870 | 249 | if (is_passed_through(pdev)) |
4cdf2f4e NS |
250 | goto out; |
251 | driver = to_pci_driver(pdev->dev.driver); | |
252 | if (driver && driver->err_handler && driver->err_handler->error_detected) | |
253 | driver->err_handler->error_detected(pdev, pdev->error_state); | |
254 | out: | |
255 | pci_dev_unlock(pdev); | |
256 | } | |
257 | ||
aa3b7c29 | 258 | static void __zpci_event_error(struct zpci_ccdf_err *ccdf) |
cbc0dd1f | 259 | { |
d795ddad | 260 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); |
9a99649f | 261 | struct pci_dev *pdev = NULL; |
4cdf2f4e | 262 | pci_ers_result_t ers_res; |
d795ddad | 263 | |
6526a597 NS |
264 | zpci_dbg(3, "err fid:%x, fh:%x, pec:%x\n", |
265 | ccdf->fid, ccdf->fh, ccdf->pec); | |
d795ddad SO |
266 | zpci_err("error CCDF:\n"); |
267 | zpci_err_hex(ccdf, sizeof(*ccdf)); | |
268 | ||
4cdf2f4e | 269 | if (zdev) { |
bcb5d6c7 | 270 | mutex_lock(&zdev->state_lock); |
4cdf2f4e NS |
271 | zpci_update_fh(zdev, ccdf->fh); |
272 | if (zdev->zbus->bus) | |
273 | pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn); | |
274 | } | |
9a99649f | 275 | |
d795ddad | 276 | pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n", |
515f022e | 277 | pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid); |
8ead7efb SO |
278 | |
279 | if (!pdev) | |
c122383d | 280 | goto no_pdev; |
8ead7efb | 281 | |
4cdf2f4e NS |
282 | switch (ccdf->pec) { |
283 | case 0x003a: /* Service Action or Error Recovery Successful */ | |
284 | ers_res = zpci_event_attempt_error_recovery(pdev); | |
285 | if (ers_res != PCI_ERS_RESULT_RECOVERED) | |
286 | zpci_event_io_failure(pdev, pci_channel_io_perm_failure); | |
287 | break; | |
288 | default: | |
289 | /* | |
290 | * Mark as frozen not permanently failed because the device | |
291 | * could be subsequently recovered by the platform. | |
292 | */ | |
293 | zpci_event_io_failure(pdev, pci_channel_io_frozen); | |
294 | break; | |
295 | } | |
9a99649f | 296 | pci_dev_put(pdev); |
c122383d | 297 | no_pdev: |
bcb5d6c7 GB |
298 | if (zdev) |
299 | mutex_unlock(&zdev->state_lock); | |
c122383d | 300 | zpci_zdev_put(zdev); |
d795ddad SO |
301 | } |
302 | ||
aa3b7c29 SO |
303 | void zpci_event_error(void *data) |
304 | { | |
305 | if (zpci_is_enabled()) | |
306 | __zpci_event_error(data); | |
307 | } | |
308 | ||
dee60c0d NS |
309 | static void zpci_event_hard_deconfigured(struct zpci_dev *zdev, u32 fh) |
310 | { | |
4fe20497 | 311 | zpci_update_fh(zdev, fh); |
dee60c0d NS |
312 | /* Give the driver a hint that the function is |
313 | * already unusable. | |
314 | */ | |
95b3a8b4 | 315 | zpci_bus_remove_device(zdev, true); |
652d40b2 NS |
316 | /* Even though the device is already gone we still |
317 | * need to free zPCI resources as part of the disable. | |
318 | */ | |
1f3f7681 NS |
319 | if (zdev_enabled(zdev)) |
320 | zpci_disable_device(zdev); | |
dee60c0d | 321 | zdev->state = ZPCI_FN_STATE_STANDBY; |
dee60c0d NS |
322 | } |
323 | ||
aa3b7c29 | 324 | static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) |
d795ddad | 325 | { |
cbc0dd1f | 326 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); |
c122383d | 327 | bool existing_zdev = !!zdev; |
0d9cf5d8 | 328 | enum zpci_state state; |
cbc0dd1f | 329 | |
6526a597 NS |
330 | zpci_dbg(3, "avl fid:%x, fh:%x, pec:%x\n", |
331 | ccdf->fid, ccdf->fh, ccdf->pec); | |
bcb5d6c7 GB |
332 | |
333 | if (existing_zdev) | |
334 | mutex_lock(&zdev->state_lock); | |
335 | ||
cbc0dd1f | 336 | switch (ccdf->pec) { |
7fc611ff SO |
337 | case 0x0301: /* Reserved|Standby -> Configured */ |
338 | if (!zdev) { | |
14c87ba8 NS |
339 | zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_CONFIGURED); |
340 | if (IS_ERR(zdev)) | |
341 | break; | |
342 | } else { | |
343 | /* the configuration request may be stale */ | |
344 | if (zdev->state != ZPCI_FN_STATE_STANDBY) | |
345 | break; | |
346 | zdev->state = ZPCI_FN_STATE_CONFIGURED; | |
f606b3ef | 347 | } |
a7f82c36 | 348 | zpci_scan_configured_device(zdev, ccdf->fh); |
cbc0dd1f | 349 | break; |
d795ddad | 350 | case 0x0302: /* Reserved -> Standby */ |
2631f6b6 | 351 | if (!zdev) |
ba764dd7 | 352 | zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY); |
2631f6b6 | 353 | else |
4fe20497 | 354 | zpci_update_fh(zdev, ccdf->fh); |
cbc0dd1f | 355 | break; |
d795ddad | 356 | case 0x0303: /* Deconfiguration requested */ |
2631f6b6 | 357 | if (zdev) { |
d0c8fd21 | 358 | /* The event may have been queued before we configured |
0d9cf5d8 NS |
359 | * the device. |
360 | */ | |
361 | if (zdev->state != ZPCI_FN_STATE_CONFIGURED) | |
362 | break; | |
4fe20497 | 363 | zpci_update_fh(zdev, ccdf->fh); |
2631f6b6 NS |
364 | zpci_deconfigure_device(zdev); |
365 | } | |
d795ddad | 366 | break; |
623bd44d | 367 | case 0x0304: /* Configured -> Standby|Reserved */ |
0d9cf5d8 | 368 | if (zdev) { |
d0c8fd21 | 369 | /* The event may have been queued before we configured |
0d9cf5d8 NS |
370 | * the device.: |
371 | */ | |
372 | if (zdev->state == ZPCI_FN_STATE_CONFIGURED) | |
373 | zpci_event_hard_deconfigured(zdev, ccdf->fh); | |
374 | /* The 0x0304 event may immediately reserve the device */ | |
375 | if (!clp_get_state(zdev->fid, &state) && | |
376 | state == ZPCI_FN_STATE_RESERVED) { | |
a46044a9 | 377 | zpci_device_reserved(zdev); |
0d9cf5d8 NS |
378 | } |
379 | } | |
d795ddad SO |
380 | break; |
381 | case 0x0306: /* 0x308 or 0x302 for multiple devices */ | |
809fcfaf NS |
382 | zpci_remove_reserved_devices(); |
383 | clp_scan_pci_devices(); | |
cbc0dd1f | 384 | break; |
d795ddad | 385 | case 0x0308: /* Standby -> Reserved */ |
70426892 SO |
386 | if (!zdev) |
387 | break; | |
a46044a9 | 388 | zpci_device_reserved(zdev); |
d795ddad | 389 | break; |
cbc0dd1f JG |
390 | default: |
391 | break; | |
392 | } | |
bcb5d6c7 GB |
393 | if (existing_zdev) { |
394 | mutex_unlock(&zdev->state_lock); | |
c122383d | 395 | zpci_zdev_put(zdev); |
bcb5d6c7 | 396 | } |
cbc0dd1f | 397 | } |
aa3b7c29 SO |
398 | |
399 | void zpci_event_availability(void *data) | |
400 | { | |
401 | if (zpci_is_enabled()) | |
402 | __zpci_event_availability(data); | |
403 | } |