From 21ea21252eddb3cea56845f58f87208062799bef Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Mon, 29 Jun 2020 14:35:41 +0100 Subject: [PATCH] sfc: commonise PCI error handlers EF100 will use the same mechanisms for PCI error recovery. Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/efx.c | 91 ----------------------------------- drivers/net/ethernet/sfc/efx_common.c | 91 +++++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/efx_common.h | 1 + 3 files changed, 92 insertions(+), 91 deletions(-) diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 86639b1..4c2d305 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1490,97 +1490,6 @@ static const struct dev_pm_ops efx_pm_ops = { .restore = efx_pm_resume, }; -/* A PCI error affecting this device was detected. - * At this point MMIO and DMA may be disabled. - * Stop the software path and request a slot reset. - */ -static pci_ers_result_t efx_io_error_detected(struct pci_dev *pdev, - enum pci_channel_state state) -{ - pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED; - struct efx_nic *efx = pci_get_drvdata(pdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - rtnl_lock(); - - if (efx->state != STATE_DISABLED) { - efx->state = STATE_RECOVERY; - efx->reset_pending = 0; - - efx_device_detach_sync(efx); - - efx_stop_all(efx); - efx_disable_interrupts(efx); - - status = PCI_ERS_RESULT_NEED_RESET; - } else { - /* If the interface is disabled we don't want to do anything - * with it. - */ - status = PCI_ERS_RESULT_RECOVERED; - } - - rtnl_unlock(); - - pci_disable_device(pdev); - - return status; -} - -/* Fake a successful reset, which will be performed later in efx_io_resume. */ -static pci_ers_result_t efx_io_slot_reset(struct pci_dev *pdev) -{ - struct efx_nic *efx = pci_get_drvdata(pdev); - pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED; - - if (pci_enable_device(pdev)) { - netif_err(efx, hw, efx->net_dev, - "Cannot re-enable PCI device after reset.\n"); - status = PCI_ERS_RESULT_DISCONNECT; - } - - return status; -} - -/* Perform the actual reset and resume I/O operations. */ -static void efx_io_resume(struct pci_dev *pdev) -{ - struct efx_nic *efx = pci_get_drvdata(pdev); - int rc; - - rtnl_lock(); - - if (efx->state == STATE_DISABLED) - goto out; - - rc = efx_reset(efx, RESET_TYPE_ALL); - if (rc) { - netif_err(efx, hw, efx->net_dev, - "efx_reset failed after PCI error (%d)\n", rc); - } else { - efx->state = STATE_READY; - netif_dbg(efx, hw, efx->net_dev, - "Done resetting and resuming IO after PCI error.\n"); - } - -out: - rtnl_unlock(); -} - -/* For simplicity and reliability, we always require a slot reset and try to - * reset the hardware when a pci error affecting the device is detected. - * We leave both the link_reset and mmio_enabled callback unimplemented: - * with our request for slot reset the mmio_enabled callback will never be - * called, and the link_reset callback is not used by AER or EEH mechanisms. - */ -static const struct pci_error_handlers efx_err_handlers = { - .error_detected = efx_io_error_detected, - .slot_reset = efx_io_slot_reset, - .resume = efx_io_resume, -}; - static struct pci_driver efx_pci_driver = { .name = KBUILD_MODNAME, .id_table = efx_pci_table, diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index 36c0ab5..88ade7f 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -1130,3 +1130,94 @@ void efx_fini_mcdi_logging(struct efx_nic *efx) device_remove_file(&efx->pci_dev->dev, &dev_attr_mcdi_logging); } #endif + +/* A PCI error affecting this device was detected. + * At this point MMIO and DMA may be disabled. + * Stop the software path and request a slot reset. + */ +static pci_ers_result_t efx_io_error_detected(struct pci_dev *pdev, + enum pci_channel_state state) +{ + pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED; + struct efx_nic *efx = pci_get_drvdata(pdev); + + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + + rtnl_lock(); + + if (efx->state != STATE_DISABLED) { + efx->state = STATE_RECOVERY; + efx->reset_pending = 0; + + efx_device_detach_sync(efx); + + efx_stop_all(efx); + efx_disable_interrupts(efx); + + status = PCI_ERS_RESULT_NEED_RESET; + } else { + /* If the interface is disabled we don't want to do anything + * with it. + */ + status = PCI_ERS_RESULT_RECOVERED; + } + + rtnl_unlock(); + + pci_disable_device(pdev); + + return status; +} + +/* Fake a successful reset, which will be performed later in efx_io_resume. */ +static pci_ers_result_t efx_io_slot_reset(struct pci_dev *pdev) +{ + struct efx_nic *efx = pci_get_drvdata(pdev); + pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED; + + if (pci_enable_device(pdev)) { + netif_err(efx, hw, efx->net_dev, + "Cannot re-enable PCI device after reset.\n"); + status = PCI_ERS_RESULT_DISCONNECT; + } + + return status; +} + +/* Perform the actual reset and resume I/O operations. */ +static void efx_io_resume(struct pci_dev *pdev) +{ + struct efx_nic *efx = pci_get_drvdata(pdev); + int rc; + + rtnl_lock(); + + if (efx->state == STATE_DISABLED) + goto out; + + rc = efx_reset(efx, RESET_TYPE_ALL); + if (rc) { + netif_err(efx, hw, efx->net_dev, + "efx_reset failed after PCI error (%d)\n", rc); + } else { + efx->state = STATE_READY; + netif_dbg(efx, hw, efx->net_dev, + "Done resetting and resuming IO after PCI error.\n"); + } + +out: + rtnl_unlock(); +} + +/* For simplicity and reliability, we always require a slot reset and try to + * reset the hardware when a pci error affecting the device is detected. + * We leave both the link_reset and mmio_enabled callback unimplemented: + * with our request for slot reset the mmio_enabled callback will never be + * called, and the link_reset callback is not used by AER or EEH mechanisms. + */ +const struct pci_error_handlers efx_err_handlers = { + .error_detected = efx_io_error_detected, + .slot_reset = efx_io_slot_reset, + .resume = efx_io_resume, +}; diff --git a/drivers/net/ethernet/sfc/efx_common.h b/drivers/net/ethernet/sfc/efx_common.h index 93a017aaf..68af2af 100644 --- a/drivers/net/ethernet/sfc/efx_common.h +++ b/drivers/net/ethernet/sfc/efx_common.h @@ -73,4 +73,5 @@ void efx_link_status_changed(struct efx_nic *efx); unsigned int efx_xdp_max_mtu(struct efx_nic *efx); int efx_change_mtu(struct net_device *net_dev, int new_mtu); +extern const struct pci_error_handlers efx_err_handlers; #endif -- 2.7.4