]> www.infradead.org Git - users/hch/misc.git/commitdiff
PCI/AER: Clear device status bits during ERR_FATAL and ERR_NONFATAL
authorOza Pawandeep <poza@codeaurora.org>
Thu, 19 Jul 2018 22:58:09 +0000 (17:58 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Fri, 20 Jul 2018 20:27:11 +0000 (15:27 -0500)
Clear the device status bits while handling both ERR_FATAL and ERR_NONFATAL
cases.

Signed-off-by: Oza Pawandeep <poza@codeaurora.org>
[bhelgaas: rename to pci_aer_clear_device_status(), declare internal to PCI
core instead of exposing it everywhere]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/pci.h
drivers/pci/pcie/aer.c
drivers/pci/pcie/err.c

index 107c64892b6624686f24161fc1528854d5c00fbf..138a2b66f620e98025ca4ba9d12ee06b5c9343f0 100644 (file)
@@ -486,11 +486,13 @@ void pci_aer_init(struct pci_dev *dev);
 void pci_aer_exit(struct pci_dev *dev);
 extern const struct attribute_group aer_stats_attr_group;
 void pci_aer_clear_fatal_status(struct pci_dev *dev);
+void pci_aer_clear_device_status(struct pci_dev *dev);
 #else
 static inline void pci_no_aer(void) { }
 static inline int pci_aer_init(struct pci_dev *d) { return -ENODEV; }
 static inline void pci_aer_exit(struct pci_dev *d) { }
 static inline void pci_aer_clear_fatal_status(struct pci_dev *dev) { }
+static inline void pci_aer_clear_device_status(struct pci_dev *dev) { }
 #endif
 
 #endif /* DRIVERS_PCI_H */
index 4411ada4a91cc7848cf3d9953b2181b6ca350917..2a40b24ae4e3c293b13511b840bb1231a6a3972e 100644 (file)
@@ -382,6 +382,14 @@ int pci_disable_pcie_error_reporting(struct pci_dev *dev)
 }
 EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
 
+void pci_aer_clear_device_status(struct pci_dev *dev)
+{
+       u16 sta;
+
+       pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &sta);
+       pcie_capability_write_word(dev, PCI_EXP_DEVSTA, sta);
+}
+
 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
 {
        int pos;
@@ -1532,12 +1540,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
  */
 static void aer_error_resume(struct pci_dev *dev)
 {
-       u16 reg16;
-
-       /* Clean up Root device status */
-       pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &reg16);
-       pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16);
-
+       pci_aer_clear_device_status(dev);
        pci_cleanup_aer_uncorrect_error_status(dev);
 }
 
index 638eda5c1d7918acd35d34a1dec2df2a4494779e..fdbcc555860dea0b4a636313e2a33e8c845f2c9b 100644 (file)
@@ -252,6 +252,7 @@ static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
                        dev->error_state = state;
                pci_walk_bus(dev->subordinate, cb, &result_data);
                if (cb == report_resume) {
+                       pci_aer_clear_device_status(dev);
                        pci_cleanup_aer_uncorrect_error_status(dev);
                        dev->error_state = pci_channel_io_normal;
                }
@@ -312,6 +313,7 @@ void pcie_do_fatal_recovery(struct pci_dev *dev, u32 service)
                 * of the bridge and clear the error status of the bridge.
                 */
                pci_aer_clear_fatal_status(dev);
+               pci_aer_clear_device_status(dev);
        }
 
        if (result == PCI_ERS_RESULT_RECOVERED) {