|
@@ -31,6 +31,7 @@
|
|
#include <linux/etherdevice.h>
|
|
#include <linux/etherdevice.h>
|
|
#include <linux/ethtool.h>
|
|
#include <linux/ethtool.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/pci.h>
|
|
|
|
+#include <linux/aer.h>
|
|
#include <linux/ip.h>
|
|
#include <linux/ip.h>
|
|
#include <net/ip.h>
|
|
#include <net/ip.h>
|
|
#include <linux/tcp.h>
|
|
#include <linux/tcp.h>
|
|
@@ -2421,7 +2422,11 @@ static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status)
|
|
|
|
|
|
static void sky2_hw_intr(struct sky2_hw *hw)
|
|
static void sky2_hw_intr(struct sky2_hw *hw)
|
|
{
|
|
{
|
|
|
|
+ struct pci_dev *pdev = hw->pdev;
|
|
u32 status = sky2_read32(hw, B0_HWE_ISRC);
|
|
u32 status = sky2_read32(hw, B0_HWE_ISRC);
|
|
|
|
+ u32 hwmsk = sky2_read32(hw, B0_HWE_IMSK);
|
|
|
|
+
|
|
|
|
+ status &= hwmsk;
|
|
|
|
|
|
if (status & Y2_IS_TIST_OV)
|
|
if (status & Y2_IS_TIST_OV)
|
|
sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
|
|
sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
|
|
@@ -2431,7 +2436,7 @@ static void sky2_hw_intr(struct sky2_hw *hw)
|
|
|
|
|
|
pci_err = sky2_pci_read16(hw, PCI_STATUS);
|
|
pci_err = sky2_pci_read16(hw, PCI_STATUS);
|
|
if (net_ratelimit())
|
|
if (net_ratelimit())
|
|
- dev_err(&hw->pdev->dev, "PCI hardware error (0x%x)\n",
|
|
|
|
|
|
+ dev_err(&pdev->dev, "PCI hardware error (0x%x)\n",
|
|
pci_err);
|
|
pci_err);
|
|
|
|
|
|
sky2_pci_write16(hw, PCI_STATUS,
|
|
sky2_pci_write16(hw, PCI_STATUS,
|
|
@@ -2440,22 +2445,13 @@ static void sky2_hw_intr(struct sky2_hw *hw)
|
|
|
|
|
|
if (status & Y2_IS_PCI_EXP) {
|
|
if (status & Y2_IS_PCI_EXP) {
|
|
/* PCI-Express uncorrectable Error occurred */
|
|
/* PCI-Express uncorrectable Error occurred */
|
|
- u32 pex_err;
|
|
|
|
-
|
|
|
|
- pex_err = sky2_pci_read32(hw, PEX_UNC_ERR_STAT);
|
|
|
|
|
|
+ int pos = pci_find_aer_capability(hw->pdev);
|
|
|
|
+ u32 err;
|
|
|
|
|
|
|
|
+ pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_STATUS, &err);
|
|
if (net_ratelimit())
|
|
if (net_ratelimit())
|
|
- dev_err(&hw->pdev->dev, "PCI Express error (0x%x)\n",
|
|
|
|
- pex_err);
|
|
|
|
-
|
|
|
|
- /* clear the interrupt */
|
|
|
|
- sky2_pci_write32(hw, PEX_UNC_ERR_STAT,
|
|
|
|
- 0xffffffffUL);
|
|
|
|
- if (pex_err & PEX_FATAL_ERRORS) {
|
|
|
|
- u32 hwmsk = sky2_read32(hw, B0_HWE_IMSK);
|
|
|
|
- hwmsk &= ~Y2_IS_PCI_EXP;
|
|
|
|
- sky2_write32(hw, B0_HWE_IMSK, hwmsk);
|
|
|
|
- }
|
|
|
|
|
|
+ dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err);
|
|
|
|
+ pci_cleanup_aer_uncorrect_error_status(pdev);
|
|
}
|
|
}
|
|
|
|
|
|
if (status & Y2_HWE_L1_MASK)
|
|
if (status & Y2_HWE_L1_MASK)
|
|
@@ -2775,8 +2771,10 @@ static int __devinit sky2_init(struct sky2_hw *hw)
|
|
|
|
|
|
static void sky2_reset(struct sky2_hw *hw)
|
|
static void sky2_reset(struct sky2_hw *hw)
|
|
{
|
|
{
|
|
|
|
+ struct pci_dev *pdev = hw->pdev;
|
|
u16 status;
|
|
u16 status;
|
|
- int i;
|
|
|
|
|
|
+ int i, cap;
|
|
|
|
+ u32 hwe_mask = Y2_HWE_ALL_MASK;
|
|
|
|
|
|
/* disable ASF */
|
|
/* disable ASF */
|
|
if (hw->chip_id == CHIP_ID_YUKON_EX) {
|
|
if (hw->chip_id == CHIP_ID_YUKON_EX) {
|
|
@@ -2800,10 +2798,19 @@ static void sky2_reset(struct sky2_hw *hw)
|
|
|
|
|
|
sky2_write8(hw, B0_CTST, CS_MRST_CLR);
|
|
sky2_write8(hw, B0_CTST, CS_MRST_CLR);
|
|
|
|
|
|
- /* clear any PEX errors */
|
|
|
|
- if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP))
|
|
|
|
- sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL);
|
|
|
|
|
|
+ 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 error bit is stuck on ignore it */
|
|
|
|
+ if (sky2_read32(hw, B0_HWE_ISRC) & Y2_IS_PCI_EXP)
|
|
|
|
+ dev_info(&pdev->dev, "ignoring stuck error report bit\n");
|
|
|
|
+
|
|
|
|
+ else if (pci_enable_pcie_error_reporting(pdev))
|
|
|
|
+ hwe_mask |= Y2_IS_PCI_EXP;
|
|
|
|
+ }
|
|
|
|
|
|
sky2_power_on(hw);
|
|
sky2_power_on(hw);
|
|
|
|
|
|
@@ -2855,7 +2862,7 @@ static void sky2_reset(struct sky2_hw *hw)
|
|
sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS2), SK_RI_TO_53);
|
|
sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS2), SK_RI_TO_53);
|
|
}
|
|
}
|
|
|
|
|
|
- sky2_write32(hw, B0_HWE_IMSK, Y2_HWE_ALL_MASK);
|
|
|
|
|
|
+ sky2_write32(hw, B0_HWE_IMSK, hwe_mask);
|
|
|
|
|
|
for (i = 0; i < hw->ports; i++)
|
|
for (i = 0; i < hw->ports; i++)
|
|
sky2_gmac_reset(hw, i);
|
|
sky2_gmac_reset(hw, i);
|