From: John Feeney <jfeeney@redhat.com> Date: Fri, 22 Oct 2010 15:21:29 -0400 Subject: [net] bnx2: add AER support Message-id: <4CC1ABF9.7090609@redhat.com> Patchwork-id: 28899 O-Subject: [RHEL5.6 PATCH] Add AER support to bnx2 Bugzilla: 617024 RH-Acked-by: Prarit Bhargava <prarit@redhat.com> RH-Acked-by: Don Dutile <ddutile@redhat.com> bz617024 https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=617024 Add AER support to bnx2 Description of problem: The bnx2 driver was missing the support for AER (Advanced Error Reporting). Solution: This patch adds this support. Upstream commits: bnx2: Add PCI Advanced Error Reporting support. cd709aa90648195e5b5823fa90eb0b3fb0e78ee4 bnx2: Enable AER on PCIE devices only c239f279e571a272c1b32a1e84b8fa037b68f49c Note: This patch bumped the version number of the bnx2 driver but since most of the patches that constitute this version are not yet in rhel5, I did not bump the bnx2 number. Brew: Successfully built in Brew for all architectures. Testing: HP wants this and so they successfully tested it. Thanks HP. Acks would be appreciated. Thanks. Signed-off-by: Jarod Wilson <jarod@redhat.com> diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 865b525..b465db4 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -47,6 +47,7 @@ #include <linux/prefetch.h> #include <linux/cache.h> #include <linux/zlib.h> +#include <linux/aer.h> #if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE) #define BCM_CNIC 1 @@ -7938,6 +7939,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) int rc, i, j; u32 reg; u64 dma_mask, persist_dma_mask; + int err; SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); @@ -7975,7 +7977,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) } pci_set_master(pdev); - pci_save_state(pdev); bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); if (bp->pm_cap == 0) { @@ -8030,6 +8031,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->flags |= BNX2_FLAG_PCIE; if (CHIP_REV(bp) == CHIP_REV_Ax) bp->flags |= BNX2_FLAG_JUMBO_BROKEN; + + /* AER (Advanced Error Reporting) hooks */ + err = pci_enable_pcie_error_reporting(pdev); + if (err) { + dev_err(&pdev->dev, "pci_enable_pcie_error_reporting " + "failed 0x%x\n", err); + /* non-fatal, continue */ + } + } else { bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX); if (bp->pcix_cap == 0) { @@ -8288,9 +8298,14 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->timer.data = (unsigned long) bp; bp->timer.function = bnx2_timer; + pci_save_state(pdev); + return 0; err_out_unmap: + if (bp->flags & BNX2_FLAG_PCIE) + pci_disable_pcie_error_reporting(pdev); + if (bp->regview) { iounmap(bp->regview); bp->regview = NULL; @@ -8481,7 +8496,11 @@ bnx2_remove_one(struct pci_dev *pdev) kfree(bp->temp_stats_blk); + if (bp->flags & BNX2_FLAG_PCIE) + pci_disable_pcie_error_reporting(pdev); + free_netdev(dev); + pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); @@ -8573,25 +8592,38 @@ static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct bnx2 *bp = netdev_priv(dev); + pci_ers_result_t result; + int err; rtnl_lock(); if (pci_enable_device(pdev)) { dev_err(&pdev->dev, "Cannot re-enable PCI device after reset.\n"); - rtnl_unlock(); - return PCI_ERS_RESULT_DISCONNECT; + result = PCI_ERS_RESULT_DISCONNECT; + } else { + pci_set_master(pdev); + pci_restore_state(pdev); + pci_save_state(pdev); + + if (netif_running(dev)) { + bnx2_set_power_state(bp, PCI_D0); + bnx2_init_nic(bp, 1); + } + result = PCI_ERS_RESULT_RECOVERED; } - pci_set_master(pdev); - pci_restore_state(pdev); - pci_save_state(pdev); + rtnl_unlock(); - if (netif_running(dev)) { - bnx2_set_power_state(bp, PCI_D0); - bnx2_init_nic(bp, 1); + if (!(bp->flags & BNX2_FLAG_PCIE)) + return result; + + err = pci_cleanup_aer_uncorrect_error_status(pdev); + if (err) { + dev_err(&pdev->dev, + "pci_cleanup_aer_uncorrect_error_status failed 0x%0x\n", + err); /* non-fatal, continue */ } - rtnl_unlock(); - return PCI_ERS_RESULT_RECOVERED; + return result; } /**