mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
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
2 changed files with 45 additions and 30 deletions
|
@ -47,6 +47,18 @@
|
||||||
#include "lpfc_debugfs.h"
|
#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. */
|
/* Called to verify a rcv'ed ADISC was intended for us. */
|
||||||
static int
|
static int
|
||||||
lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
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)
|
lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
|
||||||
{
|
{
|
||||||
LIST_HEAD(abort_list);
|
LIST_HEAD(abort_list);
|
||||||
|
LIST_HEAD(drv_cmpl_list);
|
||||||
struct lpfc_sli_ring *pring;
|
struct lpfc_sli_ring *pring;
|
||||||
struct lpfc_iocbq *iocb, *next_iocb;
|
struct lpfc_iocbq *iocb, *next_iocb;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
pring = lpfc_phba_elsring(phba);
|
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. */
|
/* Abort the targeted IOs and remove them from the abort list. */
|
||||||
list_for_each_entry_safe(iocb, next_iocb, &abort_list, dlist) {
|
list_for_each_entry_safe(iocb, next_iocb, &abort_list, dlist) {
|
||||||
spin_lock_irq(&phba->hbalock);
|
spin_lock_irq(&phba->hbalock);
|
||||||
list_del_init(&iocb->dlist);
|
list_del_init(&iocb->dlist);
|
||||||
lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL);
|
retval = lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL);
|
||||||
spin_unlock_irq(&phba->hbalock);
|
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 */
|
/* Make sure HBA is alive */
|
||||||
lpfc_issue_hb_tmo(phba);
|
lpfc_issue_hb_tmo(phba);
|
||||||
|
|
||||||
|
@ -1604,10 +1627,8 @@ lpfc_device_recov_plogi_issue(struct lpfc_vport *vport,
|
||||||
{
|
{
|
||||||
struct lpfc_hba *phba = vport->phba;
|
struct lpfc_hba *phba = vport->phba;
|
||||||
|
|
||||||
/* Don't do anything that will mess up processing of the
|
/* Don't do anything that disrupts the RSCN unless lpfc is unloading. */
|
||||||
* previous RSCN.
|
if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))
|
||||||
*/
|
|
||||||
if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag))
|
|
||||||
return ndlp->nlp_state;
|
return ndlp->nlp_state;
|
||||||
|
|
||||||
/* software abort outstanding PLOGI */
|
/* software abort outstanding PLOGI */
|
||||||
|
@ -1790,10 +1811,8 @@ lpfc_device_recov_adisc_issue(struct lpfc_vport *vport,
|
||||||
{
|
{
|
||||||
struct lpfc_hba *phba = vport->phba;
|
struct lpfc_hba *phba = vport->phba;
|
||||||
|
|
||||||
/* Don't do anything that will mess up processing of the
|
/* Don't do anything that disrupts the RSCN unless lpfc is unloading. */
|
||||||
* previous RSCN.
|
if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))
|
||||||
*/
|
|
||||||
if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag))
|
|
||||||
return ndlp->nlp_state;
|
return ndlp->nlp_state;
|
||||||
|
|
||||||
/* software abort outstanding ADISC */
|
/* software abort outstanding ADISC */
|
||||||
|
@ -2059,10 +2078,8 @@ lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport,
|
||||||
void *arg,
|
void *arg,
|
||||||
uint32_t evt)
|
uint32_t evt)
|
||||||
{
|
{
|
||||||
/* Don't do anything that will mess up processing of the
|
/* Don't do anything that disrupts the RSCN unless lpfc is unloading. */
|
||||||
* previous RSCN.
|
if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))
|
||||||
*/
|
|
||||||
if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag))
|
|
||||||
return ndlp->nlp_state;
|
return ndlp->nlp_state;
|
||||||
|
|
||||||
ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
|
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;
|
struct lpfc_hba *phba = vport->phba;
|
||||||
|
|
||||||
/* Don't do anything that will mess up processing of the
|
/* Don't do anything that disrupts the RSCN unless lpfc is unloading. */
|
||||||
* previous RSCN.
|
if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))
|
||||||
*/
|
|
||||||
if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag))
|
|
||||||
return ndlp->nlp_state;
|
return ndlp->nlp_state;
|
||||||
|
|
||||||
/* software abort outstanding PRLI */
|
/* software abort outstanding PRLI */
|
||||||
|
@ -2894,10 +2909,8 @@ static uint32_t
|
||||||
lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
void *arg, uint32_t evt)
|
void *arg, uint32_t evt)
|
||||||
{
|
{
|
||||||
/* Don't do anything that will mess up processing of the
|
/* Don't do anything that disrupts the RSCN unless lpfc is unloading. */
|
||||||
* previous RSCN.
|
if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))
|
||||||
*/
|
|
||||||
if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag))
|
|
||||||
return ndlp->nlp_state;
|
return ndlp->nlp_state;
|
||||||
|
|
||||||
lpfc_cancel_retry_delay_tmo(vport, ndlp);
|
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 */
|
/* ELS cmd tag <ulpIoTag> completes */
|
||||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
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",
|
"x%x x%x x%x x%px\n",
|
||||||
ulp_command, ulp_status, ulp_word4, iotag,
|
ulp_command, kref_read(&cmdiocb->ndlp->kref),
|
||||||
cmdiocb->ndlp);
|
ulp_status, ulp_word4, iotag, cmdiocb->ndlp);
|
||||||
/*
|
/*
|
||||||
* Deref the ndlp after free_iocb. sli_release_iocb will access the ndlp
|
* Deref the ndlp after free_iocb. sli_release_iocb will access the ndlp
|
||||||
* if exchange is busy.
|
* 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->sli_rev == LPFC_SLI_REV4 &&
|
||||||
phba->sli4_hba.link_state.status == LPFC_FC_LA_TYPE_LINK_DOWN) ||
|
phba->sli4_hba.link_state.status == LPFC_FC_LA_TYPE_LINK_DOWN) ||
|
||||||
(phba->link_flag & LS_EXTERNAL_LOOPBACK))
|
(phba->link_flag & LS_EXTERNAL_LOOPBACK))
|
||||||
|
@ -12507,10 +12509,10 @@ abort_iotag_exit:
|
||||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
|
lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
|
||||||
"0339 Abort IO XRI x%x, Original iotag x%x, "
|
"0339 Abort IO XRI x%x, Original iotag x%x, "
|
||||||
"abort tag x%x Cmdjob : x%px Abortjob : x%px "
|
"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) ?
|
ulp_context, (phba->sli_rev == LPFC_SLI_REV4) ?
|
||||||
cmdiocb->iotag : iotag, iotag, cmdiocb, abtsiocbp,
|
cmdiocb->iotag : iotag, iotag, cmdiocb, abtsiocbp,
|
||||||
retval);
|
retval, ia);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
cmdiocb->cmd_flag &= ~LPFC_DRIVER_ABORTED;
|
cmdiocb->cmd_flag &= ~LPFC_DRIVER_ABORTED;
|
||||||
__lpfc_sli_release_iocbq(phba, abtsiocbp);
|
__lpfc_sli_release_iocbq(phba, abtsiocbp);
|
||||||
|
|
Loading…
Add table
Reference in a new issue