mirror of https://gitee.com/openkylin/linux.git
ice: Implement pci_error_handler ops
This patch implements the following pci_error_handler ops: .error_detected = ice_pci_err_detected .slot_reset = ice_pci_err_slot_reset .reset_notify = ice_pci_err_reset_notify .reset_prepare = ice_pci_err_reset_prepare .reset_done = ice_pci_err_reset_done .resume = ice_pci_err_resume Signed-off-by: Brett Creeley <brett.creeley@intel.com> Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
5abac9d7e1
commit
5995b6d0c6
|
@ -1004,6 +1004,18 @@ static void ice_service_task_stop(struct ice_pf *pf)
|
|||
clear_bit(__ICE_SERVICE_SCHED, pf->state);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_service_task_restart - restart service task and schedule works
|
||||
* @pf: board private structure
|
||||
*
|
||||
* This function is needed for suspend and resume works (e.g WoL scenario)
|
||||
*/
|
||||
static void ice_service_task_restart(struct ice_pf *pf)
|
||||
{
|
||||
clear_bit(__ICE_SERVICE_DIS, pf->state);
|
||||
ice_service_task_schedule(pf);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_service_timer - timer callback to schedule service task
|
||||
* @t: pointer to timer_list
|
||||
|
@ -2395,6 +2407,136 @@ static void ice_remove(struct pci_dev *pdev)
|
|||
pci_disable_pcie_error_reporting(pdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_pci_err_detected - warning that PCI error has been detected
|
||||
* @pdev: PCI device information struct
|
||||
* @err: the type of PCI error
|
||||
*
|
||||
* Called to warn that something happened on the PCI bus and the error handling
|
||||
* is in progress. Allows the driver to gracefully prepare/handle PCI errors.
|
||||
*/
|
||||
static pci_ers_result_t
|
||||
ice_pci_err_detected(struct pci_dev *pdev, enum pci_channel_state err)
|
||||
{
|
||||
struct ice_pf *pf = pci_get_drvdata(pdev);
|
||||
|
||||
if (!pf) {
|
||||
dev_err(&pdev->dev, "%s: unrecoverable device error %d\n",
|
||||
__func__, err);
|
||||
return PCI_ERS_RESULT_DISCONNECT;
|
||||
}
|
||||
|
||||
if (!test_bit(__ICE_SUSPENDED, pf->state)) {
|
||||
ice_service_task_stop(pf);
|
||||
|
||||
if (!test_bit(__ICE_PREPARED_FOR_RESET, pf->state)) {
|
||||
set_bit(__ICE_PFR_REQ, pf->state);
|
||||
ice_prepare_for_reset(pf);
|
||||
}
|
||||
}
|
||||
|
||||
return PCI_ERS_RESULT_NEED_RESET;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_pci_err_slot_reset - a PCI slot reset has just happened
|
||||
* @pdev: PCI device information struct
|
||||
*
|
||||
* Called to determine if the driver can recover from the PCI slot reset by
|
||||
* using a register read to determine if the device is recoverable.
|
||||
*/
|
||||
static pci_ers_result_t ice_pci_err_slot_reset(struct pci_dev *pdev)
|
||||
{
|
||||
struct ice_pf *pf = pci_get_drvdata(pdev);
|
||||
pci_ers_result_t result;
|
||||
int err;
|
||||
u32 reg;
|
||||
|
||||
err = pci_enable_device_mem(pdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot re-enable PCI device after reset, error %d\n",
|
||||
err);
|
||||
result = PCI_ERS_RESULT_DISCONNECT;
|
||||
} else {
|
||||
pci_set_master(pdev);
|
||||
pci_restore_state(pdev);
|
||||
pci_save_state(pdev);
|
||||
pci_wake_from_d3(pdev, false);
|
||||
|
||||
/* Check for life */
|
||||
reg = rd32(&pf->hw, GLGEN_RTRIG);
|
||||
if (!reg)
|
||||
result = PCI_ERS_RESULT_RECOVERED;
|
||||
else
|
||||
result = PCI_ERS_RESULT_DISCONNECT;
|
||||
}
|
||||
|
||||
err = pci_cleanup_aer_uncorrect_error_status(pdev);
|
||||
if (err)
|
||||
dev_dbg(&pdev->dev,
|
||||
"pci_cleanup_aer_uncorrect_error_status failed, error %d\n",
|
||||
err);
|
||||
/* non-fatal, continue */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_pci_err_resume - restart operations after PCI error recovery
|
||||
* @pdev: PCI device information struct
|
||||
*
|
||||
* Called to allow the driver to bring things back up after PCI error and/or
|
||||
* reset recovery have finished
|
||||
*/
|
||||
static void ice_pci_err_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct ice_pf *pf = pci_get_drvdata(pdev);
|
||||
|
||||
if (!pf) {
|
||||
dev_err(&pdev->dev,
|
||||
"%s failed, device is unrecoverable\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (test_bit(__ICE_SUSPENDED, pf->state)) {
|
||||
dev_dbg(&pdev->dev, "%s failed to resume normal operations!\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ice_do_reset(pf, ICE_RESET_PFR);
|
||||
ice_service_task_restart(pf);
|
||||
mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period));
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_pci_err_reset_prepare - prepare device driver for PCI reset
|
||||
* @pdev: PCI device information struct
|
||||
*/
|
||||
static void ice_pci_err_reset_prepare(struct pci_dev *pdev)
|
||||
{
|
||||
struct ice_pf *pf = pci_get_drvdata(pdev);
|
||||
|
||||
if (!test_bit(__ICE_SUSPENDED, pf->state)) {
|
||||
ice_service_task_stop(pf);
|
||||
|
||||
if (!test_bit(__ICE_PREPARED_FOR_RESET, pf->state)) {
|
||||
set_bit(__ICE_PFR_REQ, pf->state);
|
||||
ice_prepare_for_reset(pf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_pci_err_reset_done - PCI reset done, device driver reset can begin
|
||||
* @pdev: PCI device information struct
|
||||
*/
|
||||
static void ice_pci_err_reset_done(struct pci_dev *pdev)
|
||||
{
|
||||
ice_pci_err_resume(pdev);
|
||||
}
|
||||
|
||||
/* ice_pci_tbl - PCI Device ID Table
|
||||
*
|
||||
* Wildcard entries (PCI_ANY_ID) should come last
|
||||
|
@ -2412,12 +2554,21 @@ static const struct pci_device_id ice_pci_tbl[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(pci, ice_pci_tbl);
|
||||
|
||||
static const struct pci_error_handlers ice_pci_err_handler = {
|
||||
.error_detected = ice_pci_err_detected,
|
||||
.slot_reset = ice_pci_err_slot_reset,
|
||||
.reset_prepare = ice_pci_err_reset_prepare,
|
||||
.reset_done = ice_pci_err_reset_done,
|
||||
.resume = ice_pci_err_resume
|
||||
};
|
||||
|
||||
static struct pci_driver ice_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = ice_pci_tbl,
|
||||
.probe = ice_probe,
|
||||
.remove = ice_remove,
|
||||
.sriov_configure = ice_sriov_configure,
|
||||
.err_handler = &ice_pci_err_handler
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue