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

📄 lpfc_els.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	cmdsize = sizeof (uint32_t) + sizeof (ADISC);	if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,					  ndlp, ELS_CMD_ACC)) == 0) {		return (1);	}	/* Xmit ADISC ACC response tag <ulpIoTag> */	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,			"%d:0130 Xmit ADISC 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);	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_ACC;	pcmd += sizeof (uint32_t);	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.elsXmitACC++;	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_prli_acc(struct lpfc_hba * phba,		      struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp){	PRLI *npr;	lpfc_vpd_t *vpd;	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 = sizeof (uint32_t) + sizeof (PRLI);	if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,					  ndlp,					  (ELS_CMD_ACC |					   (ELS_CMD_PRLI & ~ELS_RSP_MASK)))) ==	    0) {		return (1);	}	/* Xmit PRLI ACC response tag <ulpIoTag> */	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,			"%d:0131 Xmit PRLI 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);	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_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK));	pcmd += sizeof (uint32_t);	/* For PRLI, remainder of payload is PRLI parameter page */	memset(pcmd, 0, sizeof (PRLI));	npr = (PRLI *) pcmd;	vpd = &phba->vpd;	/*	 * If our firmware version is 3.20 or later,	 * set the following bits for FC-TAPE support.	 */	if (vpd->rev.feaLevelHigh >= 0x02) {		npr->ConfmComplAllowed = 1;		npr->Retry = 1;		npr->TaskRetryIdReq = 1;	}	npr->acceptRspCode = PRLI_REQ_EXECUTED;	npr->estabImagePair = 1;	npr->readXferRdyDis = 1;	npr->ConfmComplAllowed = 1;	npr->prliType = PRLI_FCP_TYPE;	npr->initiatorFunc = 1;	phba->fc_stat.elsXmitACC++;	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);}static intlpfc_els_rsp_rnid_acc(struct lpfc_hba * phba,		      uint8_t format,		      struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp){	RNID *rn;	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];	cmdsize = sizeof (uint32_t) + sizeof (uint32_t)		+ (2 * sizeof (struct lpfc_name));	if (format)		cmdsize += sizeof (RNID_TOP_DISC);	if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,					  ndlp, ELS_CMD_ACC)) == 0) {		return (1);	}	/* Xmit RNID ACC response tag <ulpIoTag> */	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,			"%d:0132 Xmit RNID ACC response tag x%x "			"Data: x%x\n",			phba->brd_no,			elsiocb->iocb.ulpIoTag,			elsiocb->iocb.ulpContext);	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_ACC;	pcmd += sizeof (uint32_t);	memset(pcmd, 0, sizeof (RNID));	rn = (RNID *) (pcmd);	rn->Format = format;	rn->CommonLen = (2 * sizeof (struct lpfc_name));	memcpy(&rn->portName, &phba->fc_portname, sizeof (struct lpfc_name));	memcpy(&rn->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));	switch (format) {	case 0:		rn->SpecificLen = 0;		break;	case RNID_TOPOLOGY_DISC:		rn->SpecificLen = sizeof (RNID_TOP_DISC);		memcpy(&rn->un.topologyDisc.portName,		       &phba->fc_portname, sizeof (struct lpfc_name));		rn->un.topologyDisc.unitType = RNID_HBA;		rn->un.topologyDisc.physPort = 0;		rn->un.topologyDisc.attachedNodes = 0;		break;	default:		rn->CommonLen = 0;		rn->SpecificLen = 0;		break;	}	phba->fc_stat.elsXmitACC++;	elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;	elsiocb->context1 = NULL;  /* Don't need ndlp for cmpl,				    * it could be freed */	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_disc_adisc(struct lpfc_hba * phba){	int sentadisc;	struct lpfc_nodelist *ndlp, *next_ndlp;	sentadisc = 0;	/* go thru NPR list and issue any remaining ELS ADISCs */	list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,			nlp_listp) {		if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {			if (ndlp->nlp_flag & NLP_NPR_ADISC) {				ndlp->nlp_flag &= ~NLP_NPR_ADISC;				ndlp->nlp_state = NLP_STE_ADISC_ISSUE;				lpfc_nlp_list(phba, ndlp,					NLP_ADISC_LIST);				lpfc_issue_els_adisc(phba, ndlp, 0);				sentadisc++;				phba->num_disc_nodes++;				if (phba->num_disc_nodes >=				    phba->cfg_discovery_threads) {					spin_lock_irq(phba->host->host_lock);					phba->fc_flag |= FC_NLP_MORE;					spin_unlock_irq(phba->host->host_lock);					break;				}			}		}	}	if (sentadisc == 0) {		spin_lock_irq(phba->host->host_lock);		phba->fc_flag &= ~FC_NLP_MORE;		spin_unlock_irq(phba->host->host_lock);	}	return(sentadisc);}intlpfc_els_disc_plogi(struct lpfc_hba * phba){	int sentplogi;	struct lpfc_nodelist *ndlp, *next_ndlp;	sentplogi = 0;	/* go thru NPR list and issue any remaining ELS PLOGIs */	list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,				nlp_listp) {		if ((ndlp->nlp_flag & NLP_NPR_2B_DISC) &&		   (!(ndlp->nlp_flag & NLP_DELAY_TMO))) {			if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {				ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;				lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);				lpfc_issue_els_plogi(phba, ndlp, 0);				sentplogi++;				phba->num_disc_nodes++;				if (phba->num_disc_nodes >=				    phba->cfg_discovery_threads) {					spin_lock_irq(phba->host->host_lock);					phba->fc_flag |= FC_NLP_MORE;					spin_unlock_irq(phba->host->host_lock);					break;				}			}		}	}	if (sentplogi == 0) {		spin_lock_irq(phba->host->host_lock);		phba->fc_flag &= ~FC_NLP_MORE;		spin_unlock_irq(phba->host->host_lock);	}	return(sentplogi);}intlpfc_els_flush_rscn(struct lpfc_hba * phba){	struct lpfc_dmabuf *mp;	int i;	for (i = 0; i < phba->fc_rscn_id_cnt; i++) {		mp = phba->fc_rscn_id_list[i];		lpfc_mbuf_free(phba, mp->virt, mp->phys);		kfree(mp);		phba->fc_rscn_id_list[i] = NULL;	}	phba->fc_rscn_id_cnt = 0;	spin_lock_irq(phba->host->host_lock);	phba->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY);	spin_unlock_irq(phba->host->host_lock);	lpfc_can_disctmo(phba);	return (0);}intlpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did){	D_ID ns_did;	D_ID rscn_did;	struct lpfc_dmabuf *mp;	uint32_t *lp;	uint32_t payload_len, cmd, i, match;	ns_did.un.word = did;	match = 0;	/* Never match fabric nodes for RSCNs */	if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)		return(0);	/* If we are doing a FULL RSCN rediscovery, match everything */	if (phba->fc_flag & FC_RSCN_DISCOVERY) {		return (did);	}	for (i = 0; i < phba->fc_rscn_id_cnt; i++) {		mp = phba->fc_rscn_id_list[i];		lp = (uint32_t *) mp->virt;		cmd = *lp++;		payload_len = be32_to_cpu(cmd) & 0xffff; /* payload length */		payload_len -= sizeof (uint32_t);	/* take off word 0 */		while (payload_len) {			rscn_did.un.word = *lp++;			rscn_did.un.word = be32_to_cpu(rscn_did.un.word);			payload_len -= sizeof (uint32_t);			switch (rscn_did.un.b.resv) {			case 0:	/* Single N_Port ID effected */				if (ns_did.un.word == rscn_did.un.word) {					match = did;				}				break;			case 1:	/* Whole N_Port Area effected */				if ((ns_did.un.b.domain == rscn_did.un.b.domain)				    && (ns_did.un.b.area == rscn_did.un.b.area))					{						match = did;					}				break;			case 2:	/* Whole N_Port Domain effected */				if (ns_did.un.b.domain == rscn_did.un.b.domain)					{						match = did;					}				break;			case 3:	/* Whole Fabric effected */				match = did;				break;			default:				/* Unknown Identifier in RSCN list */				lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,						"%d:0217 Unknown Identifier in "						"RSCN payload Data: x%x\n",						phba->brd_no, rscn_did.un.word);				break;			}			if (match) {				break;			}		}	}	return (match);}static intlpfc_rscn_recovery_check(struct lpfc_hba * phba){	struct lpfc_nodelist *ndlp = NULL, *next_ndlp;	struct list_head *listp;	struct list_head *node_list[7];	int i;	/* Look at all nodes effected by pending RSCNs and move	 * them to NPR list.	 */	node_list[0] = &phba->fc_npr_list;  /* MUST do this list first */	node_list[1] = &phba->fc_nlpmap_list;	node_list[2] = &phba->fc_nlpunmap_list;	node_list[3] = &phba->fc_prli_list;	node_list[4] = &phba->fc_reglogin_list;	node_list[5] = &phba->fc_adisc_list;	node_list[6] = &phba->fc_plogi_list;	for (i = 0; i < 7; i++) {		listp = node_list[i];		if (list_empty(listp))			continue;		list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) {			if (!(lpfc_rscn_payload_check(phba, ndlp->nlp_DID)))				continue;			lpfc_disc_state_machine(phba, ndlp, NULL,					NLP_EVT_DEVICE_RECOVERY);			if (ndlp->nlp_flag & NLP_DELAY_TMO) {				ndlp->nlp_flag &= ~NLP_DELAY_TMO;				del_timer_sync(&ndlp->nlp_delayfunc);				if (!list_empty(&ndlp->						els_retry_evt.evt_listp))					list_del_init(&ndlp->						els_retry_evt.evt_listp);			}		}	}	return (0);}static intlpfc_els_rcv_rscn(struct lpfc_hba * phba,		  struct lpfc_iocbq * cmdiocb,		  struct lpfc_nodelist * ndlp, uint8_t newnode){	struct lpfc_dmabuf *pcmd;	uint32_t *lp;	IOCB_t *icmd;	uint32_t payload_len, cmd;	icmd = &cmdiocb->iocb;	pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;	lp = (uint32_t *) pcmd->virt;	cmd = *lp++;	payload_len = be32_to_cpu(cmd) & 0xffff;	/* payload length */	payload_len -= sizeof (uint32_t);	/* take off word 0 */	cmd &= ELS_CMD_MASK;	/* RSCN received */	lpfc_printf_log(phba,			KERN_INFO,			LOG_DISCOVERY,			"%d:0214 RSCN received Data: x%x x%x x%x x%x\n",			phba->brd_no,			phba->fc_flag, payload_len, *lp, phba->fc_rscn_id_cnt);	/* If we are about to begin discovery, just ACC the RSCN.	 * Discovery processing will satisfy it.	 */	if (phba->hba_state < LPFC_NS_QRY) {		lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,								newnode);		return (0);	}	/* If we are already processing an RSCN, save the received	 * RSCN payload buffer, cmdiocb->context2 to process later.	 */	if (phba->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {		if ((phba->fc_rscn_id_cnt < FC_MAX_HOLD_RSCN) &&		    !(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);			phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd;			/* If we zero, cmdiocb->context2, the calling			 * routine will not try to free it.			 */			cmdiocb->context2 = NULL;			/* Deferred RSCN */			lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,					"%d:0235 Deferred RSCN "					"Data: x%x x%x x%x\n",					phba->brd_no, phba->fc_rscn_id_cnt,					phba->fc_flag, phba->hba_state);		} else {			spin_lock_irq(phba->host->host_lock);			phba->fc_flag |= FC_RSCN_DISCOVERY;			spin_unlock_irq(phba->host->host_lock);			/* ReDiscovery RSCN */			lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,					"%d:0234 ReDiscovery RSCN "					"Data: x%x x%x x%x\n",					phba->brd_no, phba->fc_rscn_id_cnt,					phba->fc_flag, phba->hba_state);		}		/* Send back ACC */		lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,								newnode);		/* send RECOVERY event for ALL nodes that match RSCN payload */		lpfc_rscn_recovery_check(phba);		return (0);	}	phba->fc_flag |= FC_RSCN_MODE;	phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd;	/*	 * If we zero, cmdiocb->context2, the calling routine will	 * not t

⌨️ 快捷键说明

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