⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lpfc_els.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		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 + -