lkml.org 
[lkml]   [2019]   [Jan]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.14 010/170] scsi: lpfc: Fix LOGO/PLOGI handling when triggerd by ABTS Timeout event
    Date
    From: James Smart <jsmart2021@gmail.com>

    [ Upstream commit 30e196cacefdd9a38c857caed23cefc9621bc5c1 ]

    After a LOGO in response to an ABTS timeout, a PLOGI wasn't issued to
    re-establish the login. An nlp_type check in the LOGO completion
    handler failed to restart discovery for NVME targets. Revised the
    nlp_type check for NVME as well as SCSI.

    While reviewing the LOGO handling a few other issues were seen and
    were addressed:

    - Better lock synchronization around ndlp data types

    - When the ABTS times out, unregister the RPI before sending the LOGO
    so that all local exchange contexts are cleared and nothing received
    while awaiting LOGO/PLOGI handling will be accepted.

    - LOGO handling optimized to:
    Wait only R_A_TOV for a response.
    It doesn't need to be retried on timeout. If there wasn't a
    response, a PLOGI will be sent, thus an implicit logout
    applies as well when the other port sees it.
    If there is a response, any kind of response is considered "good"
    and the XRI quarantined for a exchange qualifier window.

    - PLOGI is issued as soon a LOGO state is resolved.

    Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
    Signed-off-by: James Smart <jsmart2021@gmail.com>
    Reviewed-by: Hannes Reinecke <hare@suse.com>
    Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/scsi/lpfc/lpfc_els.c | 49 +++++++++++++-----------------
    drivers/scsi/lpfc/lpfc_nportdisc.c | 5 +++
    2 files changed, 26 insertions(+), 28 deletions(-)

    diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
    index fffe8a643e25..57cddbc4a977 100644
    --- a/drivers/scsi/lpfc/lpfc_els.c
    +++ b/drivers/scsi/lpfc/lpfc_els.c
    @@ -242,6 +242,8 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
    icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
    if (elscmd == ELS_CMD_FLOGI)
    icmd->ulpTimeout = FF_DEF_RATOV * 2;
    + else if (elscmd == ELS_CMD_LOGO)
    + icmd->ulpTimeout = phba->fc_ratov;
    else
    icmd->ulpTimeout = phba->fc_ratov * 2;
    } else {
    @@ -2674,16 +2676,15 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
    goto out;
    }

    + /* The LOGO will not be retried on failure. A LOGO was
    + * issued to the remote rport and a ACC or RJT or no Answer are
    + * all acceptable. Note the failure and move forward with
    + * discovery. The PLOGI will retry.
    + */
    if (irsp->ulpStatus) {
    - /* Check for retry */
    - if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
    - /* ELS command is being retried */
    - skip_recovery = 1;
    - goto out;
    - }
    /* LOGO failed */
    lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
    - "2756 LOGO failure DID:%06X Status:x%x/x%x\n",
    + "2756 LOGO failure, No Retry DID:%06X Status:x%x/x%x\n",
    ndlp->nlp_DID, irsp->ulpStatus,
    irsp->un.ulpWord[4]);
    /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
    @@ -2729,7 +2730,8 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
    * For any other port type, the rpi is unregistered as an implicit
    * LOGO.
    */
    - if ((ndlp->nlp_type & NLP_FCP_TARGET) && (skip_recovery == 0)) {
    + if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET) &&
    + skip_recovery == 0) {
    lpfc_cancel_retry_delay_tmo(vport, ndlp);
    spin_lock_irqsave(shost->host_lock, flags);
    ndlp->nlp_flag |= NLP_NPR_2B_DISC;
    @@ -2762,6 +2764,8 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
    * will be stored into the context1 field of the IOCB for the completion
    * callback function to the LOGO ELS command.
    *
    + * Callers of this routine are expected to unregister the RPI first
    + *
    * Return code
    * 0 - successfully issued logo
    * 1 - failed to issue logo
    @@ -2803,22 +2807,6 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
    "Issue LOGO: did:x%x",
    ndlp->nlp_DID, 0, 0);

    - /*
    - * If we are issuing a LOGO, we may try to recover the remote NPort
    - * by issuing a PLOGI later. Even though we issue ELS cmds by the
    - * VPI, if we have a valid RPI, and that RPI gets unreg'ed while
    - * that ELS command is in-flight, the HBA returns a IOERR_INVALID_RPI
    - * for that ELS cmd. To avoid this situation, lets get rid of the
    - * RPI right now, before any ELS cmds are sent.
    - */
    - spin_lock_irq(shost->host_lock);
    - ndlp->nlp_flag |= NLP_ISSUE_LOGO;
    - spin_unlock_irq(shost->host_lock);
    - if (lpfc_unreg_rpi(vport, ndlp)) {
    - lpfc_els_free_iocb(phba, elsiocb);
    - return 0;
    - }
    -
    phba->fc_stat.elsXmitLOGO++;
    elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
    spin_lock_irq(shost->host_lock);
    @@ -2826,7 +2814,6 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
    ndlp->nlp_flag &= ~NLP_ISSUE_LOGO;
    spin_unlock_irq(shost->host_lock);
    rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
    -
    if (rc == IOCB_ERROR) {
    spin_lock_irq(shost->host_lock);
    ndlp->nlp_flag &= ~NLP_LOGO_SND;
    @@ -2834,6 +2821,11 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
    lpfc_els_free_iocb(phba, elsiocb);
    return 1;
    }
    +
    + spin_lock_irq(shost->host_lock);
    + ndlp->nlp_prev_state = ndlp->nlp_state;
    + spin_unlock_irq(shost->host_lock);
    + lpfc_nlp_set_state(vport, ndlp, NLP_STE_LOGO_ISSUE);
    return 0;
    }

    @@ -9483,7 +9475,8 @@ lpfc_sli_abts_recover_port(struct lpfc_vport *vport,
    "rport in state 0x%x\n", ndlp->nlp_state);
    return;
    }
    - lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
    + lpfc_printf_log(phba, KERN_ERR,
    + LOG_ELS | LOG_FCP_ERROR | LOG_NVME_IOERR,
    "3094 Start rport recovery on shost id 0x%x "
    "fc_id 0x%06x vpi 0x%x rpi 0x%x state 0x%x "
    "flags 0x%x\n",
    @@ -9496,8 +9489,8 @@ lpfc_sli_abts_recover_port(struct lpfc_vport *vport,
    */
    spin_lock_irqsave(shost->host_lock, flags);
    ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
    + ndlp->nlp_flag |= NLP_ISSUE_LOGO;
    spin_unlock_irqrestore(shost->host_lock, flags);
    - lpfc_issue_els_logo(vport, ndlp, 0);
    - lpfc_nlp_set_state(vport, ndlp, NLP_STE_LOGO_ISSUE);
    + lpfc_unreg_rpi(vport, ndlp);
    }

    diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
    index d489f6827cc1..36fb549eb4e8 100644
    --- a/drivers/scsi/lpfc/lpfc_nportdisc.c
    +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
    @@ -801,7 +801,9 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
    struct Scsi_Host *shost = lpfc_shost_from_vport(vport);

    if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED)) {
    + spin_lock_irq(shost->host_lock);
    ndlp->nlp_flag &= ~NLP_NPR_ADISC;
    + spin_unlock_irq(shost->host_lock);
    return 0;
    }

    @@ -816,7 +818,10 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
    return 1;
    }
    }
    +
    + spin_lock_irq(shost->host_lock);
    ndlp->nlp_flag &= ~NLP_NPR_ADISC;
    + spin_unlock_irq(shost->host_lock);
    lpfc_unreg_rpi(vport, ndlp);
    return 0;
    }
    --
    2.19.1
    \
     
     \ /
      Last update: 2019-01-28 18:08    [W:4.302 / U:0.128 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site