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

📄 lpfc_hbadisc.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		return 1;	}	return 0;}/* * Free resources associated with LPFC_NODELIST entry * so it can be freed. */static intlpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp){	LPFC_MBOXQ_t       *mb;	LPFC_MBOXQ_t       *nextmb;	struct lpfc_dmabuf *mp;	/* Cleanup node for NPort <nlp_DID> */	lpfc_printf_log(phba, KERN_INFO, LOG_NODE,			"%d:0900 Cleanup node for 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);	lpfc_nlp_list(phba, ndlp, NLP_JUST_DQ);	/*	 * if unloading the driver - just leave the remote port in place.	 * The driver unload will force the attached devices to detach	 * and flush cache's w/o generating flush errors.	 */	if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {		lpfc_unregister_remote_port(phba, ndlp);		ndlp->nlp_sid = NLP_NO_SID;	}	/* cleanup any ndlp on mbox q waiting for reglogin cmpl */	if ((mb = phba->sli.mbox_active)) {		if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&		   (ndlp == (struct lpfc_nodelist *) mb->context2)) {			mb->context2 = NULL;			mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;		}	}	list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {		if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&		   (ndlp == (struct lpfc_nodelist *) mb->context2)) {			mp = (struct lpfc_dmabuf *) (mb->context1);			if (mp) {				lpfc_mbuf_free(phba, mp->virt, mp->phys);				kfree(mp);			}			list_del(&mb->list);			mempool_free(mb, phba->mbox_mem_pool);		}	}	lpfc_els_abort(phba,ndlp,0);	spin_lock_irq(phba->host->host_lock);	ndlp->nlp_flag &= ~(NLP_NODEV_TMO|NLP_DELAY_TMO);	spin_unlock_irq(phba->host->host_lock);	del_timer_sync(&ndlp->nlp_tmofunc);	del_timer_sync(&ndlp->nlp_delayfunc);	if (!list_empty(&ndlp->nodev_timeout_evt.evt_listp))		list_del_init(&ndlp->nodev_timeout_evt.evt_listp);	if (!list_empty(&ndlp->els_retry_evt.evt_listp))		list_del_init(&ndlp->els_retry_evt.evt_listp);	lpfc_unreg_rpi(phba, ndlp);	return (0);}/* * Check to see if we can free the nlp back to the freelist. * If we are in the middle of using the nlp in the discovery state * machine, defer the free till we reach the end of the state machine. */intlpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp){	if (ndlp->nlp_flag & NLP_NODEV_TMO) {		spin_lock_irq(phba->host->host_lock);		ndlp->nlp_flag &= ~NLP_NODEV_TMO;		spin_unlock_irq(phba->host->host_lock);		del_timer_sync(&ndlp->nlp_tmofunc);		if (!list_empty(&ndlp->nodev_timeout_evt.evt_listp))			list_del_init(&ndlp->nodev_timeout_evt.evt_listp);	}	if (ndlp->nlp_flag & NLP_DELAY_TMO) {		spin_lock_irq(phba->host->host_lock);		ndlp->nlp_flag &= ~NLP_DELAY_TMO;		spin_unlock_irq(phba->host->host_lock);		del_timer_sync(&ndlp->nlp_delayfunc);		if (!list_empty(&ndlp->els_retry_evt.evt_listp))			list_del_init(&ndlp->els_retry_evt.evt_listp);	}	if (ndlp->nlp_disc_refcnt) {		spin_lock_irq(phba->host->host_lock);		ndlp->nlp_flag |= NLP_DELAY_REMOVE;		spin_unlock_irq(phba->host->host_lock);	}	else {		lpfc_freenode(phba, ndlp);		mempool_free( ndlp, phba->nlp_mem_pool);	}	return(0);}static intlpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did){	D_ID mydid;	D_ID ndlpdid;	D_ID matchdid;	if (did == Bcast_DID)		return (0);	if (ndlp->nlp_DID == 0) {		return (0);	}	/* First check for Direct match */	if (ndlp->nlp_DID == did)		return (1);	/* Next check for area/domain identically equals 0 match */	mydid.un.word = phba->fc_myDID;	if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) {		return (0);	}	matchdid.un.word = did;	ndlpdid.un.word = ndlp->nlp_DID;	if (matchdid.un.b.id == ndlpdid.un.b.id) {		if ((mydid.un.b.domain == matchdid.un.b.domain) &&		    (mydid.un.b.area == matchdid.un.b.area)) {			if ((ndlpdid.un.b.domain == 0) &&			    (ndlpdid.un.b.area == 0)) {				if (ndlpdid.un.b.id)					return (1);			}			return (0);		}		matchdid.un.word = ndlp->nlp_DID;		if ((mydid.un.b.domain == ndlpdid.un.b.domain) &&		    (mydid.un.b.area == ndlpdid.un.b.area)) {			if ((matchdid.un.b.domain == 0) &&			    (matchdid.un.b.area == 0)) {				if (matchdid.un.b.id)					return (1);			}		}	}	return (0);}/* Search for a nodelist entry on a specific list */struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did){	struct lpfc_nodelist *ndlp, *next_ndlp;	uint32_t data1;	if (order & NLP_SEARCH_UNMAPPED) {		list_for_each_entry_safe(ndlp, next_ndlp,					 &phba->fc_nlpunmap_list, nlp_listp) {			if (lpfc_matchdid(phba, ndlp, did)) {				data1 = (((uint32_t) ndlp->nlp_state << 24) |					 ((uint32_t) ndlp->nlp_xri << 16) |					 ((uint32_t) ndlp->nlp_type << 8) |					 ((uint32_t) ndlp->nlp_rpi & 0xff));				/* FIND node DID unmapped */				lpfc_printf_log(phba, KERN_INFO, LOG_NODE,						"%d:0929 FIND node DID unmapped"						" Data: x%p x%x x%x x%x\n",						phba->brd_no,						ndlp, ndlp->nlp_DID,						ndlp->nlp_flag, data1);				return (ndlp);			}		}	}	if (order & NLP_SEARCH_MAPPED) {		list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpmap_list,					nlp_listp) {			if (lpfc_matchdid(phba, ndlp, did)) {				data1 = (((uint32_t) ndlp->nlp_state << 24) |					 ((uint32_t) ndlp->nlp_xri << 16) |					 ((uint32_t) ndlp->nlp_type << 8) |					 ((uint32_t) ndlp->nlp_rpi & 0xff));				/* FIND node DID mapped */				lpfc_printf_log(phba, KERN_INFO, LOG_NODE,						"%d:0930 FIND node DID mapped "						"Data: x%p x%x x%x x%x\n",						phba->brd_no,						ndlp, ndlp->nlp_DID,						ndlp->nlp_flag, data1);				return (ndlp);			}		}	}	if (order & NLP_SEARCH_PLOGI) {		list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list,					nlp_listp) {			if (lpfc_matchdid(phba, ndlp, did)) {				data1 = (((uint32_t) ndlp->nlp_state << 24) |					 ((uint32_t) ndlp->nlp_xri << 16) |					 ((uint32_t) ndlp->nlp_type << 8) |					 ((uint32_t) ndlp->nlp_rpi & 0xff));				/* LOG change to PLOGI */				/* FIND node DID plogi */				lpfc_printf_log(phba, KERN_INFO, LOG_NODE,						"%d:0908 FIND node DID plogi "						"Data: x%p x%x x%x x%x\n",						phba->brd_no,						ndlp, ndlp->nlp_DID,						ndlp->nlp_flag, data1);				return (ndlp);			}		}	}	if (order & NLP_SEARCH_ADISC) {		list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list,					nlp_listp) {			if (lpfc_matchdid(phba, ndlp, did)) {				data1 = (((uint32_t) ndlp->nlp_state << 24) |					 ((uint32_t) ndlp->nlp_xri << 16) |					 ((uint32_t) ndlp->nlp_type << 8) |					 ((uint32_t) ndlp->nlp_rpi & 0xff));				/* LOG change to ADISC */				/* FIND node DID adisc */				lpfc_printf_log(phba, KERN_INFO, LOG_NODE,						"%d:0931 FIND node DID adisc "						"Data: x%p x%x x%x x%x\n",						phba->brd_no,						ndlp, ndlp->nlp_DID,						ndlp->nlp_flag, data1);				return (ndlp);			}		}	}	if (order & NLP_SEARCH_REGLOGIN) {		list_for_each_entry_safe(ndlp, next_ndlp,					 &phba->fc_reglogin_list, nlp_listp) {			if (lpfc_matchdid(phba, ndlp, did)) {				data1 = (((uint32_t) ndlp->nlp_state << 24) |					 ((uint32_t) ndlp->nlp_xri << 16) |					 ((uint32_t) ndlp->nlp_type << 8) |					 ((uint32_t) ndlp->nlp_rpi & 0xff));				/* LOG change to REGLOGIN */				/* FIND node DID reglogin */				lpfc_printf_log(phba, KERN_INFO, LOG_NODE,						"%d:0931 FIND node DID reglogin"						" Data: x%p x%x x%x x%x\n",						phba->brd_no,						ndlp, ndlp->nlp_DID,						ndlp->nlp_flag, data1);				return (ndlp);			}		}	}	if (order & NLP_SEARCH_PRLI) {		list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_prli_list,					nlp_listp) {			if (lpfc_matchdid(phba, ndlp, did)) {				data1 = (((uint32_t) ndlp->nlp_state << 24) |					 ((uint32_t) ndlp->nlp_xri << 16) |					 ((uint32_t) ndlp->nlp_type << 8) |					 ((uint32_t) ndlp->nlp_rpi & 0xff));				/* LOG change to PRLI */				/* FIND node DID prli */				lpfc_printf_log(phba, KERN_INFO, LOG_NODE,						"%d:0931 FIND node DID prli "						"Data: x%p x%x x%x x%x\n",						phba->brd_no,						ndlp, ndlp->nlp_DID,						ndlp->nlp_flag, data1);				return (ndlp);			}		}	}	if (order & NLP_SEARCH_NPR) {		list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,					nlp_listp) {			if (lpfc_matchdid(phba, ndlp, did)) {				data1 = (((uint32_t) ndlp->nlp_state << 24) |					 ((uint32_t) ndlp->nlp_xri << 16) |					 ((uint32_t) ndlp->nlp_type << 8) |					 ((uint32_t) ndlp->nlp_rpi & 0xff));				/* LOG change to NPR */				/* FIND node DID npr */				lpfc_printf_log(phba, KERN_INFO, LOG_NODE,						"%d:0931 FIND node DID npr "						"Data: x%p x%x x%x x%x\n",						phba->brd_no,						ndlp, ndlp->nlp_DID,						ndlp->nlp_flag, data1);				return (ndlp);			}		}	}	if (order & NLP_SEARCH_UNUSED) {		list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list,					nlp_listp) {			if (lpfc_matchdid(phba, ndlp, did)) {				data1 = (((uint32_t) ndlp->nlp_state << 24) |					 ((uint32_t) ndlp->nlp_xri << 16) |					 ((uint32_t) ndlp->nlp_type << 8) |					 ((uint32_t) ndlp->nlp_rpi & 0xff));				/* LOG change to UNUSED */				/* FIND node DID unused */				lpfc_printf_log(phba, KERN_INFO, LOG_NODE,						"%d:0931 FIND node DID unused "						"Data: x%p x%x x%x x%x\n",						phba->brd_no,						ndlp, ndlp->nlp_DID,						ndlp->nlp_flag, data1);				return (ndlp);			}		}	}	/* FIND node did <did> NOT FOUND */	lpfc_printf_log(phba,			KERN_INFO,			LOG_NODE,			"%d:0932 FIND node did x%x NOT FOUND Data: x%x\n",			phba->brd_no, did, order);	/* no match found */	return NULL;}struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did){	struct lpfc_nodelist *ndlp;	uint32_t flg;	if ((ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did)) == 0) {		if ((phba->hba_state == LPFC_HBA_READY) &&		   ((lpfc_rscn_payload_check(phba, did) == 0)))			return NULL;		ndlp = (struct lpfc_nodelist *)		     mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);		if (!ndlp)			return NULL;		lpfc_nlp_init(phba, ndlp, did);		ndlp->nlp_state = NLP_STE_NPR_NODE;		lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);		ndlp->nlp_flag |= NLP_NPR_2B_DISC;		return ndlp;	}	if ((phba->hba_state == LPFC_HBA_READY) &&	    (phba->fc_flag & FC_RSCN_MODE)) {		if (lpfc_rscn_payload_check(phba, did)) {			ndlp->nlp_flag |= NLP_NPR_2B_DISC;		}		else {			ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;			ndlp = NULL;		}	}	else {		flg = ndlp->nlp_flag & NLP_LIST_MASK;		if ((flg == NLP_ADISC_LIST) ||		(flg == NLP_PLOGI_LIST)) {			return NULL;		}		ndlp->nlp_state = NLP_STE_NPR_NODE;		lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);		ndlp->nlp_flag |= NLP_NPR_2B_DISC;	}	return ndlp;}/* Build a list of nodes to discover based on the loopmap */voidlpfc_disc_list_loopmap(struct lpfc_hba * phba){	int j;	uint32_t alpa, index;	if (phba->hba_state <= LPFC_LINK_DOWN) {		return;	}	if (phba->fc_topology != TOPOLOGY_LOOP) {		return;	}	/* Check for loop map present or not */	if (phba->alpa_map[0]) {		for (j = 1; j <= phba->alpa_map[0]; j++) {			alpa = phba->alpa_map[j];			if (((phba->fc_myDID & 0xff) == alpa) || (alpa == 0)) {				continue;			}			lpfc_setup_disc_node(phba, alpa);		}	} else {		/* No alpamap, so try all alpa's */		for (j = 0; j < FC_MAXLOOP; j++) {			/* If cfg_scan_down is set, start from highest			 * ALPA (0xef) to lowest (0x1).			 */			if (phba->cfg_scan_down)				index = j;			else				index = FC_MAXLOOP - j - 1;			alpa = lpfcAlpaArray[index];			if ((phba->fc_myDID & 0xff) == alpa) {				continue;			}			lpfc_setup_disc_node(phba, alpa);		}	}	return;}/* Start Link up / RSCN discovery on NPR list */voidlpfc_disc_start(struct lpfc_hba * phba){	struct lpfc_sli *psli;	LPFC_MBOXQ_t *mbox;	struct lpfc_nodelist *ndlp, *next_ndlp;	uint32_t did_changed, num_sent;	uint32_t clear_la_pending;	int rc;	psli = &phba->sli;	if (phba->hba_state <= LPFC_LINK_DOWN) {		return;	}	if (phba->hba_state == LPFC_CLEAR_LA)		clear_la_pending = 1;	else		clear_la_pending = 0;	if (phba->hba_state < LPFC_HBA_READY) {		phba->hba_state = LPFC_DISC_AUTH;	}	lpfc_set_disctmo(phba);	if (phba->fc_prevDID == phba->fc_myDID) {		did_changed = 0;	} else {		did_changed = 1;	}	phba->fc_prevDID = phba->fc_myDID;	phba->num_disc_nodes = 0;	/* Start Discovery state <hba_state> */	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,			"%d:0202 Start Discovery hba state x%x "			"Data: x%x x%x x%x\n",			phba->brd_no, phba->hba_state, phba->fc_flag,			phba->fc_plogi_cnt, phba->fc_adisc_cnt);	/* If our did changed, we MUST do PLOGI */	list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,				nlp_listp) {		if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {			if (did_changed) {				spin_lock_irq(phba->host->host_lock);				ndlp->nlp_flag &= ~NLP_NPR_ADISC;				spin_unlock_irq(phba->host->host_lock);			}		}	}

⌨️ 快捷键说明

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