diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-11-05 18:52:13 -0500 |
---|---|---|
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) |
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 76038bbeb50e..a6ccd11574d0 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -2435,13 +2435,26 @@ static void sky2_hw_intr(struct sky2_hw *hw) | |||
2435 | 2435 | ||
2436 | if (status & Y2_IS_PCI_EXP) { | 2436 | if (status & Y2_IS_PCI_EXP) { |
2437 | /* PCI-Express uncorrectable Error occurred */ | 2437 | /* PCI-Express uncorrectable Error occurred */ |
2438 | int pos = pci_find_aer_capability(hw->pdev); | 2438 | int aer = pci_find_aer_capability(hw->pdev); |
2439 | u32 err; | 2439 | u32 err; |
2440 | 2440 | ||
2441 | pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_STATUS, &err); | 2441 | if (aer) { |
2442 | pci_read_config_dword(pdev, aer + PCI_ERR_UNCOR_STATUS, | ||
2443 | &err); | ||
2444 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
2445 | } else { | ||
2446 | /* Either AER not configured, or not working | ||
2447 | * because of bad MMCONFIG, so just do recover | ||
2448 | * manually. | ||
2449 | */ | ||
2450 | err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS); | ||
2451 | sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS, | ||
2452 | 0xfffffffful); | ||
2453 | } | ||
2454 | |||
2442 | if (net_ratelimit()) | 2455 | if (net_ratelimit()) |
2443 | dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err); | 2456 | dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err); |
2444 | pci_cleanup_aer_uncorrect_error_status(pdev); | 2457 | |
2445 | } | 2458 | } |
2446 | 2459 | ||
2447 | if (status & Y2_HWE_L1_MASK) | 2460 | if (status & Y2_HWE_L1_MASK) |
@@ -2799,9 +2812,18 @@ static void sky2_reset(struct sky2_hw *hw) | |||
2799 | 2812 | ||
2800 | cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); | 2813 | cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); |
2801 | if (cap) { | 2814 | if (cap) { |
2802 | /* Check for advanced error reporting */ | 2815 | if (pci_find_aer_capability(pdev)) { |
2803 | pci_cleanup_aer_uncorrect_error_status(pdev); | 2816 | /* Check for advanced error reporting */ |
2804 | pci_cleanup_aer_correct_error_status(pdev); | 2817 | pci_cleanup_aer_uncorrect_error_status(pdev); |
2818 | pci_cleanup_aer_correct_error_status(pdev); | ||
2819 | } else { | ||
2820 | dev_warn(&pdev->dev, | ||
2821 | "PCI Express Advanced Error Reporting" | ||
2822 | " not configured or MMCONFIG problem?\n"); | ||
2823 | |||
2824 | sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS, | ||
2825 | 0xfffffffful); | ||
2826 | } | ||
2805 | 2827 | ||
2806 | /* If error bit is stuck on ignore it */ | 2828 | /* If error bit is stuck on ignore it */ |
2807 | if (sky2_read32(hw, B0_HWE_ISRC) & Y2_IS_PCI_EXP) | 2829 | if (sky2_read32(hw, B0_HWE_ISRC) & Y2_IS_PCI_EXP) |