📄 lpfc_els.c
字号:
lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); lpfc_issue_els_prli(phba, ndlp, retry); break; case ELS_CMD_LOGO: ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); lpfc_issue_els_logo(phba, ndlp, retry); break; } return;}static intlpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb){ IOCB_t *irsp; struct lpfc_dmabuf *pcmd; struct lpfc_nodelist *ndlp; uint32_t *elscmd; struct ls_rjt stat; int retry, maxretry; int delay; uint32_t cmd; retry = 0; delay = 0; maxretry = lpfc_max_els_tries; irsp = &rspiocb->iocb; ndlp = (struct lpfc_nodelist *) cmdiocb->context1; pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; cmd = 0; /* Note: context2 may be 0 for internal driver abort * of delays ELS command. */ if (pcmd && pcmd->virt) { elscmd = (uint32_t *) (pcmd->virt); cmd = *elscmd++; } switch (irsp->ulpStatus) { case IOSTAT_FCP_RSP_ERROR: case IOSTAT_REMOTE_STOP: break; case IOSTAT_LOCAL_REJECT: switch ((irsp->un.ulpWord[4] & 0xff)) { case IOERR_LOOP_OPEN_FAILURE: if (cmd == ELS_CMD_PLOGI) { if (cmdiocb->retry == 0) { delay = 1; } } retry = 1; break; case IOERR_SEQUENCE_TIMEOUT: retry = 1; if ((cmd == ELS_CMD_FLOGI) && (phba->fc_topology != TOPOLOGY_LOOP)) { delay = 1; maxretry = 48; } break; case IOERR_NO_RESOURCES: if (cmd == ELS_CMD_PLOGI) { delay = 1; } retry = 1; break; case IOERR_INVALID_RPI: retry = 1; break; } break; case IOSTAT_NPORT_RJT: case IOSTAT_FABRIC_RJT: if (irsp->un.ulpWord[4] & RJT_UNAVAIL_TEMP) { retry = 1; break; } break; case IOSTAT_NPORT_BSY: case IOSTAT_FABRIC_BSY: retry = 1; break; case IOSTAT_LS_RJT: stat.un.lsRjtError = be32_to_cpu(irsp->un.ulpWord[4]); /* Added for Vendor specifc support * Just keep retrying for these Rsn / Exp codes */ switch (stat.un.b.lsRjtRsnCode) { case LSRJT_UNABLE_TPC: if (stat.un.b.lsRjtRsnCodeExp == LSEXP_CMD_IN_PROGRESS) { if (cmd == ELS_CMD_PLOGI) { delay = 1; maxretry = 48; } retry = 1; break; } if (cmd == ELS_CMD_PLOGI) { delay = 1; maxretry = lpfc_max_els_tries + 1; retry = 1; break; } break; case LSRJT_LOGICAL_BSY: if (cmd == ELS_CMD_PLOGI) { delay = 1; maxretry = 48; } retry = 1; break; } break; case IOSTAT_INTERMED_RSP: case IOSTAT_BA_RJT: break; default: break; } if (ndlp->nlp_DID == FDMI_DID) { retry = 1; } if ((++cmdiocb->retry) >= maxretry) { phba->fc_stat.elsRetryExceeded++; retry = 0; } if (retry) { /* Retry ELS command <elsCmd> to remote NPORT <did> */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0107 Retry ELS command x%x to remote " "NPORT x%x Data: x%x x%x\n", phba->brd_no, cmd, ndlp->nlp_DID, cmdiocb->retry, delay); if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) { /* If discovery / RSCN timer is running, reset it */ if (timer_pending(&phba->fc_disctmo) || (phba->fc_flag & FC_RSCN_MODE)) { lpfc_set_disctmo(phba); } } phba->fc_stat.elsXmitRetry++; if (delay) { phba->fc_stat.elsDelayRetry++; ndlp->nlp_retry = cmdiocb->retry; mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); ndlp->nlp_flag |= NLP_DELAY_TMO; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); ndlp->nlp_last_elscmd = cmd; return (1); } switch (cmd) { case ELS_CMD_FLOGI: lpfc_issue_els_flogi(phba, ndlp, cmdiocb->retry); return (1); case ELS_CMD_PLOGI: ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp, cmdiocb->retry); return (1); case ELS_CMD_ADISC: ndlp->nlp_state = NLP_STE_ADISC_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry); return (1); case ELS_CMD_PRLI: ndlp->nlp_state = NLP_STE_PRLI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry); return (1); case ELS_CMD_LOGO: ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry); return (1); } } /* No retry ELS command <elsCmd> to remote NPORT <did> */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0108 No retry ELS command x%x to remote NPORT x%x " "Data: x%x x%x\n", phba->brd_no, cmd, ndlp->nlp_DID, cmdiocb->retry, ndlp->nlp_flag); return (0);}intlpfc_els_free_iocb(struct lpfc_hba * phba, struct lpfc_iocbq * elsiocb){ struct lpfc_dmabuf *buf_ptr, *buf_ptr1; /* context2 = cmd, context2->next = rsp, context3 = bpl */ if (elsiocb->context2) { buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2; /* Free the response before processing the command. */ if (!list_empty(&buf_ptr1->list)) { list_remove_head(&buf_ptr1->list, buf_ptr, struct lpfc_dmabuf, list); lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); kfree(buf_ptr); } lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys); kfree(buf_ptr1); } if (elsiocb->context3) { buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3; lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); kfree(buf_ptr); } spin_lock_irq(phba->host->host_lock); lpfc_sli_release_iocbq(phba, elsiocb); spin_unlock_irq(phba->host->host_lock); return 0;}static voidlpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb){ struct lpfc_nodelist *ndlp; ndlp = (struct lpfc_nodelist *) cmdiocb->context1; /* ACC to LOGO completes to NPort <nlp_DID> */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0109 ACC to LOGO completes to NPort x%x " "Data: x%x x%x x%x\n", phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_LOGO_ACC; spin_unlock_irq(phba->host->host_lock); switch (ndlp->nlp_state) { case NLP_STE_UNUSED_NODE: /* node is just allocated */ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); break; case NLP_STE_NPR_NODE: /* NPort Recovery mode */ lpfc_unreg_rpi(phba, ndlp); break; default: break; } lpfc_els_free_iocb(phba, cmdiocb); return;}static voidlpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb){ struct lpfc_nodelist *ndlp; LPFC_MBOXQ_t *mbox = NULL; ndlp = (struct lpfc_nodelist *) cmdiocb->context1; if (cmdiocb->context_un.mbox) mbox = cmdiocb->context_un.mbox; /* Check to see if link went down during discovery */ if ((lpfc_els_chk_latt(phba)) || !ndlp) { if (mbox) { mempool_free( mbox, phba->mbox_mem_pool); } goto out; } /* ELS response tag <ulpIoTag> completes */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0110 ELS response tag x%x completes " "Data: x%x x%x x%x x%x x%x x%x\n", phba->brd_no, cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus, rspiocb->iocb.un.ulpWord[4], ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); if (mbox) { if ((rspiocb->iocb.ulpStatus == 0) && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { /* set_slim mailbox command needs to execute first, * queue this command to be processed later. */ lpfc_unreg_rpi(phba, ndlp); mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; mbox->context2 = ndlp; ndlp->nlp_state = NLP_STE_REG_LOGIN_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_REGLOGIN_LIST); if (lpfc_sli_issue_mbox(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) { goto out; } /* NOTE: we should have messages for unsuccessful reglogin */ mempool_free( mbox, phba->mbox_mem_pool); } else { mempool_free( mbox, phba->mbox_mem_pool); if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) { lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); } } }out: if (ndlp) { spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN; spin_unlock_irq(phba->host->host_lock); } lpfc_els_free_iocb(phba, cmdiocb); return;}intlpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp, LPFC_MBOXQ_t * mbox, uint8_t newnode){ IOCB_t *icmd; IOCB_t *oldcmd; struct lpfc_iocbq *elsiocb; struct lpfc_sli_ring *pring; struct lpfc_sli *psli; uint8_t *pcmd; uint16_t cmdsize; int rc; psli = &phba->sli; pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ oldcmd = &oldiocb->iocb; switch (flag) { case ELS_CMD_ACC: cmdsize = sizeof (uint32_t); if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp, ELS_CMD_ACC)) == 0) { return (1); } icmd = &elsiocb->iocb; icmd->ulpContext = oldcmd->ulpContext; /* Xri */ pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); *((uint32_t *) (pcmd)) = ELS_CMD_ACC; pcmd += sizeof (uint32_t); break; case ELS_CMD_PLOGI: cmdsize = (sizeof (struct serv_parm) + sizeof (uint32_t)); if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp, ELS_CMD_ACC)) == 0) { return (1); } icmd = &elsiocb->iocb; icmd->ulpContext = oldcmd->ulpContext; /* Xri */ pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); if (mbox) elsiocb->context_un.mbox = mbox; *((uint32_t *) (pcmd)) = ELS_CMD_ACC; pcmd += sizeof (uint32_t); memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm)); break; default: return (1); } if (newnode) elsiocb->context1 = NULL; /* Xmit ELS ACC response tag <ulpIoTag> */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0128 Xmit ELS ACC response tag x%x " "Data: x%x x%x x%x x%x x%x\n", phba->brd_no, elsiocb->iocb.ulpIoTag, elsiocb->iocb.ulpContext, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); if (ndlp->nlp_flag & NLP_LOGO_ACC) { elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc; } else { elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; } phba->fc_stat.elsXmitACC++; spin_lock_irq(phba->host->host_lock); rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); spin_unlock_irq(phba->host->host_lock); if (rc == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); return (1); } return (0);}intlpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError, struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp){ IOCB_t *icmd; IOCB_t *oldcmd; struct lpfc_iocbq *elsiocb; struct lpfc_sli_ring *pring; struct lpfc_sli *psli; uint8_t *pcmd; uint16_t cmdsize; int rc; psli = &phba->sli; pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ cmdsize = 2 * sizeof (uint32_t); if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp, ELS_CMD_LS_RJT)) == 0) { return (1); } icmd = &elsiocb->iocb; oldcmd = &oldiocb->iocb; icmd->ulpContext = oldcmd->ulpContext; /* Xri */ pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); *((uint32_t *) (pcmd)) = ELS_CMD_LS_RJT; pcmd += sizeof (uint32_t); *((uint32_t *) (pcmd)) = rejectError; /* Xmit ELS RJT <err> response tag <ulpIoTag> */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0129 Xmit ELS RJT x%x response tag x%x " "Data: x%x x%x x%x x%x x%x\n", phba->brd_no, rejectError, elsiocb->iocb.ulpIoTag, elsiocb->iocb.ulpContext, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); phba->fc_stat.elsXmitLSRJT++; elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; spin_lock_irq(phba->host->host_lock); rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); spin_unlock_irq(phba->host->host_lock); if (rc == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); return (1); } return (0);}intlpfc_els_rsp_adisc_acc(struct lpfc_hba * phba, struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp){ ADISC *ap; IOCB_t *icmd; IOCB_t *oldcmd; struct lpfc_iocbq *elsiocb; struct lpfc_sli_ring *pring; struct lpfc_sli *psli; uint8_t *pcmd; uint16_t cmdsize; int rc; psli = &phba->sli; pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -