From 5ac6b303834aa74855ecc3db98b4b1d9cad0de2f Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 22 Oct 2010 11:05:36 -0400 Subject: [SCSI] lpfc 8.3.18: FC/FCoE Discovery fixes FC/FCoE Discovery fixes: - Call the lpfc_drain_txq only for SLI4 hba - In lpfc_cmpl_els_fdisc, fix code path that does not free IOCB. - Treated firmware matching FCF property with different index as error - Propagate error returns from lpfc_issue_els_flogi() - Refactored lpfc_unregister_unused_fcf() to create a post lpfc_dev_loss_tmo handler call for SLI-4 devices. Allows checking of fcf after last ndlp released so that fcf can be released if no longer in use. - Replaced individual FCF_XXXX_DISC flag clearing in lieu of aggregate FCF_DISCOVERY flag upon succesful completion of flogi. - Correct setting of altBbCredit value in sparams to correct issue with logins with remote loop-based devices. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers/scsi/lpfc/lpfc_els.c') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index e6ca12f6c6cb..b16311d60c66 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -523,12 +523,6 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_PUBLIC_LOOP; spin_unlock_irq(shost->host_lock); - } else { - /* - * If we are a N-port connected to a Fabric, fixup sparam's so - * logins to devices on remote loops work. - */ - vport->fc_sparam.cmn.altBbCredit = 1; } vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID; @@ -1175,12 +1169,13 @@ lpfc_initial_flogi(struct lpfc_vport *vport) return 0; } - if (lpfc_issue_els_flogi(vport, ndlp, 0)) + if (lpfc_issue_els_flogi(vport, ndlp, 0)) { /* This decrement of reference count to node shall kick off * the release of the node. */ lpfc_nlp_put(ndlp); - + return 0; + } return 1; } @@ -1645,6 +1640,13 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm)); sp = (struct serv_parm *) pcmd; + /* + * If we are a N-port connected to a Fabric, fix-up paramm's so logins + * to device on remote loops work. + */ + if ((vport->fc_flag & FC_FABRIC) && !(vport->fc_flag & FC_PUBLIC_LOOP)) + sp->cmn.altBbCredit = 1; + if (sp->cmn.fcphLow < FC_PH_4_3) sp->cmn.fcphLow = FC_PH_4_3; @@ -6452,7 +6454,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * to update the MAC address. */ lpfc_register_new_vport(phba, vport, ndlp); - return ; + goto out; } if (vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI) -- cgit v1.2.1 From 12265f68ae925b9dee8099140b4213c28ef54f14 Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 22 Oct 2010 11:05:53 -0400 Subject: [SCSI] lpfc 8.3.18: Add support of received ELS commands Add support of received ELS commands - Add support for received RLS ELS command - Add support for received ECHO ELS command - Add support for received RTV ELS command Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 346 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 344 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/lpfc/lpfc_els.c') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index b16311d60c66..ea511d18f0ec 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -517,6 +517,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (sp->cmn.edtovResolution) /* E_D_TOV ticks are in nanoseconds */ phba->fc_edtov = (phba->fc_edtov + 999999) / 1000000; + phba->fc_edtovResol = sp->cmn.edtovResolution; phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000; if (phba->fc_topology == TOPOLOGY_LOOP) { @@ -3927,6 +3928,64 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, return 0; } +/** + * lpfc_els_rsp_echo_acc - Issue echo acc response + * @vport: pointer to a virtual N_Port data structure. + * @data: pointer to echo data to return in the accept. + * @oldiocb: pointer to the original lpfc command iocb data structure. + * @ndlp: pointer to a node-list data structure. + * + * Return code + * 0 - Successfully issued acc echo response + * 1 - Failed to issue acc echo response + **/ +static int +lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data, + struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp) +{ + struct lpfc_hba *phba = vport->phba; + struct lpfc_iocbq *elsiocb; + struct lpfc_sli *psli; + uint8_t *pcmd; + uint16_t cmdsize; + int rc; + + psli = &phba->sli; + cmdsize = oldiocb->iocb.unsli3.rcvsli3.acc_len; + + elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, + ndlp->nlp_DID, ELS_CMD_ACC); + if (!elsiocb) + return 1; + + elsiocb->iocb.ulpContext = oldiocb->iocb.ulpContext; /* Xri */ + /* Xmit ECHO ACC response tag */ + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "2876 Xmit ECHO ACC response tag x%x xri x%x\n", + elsiocb->iotag, elsiocb->iocb.ulpContext); + pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); + *((uint32_t *) (pcmd)) = ELS_CMD_ACC; + pcmd += sizeof(uint32_t); + memcpy(pcmd, data, cmdsize - sizeof(uint32_t)); + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, + "Issue ACC ECHO: did:x%x flg:x%x", + ndlp->nlp_DID, ndlp->nlp_flag, 0); + + phba->fc_stat.elsXmitACC++; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + lpfc_nlp_put(ndlp); + elsiocb->context1 = NULL; /* Don't need ndlp for cmpl, + * it could be freed */ + + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (rc == IOCB_ERROR) { + lpfc_els_free_iocb(phba, elsiocb); + return 1; + } + return 0; +} + /** * lpfc_els_disc_adisc - Issue remaining adisc iocbs to npr nodes of a vport * @vport: pointer to a host virtual N_Port data structure. @@ -4685,6 +4744,30 @@ lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, return 0; } +/** + * lpfc_els_rcv_echo - Process an unsolicited echo iocb + * @vport: pointer to a host virtual N_Port data structure. + * @cmdiocb: pointer to lpfc command iocb data structure. + * @ndlp: pointer to a node-list data structure. + * + * Return code + * 0 - Successfully processed echo iocb (currently always return 0) + **/ +static int +lpfc_els_rcv_echo(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, + struct lpfc_nodelist *ndlp) +{ + uint8_t *pcmd; + + pcmd = (uint8_t *) (((struct lpfc_dmabuf *) cmdiocb->context2)->virt); + + /* skip over first word of echo command to find echo data */ + pcmd += sizeof(uint32_t); + + lpfc_els_rsp_echo_acc(vport, pcmd, cmdiocb, ndlp); + return 0; +} + /** * lpfc_els_rcv_lirr - Process an unsolicited lirr iocb * @vport: pointer to a host virtual N_Port data structure. @@ -4736,6 +4819,89 @@ lpfc_els_rcv_rrq(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); } +/** + * lpfc_els_rsp_rls_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd + * @phba: pointer to lpfc hba data structure. + * @pmb: pointer to the driver internal queue element for mailbox command. + * + * This routine is the completion callback function for the MBX_READ_LNK_STAT + * mailbox command. This callback function is to actually send the Accept + * (ACC) response to a Read Port Status (RPS) unsolicited IOCB event. It + * collects the link statistics from the completion of the MBX_READ_LNK_STAT + * mailbox command, constructs the RPS response with the link statistics + * collected, and then invokes the lpfc_sli_issue_iocb() routine to send ACC + * response to the RPS. + * + * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp + * will be incremented by 1 for holding the ndlp and the reference to ndlp + * will be stored into the context1 field of the IOCB for the completion + * callback function to the RPS Accept Response ELS IOCB command. + * + **/ +static void +lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) +{ + MAILBOX_t *mb; + IOCB_t *icmd; + struct RLS_RSP *rls_rsp; + uint8_t *pcmd; + struct lpfc_iocbq *elsiocb; + struct lpfc_nodelist *ndlp; + uint16_t xri; + uint32_t cmdsize; + + mb = &pmb->u.mb; + + ndlp = (struct lpfc_nodelist *) pmb->context2; + xri = (uint16_t) ((unsigned long)(pmb->context1)); + pmb->context1 = NULL; + pmb->context2 = NULL; + + if (mb->mbxStatus) { + mempool_free(pmb, phba->mbox_mem_pool); + return; + } + + cmdsize = sizeof(struct RLS_RSP) + sizeof(uint32_t); + mempool_free(pmb, phba->mbox_mem_pool); + elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize, + lpfc_max_els_tries, ndlp, + ndlp->nlp_DID, ELS_CMD_ACC); + + /* Decrement the ndlp reference count from previous mbox command */ + lpfc_nlp_put(ndlp); + + if (!elsiocb) + return; + + icmd = &elsiocb->iocb; + icmd->ulpContext = xri; + + pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); + *((uint32_t *) (pcmd)) = ELS_CMD_ACC; + pcmd += sizeof(uint32_t); /* Skip past command */ + rls_rsp = (struct RLS_RSP *)pcmd; + + rls_rsp->linkFailureCnt = cpu_to_be32(mb->un.varRdLnk.linkFailureCnt); + rls_rsp->lossSyncCnt = cpu_to_be32(mb->un.varRdLnk.lossSyncCnt); + rls_rsp->lossSignalCnt = cpu_to_be32(mb->un.varRdLnk.lossSignalCnt); + rls_rsp->primSeqErrCnt = cpu_to_be32(mb->un.varRdLnk.primSeqErrCnt); + rls_rsp->invalidXmitWord = cpu_to_be32(mb->un.varRdLnk.invalidXmitWord); + rls_rsp->crcCnt = cpu_to_be32(mb->un.varRdLnk.crcCnt); + + /* Xmit ELS RLS ACC response tag */ + lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS, + "2874 Xmit ELS RLS ACC response tag x%x xri x%x, " + "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n", + elsiocb->iotag, elsiocb->iocb.ulpContext, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi); + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + phba->fc_stat.elsXmitACC++; + if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == IOCB_ERROR) + lpfc_els_free_iocb(phba, elsiocb); +} + /** * lpfc_els_rsp_rps_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd * @phba: pointer to lpfc hba data structure. @@ -4829,7 +4995,155 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } /** - * lpfc_els_rcv_rps - Process an unsolicited rps iocb + * lpfc_els_rcv_rls - Process an unsolicited rls iocb + * @vport: pointer to a host virtual N_Port data structure. + * @cmdiocb: pointer to lpfc command iocb data structure. + * @ndlp: pointer to a node-list data structure. + * + * This routine processes Read Port Status (RPL) IOCB received as an + * ELS unsolicited event. It first checks the remote port state. If the + * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE + * state, it invokes the lpfc_els_rsl_reject() routine to send the reject + * response. Otherwise, it issue the MBX_READ_LNK_STAT mailbox command + * for reading the HBA link statistics. It is for the callback function, + * lpfc_els_rsp_rls_acc(), set to the MBX_READ_LNK_STAT mailbox command + * to actually sending out RPL Accept (ACC) response. + * + * Return codes + * 0 - Successfully processed rls iocb (currently always return 0) + **/ +static int +lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, + struct lpfc_nodelist *ndlp) +{ + struct lpfc_hba *phba = vport->phba; + LPFC_MBOXQ_t *mbox; + struct lpfc_dmabuf *pcmd; + struct ls_rjt stat; + + if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && + (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) + /* reject the unsolicited RPS request and done with it */ + goto reject_out; + + pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; + + mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC); + if (mbox) { + lpfc_read_lnk_stat(phba, mbox); + mbox->context1 = + (void *)((unsigned long) cmdiocb->iocb.ulpContext); + mbox->context2 = lpfc_nlp_get(ndlp); + mbox->vport = vport; + mbox->mbox_cmpl = lpfc_els_rsp_rls_acc; + if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) + != MBX_NOT_FINISHED) + /* Mbox completion will send ELS Response */ + return 0; + /* Decrement reference count used for the failed mbox + * command. + */ + lpfc_nlp_put(ndlp); + mempool_free(mbox, phba->mbox_mem_pool); + } +reject_out: + /* issue rejection response */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; + stat.un.b.vendorUnique = 0; + lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); + return 0; +} + +/** + * lpfc_els_rcv_rtv - Process an unsolicited rtv iocb + * @vport: pointer to a host virtual N_Port data structure. + * @cmdiocb: pointer to lpfc command iocb data structure. + * @ndlp: pointer to a node-list data structure. + * + * This routine processes Read Timout Value (RTV) IOCB received as an + * ELS unsolicited event. It first checks the remote port state. If the + * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE + * state, it invokes the lpfc_els_rsl_reject() routine to send the reject + * response. Otherwise, it sends the Accept(ACC) response to a Read Timeout + * Value (RTV) unsolicited IOCB event. + * + * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp + * will be incremented by 1 for holding the ndlp and the reference to ndlp + * will be stored into the context1 field of the IOCB for the completion + * callback function to the RPS Accept Response ELS IOCB command. + * + * Return codes + * 0 - Successfully processed rtv iocb (currently always return 0) + **/ +static int +lpfc_els_rcv_rtv(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, + struct lpfc_nodelist *ndlp) +{ + struct lpfc_hba *phba = vport->phba; + struct ls_rjt stat; + struct RTV_RSP *rtv_rsp; + uint8_t *pcmd; + struct lpfc_iocbq *elsiocb; + uint32_t cmdsize; + + + if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && + (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) + /* reject the unsolicited RPS request and done with it */ + goto reject_out; + + cmdsize = sizeof(struct RTV_RSP) + sizeof(uint32_t); + elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize, + lpfc_max_els_tries, ndlp, + ndlp->nlp_DID, ELS_CMD_ACC); + + if (!elsiocb) + return 1; + + pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); + *((uint32_t *) (pcmd)) = ELS_CMD_ACC; + pcmd += sizeof(uint32_t); /* Skip past command */ + + /* use the command's xri in the response */ + elsiocb->iocb.ulpContext = cmdiocb->iocb.ulpContext; + + rtv_rsp = (struct RTV_RSP *)pcmd; + + /* populate RTV payload */ + rtv_rsp->ratov = cpu_to_be32(phba->fc_ratov * 1000); /* report msecs */ + rtv_rsp->edtov = cpu_to_be32(phba->fc_edtov); + bf_set(qtov_edtovres, rtv_rsp, phba->fc_edtovResol ? 1 : 0); + bf_set(qtov_rttov, rtv_rsp, 0); /* Field is for FC ONLY */ + rtv_rsp->qtov = cpu_to_be32(rtv_rsp->qtov); + + /* Xmit ELS RLS ACC response tag */ + lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS, + "2875 Xmit ELS RTV ACC response tag x%x xri x%x, " + "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x, " + "Data: x%x x%x x%x\n", + elsiocb->iotag, elsiocb->iocb.ulpContext, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi, + rtv_rsp->ratov, rtv_rsp->edtov, rtv_rsp->qtov); + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + phba->fc_stat.elsXmitACC++; + if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == IOCB_ERROR) + lpfc_els_free_iocb(phba, elsiocb); + return 0; + +reject_out: + /* issue rejection response */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; + stat.un.b.vendorUnique = 0; + lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); + return 0; +} + +/* lpfc_els_rcv_rps - Process an unsolicited rps iocb * @vport: pointer to a host virtual N_Port data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @ndlp: pointer to a node-list data structure. @@ -5019,7 +5333,6 @@ lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; lp = (uint32_t *) pcmd->virt; rpl = (RPL *) (lp + 1); - maxsize = be32_to_cpu(rpl->maxsize); /* We support only one port */ @@ -5838,6 +6151,16 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (newnode) lpfc_nlp_put(ndlp); break; + case ELS_CMD_RLS: + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, + "RCV RLS: did:x%x/ste:x%x flg:x%x", + did, vport->port_state, ndlp->nlp_flag); + + phba->fc_stat.elsRcvRLS++; + lpfc_els_rcv_rls(vport, elsiocb, ndlp); + if (newnode) + lpfc_nlp_put(ndlp); + break; case ELS_CMD_RPS: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, "RCV RPS: did:x%x/ste:x%x flg:x%x", @@ -5868,6 +6191,15 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (newnode) lpfc_nlp_put(ndlp); break; + case ELS_CMD_RTV: + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, + "RCV RTV: did:x%x/ste:x%x flg:x%x", + did, vport->port_state, ndlp->nlp_flag); + phba->fc_stat.elsRcvRTV++; + lpfc_els_rcv_rtv(vport, elsiocb, ndlp); + if (newnode) + lpfc_nlp_put(ndlp); + break; case ELS_CMD_RRQ: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, "RCV RRQ: did:x%x/ste:x%x flg:x%x", @@ -5878,6 +6210,16 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (newnode) lpfc_nlp_put(ndlp); break; + case ELS_CMD_ECHO: + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, + "RCV ECHO: did:x%x/ste:x%x flg:x%x", + did, vport->port_state, ndlp->nlp_flag); + + phba->fc_stat.elsRcvECHO++; + lpfc_els_rcv_echo(vport, elsiocb, ndlp); + if (newnode) + lpfc_nlp_put(ndlp); + break; default: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, "RCV ELS cmd: cmd:x%x did:x%x/ste:x%x", -- cgit v1.2.1 From a93ff37a8a869c7065a1b05f75e69bfb74eb599c Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 22 Oct 2010 11:06:08 -0400 Subject: [SCSI] lpfc 8.3.18: Add logic to detect last devloss timeout Added driver logic to detect the last devloss timeout of remote nodes which was still in use of FCF. At that point, the driver should set the last in-use remote node devloss timeout flag if it was not already set and should perform proper action on the in-use FCF and recover of FCF from firmware, depending on the state the driver's FIP engine is in. Find eligible FCF through FCF table rescan or the next new FCF event when FCF table rescan turned out empty eligible FCF, and the successful flogi into an FCF shall clear the HBA_DEVLOSS_TMO flag, indicating the successful recovery from devloss timeout. [jejb: add delay.h include to lpfc_hbadisc.c to fix ppc compile] Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 54 +++++++++----------------------------------- 1 file changed, 11 insertions(+), 43 deletions(-) (limited to 'drivers/scsi/lpfc/lpfc_els.c') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index ea511d18f0ec..b115e92025e5 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -795,7 +795,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (irsp->ulpStatus) { /* - * In case of FIP mode, perform round robin FCF failover + * In case of FIP mode, perform roundrobin FCF failover * due to new FCF discovery */ if ((phba->hba_flag & HBA_FIP_SUPPORT) && @@ -803,48 +803,16 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, (irsp->ulpStatus != IOSTAT_LOCAL_REJECT) && (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED)) { lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS, - "2611 FLOGI failed on registered " - "FCF record fcf_index(%d), status: " - "x%x/x%x, tmo:x%x, trying to perform " - "round robin failover\n", + "2611 FLOGI failed on FCF (x%x), " + "status:x%x/x%x, tmo:x%x, perform " + "roundrobin FCF failover\n", phba->fcf.current_rec.fcf_indx, irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout); fcf_index = lpfc_sli4_fcf_rr_next_index_get(phba); - if (fcf_index == LPFC_FCOE_FCF_NEXT_NONE) { - /* - * Exhausted the eligible FCF record list, - * fail through to retry FLOGI on current - * FCF record. - */ - lpfc_printf_log(phba, KERN_WARNING, - LOG_FIP | LOG_ELS, - "2760 Completed one round " - "of FLOGI FCF round robin " - "failover list, retry FLOGI " - "on currently registered " - "FCF index:%d\n", - phba->fcf.current_rec.fcf_indx); - } else { - lpfc_printf_log(phba, KERN_INFO, - LOG_FIP | LOG_ELS, - "2794 FLOGI FCF round robin " - "failover to FCF index x%x\n", - fcf_index); - rc = lpfc_sli4_fcf_rr_read_fcf_rec(phba, - fcf_index); - if (rc) - lpfc_printf_log(phba, KERN_WARNING, - LOG_FIP | LOG_ELS, - "2761 FLOGI round " - "robin FCF failover " - "read FCF failed " - "rc:x%x, fcf_index:" - "%d\n", rc, - phba->fcf.current_rec.fcf_indx); - else - goto out; - } + rc = lpfc_sli4_fcf_rr_next_proc(vport, fcf_index); + if (rc) + goto out; } /* FLOGI failure */ @@ -934,6 +902,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_nlp_put(ndlp); spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag &= ~FCF_DISCOVERY; + phba->hba_flag &= ~(FCF_RR_INPROG | HBA_DEVLOSS_TMO); spin_unlock_irq(&phba->hbalock); goto out; } @@ -942,13 +911,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (phba->hba_flag & HBA_FIP_SUPPORT) lpfc_printf_vlog(vport, KERN_INFO, LOG_FIP | LOG_ELS, - "2769 FLOGI successful on FCF " - "record: current_fcf_index:" - "x%x, terminate FCF round " - "robin failover process\n", + "2769 FLOGI to FCF (x%x) " + "completed successfully\n", phba->fcf.current_rec.fcf_indx); spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag &= ~FCF_DISCOVERY; + phba->hba_flag &= ~(FCF_RR_INPROG | HBA_DEVLOSS_TMO); spin_unlock_irq(&phba->hbalock); goto out; } -- cgit v1.2.1 From 5af5eee7ca4051d8ca31edeb5216831da9625b5c Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 22 Oct 2010 11:06:38 -0400 Subject: [SCSI] lpfc 8.3.18: Adapter Shutdown and Unregistration cleanup Adapter Shutdown and Unregistration cleanup - Correct the logic around hba shutdown. Prior to final reset, the driver must wait for all XRIs to return from the adapter. Added logic to poll, progressively slowing the poll rate as delay gets longer. - Correct behavior around the rsvd1 field in UNREG_RPI_ALL mailbox completion and final rpi cleanup. - Updated logic to move pending VPI registrations to their completion in cases where a CVL may be received while registration in progress. - Added unreg all rpi mailbox command before unreg vpi. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/scsi/lpfc/lpfc_els.c') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index b115e92025e5..e61b57df241b 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -580,6 +580,10 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_unreg_rpi(vport, np); } lpfc_cleanup_pending_mbox(vport); + + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_unreg_all_rpis(vport); + if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { lpfc_mbx_unreg_vpi(vport); spin_lock_irq(shost->host_lock); @@ -6482,6 +6486,8 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) default: /* Try to recover from this error */ + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_unreg_all_rpis(vport); lpfc_mbx_unreg_vpi(vport); spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; @@ -6749,6 +6755,10 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_unreg_rpi(vport, np); } lpfc_cleanup_pending_mbox(vport); + + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_unreg_all_rpis(vport); + lpfc_mbx_unreg_vpi(vport); spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; -- cgit v1.2.1 From f0d9bccc9084b8fe86fa2830a434259d140679c9 Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 22 Oct 2010 11:07:09 -0400 Subject: [SCSI] lpfc 8.3.18: Add new WQE support - Add new WQE fields as defined by new SLI interface to support new hardware. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/lpfc/lpfc_els.c') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index e61b57df241b..884f4d321799 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -177,15 +177,18 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, (elscmd == ELS_CMD_LOGO))) switch (elscmd) { case ELS_CMD_FLOGI: - elsiocb->iocb_flag |= ((ELS_ID_FLOGI << LPFC_FIP_ELS_ID_SHIFT) + elsiocb->iocb_flag |= + ((LPFC_ELS_ID_FLOGI << LPFC_FIP_ELS_ID_SHIFT) & LPFC_FIP_ELS_ID_MASK); break; case ELS_CMD_FDISC: - elsiocb->iocb_flag |= ((ELS_ID_FDISC << LPFC_FIP_ELS_ID_SHIFT) + elsiocb->iocb_flag |= + ((LPFC_ELS_ID_FDISC << LPFC_FIP_ELS_ID_SHIFT) & LPFC_FIP_ELS_ID_MASK); break; case ELS_CMD_LOGO: - elsiocb->iocb_flag |= ((ELS_ID_LOGO << LPFC_FIP_ELS_ID_SHIFT) + elsiocb->iocb_flag |= + ((LPFC_ELS_ID_LOGO << LPFC_FIP_ELS_ID_SHIFT) & LPFC_FIP_ELS_ID_MASK); break; } -- cgit v1.2.1