scsi: lpfc: Change lpfc_nodelist save_flags member into a bitmask

In attempt to reduce the amount of unnecessary ndlp->lock acquisitions in
the lpfc driver, change save_flags into an unsigned long bitmask and use
clear_bit/test_bit bitwise atomic APIs instead of reliance on ndlp->lock
for synchronization.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20241212233309.71356-7-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Justin Tee 2024-12-12 15:33:05 -08:00 committed by Martin K. Petersen
parent 06dbe31e89
commit 3f8f9f16f8
7 changed files with 33 additions and 53 deletions

View File

@ -1646,14 +1646,12 @@ lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* If the caller wanted a synchronous DA_ID completion, signal the
* wait obj and clear flag to reset the vport.
*/
if (ndlp->save_flags & NLP_WAIT_FOR_DA_ID) {
if (test_bit(NLP_WAIT_FOR_DA_ID, &ndlp->save_flags)) {
if (ndlp->da_id_waitq)
wake_up(ndlp->da_id_waitq);
}
spin_lock_irq(&ndlp->lock);
ndlp->save_flags &= ~NLP_WAIT_FOR_DA_ID;
spin_unlock_irq(&ndlp->lock);
clear_bit(NLP_WAIT_FOR_DA_ID, &ndlp->save_flags);
lpfc_ct_free_iocb(phba, cmdiocb);
lpfc_nlp_put(ndlp);

View File

@ -85,13 +85,13 @@ enum lpfc_fc4_xpt_flags {
NLP_XPT_HAS_HH = 0x10
};
enum lpfc_nlp_save_flags {
enum lpfc_nlp_save_flags { /* mask bits */
/* devloss occurred during recovery */
NLP_IN_RECOV_POST_DEV_LOSS = 0x1,
NLP_IN_RECOV_POST_DEV_LOSS,
/* wait for outstanding LOGO to cmpl */
NLP_WAIT_FOR_LOGO = 0x2,
NLP_WAIT_FOR_LOGO,
/* wait for outstanding DA_ID to finish */
NLP_WAIT_FOR_DA_ID = 0x4
NLP_WAIT_FOR_DA_ID
};
struct lpfc_nodelist {
@ -154,7 +154,7 @@ struct lpfc_nodelist {
uint32_t fc4_prli_sent;
/* flags to keep ndlp alive until special conditions are met */
enum lpfc_nlp_save_flags save_flags;
unsigned long save_flags;
enum lpfc_fc4_xpt_flags fc4_xpt_flags;

View File

@ -2988,12 +2988,8 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
clear_bit(NLP_LOGO_SND, &ndlp->nlp_flag);
spin_lock_irq(&ndlp->lock);
if (ndlp->save_flags & NLP_WAIT_FOR_LOGO) {
if (test_and_clear_bit(NLP_WAIT_FOR_LOGO, &ndlp->save_flags))
wake_up_waiter = 1;
ndlp->save_flags &= ~NLP_WAIT_FOR_LOGO;
}
spin_unlock_irq(&ndlp->lock);
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
"LOGO cmpl: status:x%x/x%x did:x%x",
@ -11509,15 +11505,13 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_can_disctmo(vport);
}
if (ndlp->save_flags & NLP_WAIT_FOR_LOGO) {
if (test_bit(NLP_WAIT_FOR_LOGO, &ndlp->save_flags)) {
/* Wake up lpfc_vport_delete if waiting...*/
if (ndlp->logo_waitq)
wake_up(ndlp->logo_waitq);
clear_bit(NLP_ISSUE_LOGO, &ndlp->nlp_flag);
clear_bit(NLP_LOGO_SND, &ndlp->nlp_flag);
spin_lock_irq(&ndlp->lock);
ndlp->save_flags &= ~NLP_WAIT_FOR_LOGO;
spin_unlock_irq(&ndlp->lock);
clear_bit(NLP_WAIT_FOR_LOGO, &ndlp->save_flags);
}
/* Safe to release resources now. */

View File

@ -414,12 +414,7 @@ void
lpfc_check_nlp_post_devloss(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp)
{
unsigned long iflags;
spin_lock_irqsave(&ndlp->lock, iflags);
if (ndlp->save_flags & NLP_IN_RECOV_POST_DEV_LOSS) {
ndlp->save_flags &= ~NLP_IN_RECOV_POST_DEV_LOSS;
spin_unlock_irqrestore(&ndlp->lock, iflags);
if (test_and_clear_bit(NLP_IN_RECOV_POST_DEV_LOSS, &ndlp->save_flags)) {
lpfc_nlp_get(ndlp);
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY | LOG_NODE,
"8438 Devloss timeout reversed on DID x%x "
@ -427,9 +422,7 @@ lpfc_check_nlp_post_devloss(struct lpfc_vport *vport,
"port_state = x%x\n",
ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp,
ndlp->nlp_flag, vport->port_state);
return;
}
spin_unlock_irqrestore(&ndlp->lock, iflags);
}
/**
@ -546,9 +539,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
ndlp->nlp_DID, kref_read(&ndlp->kref),
ndlp, ndlp->nlp_flag,
vport->port_state);
spin_lock_irqsave(&ndlp->lock, iflags);
ndlp->save_flags |= NLP_IN_RECOV_POST_DEV_LOSS;
spin_unlock_irqrestore(&ndlp->lock, iflags);
set_bit(NLP_IN_RECOV_POST_DEV_LOSS, &ndlp->save_flags);
return fcf_inuse;
} else if (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
/* Fabric node fully recovered before this dev_loss_tmo

View File

@ -3847,8 +3847,8 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
* Otherwise, let dev_loss take care of
* the node.
*/
if (!(ndlp->save_flags &
NLP_IN_RECOV_POST_DEV_LOSS) &&
if (!test_bit(NLP_IN_RECOV_POST_DEV_LOSS,
&ndlp->save_flags) &&
!(ndlp->fc4_xpt_flags &
(NVME_XPT_REGD | SCSI_XPT_REGD)))
lpfc_disc_state_machine

View File

@ -6120,31 +6120,28 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
/* Issue LOGO, if no LOGO is outstanding */
spin_lock_irqsave(&pnode->lock, flags);
if (!(pnode->save_flags & NLP_WAIT_FOR_LOGO) &&
if (!test_bit(NLP_WAIT_FOR_LOGO, &pnode->save_flags) &&
!pnode->logo_waitq) {
pnode->logo_waitq = &waitq;
pnode->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
set_bit(NLP_ISSUE_LOGO, &pnode->nlp_flag);
pnode->save_flags |= NLP_WAIT_FOR_LOGO;
spin_unlock_irqrestore(&pnode->lock, flags);
set_bit(NLP_ISSUE_LOGO, &pnode->nlp_flag);
set_bit(NLP_WAIT_FOR_LOGO, &pnode->save_flags);
lpfc_unreg_rpi(vport, pnode);
wait_event_timeout(waitq,
(!(pnode->save_flags &
NLP_WAIT_FOR_LOGO)),
!test_bit(NLP_WAIT_FOR_LOGO,
&pnode->save_flags),
msecs_to_jiffies(dev_loss_tmo *
1000));
if (pnode->save_flags & NLP_WAIT_FOR_LOGO) {
if (test_and_clear_bit(NLP_WAIT_FOR_LOGO,
&pnode->save_flags))
lpfc_printf_vlog(vport, KERN_ERR, logit,
"0725 SCSI layer TGTRST "
"failed & LOGO TMO (%d, %llu) "
"return x%x\n",
tgt_id, lun_id, status);
spin_lock_irqsave(&pnode->lock, flags);
pnode->save_flags &= ~NLP_WAIT_FOR_LOGO;
} else {
spin_lock_irqsave(&pnode->lock, flags);
}
spin_lock_irqsave(&pnode->lock, flags);
pnode->logo_waitq = NULL;
spin_unlock_irqrestore(&pnode->lock, flags);
status = SUCCESS;

View File

@ -492,21 +492,22 @@ lpfc_send_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
spin_lock_irq(&ndlp->lock);
if (!(ndlp->save_flags & NLP_WAIT_FOR_LOGO) &&
if (!test_bit(NLP_WAIT_FOR_LOGO, &ndlp->save_flags) &&
!ndlp->logo_waitq) {
ndlp->logo_waitq = &waitq;
ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
set_bit(NLP_ISSUE_LOGO, &ndlp->nlp_flag);
ndlp->save_flags |= NLP_WAIT_FOR_LOGO;
set_bit(NLP_WAIT_FOR_LOGO, &ndlp->save_flags);
}
spin_unlock_irq(&ndlp->lock);
rc = lpfc_issue_els_npiv_logo(vport, ndlp);
if (!rc) {
wait_event_timeout(waitq,
(!(ndlp->save_flags & NLP_WAIT_FOR_LOGO)),
!test_bit(NLP_WAIT_FOR_LOGO,
&ndlp->save_flags),
msecs_to_jiffies(phba->fc_ratov * 2000));
if (!(ndlp->save_flags & NLP_WAIT_FOR_LOGO))
if (!test_bit(NLP_WAIT_FOR_LOGO, &ndlp->save_flags))
goto logo_cmpl;
/* LOGO wait failed. Correct status. */
rc = -EINTR;
@ -516,9 +517,7 @@ lpfc_send_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
/* Error - clean up node flags. */
clear_bit(NLP_ISSUE_LOGO, &ndlp->nlp_flag);
spin_lock_irq(&ndlp->lock);
ndlp->save_flags &= ~NLP_WAIT_FOR_LOGO;
spin_unlock_irq(&ndlp->lock);
clear_bit(NLP_WAIT_FOR_LOGO, &ndlp->save_flags);
logo_cmpl:
lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT,
@ -696,19 +695,20 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
spin_lock_irq(&ndlp->lock);
ndlp->da_id_waitq = &waitq;
ndlp->save_flags |= NLP_WAIT_FOR_DA_ID;
spin_unlock_irq(&ndlp->lock);
set_bit(NLP_WAIT_FOR_DA_ID, &ndlp->save_flags);
rc = lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0);
if (!rc) {
wait_event_timeout(waitq,
!(ndlp->save_flags & NLP_WAIT_FOR_DA_ID),
!test_bit(NLP_WAIT_FOR_DA_ID,
&ndlp->save_flags),
msecs_to_jiffies(phba->fc_ratov * 2000));
}
lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT | LOG_ELS,
"1829 DA_ID issue status %d. "
"SFlag x%x NState x%x, NFlag x%lx "
"SFlag x%lx NState x%x, NFlag x%lx "
"Rpi x%x\n",
rc, ndlp->save_flags, ndlp->nlp_state,
ndlp->nlp_flag, ndlp->nlp_rpi);
@ -718,8 +718,8 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
*/
spin_lock_irq(&ndlp->lock);
ndlp->da_id_waitq = NULL;
ndlp->save_flags &= ~NLP_WAIT_FOR_DA_ID;
spin_unlock_irq(&ndlp->lock);
clear_bit(NLP_WAIT_FOR_DA_ID, &ndlp->save_flags);
}
issue_logo: