diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-11-05 15:52:13 -0800 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-11-10 04:25:09 -0500 |
commit | cf06ffb4df5314d240a002e3e1c63722e9362070 (patch) | |
tree | 2c96afb706f9a87129c95f2631aeab7d21acd6bb /drivers/net/sky2.c | |
parent | ab1a145638addee40587daf12c98ec6a30029f0a (diff) | |
download | kernel-crypto-cf06ffb4df5314d240a002e3e1c63722e9362070.tar.gz kernel-crypto-cf06ffb4df5314d240a002e3e1c63722e9362070.tar.xz kernel-crypto-cf06ffb4df5314d240a002e3e1c63722e9362070.zip |
sky2: handle advanced error recovery config issues
The PCI AER support may not work for a couple of reasons.
It may not be configured into the kernel or there may be a BIOS
bug that prevents MMCONFIG from working. If MMCONFIG doesn't work
then the PCI registers that control AER will not be accessible via
pci_read_config functions; luckly there is another window to access
PCI space in the device, so use that.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 76038bbeb50..a6ccd11574d 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2435,13 +2435,26 @@ static void sky2_hw_intr(struct sky2_hw *hw) if (status & Y2_IS_PCI_EXP) { /* PCI-Express uncorrectable Error occurred */ - int pos = pci_find_aer_capability(hw->pdev); + int aer = pci_find_aer_capability(hw->pdev); u32 err; - pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_STATUS, &err); + if (aer) { + pci_read_config_dword(pdev, aer + PCI_ERR_UNCOR_STATUS, + &err); + pci_cleanup_aer_uncorrect_error_status(pdev); + } else { + /* Either AER not configured, or not working + * because of bad MMCONFIG, so just do recover + * manually. + */ + err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS); + sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS, + 0xfffffffful); + } + if (net_ratelimit()) dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err); - pci_cleanup_aer_uncorrect_error_status(pdev); + } if (status & Y2_HWE_L1_MASK) @@ -2799,9 +2812,18 @@ static void sky2_reset(struct sky2_hw *hw) cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (cap) { - /* Check for advanced error reporting */ - pci_cleanup_aer_uncorrect_error_status(pdev); - pci_cleanup_aer_correct_error_status(pdev); + if (pci_find_aer_capability(pdev)) { + /* Check for advanced error reporting */ + pci_cleanup_aer_uncorrect_error_status(pdev); + pci_cleanup_aer_correct_error_status(pdev); + } else { + dev_warn(&pdev->dev, + "PCI Express Advanced Error Reporting" + " not configured or MMCONFIG problem?\n"); + + sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS, + 0xfffffffful); + } /* If error bit is stuck on ignore it */ if (sky2_read32(hw, B0_HWE_ISRC) & Y2_IS_PCI_EXP) |