Skip to content

Commit

Permalink
bnx2: Add EEH PCI recovery.
Browse files Browse the repository at this point in the history
Add PCI recovery functions to the driver.  The initial pci state is
also saved so the the MSI state can be restored during PCI recovery.

Signed-off-by: Wendy Xiong <wendyx@us.ibm.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Wendy Xiong authored and David S. Miller committed May 17, 2008
1 parent 9a120bc commit 6ff2da4
Showing 1 changed file with 88 additions and 0 deletions.
88 changes: 88 additions & 0 deletions drivers/net/bnx2.c
Original file line number Diff line number Diff line change
Expand Up @@ -7119,6 +7119,7 @@ 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) {
Expand Down Expand Up @@ -7628,13 +7629,100 @@ bnx2_resume(struct pci_dev *pdev)
return 0;
}

/**
* bnx2_io_error_detected - called when PCI error is detected
* @pdev: Pointer to PCI device
* @state: The current pci connection state
*
* This function is called after a PCI bus error affecting
* this device has been detected.
*/
static pci_ers_result_t bnx2_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct bnx2 *bp = netdev_priv(dev);

rtnl_lock();
netif_device_detach(dev);

if (netif_running(dev)) {
bnx2_netif_stop(bp);
del_timer_sync(&bp->timer);
bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET);
}

pci_disable_device(pdev);
rtnl_unlock();

/* Request a slot slot reset. */
return PCI_ERS_RESULT_NEED_RESET;
}

/**
* bnx2_io_slot_reset - called after the pci bus has been reset.
* @pdev: Pointer to PCI device
*
* Restart the card from scratch, as if from a cold-boot.
*/
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);

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;
}
pci_set_master(pdev);
pci_restore_state(pdev);

if (netif_running(dev)) {
bnx2_set_power_state(bp, PCI_D0);
bnx2_init_nic(bp, 1);
}

rtnl_unlock();
return PCI_ERS_RESULT_RECOVERED;
}

/**
* bnx2_io_resume - called when traffic can start flowing again.
* @pdev: Pointer to PCI device
*
* This callback is called when the error recovery driver tells us that
* its OK to resume normal operation.
*/
static void bnx2_io_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct bnx2 *bp = netdev_priv(dev);

rtnl_lock();
if (netif_running(dev))
bnx2_netif_start(bp);

netif_device_attach(dev);
rtnl_unlock();
}

static struct pci_error_handlers bnx2_err_handler = {
.error_detected = bnx2_io_error_detected,
.slot_reset = bnx2_io_slot_reset,
.resume = bnx2_io_resume,
};

static struct pci_driver bnx2_pci_driver = {
.name = DRV_MODULE_NAME,
.id_table = bnx2_pci_tbl,
.probe = bnx2_init_one,
.remove = __devexit_p(bnx2_remove_one),
.suspend = bnx2_suspend,
.resume = bnx2_resume,
.err_handler = &bnx2_err_handler,
};

static int __init bnx2_init(void)
Expand Down

0 comments on commit 6ff2da4

Please sign in to comment.