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

📄 lpfc_els.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	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);		}	}}static voidlpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,		    struct lpfc_iocbq * rspiocb){	IOCB_t *irsp;	struct lpfc_sli *psli;	struct lpfc_nodelist *ndlp;	LPFC_MBOXQ_t *mbox;	int disc, rc;	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_ADISC_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);	/* ADISC completes to NPort <nlp_DID> */	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,			"%d:0104 ADISC 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;	}	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);				lpfc_set_disctmo(phba);			}			goto out;		}		/* ADISC 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 {			lpfc_disc_state_machine(phba, ndlp, cmdiocb,					NLP_EVT_CMPL_ADISC);		}	} else {		/* Good status, call state machine */		lpfc_disc_state_machine(phba, ndlp, cmdiocb,					NLP_EVT_CMPL_ADISC);	}	if (disc && phba->num_disc_nodes) {		/* Check to see if there are more ADISCs to be sent */		lpfc_more_adisc(phba);		/* Check to see if we are done with ADISC authentication */		if (phba->num_disc_nodes == 0) {			lpfc_can_disctmo(phba);			/* If we get here, there is nothing left to wait for */			if ((phba->hba_state < LPFC_HBA_READY) &&			    (phba->hba_state != LPFC_CLEAR_LA)) {				/* Link up discovery */				if ((mbox = mempool_alloc(phba->mbox_mem_pool,							  GFP_KERNEL))) {					phba->hba_state = LPFC_CLEAR_LA;					lpfc_clear_la(phba, mbox);					mbox->mbox_cmpl =					    lpfc_mbx_cmpl_clear_la;					rc = lpfc_sli_issue_mbox						(phba, mbox,						 (MBX_NOWAIT | MBX_STOP_IOCB));					if (rc == MBX_NOT_FINISHED) {						mempool_free(mbox,						     phba->mbox_mem_pool);						lpfc_disc_flush_list(phba);						psli->ring[(psli->ip_ring)].						    flag &=						    ~LPFC_STOP_IOCB_EVENT;						psli->ring[(psli->fcp_ring)].						    flag &=						    ~LPFC_STOP_IOCB_EVENT;						psli->ring[(psli->next_ring)].						    flag &=						    ~LPFC_STOP_IOCB_EVENT;						phba->hba_state =						    LPFC_HBA_READY;					}				}			} else {				lpfc_rscn_disc(phba);			}		}	}	spin_lock_irq(phba->host->host_lock);	ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;	spin_unlock_irq(phba->host->host_lock);out:	lpfc_els_free_iocb(phba, cmdiocb);	return;}intlpfc_issue_els_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,		     uint8_t retry){	ADISC *ap;	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 (ADISC));	if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry,					  ndlp, ELS_CMD_ADISC)) == 0) {		return (1);	}	icmd = &elsiocb->iocb;	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);	/* For ADISC request, remainder of payload is service parameters */	*((uint32_t *) (pcmd)) = ELS_CMD_ADISC;	pcmd += sizeof (uint32_t);	/* Fill in ADISC payload */	ap = (ADISC *) pcmd;	ap->hardAL_PA = phba->fc_pref_ALPA;	memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name));	memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));	ap->DID = be32_to_cpu(phba->fc_myDID);	phba->fc_stat.elsXmitADISC++;	elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc;	spin_lock_irq(phba->host->host_lock);	ndlp->nlp_flag |= NLP_ADISC_SND;	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {		ndlp->nlp_flag &= ~NLP_ADISC_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_logo(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_LOGO_SND;	spin_unlock_irq(phba->host->host_lock);	/* LOGO completes to NPort <nlp_DID> */	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,			"%d:0105 LOGO 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);	/* 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;		}		/* LOGO 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_LOGO);		}	} else {		/* Good status, call state machine */		lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO);		if (ndlp->nlp_flag & NLP_DELAY_TMO) {			lpfc_unreg_rpi(phba, ndlp);		}	}out:	lpfc_els_free_iocb(phba, cmdiocb);	return;}intlpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,		    uint8_t retry){	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];	cmdsize = 2 * (sizeof (uint32_t) + sizeof (struct lpfc_name));	if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry,					  ndlp, ELS_CMD_LOGO)) == 0) {		return (1);	}	icmd = &elsiocb->iocb;	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);	*((uint32_t *) (pcmd)) = ELS_CMD_LOGO;	pcmd += sizeof (uint32_t);	/* Fill in LOGO payload */	*((uint32_t *) (pcmd)) = be32_to_cpu(phba->fc_myDID);	pcmd += sizeof (uint32_t);	memcpy(pcmd, &phba->fc_portname, sizeof (struct lpfc_name));	phba->fc_stat.elsXmitLOGO++;	elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;	spin_lock_irq(phba->host->host_lock);	ndlp->nlp_flag |= NLP_LOGO_SND;	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {		ndlp->nlp_flag &= ~NLP_LOGO_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_cmd(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,		  struct lpfc_iocbq * rspiocb){	IOCB_t *irsp;	irsp = &rspiocb->iocb;	/* ELS cmd tag <ulpIoTag> completes */	lpfc_printf_log(phba,			KERN_INFO,			LOG_ELS,			"%d:0106 ELS cmd tag x%x completes Data: x%x x%x\n",			phba->brd_no,			irsp->ulpIoTag, irsp->ulpStatus, irsp->un.ulpWord[4]);	/* Check to see if link went down during discovery */	lpfc_els_chk_latt(phba);	lpfc_els_free_iocb(phba, cmdiocb);	return;}intlpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry){	IOCB_t *icmd;	struct lpfc_iocbq *elsiocb;	struct lpfc_sli_ring *pring;	struct lpfc_sli *psli;	uint8_t *pcmd;	uint16_t cmdsize;	struct lpfc_nodelist *ndlp;	psli = &phba->sli;	pring = &psli->ring[LPFC_ELS_RING];	/* ELS ring */	cmdsize = (sizeof (uint32_t) + sizeof (SCR));	if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) == 0) {		return (1);	}	lpfc_nlp_init(phba, ndlp, nportid);	if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry,					  ndlp, ELS_CMD_SCR)) == 0) {		mempool_free( ndlp, phba->nlp_mem_pool);		return (1);	}	icmd = &elsiocb->iocb;	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);	*((uint32_t *) (pcmd)) = ELS_CMD_SCR;	pcmd += sizeof (uint32_t);	/* For SCR, remainder of payload is SCR parameter page */	memset(pcmd, 0, sizeof (SCR));	((SCR *) pcmd)->Function = SCR_FUNC_FULL;	phba->fc_stat.elsXmitSCR++;	elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;	spin_lock_irq(phba->host->host_lock);	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {		spin_unlock_irq(phba->host->host_lock);		mempool_free( ndlp, phba->nlp_mem_pool);		lpfc_els_free_iocb(phba, elsiocb);		return (1);	}	spin_unlock_irq(phba->host->host_lock);	mempool_free( ndlp, phba->nlp_mem_pool);	return (0);}static intlpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry){	IOCB_t *icmd;	struct lpfc_iocbq *elsiocb;	struct lpfc_sli_ring *pring;	struct lpfc_sli *psli;	FARP *fp;	uint8_t *pcmd;	uint32_t *lp;	uint16_t cmdsize;	struct lpfc_nodelist *ondlp;	struct lpfc_nodelist *ndlp;	psli = &phba->sli;	pring = &psli->ring[LPFC_ELS_RING];	/* ELS ring */	cmdsize = (sizeof (uint32_t) + sizeof (FARP));	if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) == 0) {		return (1);	}	lpfc_nlp_init(phba, ndlp, nportid);	if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry,					  ndlp, ELS_CMD_RNID)) == 0) {		mempool_free( ndlp, phba->nlp_mem_pool);		return (1);	}	icmd = &elsiocb->iocb;	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);	*((uint32_t *) (pcmd)) = ELS_CMD_FARPR;	pcmd += sizeof (uint32_t);	/* Fill in FARPR payload */	fp = (FARP *) (pcmd);	memset(fp, 0, sizeof (FARP));	lp = (uint32_t *) pcmd;	*lp++ = be32_to_cpu(nportid);	*lp++ = be32_to_cpu(phba->fc_myDID);	fp->Rflags = 0;	fp->Mflags = (FARP_MATCH_PORT | FARP_MATCH_NODE);	memcpy(&fp->RportName, &phba->fc_portname, sizeof (struct lpfc_name));	memcpy(&fp->RnodeName, &phba->fc_nodename, sizeof (struct lpfc_name));	if ((ondlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, nportid))) {		memcpy(&fp->OportName, &ondlp->nlp_portname,		       sizeof (struct lpfc_name));		memcpy(&fp->OnodeName, &ondlp->nlp_nodename,		       sizeof (struct lpfc_name));	}	phba->fc_stat.elsXmitFARPR++;	elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;	spin_lock_irq(phba->host->host_lock);	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {		spin_unlock_irq(phba->host->host_lock);		mempool_free( ndlp, phba->nlp_mem_pool);		lpfc_els_free_iocb(phba, elsiocb);		return (1);	}	spin_unlock_irq(phba->host->host_lock);	mempool_free( ndlp, phba->nlp_mem_pool);	return (0);}voidlpfc_els_retry_delay(unsigned long ptr){	struct lpfc_nodelist *ndlp;	struct lpfc_hba *phba;	unsigned long iflag;	struct lpfc_work_evt  *evtp;	ndlp = (struct lpfc_nodelist *)ptr;	phba = ndlp->nlp_phba;	evtp = &ndlp->els_retry_evt;	spin_lock_irqsave(phba->host->host_lock, iflag);	if (!list_empty(&evtp->evt_listp)) {		spin_unlock_irqrestore(phba->host->host_lock, iflag);		return;	}	evtp->evt_arg1  = ndlp;	evtp->evt       = LPFC_EVT_ELS_RETRY;	list_add_tail(&evtp->evt_listp, &phba->work_list);	if (phba->work_wait)		wake_up(phba->work_wait);	spin_unlock_irqrestore(phba->host->host_lock, iflag);	return;}voidlpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp){	struct lpfc_hba *phba;	uint32_t cmd;	uint32_t did;	uint8_t retry;	phba = ndlp->nlp_phba;	spin_lock_irq(phba->host->host_lock);	did = (uint32_t) (ndlp->nlp_DID);	cmd = (uint32_t) (ndlp->nlp_last_elscmd);	if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {		spin_unlock_irq(phba->host->host_lock);		return;	}	ndlp->nlp_flag &= ~NLP_DELAY_TMO;	spin_unlock_irq(phba->host->host_lock);	retry = ndlp->nlp_retry;	switch (cmd) {	case ELS_CMD_FLOGI:		lpfc_issue_els_flogi(phba, ndlp, retry);		break;	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, retry);		break;	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, retry);		break;	case ELS_CMD_PRLI:		ndlp->nlp_state = NLP_STE_PRLI_ISSUE;

⌨️ 快捷键说明

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