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>
This commit is contained in:
parent
18f7761d5c
commit
bf81e9cd17
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user