Commit bf81e9cd authored by Justin Tee's avatar Justin Tee Committed by Martin K. Petersen

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: default avatarJustin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20240429221547.6842-4-justintee8345@gmail.comSigned-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 18f7761d
......@@ -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 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment