diff options
author | Ron Mercer <ron.mercer@qlogic.com> | 2010-02-03 08:24:12 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-04 05:06:03 +0100 |
commit | 4bbd1a1903639f826215d76af74f4901efc34daa (patch) | |
tree | d578f3ce4ec90708260a376db46cf769f998c890 /drivers/net/qlge/qlge_main.c | |
parent | qlge: Move reset from eeh io_resume to slot_reset. (diff) | |
download | linux-4bbd1a1903639f826215d76af74f4901efc34daa.tar.xz linux-4bbd1a1903639f826215d76af74f4901efc34daa.zip |
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/qlge_main.c')
-rw-r--r-- | drivers/net/qlge/qlge_main.c | 14 |
1 files changed, 14 insertions, 0 deletions
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) { struct ql_adapter *qdev = netdev_priv(ndev); + /* If we hit pci_channel_io_perm_failure + * failure condition, then we already + * brought the adapter down. + */ + if (test_bit(QL_EEH_FATAL, &qdev->flags)) { + QPRINTK(qdev, DRV, ERR, "EEH fatal did unload.\n"); + clear_bit(QL_EEH_FATAL, &qdev->flags); + return 0; + } + /* * Wait for device to recover from a reset. * (Rarely happens, but possible.) @@ -4677,6 +4687,7 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev, enum pci_channel_state state) { struct net_device *ndev = pci_get_drvdata(pdev); + struct ql_adapter *qdev = netdev_priv(ndev); switch (state) { case pci_channel_io_normal: @@ -4690,6 +4701,8 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev, case pci_channel_io_perm_failure: dev_err(&pdev->dev, "%s: pci_channel_io_perm_failure.\n", __func__); + ql_eeh_close(ndev); + set_bit(QL_EEH_FATAL, &qdev->flags); return PCI_ERS_RESULT_DISCONNECT; } @@ -4720,6 +4733,7 @@ static pci_ers_result_t qlge_io_slot_reset(struct pci_dev *pdev) if (ql_adapter_reset(qdev)) { QPRINTK(qdev, DRV, ERR, "reset FAILED!\n"); + set_bit(QL_EEH_FATAL, &qdev->flags); return PCI_ERS_RESULT_DISCONNECT; } |