|
13 | 13 | #define dev_fmt(fmt) "AER: " fmt
|
14 | 14 |
|
15 | 15 | #include <linux/pci.h>
|
| 16 | +#include <linux/pm_runtime.h> |
16 | 17 | #include <linux/module.h>
|
17 | 18 | #include <linux/kernel.h>
|
18 | 19 | #include <linux/errno.h>
|
@@ -85,6 +86,18 @@ static int report_error_detected(struct pci_dev *dev,
|
85 | 86 | return 0;
|
86 | 87 | }
|
87 | 88 |
|
| 89 | +static int pci_pm_runtime_get_sync(struct pci_dev *pdev, void *data) |
| 90 | +{ |
| 91 | + pm_runtime_get_sync(&pdev->dev); |
| 92 | + return 0; |
| 93 | +} |
| 94 | + |
| 95 | +static int pci_pm_runtime_put(struct pci_dev *pdev, void *data) |
| 96 | +{ |
| 97 | + pm_runtime_put(&pdev->dev); |
| 98 | + return 0; |
| 99 | +} |
| 100 | + |
88 | 101 | static int report_frozen_detected(struct pci_dev *dev, void *data)
|
89 | 102 | {
|
90 | 103 | return report_error_detected(dev, pci_channel_io_frozen, data);
|
@@ -207,6 +220,8 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
|
207 | 220 | else
|
208 | 221 | bridge = pci_upstream_bridge(dev);
|
209 | 222 |
|
| 223 | + pci_walk_bridge(bridge, pci_pm_runtime_get_sync, NULL); |
| 224 | + |
210 | 225 | pci_dbg(bridge, "broadcast error_detected message\n");
|
211 | 226 | if (state == pci_channel_io_frozen) {
|
212 | 227 | pci_walk_bridge(bridge, report_frozen_detected, &status);
|
@@ -251,10 +266,15 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
|
251 | 266 | pcie_clear_device_status(dev);
|
252 | 267 | pci_aer_clear_nonfatal_status(dev);
|
253 | 268 | }
|
| 269 | + |
| 270 | + pci_walk_bridge(bridge, pci_pm_runtime_put, NULL); |
| 271 | + |
254 | 272 | pci_info(bridge, "device recovery successful\n");
|
255 | 273 | return status;
|
256 | 274 |
|
257 | 275 | failed:
|
| 276 | + pci_walk_bridge(bridge, pci_pm_runtime_put, NULL); |
| 277 | + |
258 | 278 | pci_uevent_ers(bridge, PCI_ERS_RESULT_DISCONNECT);
|
259 | 279 |
|
260 | 280 | /* TODO: Should kernel panic here? */
|
|
0 commit comments