diff options
author | Wendy Xiong <wendyx@us.ibm.com> | 2008-05-17 01:18:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-05-17 01:18:21 -0400 |
commit | 6ff2da49c8a68320c2564006c94a492db58de5cd (patch) | |
tree | 547db2972c71690e9ee48120b26f458e7417a3f1 /drivers/net/bnx2.c | |
parent | 9a120bc570627342c17befaa6af9b0a556dfda48 (diff) |
bnx2: Add EEH PCI recovery.
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>
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r-- | drivers/net/bnx2.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 934c2bfc464d..2589b99a8597 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -7119,6 +7119,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | |||
7119 | } | 7119 | } |
7120 | 7120 | ||
7121 | pci_set_master(pdev); | 7121 | pci_set_master(pdev); |
7122 | pci_save_state(pdev); | ||
7122 | 7123 | ||
7123 | bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); | 7124 | bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); |
7124 | if (bp->pm_cap == 0) { | 7125 | if (bp->pm_cap == 0) { |
@@ -7628,6 +7629,92 @@ bnx2_resume(struct pci_dev *pdev) | |||
7628 | return 0; | 7629 | return 0; |
7629 | } | 7630 | } |
7630 | 7631 | ||
7632 | /** | ||
7633 | * bnx2_io_error_detected - called when PCI error is detected | ||
7634 | * @pdev: Pointer to PCI device | ||
7635 | * @state: The current pci connection state | ||
7636 | * | ||
7637 | * This function is called after a PCI bus error affecting | ||
7638 | * this device has been detected. | ||
7639 | */ | ||
7640 | static pci_ers_result_t bnx2_io_error_detected(struct pci_dev *pdev, | ||
7641 | pci_channel_state_t state) | ||
7642 | { | ||
7643 | struct net_device *dev = pci_get_drvdata(pdev); | ||
7644 | struct bnx2 *bp = netdev_priv(dev); | ||
7645 | |||
7646 | rtnl_lock(); | ||
7647 | netif_device_detach(dev); | ||
7648 | |||
7649 | if (netif_running(dev)) { | ||
7650 | bnx2_netif_stop(bp); | ||
7651 | del_timer_sync(&bp->timer); | ||
7652 | bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET); | ||
7653 | } | ||
7654 | |||
7655 | pci_disable_device(pdev); | ||
7656 | rtnl_unlock(); | ||
7657 | |||
7658 | /* Request a slot slot reset. */ | ||
7659 | return PCI_ERS_RESULT_NEED_RESET; | ||
7660 | } | ||
7661 | |||
7662 | /** | ||
7663 | * bnx2_io_slot_reset - called after the pci bus has been reset. | ||
7664 | * @pdev: Pointer to PCI device | ||
7665 | * | ||
7666 | * Restart the card from scratch, as if from a cold-boot. | ||
7667 | */ | ||
7668 | static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev) | ||
7669 | { | ||
7670 | struct net_device *dev = pci_get_drvdata(pdev); | ||
7671 | struct bnx2 *bp = netdev_priv(dev); | ||
7672 | |||
7673 | rtnl_lock(); | ||
7674 | if (pci_enable_device(pdev)) { | ||
7675 | dev_err(&pdev->dev, | ||
7676 | "Cannot re-enable PCI device after reset.\n"); | ||
7677 | rtnl_unlock(); | ||
7678 | return PCI_ERS_RESULT_DISCONNECT; | ||
7679 | } | ||
7680 | pci_set_master(pdev); | ||
7681 | pci_restore_state(pdev); | ||
7682 | |||
7683 | if (netif_running(dev)) { | ||
7684 | bnx2_set_power_state(bp, PCI_D0); | ||
7685 | bnx2_init_nic(bp, 1); | ||
7686 | } | ||
7687 | |||
7688 | rtnl_unlock(); | ||
7689 | return PCI_ERS_RESULT_RECOVERED; | ||
7690 | } | ||
7691 | |||
7692 | /** | ||
7693 | * bnx2_io_resume - called when traffic can start flowing again. | ||
7694 | * @pdev: Pointer to PCI device | ||
7695 | * | ||
7696 | * This callback is called when the error recovery driver tells us that | ||
7697 | * its OK to resume normal operation. | ||
7698 | */ | ||
7699 | static void bnx2_io_resume(struct pci_dev *pdev) | ||
7700 | { | ||
7701 | struct net_device *dev = pci_get_drvdata(pdev); | ||
7702 | struct bnx2 *bp = netdev_priv(dev); | ||
7703 | |||
7704 | rtnl_lock(); | ||
7705 | if (netif_running(dev)) | ||
7706 | bnx2_netif_start(bp); | ||
7707 | |||
7708 | netif_device_attach(dev); | ||
7709 | rtnl_unlock(); | ||
7710 | } | ||
7711 | |||
7712 | static struct pci_error_handlers bnx2_err_handler = { | ||
7713 | .error_detected = bnx2_io_error_detected, | ||
7714 | .slot_reset = bnx2_io_slot_reset, | ||
7715 | .resume = bnx2_io_resume, | ||
7716 | }; | ||
7717 | |||
7631 | static struct pci_driver bnx2_pci_driver = { | 7718 | static struct pci_driver bnx2_pci_driver = { |
7632 | .name = DRV_MODULE_NAME, | 7719 | .name = DRV_MODULE_NAME, |
7633 | .id_table = bnx2_pci_tbl, | 7720 | .id_table = bnx2_pci_tbl, |
@@ -7635,6 +7722,7 @@ static struct pci_driver bnx2_pci_driver = { | |||
7635 | .remove = __devexit_p(bnx2_remove_one), | 7722 | .remove = __devexit_p(bnx2_remove_one), |
7636 | .suspend = bnx2_suspend, | 7723 | .suspend = bnx2_suspend, |
7637 | .resume = bnx2_resume, | 7724 | .resume = bnx2_resume, |
7725 | .err_handler = &bnx2_err_handler, | ||
7638 | }; | 7726 | }; |
7639 | 7727 | ||
7640 | static int __init bnx2_init(void) | 7728 | static int __init bnx2_init(void) |