PCI: unconditionally clear AER uncorr status register during cleanup
authorAndrew Patterson <andrew.patterson@hp.com>
Thu, 3 Dec 2009 17:28:20 +0000 (10:28 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 1 Apr 2010 22:58:12 +0000 (15:58 -0700)
commit 6cdfd995a65a52e05b99e3a72a9b979abe73b312 upstream.

The current implementation of pci_cleanup_aer_uncorrect_error_status
only clears either fatal or non-fatal error status bits depending
on the state of the I/O channel. This implementation will then often
leave some bits set after PCI error recovery completes.  The uncleared bit
settings will then be falsely reported the next time an AER interrupt is
generated for that hierarchy. An easy way to illustrate this issue is to
use the aer-inject module to simultaneously inject both an uncorrectable
non-fatal and uncorrectable fatal error.  One of the errors will not be
cleared.

This patch resolves this issue by unconditionally clearing all bits in
the AER uncorrectable status register. All settings and corrective action
strategies are saved and determined before
pci_cleanup_aer_uncorrect_error_status is called, so this change should not
affect errory handling functionality.

Signed-off-by: Andrew Patterson <andrew.patterson@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Alex Chiang <achiang@hp.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/pci/pcie/aer/aerdrv_core.c

index 9f5ccbeb4fa5fcef281eb2ed3d3a079ae885909e..72fa87c095d8c6752232e070c70dd96f74ed9111 100644 (file)
@@ -78,19 +78,15 @@ EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
 {
        int pos;
-       u32 status, mask;
+       u32 status;
 
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
        if (!pos)
                return -EIO;
 
        pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
-       pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
-       if (dev->error_state == pci_channel_io_normal)
-               status &= ~mask; /* Clear corresponding nonfatal bits */
-       else
-               status &= mask; /* Clear corresponding fatal bits */
-       pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
+       if (status)
+               pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
 
        return 0;
 }