From: Saurav Kashyap <skashyap@xxxxxxxxxxx> If we receive a fan failure message from qed, disable the PCI function. Initiate recovery for errors like ramrod failure Signed-off-by: Javed Hasan <jhasan@xxxxxxxxxxx> --- drivers/scsi/qedf/qedf.h | 4 ++++ drivers/scsi/qedf/qedf_main.c | 45 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h index 15d6cbe..0e2cbb1 100644 --- a/drivers/scsi/qedf/qedf.h +++ b/drivers/scsi/qedf/qedf.h @@ -389,6 +389,7 @@ struct qedf_ctx { mempool_t *io_mempool; struct workqueue_struct *dpc_wq; struct delayed_work recovery_work; + struct delayed_work board_disable_work; struct delayed_work grcdump_work; struct delayed_work stag_work; @@ -541,6 +542,9 @@ extern void qedf_process_seq_cleanup_compl(struct qedf_ctx *qedf, extern void qedf_wq_grcdump(struct work_struct *work); void qedf_stag_change_work(struct work_struct *work); void qedf_ctx_soft_reset(struct fc_lport *lport); +extern void qedf_board_disable_work(struct work_struct *work); +extern void qedf_schedule_hw_err_handler(void *dev, + enum qed_hw_err_type err_type); #define FCOE_WORD_TO_BYTE 4 #define QEDF_MAX_TASK_NUM 0xFFFF diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 50af70a..3a45ca7 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -104,6 +104,12 @@ MODULE_PARM_DESC(dp_level, " printk verbosity control passed to qed module " "during probe (0-3: 0 more verbose)."); +static bool qedf_enable_recovery = true; +module_param_named(enable_recovery, qedf_enable_recovery, + bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(enable_recovery, "Enable/disable recovery on driver/firmware " + "interface level errors 0 = Disabled, 1 = Enabled (Default: 1)."); + struct workqueue_struct *qedf_io_wq; static struct fcoe_percpu_s qedf_global; @@ -668,6 +674,7 @@ static u32 qedf_get_login_failures(void *cookie) .dcbx_aen = qedf_dcbx_handler, .get_generic_tlv_data = qedf_get_generic_tlv_data, .get_protocol_tlv_data = qedf_get_protocol_tlv_data, + .schedule_hw_err_handler = qedf_schedule_hw_err_handler, } }; @@ -3777,6 +3784,44 @@ void qedf_wq_grcdump(struct work_struct *work) qedf_capture_grc_dump(qedf); } +void qedf_schedule_hw_err_handler(void *dev, enum qed_hw_err_type err_type) +{ + struct qedf_ctx *qedf = dev; + + QEDF_ERR(&(qedf->dbg_ctx), + "Hardware error handler scheduled, event=%d.\n", + err_type); + + if (test_bit(QEDF_IN_RECOVERY, &qedf->flags)) { + QEDF_ERR(&(qedf->dbg_ctx), + "Already in recovery, not scheduling board disable work.\n"); + return; + } + + switch (err_type) { + case QED_HW_ERR_FAN_FAIL: + schedule_delayed_work(&qedf->board_disable_work, 0); + break; + case QED_HW_ERR_MFW_RESP_FAIL: + case QED_HW_ERR_HW_ATTN: + case QED_HW_ERR_DMAE_FAIL: + case QED_HW_ERR_FW_ASSERT: + /* Prevent HW attentions from being reasserted */ + qed_ops->common->attn_clr_enable(qedf->cdev, true); + break; + case QED_HW_ERR_RAMROD_FAIL: + /* Prevent HW attentions from being reasserted */ + qed_ops->common->attn_clr_enable(qedf->cdev, true); + + if (qedf_enable_recovery) + qed_ops->common->recovery_process(qedf->cdev); + + break; + default: + break; + } +} + /* * Protocol TLV handler */ -- 1.8.3.1