diff options
author | Ron Mercer <ron.mercer@qlogic.com> | 2010-02-03 02:24:12 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-03 23:06:03 -0500 |
commit | 4bbd1a1903639f826215d76af74f4901efc34daa (patch) | |
tree | d578f3ce4ec90708260a376db46cf769f998c890 /drivers/net/qlge | |
parent | a112fd4ce3ed965dfb8dc6791622cb4f25ba3619 (diff) |
qlge: Add check for eeh failure when closing device.
Fix crash where resources are freed twice on an eeh recovery failure.
If eeh recovery fails we set a flag to indicate to close() that
resources have been freed.
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/qlge')
-rw-r--r-- | drivers/net/qlge/qlge.h | 1 | ||||
-rw-r--r-- | drivers/net/qlge/qlge_main.c | 14 |
2 files changed, 15 insertions, 0 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 9169c4cf413a..780a38731bcc 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h | |||
@@ -2005,6 +2005,7 @@ enum { | |||
2005 | QL_SELFTEST = 9, | 2005 | QL_SELFTEST = 9, |
2006 | QL_LB_LINK_UP = 10, | 2006 | QL_LB_LINK_UP = 10, |
2007 | QL_FRC_COREDUMP = 11, | 2007 | QL_FRC_COREDUMP = 11, |
2008 | QL_EEH_FATAL = 12, | ||
2008 | }; | 2009 | }; |
2009 | 2010 | ||
2010 | /* link_status bit definitions */ | 2011 | /* link_status bit definitions */ |
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 87ec72064158..7e000295f359 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c | |||
@@ -3929,6 +3929,16 @@ static int qlge_close(struct net_device *ndev) | |||
3929 | { | 3929 | { |
3930 | struct ql_adapter *qdev = netdev_priv(ndev); | 3930 | struct ql_adapter *qdev = netdev_priv(ndev); |
3931 | 3931 | ||
3932 | /* If we hit pci_channel_io_perm_failure | ||
3933 | * failure condition, then we already | ||
3934 | * brought the adapter down. | ||
3935 | */ | ||
3936 | if (test_bit(QL_EEH_FATAL, &qdev->flags)) { | ||
3937 | QPRINTK(qdev, DRV, ERR, "EEH fatal did unload.\n"); | ||
3938 | clear_bit(QL_EEH_FATAL, &qdev->flags); | ||
3939 | return 0; | ||
3940 | } | ||
3941 | |||
3932 | /* | 3942 | /* |
3933 | * Wait for device to recover from a reset. | 3943 | * Wait for device to recover from a reset. |
3934 | * (Rarely happens, but possible.) | 3944 | * (Rarely happens, but possible.) |
@@ -4677,6 +4687,7 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev, | |||
4677 | enum pci_channel_state state) | 4687 | enum pci_channel_state state) |
4678 | { | 4688 | { |
4679 | struct net_device *ndev = pci_get_drvdata(pdev); | 4689 | struct net_device *ndev = pci_get_drvdata(pdev); |
4690 | struct ql_adapter *qdev = netdev_priv(ndev); | ||
4680 | 4691 | ||
4681 | switch (state) { | 4692 | switch (state) { |
4682 | case pci_channel_io_normal: | 4693 | case pci_channel_io_normal: |
@@ -4690,6 +4701,8 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev, | |||
4690 | case pci_channel_io_perm_failure: | 4701 | case pci_channel_io_perm_failure: |
4691 | dev_err(&pdev->dev, | 4702 | dev_err(&pdev->dev, |
4692 | "%s: pci_channel_io_perm_failure.\n", __func__); | 4703 | "%s: pci_channel_io_perm_failure.\n", __func__); |
4704 | ql_eeh_close(ndev); | ||
4705 | set_bit(QL_EEH_FATAL, &qdev->flags); | ||
4693 | return PCI_ERS_RESULT_DISCONNECT; | 4706 | return PCI_ERS_RESULT_DISCONNECT; |
4694 | } | 4707 | } |
4695 | 4708 | ||
@@ -4720,6 +4733,7 @@ static pci_ers_result_t qlge_io_slot_reset(struct pci_dev *pdev) | |||
4720 | 4733 | ||
4721 | if (ql_adapter_reset(qdev)) { | 4734 | if (ql_adapter_reset(qdev)) { |
4722 | QPRINTK(qdev, DRV, ERR, "reset FAILED!\n"); | 4735 | QPRINTK(qdev, DRV, ERR, "reset FAILED!\n"); |
4736 | set_bit(QL_EEH_FATAL, &qdev->flags); | ||
4723 | return PCI_ERS_RESULT_DISCONNECT; | 4737 | return PCI_ERS_RESULT_DISCONNECT; |
4724 | } | 4738 | } |
4725 | 4739 | ||