Commit f3c9e9b1 authored by Gavin Shan's avatar Gavin Shan Committed by Jiri Slaby

net/qlge: Avoids recursive EEH error

commit 3275c0c6 upstream.

One timer, whose handler keeps reading on MMIO register for EEH
core to detect error in time, is started when the PCI device driver
is loaded. MMIO register can't be accessed during PE reset in EEH
recovery. Otherwise, the unexpected recursive error is triggered.
The timer isn't closed that time if the interface isn't brought
up. So the unexpected recursive error is seen during EEH recovery
when the interface is down.

This avoids the unexpected recursive EEH error by closing the timer
in qlge_io_error_detected() before EEH PE reset unconditionally. The
timer is started unconditionally after EEH PE reset in qlge_io_resume().
Also, the timer should be closed unconditionally when the device is
removed from the system permanently in qlge_io_error_detected().
Reported-by: default avatarShriya R. Kulkarni <shriyakul@in.ibm.com>
Signed-off-by: default avatarGavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
parent bdb8bc5f
...@@ -4780,7 +4780,6 @@ static void ql_eeh_close(struct net_device *ndev) ...@@ -4780,7 +4780,6 @@ static void ql_eeh_close(struct net_device *ndev)
} }
/* Disabling the timer */ /* Disabling the timer */
del_timer_sync(&qdev->timer);
ql_cancel_all_work_sync(qdev); ql_cancel_all_work_sync(qdev);
for (i = 0; i < qdev->rss_ring_count; i++) for (i = 0; i < qdev->rss_ring_count; i++)
...@@ -4807,6 +4806,7 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev, ...@@ -4807,6 +4806,7 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev,
return PCI_ERS_RESULT_CAN_RECOVER; return PCI_ERS_RESULT_CAN_RECOVER;
case pci_channel_io_frozen: case pci_channel_io_frozen:
netif_device_detach(ndev); netif_device_detach(ndev);
del_timer_sync(&qdev->timer);
if (netif_running(ndev)) if (netif_running(ndev))
ql_eeh_close(ndev); ql_eeh_close(ndev);
pci_disable_device(pdev); pci_disable_device(pdev);
...@@ -4814,6 +4814,7 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev, ...@@ -4814,6 +4814,7 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev,
case pci_channel_io_perm_failure: case pci_channel_io_perm_failure:
dev_err(&pdev->dev, dev_err(&pdev->dev,
"%s: pci_channel_io_perm_failure.\n", __func__); "%s: pci_channel_io_perm_failure.\n", __func__);
del_timer_sync(&qdev->timer);
ql_eeh_close(ndev); ql_eeh_close(ndev);
set_bit(QL_EEH_FATAL, &qdev->flags); set_bit(QL_EEH_FATAL, &qdev->flags);
return PCI_ERS_RESULT_DISCONNECT; return PCI_ERS_RESULT_DISCONNECT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment