|
Daniel Wagner |
aad03e |
From: James Smart <jsmart2021@gmail.com>
|
|
Daniel Wagner |
aad03e |
Date: Fri, 3 Dec 2021 16:26:39 -0800
|
|
Daniel Wagner |
aad03e |
Subject: scsi: lpfc: Fix NPIV port deletion crash
|
|
Daniel Wagner |
aad03e |
Patch-mainline: Queued in subsystem maintainer repository
|
|
Daniel Wagner |
aad03e |
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
|
|
Daniel Wagner |
aad03e |
Git-commit: 8ed190a91950564775cbaae9e8e8083a69a8da23
|
|
Daniel Wagner |
aad03e |
References: bsc1192145
|
|
Daniel Wagner |
aad03e |
|
|
Daniel Wagner |
aad03e |
The driver is calling schedule_timeout after the DA_ID nameserver request
|
|
Daniel Wagner |
aad03e |
and LOGO commands are issued to the fabric by the initiator virtual
|
|
Daniel Wagner |
aad03e |
endport. These fixed delay functions are causing long delays in the
|
|
Daniel Wagner |
aad03e |
driver's worker thread when processing discovery I/Os in a serialized
|
|
Daniel Wagner |
aad03e |
fashion, which is then triggering mailbox timeout errors artificially.
|
|
Daniel Wagner |
aad03e |
|
|
Daniel Wagner |
aad03e |
To fix this, don't wait on the DA_ID request to complete and call
|
|
Daniel Wagner |
aad03e |
wait_event_timeout to allow the vport delete thread to make progress on an
|
|
Daniel Wagner |
aad03e |
event driven basis rather than fixing the wait time.
|
|
Daniel Wagner |
aad03e |
|
|
Daniel Wagner |
aad03e |
Link: https://lore.kernel.org/r/20211204002644.116455-5-jsmart2021@gmail.com
|
|
Daniel Wagner |
aad03e |
Co-developed-by: Justin Tee <justin.tee@broadcom.com>
|
|
Daniel Wagner |
aad03e |
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
|
|
Daniel Wagner |
aad03e |
Signed-off-by: James Smart <jsmart2021@gmail.com>
|
|
Daniel Wagner |
aad03e |
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
|
|
Daniel Wagner |
aad03e |
Acked-by: Daniel Wagner <dwagner@suse.de>
|
|
Daniel Wagner |
aad03e |
---
|
|
Daniel Wagner |
aad03e |
drivers/scsi/lpfc/lpfc.h | 2
|
|
Daniel Wagner |
aad03e |
drivers/scsi/lpfc/lpfc_els.c | 11 ++++-
|
|
Daniel Wagner |
aad03e |
drivers/scsi/lpfc/lpfc_hbadisc.c | 2
|
|
Daniel Wagner |
aad03e |
drivers/scsi/lpfc/lpfc_vport.c | 83 +++++++++++++++++++++++++++++----------
|
|
Daniel Wagner |
aad03e |
4 files changed, 73 insertions(+), 25 deletions(-)
|
|
Daniel Wagner |
aad03e |
|
|
Daniel Wagner |
aad03e |
--- a/drivers/scsi/lpfc/lpfc.h
|
|
Daniel Wagner |
aad03e |
+++ b/drivers/scsi/lpfc/lpfc.h
|
|
Daniel Wagner |
aad03e |
@@ -607,8 +607,6 @@ struct lpfc_vport {
|
|
Daniel Wagner |
aad03e |
struct timer_list els_tmofunc;
|
|
Daniel Wagner |
aad03e |
struct timer_list delayed_disc_tmo;
|
|
Daniel Wagner |
aad03e |
|
|
Daniel Wagner |
aad03e |
- int unreg_vpi_cmpl;
|
|
Daniel Wagner |
aad03e |
-
|
|
Daniel Wagner |
aad03e |
uint8_t load_flag;
|
|
Daniel Wagner |
aad03e |
#define FC_LOADING 0x1 /* HBA in process of loading drvr */
|
|
Daniel Wagner |
aad03e |
#define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */
|
|
Daniel Wagner |
aad03e |
--- a/drivers/scsi/lpfc/lpfc_els.c
|
|
Daniel Wagner |
aad03e |
+++ b/drivers/scsi/lpfc/lpfc_els.c
|
|
Daniel Wagner |
aad03e |
@@ -10925,10 +10925,19 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba
|
|
Daniel Wagner |
aad03e |
lpfc_can_disctmo(vport);
|
|
Daniel Wagner |
aad03e |
}
|
|
Daniel Wagner |
aad03e |
|
|
Daniel Wagner |
aad03e |
+ if (ndlp->save_flags & NLP_WAIT_FOR_LOGO) {
|
|
Daniel Wagner |
aad03e |
+ /* Wake up lpfc_vport_delete if waiting...*/
|
|
Daniel Wagner |
aad03e |
+ if (ndlp->logo_waitq)
|
|
Daniel Wagner |
aad03e |
+ wake_up(ndlp->logo_waitq);
|
|
Daniel Wagner |
aad03e |
+ spin_lock_irq(&ndlp->lock);
|
|
Daniel Wagner |
aad03e |
+ ndlp->nlp_flag &= ~(NLP_ISSUE_LOGO | NLP_LOGO_SND);
|
|
Daniel Wagner |
aad03e |
+ ndlp->save_flags &= ~NLP_WAIT_FOR_LOGO;
|
|
Daniel Wagner |
aad03e |
+ spin_unlock_irq(&ndlp->lock);
|
|
Daniel Wagner |
aad03e |
+ }
|
|
Daniel Wagner |
aad03e |
+
|
|
Daniel Wagner |
aad03e |
/* Safe to release resources now. */
|
|
Daniel Wagner |
aad03e |
lpfc_els_free_iocb(phba, cmdiocb);
|
|
Daniel Wagner |
aad03e |
lpfc_nlp_put(ndlp);
|
|
Daniel Wagner |
aad03e |
- vport->unreg_vpi_cmpl = VPORT_ERROR;
|
|
Daniel Wagner |
aad03e |
}
|
|
Daniel Wagner |
aad03e |
|
|
Daniel Wagner |
aad03e |
/**
|
|
Daniel Wagner |
aad03e |
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
|
|
Daniel Wagner |
aad03e |
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
|
|
Daniel Wagner |
aad03e |
@@ -3776,7 +3776,6 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba
|
|
Daniel Wagner |
aad03e |
vport->vpi_state &= ~LPFC_VPI_REGISTERED;
|
|
Daniel Wagner |
aad03e |
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
|
|
Daniel Wagner |
aad03e |
spin_unlock_irq(shost->host_lock);
|
|
Daniel Wagner |
aad03e |
- vport->unreg_vpi_cmpl = VPORT_OK;
|
|
Daniel Wagner |
aad03e |
mempool_free(pmb, phba->mbox_mem_pool);
|
|
Daniel Wagner |
aad03e |
lpfc_cleanup_vports_rrqs(vport, NULL);
|
|
Daniel Wagner |
aad03e |
/*
|
|
Daniel Wagner |
aad03e |
@@ -3806,7 +3805,6 @@ lpfc_mbx_unreg_vpi(struct lpfc_vport *vp
|
|
Daniel Wagner |
aad03e |
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
|
Daniel Wagner |
aad03e |
"1800 Could not issue unreg_vpi\n");
|
|
Daniel Wagner |
aad03e |
mempool_free(mbox, phba->mbox_mem_pool);
|
|
Daniel Wagner |
aad03e |
- vport->unreg_vpi_cmpl = VPORT_ERROR;
|
|
Daniel Wagner |
aad03e |
return rc;
|
|
Daniel Wagner |
aad03e |
}
|
|
Daniel Wagner |
aad03e |
return 0;
|
|
Daniel Wagner |
aad03e |
--- a/drivers/scsi/lpfc/lpfc_vport.c
|
|
Daniel Wagner |
aad03e |
+++ b/drivers/scsi/lpfc/lpfc_vport.c
|
|
Daniel Wagner |
aad03e |
@@ -486,22 +486,67 @@ lpfc_vport_create(struct fc_vport *fc_vp
|
|
Daniel Wagner |
aad03e |
}
|
|
Daniel Wagner |
aad03e |
|
|
Daniel Wagner |
aad03e |
static int
|
|
Daniel Wagner |
aad03e |
+lpfc_send_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
|
Daniel Wagner |
aad03e |
+{
|
|
Daniel Wagner |
aad03e |
+ int rc;
|
|
Daniel Wagner |
aad03e |
+ struct lpfc_hba *phba = vport->phba;
|
|
Daniel Wagner |
aad03e |
+
|
|
Daniel Wagner |
aad03e |
+ DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
|
|
Daniel Wagner |
aad03e |
+
|
|
Daniel Wagner |
aad03e |
+ spin_lock_irq(&ndlp->lock);
|
|
Daniel Wagner |
aad03e |
+ if (!(ndlp->save_flags & NLP_WAIT_FOR_LOGO) &&
|
|
Daniel Wagner |
aad03e |
+ !ndlp->logo_waitq) {
|
|
Daniel Wagner |
aad03e |
+ ndlp->logo_waitq = &waitq;
|
|
Daniel Wagner |
aad03e |
+ ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
|
|
Daniel Wagner |
aad03e |
+ ndlp->nlp_flag |= NLP_ISSUE_LOGO;
|
|
Daniel Wagner |
aad03e |
+ ndlp->save_flags |= NLP_WAIT_FOR_LOGO;
|
|
Daniel Wagner |
aad03e |
+ }
|
|
Daniel Wagner |
aad03e |
+ spin_unlock_irq(&ndlp->lock);
|
|
Daniel Wagner |
aad03e |
+ rc = lpfc_issue_els_npiv_logo(vport, ndlp);
|
|
Daniel Wagner |
aad03e |
+ if (!rc) {
|
|
Daniel Wagner |
aad03e |
+ wait_event_timeout(waitq,
|
|
Daniel Wagner |
aad03e |
+ (!(ndlp->save_flags & NLP_WAIT_FOR_LOGO)),
|
|
Daniel Wagner |
aad03e |
+ msecs_to_jiffies(phba->fc_ratov * 2000));
|
|
Daniel Wagner |
aad03e |
+
|
|
Daniel Wagner |
aad03e |
+ if (!(ndlp->save_flags & NLP_WAIT_FOR_LOGO))
|
|
Daniel Wagner |
aad03e |
+ goto logo_cmpl;
|
|
Daniel Wagner |
aad03e |
+ /* LOGO wait failed. Correct status. */
|
|
Daniel Wagner |
aad03e |
+ rc = -EINTR;
|
|
Daniel Wagner |
aad03e |
+ } else {
|
|
Daniel Wagner |
aad03e |
+ rc = -EIO;
|
|
Daniel Wagner |
aad03e |
+ }
|
|
Daniel Wagner |
aad03e |
+
|
|
Daniel Wagner |
aad03e |
+ /* Error - clean up node flags. */
|
|
Daniel Wagner |
aad03e |
+ spin_lock_irq(&ndlp->lock);
|
|
Daniel Wagner |
aad03e |
+ ndlp->nlp_flag &= ~NLP_ISSUE_LOGO;
|
|
Daniel Wagner |
aad03e |
+ ndlp->save_flags &= ~NLP_WAIT_FOR_LOGO;
|
|
Daniel Wagner |
aad03e |
+ spin_unlock_irq(&ndlp->lock);
|
|
Daniel Wagner |
aad03e |
+
|
|
Daniel Wagner |
aad03e |
+ logo_cmpl:
|
|
Daniel Wagner |
aad03e |
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT,
|
|
Daniel Wagner |
aad03e |
+ "1824 Issue LOGO completes with status %d\n",
|
|
Daniel Wagner |
aad03e |
+ rc);
|
|
Daniel Wagner |
aad03e |
+ spin_lock_irq(&ndlp->lock);
|
|
Daniel Wagner |
aad03e |
+ ndlp->logo_waitq = NULL;
|
|
Daniel Wagner |
aad03e |
+ spin_unlock_irq(&ndlp->lock);
|
|
Daniel Wagner |
aad03e |
+ return rc;
|
|
Daniel Wagner |
aad03e |
+}
|
|
Daniel Wagner |
aad03e |
+
|
|
Daniel Wagner |
aad03e |
+static int
|
|
Daniel Wagner |
aad03e |
disable_vport(struct fc_vport *fc_vport)
|
|
Daniel Wagner |
aad03e |
{
|
|
Daniel Wagner |
aad03e |
struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
|
|
Daniel Wagner |
aad03e |
struct lpfc_hba *phba = vport->phba;
|
|
Daniel Wagner |
aad03e |
struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
|
|
Daniel Wagner |
aad03e |
- long timeout;
|
|
Daniel Wagner |
aad03e |
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
|
Daniel Wagner |
aad03e |
|
|
Daniel Wagner |
aad03e |
+ /* Can't disable during an outstanding delete. */
|
|
Daniel Wagner |
aad03e |
+ if (vport->load_flag & FC_UNLOADING)
|
|
Daniel Wagner |
aad03e |
+ return 0;
|
|
Daniel Wagner |
aad03e |
+
|
|
Daniel Wagner |
aad03e |
ndlp = lpfc_findnode_did(vport, Fabric_DID);
|
|
Daniel Wagner |
aad03e |
- if (ndlp && phba->link_state >= LPFC_LINK_UP) {
|
|
Daniel Wagner |
aad03e |
- vport->unreg_vpi_cmpl = VPORT_INVAL;
|
|
Daniel Wagner |
aad03e |
- timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
|
|
Daniel Wagner |
aad03e |
- if (!lpfc_issue_els_npiv_logo(vport, ndlp))
|
|
Daniel Wagner |
aad03e |
- while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
|
|
Daniel Wagner |
aad03e |
- timeout = schedule_timeout(timeout);
|
|
Daniel Wagner |
aad03e |
- }
|
|
Daniel Wagner |
aad03e |
+ if (ndlp && phba->link_state >= LPFC_LINK_UP)
|
|
Daniel Wagner |
aad03e |
+ (void)lpfc_send_npiv_logo(vport, ndlp);
|
|
Daniel Wagner |
aad03e |
|
|
Daniel Wagner |
aad03e |
lpfc_sli_host_down(vport);
|
|
Daniel Wagner |
aad03e |
|
|
Daniel Wagner |
aad03e |
@@ -600,7 +645,7 @@ lpfc_vport_delete(struct fc_vport *fc_vp
|
|
Daniel Wagner |
aad03e |
struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
|
|
Daniel Wagner |
aad03e |
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
|
Daniel Wagner |
aad03e |
struct lpfc_hba *phba = vport->phba;
|
|
Daniel Wagner |
aad03e |
- long timeout;
|
|
Daniel Wagner |
aad03e |
+ int rc;
|
|
Daniel Wagner |
aad03e |
|
|
Daniel Wagner |
aad03e |
if (vport->port_type == LPFC_PHYSICAL_PORT) {
|
|
Daniel Wagner |
aad03e |
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
|
Daniel Wagner |
aad03e |
@@ -665,15 +710,14 @@ lpfc_vport_delete(struct fc_vport *fc_vp
|
|
Daniel Wagner |
aad03e |
phba->fc_topology != LPFC_TOPOLOGY_LOOP) {
|
|
Daniel Wagner |
aad03e |
if (vport->cfg_enable_da_id) {
|
|
Daniel Wagner |
aad03e |
/* Send DA_ID and wait for a completion. */
|
|
Daniel Wagner |
aad03e |
- timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
|
|
Daniel Wagner |
aad03e |
- if (!lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0))
|
|
Daniel Wagner |
aad03e |
- while (vport->ct_flags && timeout)
|
|
Daniel Wagner |
aad03e |
- timeout = schedule_timeout(timeout);
|
|
Daniel Wagner |
aad03e |
- else
|
|
Daniel Wagner |
aad03e |
+ rc = lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0);
|
|
Daniel Wagner |
aad03e |
+ if (rc) {
|
|
Daniel Wagner |
aad03e |
lpfc_printf_log(vport->phba, KERN_WARNING,
|
|
Daniel Wagner |
aad03e |
LOG_VPORT,
|
|
Daniel Wagner |
aad03e |
"1829 CT command failed to "
|
|
Daniel Wagner |
aad03e |
- "delete objects on fabric\n");
|
|
Daniel Wagner |
aad03e |
+ "delete objects on fabric, "
|
|
Daniel Wagner |
aad03e |
+ "rc %d\n", rc);
|
|
Daniel Wagner |
aad03e |
+ }
|
|
Daniel Wagner |
aad03e |
}
|
|
Daniel Wagner |
aad03e |
|
|
Daniel Wagner |
aad03e |
/*
|
|
Daniel Wagner |
aad03e |
@@ -688,11 +732,10 @@ lpfc_vport_delete(struct fc_vport *fc_vp
|
|
Daniel Wagner |
aad03e |
ndlp = lpfc_findnode_did(vport, Fabric_DID);
|
|
Daniel Wagner |
aad03e |
if (!ndlp)
|
|
Daniel Wagner |
aad03e |
goto skip_logo;
|
|
Daniel Wagner |
aad03e |
- vport->unreg_vpi_cmpl = VPORT_INVAL;
|
|
Daniel Wagner |
aad03e |
- timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
|
|
Daniel Wagner |
aad03e |
- if (!lpfc_issue_els_npiv_logo(vport, ndlp))
|
|
Daniel Wagner |
aad03e |
- while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
|
|
Daniel Wagner |
aad03e |
- timeout = schedule_timeout(timeout);
|
|
Daniel Wagner |
aad03e |
+
|
|
Daniel Wagner |
aad03e |
+ rc = lpfc_send_npiv_logo(vport, ndlp);
|
|
Daniel Wagner |
aad03e |
+ if (rc)
|
|
Daniel Wagner |
aad03e |
+ goto skip_logo;
|
|
Daniel Wagner |
aad03e |
}
|
|
Daniel Wagner |
aad03e |
|
|
Daniel Wagner |
aad03e |
if (!(phba->pport->load_flag & FC_UNLOADING))
|