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

📄 lpfc_nportdisc.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
lpfc_rcv_logo(struct lpfc_hba * phba,		      struct lpfc_nodelist * ndlp,		      struct lpfc_iocbq *cmdiocb){	/* Put ndlp on NPR list with 1 sec timeout for plogi, ACC logo */	/* Only call LOGO ACC for first LOGO, this avoids sending unnecessary	 * PLOGIs during LOGO storms from a device.	 */	ndlp->nlp_flag |= NLP_LOGO_ACC;	lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);	if (!(ndlp->nlp_type & NLP_FABRIC)) {		/* Only try to re-login if this is NOT a Fabric Node */		ndlp->nlp_last_elscmd = (unsigned long)ELS_CMD_PLOGI;		mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);		spin_lock_irq(phba->host->host_lock);		ndlp->nlp_flag |= NLP_DELAY_TMO;		spin_unlock_irq(phba->host->host_lock);	}	ndlp->nlp_state = NLP_STE_NPR_NODE;	lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);	ndlp->nlp_flag &= ~NLP_NPR_ADISC;	/* The driver has to wait until the ACC completes before it continues	 * processing the LOGO.  The action will resume in	 * lpfc_cmpl_els_logo_acc routine. Since part of processing includes an	 * unreg_login, the driver waits so the ACC does not get aborted.	 */	return (0);}static voidlpfc_rcv_prli(struct lpfc_hba * phba,		      struct lpfc_nodelist * ndlp,		      struct lpfc_iocbq *cmdiocb){	struct lpfc_dmabuf *pcmd;	uint32_t *lp;	PRLI *npr;	struct fc_rport *rport = ndlp->rport;	u32 roles;	pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;	lp = (uint32_t *) pcmd->virt;	npr = (PRLI *) ((uint8_t *) lp + sizeof (uint32_t));	ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);	ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;	if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) &&	    (npr->prliType == PRLI_FCP_TYPE)) {		if (npr->initiatorFunc)			ndlp->nlp_type |= NLP_FCP_INITIATOR;		if (npr->targetFunc)			ndlp->nlp_type |= NLP_FCP_TARGET;		if (npr->Retry)			ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;	}	if (rport) {		/* We need to update the rport role values */		roles = FC_RPORT_ROLE_UNKNOWN;		if (ndlp->nlp_type & NLP_FCP_INITIATOR)			roles |= FC_RPORT_ROLE_FCP_INITIATOR;		if (ndlp->nlp_type & NLP_FCP_TARGET)			roles |= FC_RPORT_ROLE_FCP_TARGET;		fc_remote_port_rolechg(rport, roles);	}}static uint32_tlpfc_disc_set_adisc(struct lpfc_hba * phba,		      struct lpfc_nodelist * ndlp){	/* Check config parameter use-adisc or FCP-2 */	if ((phba->cfg_use_adisc == 0) &&		!(phba->fc_flag & FC_RSCN_MODE)) {		if (!(ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE))			return (0);	}	spin_lock_irq(phba->host->host_lock);	ndlp->nlp_flag |= NLP_NPR_ADISC;	spin_unlock_irq(phba->host->host_lock);	return (1);}static uint32_tlpfc_disc_noop(struct lpfc_hba * phba,		struct lpfc_nodelist * ndlp, void *arg, uint32_t evt){	/* This routine does nothing, just return the current state */	return (ndlp->nlp_state);}static uint32_tlpfc_disc_illegal(struct lpfc_hba * phba,		   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt){	lpfc_printf_log(phba,			KERN_ERR,			LOG_DISCOVERY,			"%d:0253 Illegal State Transition: node x%x event x%x, "			"state x%x Data: x%x x%x\n",			phba->brd_no,			ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,			ndlp->nlp_flag);	return (ndlp->nlp_state);}/* Start of Discovery State Machine routines */static uint32_tlpfc_rcv_plogi_unused_node(struct lpfc_hba * phba,			   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt){	struct lpfc_iocbq *cmdiocb;	cmdiocb = (struct lpfc_iocbq *) arg;	if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {		ndlp->nlp_state = NLP_STE_UNUSED_NODE;		lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);		return (ndlp->nlp_state);	}	lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);	return (NLP_STE_FREED_NODE);}static uint32_tlpfc_rcv_els_unused_node(struct lpfc_hba * phba,			 struct lpfc_nodelist * ndlp, void *arg, uint32_t evt){	lpfc_issue_els_logo(phba, ndlp, 0);	lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);	return (ndlp->nlp_state);}static uint32_tlpfc_rcv_logo_unused_node(struct lpfc_hba * phba,			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt){	struct lpfc_iocbq     *cmdiocb;	cmdiocb = (struct lpfc_iocbq *) arg;	spin_lock_irq(phba->host->host_lock);	ndlp->nlp_flag |= NLP_LOGO_ACC;	spin_unlock_irq(phba->host->host_lock);	lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);	lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);	return (ndlp->nlp_state);}static uint32_tlpfc_cmpl_logo_unused_node(struct lpfc_hba * phba,			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt){	lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);	return (NLP_STE_FREED_NODE);}static uint32_tlpfc_device_rm_unused_node(struct lpfc_hba * phba,			   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt){	lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);	return (NLP_STE_FREED_NODE);}static uint32_tlpfc_rcv_plogi_plogi_issue(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,			   void *arg, uint32_t evt){	struct lpfc_iocbq *cmdiocb = arg;	struct lpfc_dmabuf *pcmd;	struct serv_parm *sp;	uint32_t *lp;	struct ls_rjt stat;	int port_cmp;	pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;	lp = (uint32_t *) pcmd->virt;	sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));	memset(&stat, 0, sizeof (struct ls_rjt));	/* For a PLOGI, we only accept if our portname is less	 * than the remote portname.	 */	phba->fc_stat.elsLogiCol++;	port_cmp = memcmp(&phba->fc_portname, &sp->portName,			  sizeof (struct lpfc_name));	if (port_cmp >= 0) {		/* Reject this request because the remote node will accept		   ours */		stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;		stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;		lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);	}	else {		lpfc_rcv_plogi(phba, ndlp, cmdiocb);	} /* if our portname was less */	return (ndlp->nlp_state);}static uint32_tlpfc_rcv_els_plogi_issue(struct lpfc_hba * phba,			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt){	struct lpfc_iocbq     *cmdiocb;	cmdiocb = (struct lpfc_iocbq *) arg;	/* software abort outstanding PLOGI */	lpfc_els_abort(phba, ndlp, 1);	mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);	spin_lock_irq(phba->host->host_lock);	ndlp->nlp_flag |= NLP_DELAY_TMO;	spin_unlock_irq(phba->host->host_lock);	if (evt == NLP_EVT_RCV_LOGO) {		lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);	}	else {		lpfc_issue_els_logo(phba, ndlp, 0);	}	/* Put ndlp in npr list set plogi timer for 1 sec */	ndlp->nlp_last_elscmd = (unsigned long)ELS_CMD_PLOGI;	ndlp->nlp_state = NLP_STE_NPR_NODE;	lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);	return (ndlp->nlp_state);}static uint32_tlpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,			    struct lpfc_nodelist * ndlp, void *arg,			    uint32_t evt){	struct lpfc_iocbq *cmdiocb, *rspiocb;	struct lpfc_dmabuf *pcmd, *prsp;	uint32_t *lp;	IOCB_t *irsp;	struct serv_parm *sp;	LPFC_MBOXQ_t *mbox;	cmdiocb = (struct lpfc_iocbq *) arg;	rspiocb = cmdiocb->context_un.rsp_iocb;	if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {		return (ndlp->nlp_state);	}	irsp = &rspiocb->iocb;	if (irsp->ulpStatus)		goto out;	pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;	prsp = list_get_first(&pcmd->list,			      struct lpfc_dmabuf,			      list);	lp = (uint32_t *) prsp->virt;	sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));	if (!lpfc_check_sparm(phba, ndlp, sp, CLASS3))		goto out;	/* PLOGI chkparm OK */	lpfc_printf_log(phba,			KERN_INFO,			LOG_ELS,			"%d:0121 PLOGI chkparm OK "			"Data: x%x x%x x%x x%x\n",			phba->brd_no,			ndlp->nlp_DID, ndlp->nlp_state,			ndlp->nlp_flag, ndlp->nlp_rpi);	if ((phba->cfg_fcp_class == 2) &&	    (sp->cls2.classValid)) {		ndlp->nlp_fcp_info |= CLASS2;	} else {		ndlp->nlp_fcp_info |= CLASS3;	}	ndlp->nlp_class_sup = 0;	if (sp->cls1.classValid)		ndlp->nlp_class_sup |= FC_COS_CLASS1;	if (sp->cls2.classValid)		ndlp->nlp_class_sup |= FC_COS_CLASS2;	if (sp->cls3.classValid)		ndlp->nlp_class_sup |= FC_COS_CLASS3;	if (sp->cls4.classValid)		ndlp->nlp_class_sup |= FC_COS_CLASS4;	ndlp->nlp_maxframe =		((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |		sp->cmn.bbRcvSizeLsb;	if (!(mbox = mempool_alloc(phba->mbox_mem_pool,				   GFP_KERNEL)))		goto out;	lpfc_unreg_rpi(phba, ndlp);	if (lpfc_reg_login	    (phba, irsp->un.elsreq64.remoteID,	     (uint8_t *) sp, mbox, 0) == 0) {		/* set_slim mailbox command needs to		 * execute first, queue this command to		 * be processed later.		 */		switch(ndlp->nlp_DID) {		case NameServer_DID:			mbox->mbox_cmpl =				lpfc_mbx_cmpl_ns_reg_login;			break;		case FDMI_DID:			mbox->mbox_cmpl =				lpfc_mbx_cmpl_fdmi_reg_login;			break;		default:			mbox->mbox_cmpl =				lpfc_mbx_cmpl_reg_login;		}		mbox->context2 = ndlp;		if (lpfc_sli_issue_mbox(phba, mbox,					(MBX_NOWAIT | MBX_STOP_IOCB))		    != MBX_NOT_FINISHED) {			ndlp->nlp_state =				NLP_STE_REG_LOGIN_ISSUE;			lpfc_nlp_list(phba, ndlp,				      NLP_REGLOGIN_LIST);			return (ndlp->nlp_state);		}		mempool_free(mbox, phba->mbox_mem_pool);	} else {		mempool_free(mbox, phba->mbox_mem_pool);	} out:	/* Free this node since the driver cannot login or has the wrong	   sparm */	lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);	return (NLP_STE_FREED_NODE);}static uint32_tlpfc_device_rm_plogi_issue(struct lpfc_hba * phba,			   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt){	/* software abort outstanding PLOGI */	lpfc_els_abort(phba, ndlp, 1);	lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);	return (NLP_STE_FREED_NODE);}static uint32_tlpfc_device_recov_plogi_issue(struct lpfc_hba * phba,			    struct lpfc_nodelist * ndlp, void *arg,			    uint32_t evt){	/* software abort outstanding PLOGI */	lpfc_els_abort(phba, ndlp, 1);	ndlp->nlp_state = NLP_STE_NPR_NODE;	lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);	spin_lock_irq(phba->host->host_lock);	ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;	spin_unlock_irq(phba->host->host_lock);	return (ndlp->nlp_state);}static uint32_tlpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba,			    struct lpfc_nodelist * ndlp, void *arg,			    uint32_t evt){	struct lpfc_iocbq *cmdiocb;	/* software abort outstanding ADISC */	lpfc_els_abort(phba, ndlp, 1);	cmdiocb = (struct lpfc_iocbq *) arg;	if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {		return (ndlp->nlp_state);	}	ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;	lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);	lpfc_issue_els_plogi(phba, ndlp, 0);	return (ndlp->nlp_state);}static uint32_tlpfc_rcv_prli_adisc_issue(struct lpfc_hba * phba,			    struct lpfc_nodelist * ndlp, void *arg,			    uint32_t evt){	struct lpfc_iocbq *cmdiocb;	cmdiocb = (struct lpfc_iocbq *) arg;	lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);	return (ndlp->nlp_state);}static uint32_tlpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba,			    struct lpfc_nodelist * ndlp, void *arg,			    uint32_t evt){	struct lpfc_iocbq *cmdiocb;	cmdiocb = (struct lpfc_iocbq *) arg;	/* software abort outstanding ADISC */	lpfc_els_abort(phba, ndlp, 0);	lpfc_rcv_logo(phba, ndlp, cmdiocb);	return (ndlp->nlp_state);}static uint32_tlpfc_rcv_padisc_adisc_issue(struct lpfc_hba * phba,			    struct lpfc_nodelist * ndlp, void *arg,			    uint32_t evt){	struct lpfc_iocbq *cmdiocb;	cmdiocb = (struct lpfc_iocbq *) arg;	lpfc_rcv_padisc(phba, ndlp, cmdiocb);	return (ndlp->nlp_state);}static uint32_tlpfc_rcv_prlo_adisc_issue(struct lpfc_hba * phba,			    struct lpfc_nodelist * ndlp, void *arg,			    uint32_t evt){	struct lpfc_iocbq *cmdiocb;	cmdiocb = (struct lpfc_iocbq *) arg;	/* Treat like rcv logo */	lpfc_rcv_logo(phba, ndlp, cmdiocb);	return (ndlp->nlp_state);}static uint32_tlpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba,			    struct lpfc_nodelist * ndlp, void *arg,			    uint32_t evt)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -