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

📄 lpfc_els.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* Start discovery */		lpfc_disc_start(phba);	}out:	lpfc_els_free_iocb(phba, cmdiocb);}static intlpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,		     uint8_t retry){	struct serv_parm *sp;	IOCB_t *icmd;	struct lpfc_iocbq *elsiocb;	struct lpfc_sli_ring *pring;	uint8_t *pcmd;	uint16_t cmdsize;	uint32_t tmo;	int rc;	pring = &phba->sli.ring[LPFC_ELS_RING];	cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));	if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry,					  ndlp, ELS_CMD_FLOGI)) == 0) {		return (1);	}	icmd = &elsiocb->iocb;	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);	/* For FLOGI request, remainder of payload is service parameters */	*((uint32_t *) (pcmd)) = ELS_CMD_FLOGI;	pcmd += sizeof (uint32_t);	memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));	sp = (struct serv_parm *) pcmd;	/* Setup CSPs accordingly for Fabric */	sp->cmn.e_d_tov = 0;	sp->cmn.w2.r_a_tov = 0;	sp->cls1.classValid = 0;	sp->cls2.seqDelivery = 1;	sp->cls3.seqDelivery = 1;	if (sp->cmn.fcphLow < FC_PH3)		sp->cmn.fcphLow = FC_PH3;	if (sp->cmn.fcphHigh < FC_PH3)		sp->cmn.fcphHigh = FC_PH3;	tmo = phba->fc_ratov;	phba->fc_ratov = LPFC_DISC_FLOGI_TMO;	lpfc_set_disctmo(phba);	phba->fc_ratov = tmo;	phba->fc_stat.elsXmitFLOGI++;	elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi;	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_abort_flogi(struct lpfc_hba * phba){	struct lpfc_sli_ring *pring;	struct lpfc_iocbq *iocb, *next_iocb;	struct lpfc_nodelist *ndlp;	IOCB_t *icmd;	/* Abort outstanding I/O on NPort <nlp_DID> */	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,			"%d:0201 Abort outstanding I/O on NPort x%x\n",			phba->brd_no, Fabric_DID);	pring = &phba->sli.ring[LPFC_ELS_RING];	/*	 * Check the txcmplq for an iocb that matches the nport the driver is	 * searching for.	 */	spin_lock_irq(phba->host->host_lock);	list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {		icmd = &iocb->iocb;		if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) {			ndlp = (struct lpfc_nodelist *)(iocb->context1);			if (ndlp && (ndlp->nlp_DID == Fabric_DID)) {				list_del(&iocb->list);				pring->txcmplq_cnt--;				if ((icmd->un.elsreq64.bdl.ulpIoTag32)) {					lpfc_sli_issue_abort_iotag32						(phba, pring, iocb);				}				if (iocb->iocb_cmpl) {					icmd->ulpStatus = IOSTAT_LOCAL_REJECT;					icmd->un.ulpWord[4] =					    IOERR_SLI_ABORTED;					spin_unlock_irq(phba->host->host_lock);					(iocb->iocb_cmpl) (phba, iocb, iocb);					spin_lock_irq(phba->host->host_lock);				} else					lpfc_sli_release_iocbq(phba, iocb);			}		}	}	spin_unlock_irq(phba->host->host_lock);	return 0;}intlpfc_initial_flogi(struct lpfc_hba * phba){	struct lpfc_nodelist *ndlp;	/* First look for Fabric ndlp on the unmapped list */	if ((ndlp =	     lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED,			       Fabric_DID)) == 0) {		/* Cannot find existing Fabric ndlp, so allocate a new one */		if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL))		    == 0) {			return (0);		}		lpfc_nlp_init(phba, ndlp, Fabric_DID);	}	else {		phba->fc_unmap_cnt--;		list_del(&ndlp->nlp_listp);		spin_lock_irq(phba->host->host_lock);		ndlp->nlp_flag &= ~NLP_LIST_MASK;		spin_unlock_irq(phba->host->host_lock);	}	if (lpfc_issue_els_flogi(phba, ndlp, 0)) {		mempool_free( ndlp, phba->nlp_mem_pool);	}	return (1);}static voidlpfc_more_plogi(struct lpfc_hba * phba){	int sentplogi;	if (phba->num_disc_nodes)		phba->num_disc_nodes--;	/* Continue discovery with <num_disc_nodes> PLOGIs to go */	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,			"%d:0232 Continue discovery with %d PLOGIs to go "			"Data: x%x x%x x%x\n",			phba->brd_no, phba->num_disc_nodes, phba->fc_plogi_cnt,			phba->fc_flag, phba->hba_state);	/* Check to see if there are more PLOGIs to be sent */	if (phba->fc_flag & FC_NLP_MORE) {		/* go thru NPR list and issue any remaining ELS PLOGIs */		sentplogi = lpfc_els_disc_plogi(phba);	}	return;}static voidlpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,		    struct lpfc_iocbq * rspiocb){	IOCB_t *irsp;	struct lpfc_sli *psli;	struct lpfc_nodelist *ndlp;	int disc, rc, did, type;	psli = &phba->sli;	/* we pass cmdiocb to state machine which needs rspiocb as well */	cmdiocb->context_un.rsp_iocb = rspiocb;	irsp = &rspiocb->iocb;	ndlp = (struct lpfc_nodelist *) cmdiocb->context1;	spin_lock_irq(phba->host->host_lock);	ndlp->nlp_flag &= ~NLP_PLOGI_SND;	spin_unlock_irq(phba->host->host_lock);	/* Since ndlp can be freed in the disc state machine, note if this node	 * is being used during discovery.	 */	disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);	rc   = 0;	/* PLOGI completes to NPort <nlp_DID> */	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,			"%d:0102 PLOGI completes to NPort x%x "			"Data: x%x x%x x%x x%x\n",			phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,			irsp->un.ulpWord[4], disc, phba->num_disc_nodes);	/* Check to see if link went down during discovery */	if (lpfc_els_chk_latt(phba)) {		spin_lock_irq(phba->host->host_lock);		ndlp->nlp_flag |= NLP_NPR_2B_DISC;		spin_unlock_irq(phba->host->host_lock);		goto out;	}	/* ndlp could be freed in DSM, save these values now */	type = ndlp->nlp_type;	did = ndlp->nlp_DID;	if (irsp->ulpStatus) {		/* Check for retry */		if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {			/* ELS command is being retried */			if (disc) {				spin_lock_irq(phba->host->host_lock);				ndlp->nlp_flag |= NLP_NPR_2B_DISC;				spin_unlock_irq(phba->host->host_lock);			}			goto out;		}		/* PLOGI failed */		/* Do not call DSM for lpfc_els_abort'ed ELS cmds */		if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&		   ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||		   (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {			disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);		}		else {			rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,					NLP_EVT_CMPL_PLOGI);		}	} else {		/* Good status, call state machine */		rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,					NLP_EVT_CMPL_PLOGI);	}	if (type & NLP_FABRIC) {		/* If we cannot login to Nameserver, kick off discovery now */		if ((did == NameServer_DID) && (rc == NLP_STE_FREED_NODE)) {			lpfc_disc_start(phba);		}		goto out;	}	if (disc && phba->num_disc_nodes) {		/* Check to see if there are more PLOGIs to be sent */		lpfc_more_plogi(phba);	}	if (rc != NLP_STE_FREED_NODE) {		spin_lock_irq(phba->host->host_lock);		ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;		spin_unlock_irq(phba->host->host_lock);	}	if (phba->num_disc_nodes == 0) {		if(disc) {			spin_lock_irq(phba->host->host_lock);			phba->fc_flag &= ~FC_NDISC_ACTIVE;			spin_unlock_irq(phba->host->host_lock);		}		lpfc_can_disctmo(phba);		if (phba->fc_flag & FC_RSCN_MODE) {			/* Check to see if more RSCNs came in while we were			 * processing this one.			 */			if ((phba->fc_rscn_id_cnt == 0) &&			    (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {				spin_lock_irq(phba->host->host_lock);				phba->fc_flag &= ~FC_RSCN_MODE;				spin_unlock_irq(phba->host->host_lock);			} else {				lpfc_els_handle_rscn(phba);			}		}	}out:	lpfc_els_free_iocb(phba, cmdiocb);	return;}intlpfc_issue_els_plogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,		     uint8_t retry){	struct serv_parm *sp;	IOCB_t *icmd;	struct lpfc_iocbq *elsiocb;	struct lpfc_sli_ring *pring;	struct lpfc_sli *psli;	uint8_t *pcmd;	uint16_t cmdsize;	psli = &phba->sli;	pring = &psli->ring[LPFC_ELS_RING];	/* ELS ring */	cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));	if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry,					  ndlp, ELS_CMD_PLOGI)) == 0) {		return (1);	}	icmd = &elsiocb->iocb;	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);	/* For PLOGI request, remainder of payload is service parameters */	*((uint32_t *) (pcmd)) = ELS_CMD_PLOGI;	pcmd += sizeof (uint32_t);	memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));	sp = (struct serv_parm *) pcmd;	if (sp->cmn.fcphLow < FC_PH_4_3)		sp->cmn.fcphLow = FC_PH_4_3;	if (sp->cmn.fcphHigh < FC_PH3)		sp->cmn.fcphHigh = FC_PH3;	phba->fc_stat.elsXmitPLOGI++;	elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi;	spin_lock_irq(phba->host->host_lock);	ndlp->nlp_flag |= NLP_PLOGI_SND;	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {		ndlp->nlp_flag &= ~NLP_PLOGI_SND;		spin_unlock_irq(phba->host->host_lock);		lpfc_els_free_iocb(phba, elsiocb);		return (1);	}	spin_unlock_irq(phba->host->host_lock);	return (0);}static voidlpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,		   struct lpfc_iocbq * rspiocb){	IOCB_t *irsp;	struct lpfc_sli *psli;	struct lpfc_nodelist *ndlp;	psli = &phba->sli;	/* we pass cmdiocb to state machine which needs rspiocb as well */	cmdiocb->context_un.rsp_iocb = rspiocb;	irsp = &(rspiocb->iocb);	ndlp = (struct lpfc_nodelist *) cmdiocb->context1;	spin_lock_irq(phba->host->host_lock);	ndlp->nlp_flag &= ~NLP_PRLI_SND;	spin_unlock_irq(phba->host->host_lock);	/* PRLI completes to NPort <nlp_DID> */	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,			"%d:0103 PRLI completes to NPort x%x "			"Data: x%x x%x x%x\n",			phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,			irsp->un.ulpWord[4], phba->num_disc_nodes);	phba->fc_prli_sent--;	/* Check to see if link went down during discovery */	if (lpfc_els_chk_latt(phba))		goto out;	if (irsp->ulpStatus) {		/* Check for retry */		if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {			/* ELS command is being retried */			goto out;		}		/* PRLI failed */		/* Do not call DSM for lpfc_els_abort'ed ELS cmds */		if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&		   ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||		   (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {			goto out;		}		else {			lpfc_disc_state_machine(phba, ndlp, cmdiocb,					NLP_EVT_CMPL_PRLI);		}	} else {		/* Good status, call state machine */		lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_PRLI);	}out:	lpfc_els_free_iocb(phba, cmdiocb);	return;}intlpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,		    uint8_t retry){	PRLI *npr;	IOCB_t *icmd;	struct lpfc_iocbq *elsiocb;	struct lpfc_sli_ring *pring;	struct lpfc_sli *psli;	uint8_t *pcmd;	uint16_t cmdsize;	psli = &phba->sli;	pring = &psli->ring[LPFC_ELS_RING];	/* ELS ring */	cmdsize = (sizeof (uint32_t) + sizeof (PRLI));	if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry,					  ndlp, ELS_CMD_PRLI)) == 0) {		return (1);	}	icmd = &elsiocb->iocb;	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);	/* For PRLI request, remainder of payload is service parameters */	memset(pcmd, 0, (sizeof (PRLI) + sizeof (uint32_t)));	*((uint32_t *) (pcmd)) = ELS_CMD_PRLI;	pcmd += sizeof (uint32_t);	/* For PRLI, remainder of payload is PRLI parameter page */	npr = (PRLI *) pcmd;	/*	 * If our firmware version is 3.20 or later,	 * set the following bits for FC-TAPE support.	 */	if (phba->vpd.rev.feaLevelHigh >= 0x02) {		npr->ConfmComplAllowed = 1;		npr->Retry = 1;		npr->TaskRetryIdReq = 1;	}	npr->estabImagePair = 1;	npr->readXferRdyDis = 1;	/* For FCP support */	npr->prliType = PRLI_FCP_TYPE;	npr->initiatorFunc = 1;	phba->fc_stat.elsXmitPRLI++;	elsiocb->iocb_cmpl = lpfc_cmpl_els_prli;	spin_lock_irq(phba->host->host_lock);	ndlp->nlp_flag |= NLP_PRLI_SND;	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {		ndlp->nlp_flag &= ~NLP_PRLI_SND;		spin_unlock_irq(phba->host->host_lock);		lpfc_els_free_iocb(phba, elsiocb);		return (1);	}	spin_unlock_irq(phba->host->host_lock);	phba->fc_prli_sent++;	return (0);}static voidlpfc_more_adisc(struct lpfc_hba * phba){	int sentadisc;	if (phba->num_disc_nodes)		phba->num_disc_nodes--;	/* Continue discovery with <num_disc_nodes> ADISCs to go */	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,			"%d:0210 Continue discovery with %d ADISCs to go "			"Data: x%x x%x x%x\n",			phba->brd_no, phba->num_disc_nodes, phba->fc_adisc_cnt,			phba->fc_flag, phba->hba_state);	/* Check to see if there are more ADISCs to be sent */	if (phba->fc_flag & FC_NLP_MORE) {		lpfc_set_disctmo(phba);		/* go thru NPR list and issue any remaining ELS ADISCs */		sentadisc = lpfc_els_disc_adisc(phba);	}	return;}static voidlpfc_rscn_disc(struct lpfc_hba * phba){	/* RSCN discovery */	/* go thru NPR list and issue ELS PLOGIs */	if (phba->fc_npr_cnt) {		if (lpfc_els_disc_plogi(phba))			return;	}

⌨️ 快捷键说明

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