diff options
author | Justin Tee <justin.tee@broadcom.com> | 2024-04-29 15:15:42 -0700 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2024-05-06 21:53:58 -0400 |
commit | bf81e9cd1767cb3a6abe13af1054e0504072c455 (patch) | |
tree | 4a994b46f4f8b445812d3f11e02e334bb2441fcb /drivers/scsi/lpfc | |
parent | 18f7761d5c6f290236a0d181feecea592226a9df (diff) |
scsi: lpfc: Clear deferred RSCN processing flag when driver is unloading
Device recovery logic is skipped when the RSCN processing flag is set.
However during rmmod, the flag is not cleared leading to unnecessary delays
in waiting for completions on a link that is being offlined.
Move clearing of the RSCN deferred flag to a refactored routine when called
from device recovery, and set the IA flag when issuing an abort during
unload.
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20240429221547.6842-4-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 61 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 14 |
2 files changed, 45 insertions, 30 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index c4172791c267..b24fabbf20c4 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -47,6 +47,18 @@ #include "lpfc_debugfs.h" +/* Called to clear RSCN discovery flags when driver is unloading. */ +static bool +lpfc_check_unload_and_clr_rscn(unsigned long *fc_flag) +{ + /* If unloading, then clear the FC_RSCN_DEFERRED flag */ + if (test_bit(FC_UNLOADING, fc_flag)) { + clear_bit(FC_RSCN_DEFERRED, fc_flag); + return false; + } + return test_bit(FC_RSCN_DEFERRED, fc_flag); +} + /* Called to verify a rcv'ed ADISC was intended for us. */ static int lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, @@ -213,8 +225,10 @@ void lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) { LIST_HEAD(abort_list); + LIST_HEAD(drv_cmpl_list); struct lpfc_sli_ring *pring; struct lpfc_iocbq *iocb, *next_iocb; + int retval = 0; pring = lpfc_phba_elsring(phba); @@ -250,11 +264,20 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) /* Abort the targeted IOs and remove them from the abort list. */ list_for_each_entry_safe(iocb, next_iocb, &abort_list, dlist) { - spin_lock_irq(&phba->hbalock); - list_del_init(&iocb->dlist); - lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL); - spin_unlock_irq(&phba->hbalock); + spin_lock_irq(&phba->hbalock); + list_del_init(&iocb->dlist); + retval = lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL); + spin_unlock_irq(&phba->hbalock); + + if (retval && test_bit(FC_UNLOADING, &phba->pport->load_flag)) { + list_del_init(&iocb->list); + list_add_tail(&iocb->list, &drv_cmpl_list); + } } + + lpfc_sli_cancel_iocbs(phba, &drv_cmpl_list, IOSTAT_LOCAL_REJECT, + IOERR_SLI_ABORTED); + /* Make sure HBA is alive */ lpfc_issue_hb_tmo(phba); @@ -1604,10 +1627,8 @@ lpfc_device_recov_plogi_issue(struct lpfc_vport *vport, { struct lpfc_hba *phba = vport->phba; - /* Don't do anything that will mess up processing of the - * previous RSCN. - */ - if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag)) + /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */ + if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag)) return ndlp->nlp_state; /* software abort outstanding PLOGI */ @@ -1790,10 +1811,8 @@ lpfc_device_recov_adisc_issue(struct lpfc_vport *vport, { struct lpfc_hba *phba = vport->phba; - /* Don't do anything that will mess up processing of the - * previous RSCN. - */ - if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag)) + /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */ + if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag)) return ndlp->nlp_state; /* software abort outstanding ADISC */ @@ -2059,10 +2078,8 @@ lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport, void *arg, uint32_t evt) { - /* Don't do anything that will mess up processing of the - * previous RSCN. - */ - if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag)) + /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */ + if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag)) return ndlp->nlp_state; ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; @@ -2375,10 +2392,8 @@ lpfc_device_recov_prli_issue(struct lpfc_vport *vport, { struct lpfc_hba *phba = vport->phba; - /* Don't do anything that will mess up processing of the - * previous RSCN. - */ - if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag)) + /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */ + if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag)) return ndlp->nlp_state; /* software abort outstanding PRLI */ @@ -2894,10 +2909,8 @@ static uint32_t lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - /* Don't do anything that will mess up processing of the - * previous RSCN. - */ - if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag)) + /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */ + if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag)) return ndlp->nlp_state; lpfc_cancel_retry_delay_tmo(vport, ndlp); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index a028e008dd1e..fa3d458af193 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -12361,10 +12361,10 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* ELS cmd tag <ulpIoTag> completes */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "0139 Ignoring ELS cmd code x%x completion Data: " + "0139 Ignoring ELS cmd code x%x ref cnt x%x Data: " "x%x x%x x%x x%px\n", - ulp_command, ulp_status, ulp_word4, iotag, - cmdiocb->ndlp); + ulp_command, kref_read(&cmdiocb->ndlp->kref), + ulp_status, ulp_word4, iotag, cmdiocb->ndlp); /* * Deref the ndlp after free_iocb. sli_release_iocb will access the ndlp * if exchange is busy. @@ -12460,7 +12460,9 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } } - if (phba->link_state < LPFC_LINK_UP || + /* Just close the exchange under certain conditions. */ + if (test_bit(FC_UNLOADING, &vport->load_flag) || + phba->link_state < LPFC_LINK_UP || (phba->sli_rev == LPFC_SLI_REV4 && phba->sli4_hba.link_state.status == LPFC_FC_LA_TYPE_LINK_DOWN) || (phba->link_flag & LS_EXTERNAL_LOOPBACK)) @@ -12507,10 +12509,10 @@ abort_iotag_exit: lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, "0339 Abort IO XRI x%x, Original iotag x%x, " "abort tag x%x Cmdjob : x%px Abortjob : x%px " - "retval x%x\n", + "retval x%x : IA %d\n", ulp_context, (phba->sli_rev == LPFC_SLI_REV4) ? cmdiocb->iotag : iotag, iotag, cmdiocb, abtsiocbp, - retval); + retval, ia); if (retval) { cmdiocb->cmd_flag &= ~LPFC_DRIVER_ABORTED; __lpfc_sli_release_iocbq(phba, abtsiocbp); |