1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22fcf3ce44SJohn Forte /*
23291a2b48SSukumar Swaminathan  * Copyright 2009 Emulex.  All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
2782527734SSukumar Swaminathan 
28291a2b48SSukumar Swaminathan #include <emlxs.h>
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte 
31fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
32fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_NODE_C);
33fcf3ce44SJohn Forte 
34291a2b48SSukumar Swaminathan /* Timeout == -1 will enable the offline timer */
3582527734SSukumar Swaminathan /* Timeout not -1 will apply the timeout */
36fcf3ce44SJohn Forte extern void
3782527734SSukumar Swaminathan emlxs_node_close(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno,
38291a2b48SSukumar Swaminathan     int32_t timeout)
39fcf3ce44SJohn Forte {
40fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
41291a2b48SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
4282527734SSukumar Swaminathan 	CHANNEL *cp;
43fcf3ce44SJohn Forte 	NODELIST *prev;
44291a2b48SSukumar Swaminathan 	uint32_t offline = 0;
45fcf3ce44SJohn Forte 
4682527734SSukumar Swaminathan 
4782527734SSukumar Swaminathan 	/* If node is on a channel service queue, then remove it */
4882527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
49fcf3ce44SJohn Forte 
50fcf3ce44SJohn Forte 	/* Return if node destroyed */
51fcf3ce44SJohn Forte 	if (!ndlp || !ndlp->nlp_active) {
5282527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
53fcf3ce44SJohn Forte 
54fcf3ce44SJohn Forte 		return;
55fcf3ce44SJohn Forte 	}
56291a2b48SSukumar Swaminathan 
57291a2b48SSukumar Swaminathan 	/* Check offline support */
58291a2b48SSukumar Swaminathan 	if (timeout == -1) {
59291a2b48SSukumar Swaminathan 		if (cfg[CFG_OFFLINE_TIMEOUT].current) {
60291a2b48SSukumar Swaminathan 			timeout = cfg[CFG_OFFLINE_TIMEOUT].current;
61291a2b48SSukumar Swaminathan 			offline = 1;
62291a2b48SSukumar Swaminathan 		} else {
63291a2b48SSukumar Swaminathan 			timeout = 0;
64291a2b48SSukumar Swaminathan 		}
65291a2b48SSukumar Swaminathan 	}
66291a2b48SSukumar Swaminathan 
6782527734SSukumar Swaminathan 	if (channelno == hba->channel_ip) {
68fcf3ce44SJohn Forte 		/* Clear IP XRI */
69fcf3ce44SJohn Forte 		ndlp->nlp_Xri = 0;
70fcf3ce44SJohn Forte 	}
71291a2b48SSukumar Swaminathan 
72fcf3ce44SJohn Forte 	/* Check if node is already closed */
7382527734SSukumar Swaminathan 	if (ndlp->nlp_flag[channelno] & NLP_CLOSED) {
7482527734SSukumar Swaminathan 		if (ndlp->nlp_flag[channelno] & NLP_OFFLINE) {
7582527734SSukumar Swaminathan 			mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
76291a2b48SSukumar Swaminathan 			return;
77291a2b48SSukumar Swaminathan 		}
78291a2b48SSukumar Swaminathan 
79291a2b48SSukumar Swaminathan 		if (offline) {
8082527734SSukumar Swaminathan 			ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
8182527734SSukumar Swaminathan 			ndlp->nlp_flag[channelno] |= NLP_OFFLINE;
8282527734SSukumar Swaminathan 			mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
83291a2b48SSukumar Swaminathan 
84291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
85*fe199829SSukumar Swaminathan 			    "node=%p did=%06x channel=%d. offline=%d update.",
8682527734SSukumar Swaminathan 			    ndlp, ndlp->nlp_DID, channelno, timeout);
87291a2b48SSukumar Swaminathan 
88291a2b48SSukumar Swaminathan 		} else if (timeout) {
8982527734SSukumar Swaminathan 			ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
9082527734SSukumar Swaminathan 			mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
91291a2b48SSukumar Swaminathan 
92291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
93*fe199829SSukumar Swaminathan 			    "node=%p did=%06x channel=%d. timeout=%d update.",
9482527734SSukumar Swaminathan 			    ndlp, ndlp->nlp_DID, channelno, timeout);
95291a2b48SSukumar Swaminathan 		} else {
9682527734SSukumar Swaminathan 			mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
97fcf3ce44SJohn Forte 		}
98fcf3ce44SJohn Forte 
99fcf3ce44SJohn Forte 		return;
100fcf3ce44SJohn Forte 	}
101291a2b48SSukumar Swaminathan 
102fcf3ce44SJohn Forte 	/* Set the node closed */
10382527734SSukumar Swaminathan 	ndlp->nlp_flag[channelno] |= NLP_CLOSED;
104fcf3ce44SJohn Forte 
105291a2b48SSukumar Swaminathan 	if (offline) {
10682527734SSukumar Swaminathan 		ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
10782527734SSukumar Swaminathan 		ndlp->nlp_flag[channelno] |= NLP_OFFLINE;
108291a2b48SSukumar Swaminathan 
109*fe199829SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
110*fe199829SSukumar Swaminathan 		    "node=%p did=%06x channel=%d. offline=%d set.",
111*fe199829SSukumar Swaminathan 		    ndlp, ndlp->nlp_DID, channelno, timeout);
112*fe199829SSukumar Swaminathan 
113291a2b48SSukumar Swaminathan 	} else if (timeout) {
11482527734SSukumar Swaminathan 		ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
115*fe199829SSukumar Swaminathan 
116*fe199829SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
117*fe199829SSukumar Swaminathan 		    "node=%p did=%06x channel=%d. timeout=%d set.",
118*fe199829SSukumar Swaminathan 		    ndlp, ndlp->nlp_DID, channelno, timeout);
119*fe199829SSukumar Swaminathan 	} else {
120*fe199829SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
121*fe199829SSukumar Swaminathan 		    "node=%p did=%06x channel=%d.",
122*fe199829SSukumar Swaminathan 		    ndlp, ndlp->nlp_DID, channelno);
123fcf3ce44SJohn Forte 	}
124fcf3ce44SJohn Forte 
12582527734SSukumar Swaminathan 
12682527734SSukumar Swaminathan 	/*
12782527734SSukumar Swaminathan 	 * ndlp->nlp_next[] and cp->nodeq list have to be updated
12882527734SSukumar Swaminathan 	 * simulaneously
12982527734SSukumar Swaminathan 	 */
13082527734SSukumar Swaminathan 	if (ndlp->nlp_next[channelno]) {
13182527734SSukumar Swaminathan 		/* Remove node from channel queue */
13282527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
133fcf3ce44SJohn Forte 
134fcf3ce44SJohn Forte 		/* If this is the only node on list */
13582527734SSukumar Swaminathan 		if (cp->nodeq.q_first == (void *)ndlp &&
13682527734SSukumar Swaminathan 		    cp->nodeq.q_last == (void *)ndlp) {
13782527734SSukumar Swaminathan 			cp->nodeq.q_last = NULL;
13882527734SSukumar Swaminathan 			cp->nodeq.q_first = NULL;
13982527734SSukumar Swaminathan 			cp->nodeq.q_cnt = 0;
14082527734SSukumar Swaminathan 		} else if (cp->nodeq.q_first == (void *)ndlp) {
14182527734SSukumar Swaminathan 			cp->nodeq.q_first = ndlp->nlp_next[channelno];
14282527734SSukumar Swaminathan 			((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] =
14382527734SSukumar Swaminathan 			    cp->nodeq.q_first;
14482527734SSukumar Swaminathan 			cp->nodeq.q_cnt--;
145fcf3ce44SJohn Forte 		} else {	/* This is a little more difficult */
146291a2b48SSukumar Swaminathan 
14782527734SSukumar Swaminathan 			/* Find the previous node in circular channel queue */
148fcf3ce44SJohn Forte 			prev = ndlp;
14982527734SSukumar Swaminathan 			while (prev->nlp_next[channelno] != ndlp) {
15082527734SSukumar Swaminathan 				prev = prev->nlp_next[channelno];
151fcf3ce44SJohn Forte 			}
152fcf3ce44SJohn Forte 
15382527734SSukumar Swaminathan 			prev->nlp_next[channelno] = ndlp->nlp_next[channelno];
154fcf3ce44SJohn Forte 
15582527734SSukumar Swaminathan 			if (cp->nodeq.q_last == (void *)ndlp) {
15682527734SSukumar Swaminathan 				cp->nodeq.q_last = (void *)prev;
157fcf3ce44SJohn Forte 			}
15882527734SSukumar Swaminathan 			cp->nodeq.q_cnt--;
159fcf3ce44SJohn Forte 
160fcf3ce44SJohn Forte 		}
161fcf3ce44SJohn Forte 
162fcf3ce44SJohn Forte 		/* Clear node */
16382527734SSukumar Swaminathan 		ndlp->nlp_next[channelno] = NULL;
164fcf3ce44SJohn Forte 	}
165291a2b48SSukumar Swaminathan 
16682527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
167728bdc9bSSukumar Swaminathan 
168291a2b48SSukumar Swaminathan 	return;
169291a2b48SSukumar Swaminathan 
17082527734SSukumar Swaminathan } /* emlxs_node_close() */
171291a2b48SSukumar Swaminathan 
172291a2b48SSukumar Swaminathan 
173291a2b48SSukumar Swaminathan /* Called by emlxs_timer_check_nodes() */
174291a2b48SSukumar Swaminathan extern void
17582527734SSukumar Swaminathan emlxs_node_timeout(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno)
176291a2b48SSukumar Swaminathan {
177291a2b48SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
178291a2b48SSukumar Swaminathan 
17982527734SSukumar Swaminathan 	/* If node needs servicing, then add it to the channel queues */
18082527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
181291a2b48SSukumar Swaminathan 
182291a2b48SSukumar Swaminathan 	/* Return if node destroyed */
183291a2b48SSukumar Swaminathan 	if (!ndlp || !ndlp->nlp_active) {
18482527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
185291a2b48SSukumar Swaminathan 		return;
186291a2b48SSukumar Swaminathan 	}
187291a2b48SSukumar Swaminathan 
188291a2b48SSukumar Swaminathan 	/* Open the node if not offline */
18982527734SSukumar Swaminathan 	if (!(ndlp->nlp_flag[channelno] & NLP_OFFLINE)) {
19082527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
191291a2b48SSukumar Swaminathan 
192291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg,
19382527734SSukumar Swaminathan 		    "node=%p did=%06x channel=%d Opening.", ndlp, ndlp->nlp_DID,
19482527734SSukumar Swaminathan 		    channelno);
195291a2b48SSukumar Swaminathan 
19682527734SSukumar Swaminathan 		emlxs_node_open(port, ndlp, channelno);
197291a2b48SSukumar Swaminathan 		return;
198728bdc9bSSukumar Swaminathan 	}
199fcf3ce44SJohn Forte 
200291a2b48SSukumar Swaminathan 	/* OFFLINE TIMEOUT OCCURRED! */
201291a2b48SSukumar Swaminathan 
202291a2b48SSukumar Swaminathan 	/* Clear the timer */
20382527734SSukumar Swaminathan 	ndlp->nlp_tics[channelno] = 0;
204291a2b48SSukumar Swaminathan 
20582527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
206291a2b48SSukumar Swaminathan 
207291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg,
208291a2b48SSukumar Swaminathan 	    "node=%p did=%06x %s. Flushing.", ndlp, ndlp->nlp_DID,
20982527734SSukumar Swaminathan 	    channelno);
210291a2b48SSukumar Swaminathan 
21182527734SSukumar Swaminathan 	/* Flush tx queue for this channel */
21282527734SSukumar Swaminathan 	(void) emlxs_tx_node_flush(port, ndlp, &hba->chan[channelno], 0, 0);
213291a2b48SSukumar Swaminathan 
21482527734SSukumar Swaminathan 	/* Flush chip queue for this channel */
21582527734SSukumar Swaminathan 	(void) emlxs_chipq_node_flush(port, &hba->chan[channelno], ndlp, 0);
216291a2b48SSukumar Swaminathan 
217fcf3ce44SJohn Forte 	return;
218fcf3ce44SJohn Forte 
21982527734SSukumar Swaminathan } /* emlxs_node_timeout() */
220fcf3ce44SJohn Forte 
221fcf3ce44SJohn Forte 
222fcf3ce44SJohn Forte extern void
22382527734SSukumar Swaminathan emlxs_node_open(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno)
224fcf3ce44SJohn Forte {
225fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
22682527734SSukumar Swaminathan 	CHANNEL *cp;
227fcf3ce44SJohn Forte 	uint32_t found;
228fcf3ce44SJohn Forte 	NODELIST *nlp;
229fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
230fcf3ce44SJohn Forte 	uint32_t i;
23182527734SSukumar Swaminathan 	int rc;
232fcf3ce44SJohn Forte 
23382527734SSukumar Swaminathan 	/* If node needs servicing, then add it to the channel queues */
23482527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
235fcf3ce44SJohn Forte 
236fcf3ce44SJohn Forte 	/* Return if node destroyed */
237fcf3ce44SJohn Forte 	if (!ndlp || !ndlp->nlp_active) {
23882527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
239fcf3ce44SJohn Forte 
240fcf3ce44SJohn Forte 		return;
241fcf3ce44SJohn Forte 	}
242291a2b48SSukumar Swaminathan 
243fcf3ce44SJohn Forte 	/* Return if node already open */
24482527734SSukumar Swaminathan 	if (!(ndlp->nlp_flag[channelno] & NLP_CLOSED)) {
24582527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
246fcf3ce44SJohn Forte 
247fcf3ce44SJohn Forte 		return;
248fcf3ce44SJohn Forte 	}
249fcf3ce44SJohn Forte 
250291a2b48SSukumar Swaminathan 	/* Set the node open (not closed) */
25182527734SSukumar Swaminathan 	ndlp->nlp_flag[channelno] &= ~(NLP_CLOSED|NLP_OFFLINE);
252fcf3ce44SJohn Forte 
253fcf3ce44SJohn Forte 	/* Clear the timer */
25482527734SSukumar Swaminathan 	ndlp->nlp_tics[channelno] = 0;
255fcf3ce44SJohn Forte 
256fcf3ce44SJohn Forte 	/*
257291a2b48SSukumar Swaminathan 	 * If the ptx or the tx queue needs servicing and
25882527734SSukumar Swaminathan 	 * the node is not already on the channel queue
259fcf3ce44SJohn Forte 	 */
26082527734SSukumar Swaminathan 	if ((ndlp->nlp_ptx[channelno].q_first ||
26182527734SSukumar Swaminathan 	    ndlp->nlp_tx[channelno].q_first) && !ndlp->nlp_next[channelno]) {
26282527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
263fcf3ce44SJohn Forte 
26482527734SSukumar Swaminathan 		/* If so, then add it to the channel queue */
26582527734SSukumar Swaminathan 		if (cp->nodeq.q_first) {
26682527734SSukumar Swaminathan 			((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] =
267fcf3ce44SJohn Forte 			    (uint8_t *)ndlp;
26882527734SSukumar Swaminathan 			ndlp->nlp_next[channelno] = cp->nodeq.q_first;
269fcf3ce44SJohn Forte 
270291a2b48SSukumar Swaminathan 			/* If this is not the base node then */
271291a2b48SSukumar Swaminathan 			/* add it to the tail */
272fcf3ce44SJohn Forte 			if (!ndlp->nlp_base) {
27382527734SSukumar Swaminathan 				cp->nodeq.q_last = (uint8_t *)ndlp;
274fcf3ce44SJohn Forte 			} else {	/* Otherwise, add it to the head */
275291a2b48SSukumar Swaminathan 
276fcf3ce44SJohn Forte 				/* The command node always gets priority */
27782527734SSukumar Swaminathan 				cp->nodeq.q_first = (uint8_t *)ndlp;
278fcf3ce44SJohn Forte 			}
279fcf3ce44SJohn Forte 
28082527734SSukumar Swaminathan 			cp->nodeq.q_cnt++;
281fcf3ce44SJohn Forte 		} else {
28282527734SSukumar Swaminathan 			cp->nodeq.q_first = (uint8_t *)ndlp;
28382527734SSukumar Swaminathan 			cp->nodeq.q_last = (uint8_t *)ndlp;
28482527734SSukumar Swaminathan 			ndlp->nlp_next[channelno] = ndlp;
28582527734SSukumar Swaminathan 			cp->nodeq.q_cnt = 1;
286fcf3ce44SJohn Forte 		}
287fcf3ce44SJohn Forte 	}
288291a2b48SSukumar Swaminathan 
28982527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
290fcf3ce44SJohn Forte 
291291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_opened_msg,
29282527734SSukumar Swaminathan 	    "node=%p did=%06x channel=%d", ndlp, ndlp->nlp_DID, channelno);
293728bdc9bSSukumar Swaminathan 
294fcf3ce44SJohn Forte 	/* If link attention needs to be cleared */
29582527734SSukumar Swaminathan 	if ((hba->state == FC_LINK_UP) && (channelno == hba->channel_fcp)) {
29682527734SSukumar Swaminathan 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
29782527734SSukumar Swaminathan 		/* re Think this code path. For SLI4 channel fcp == els */
29882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
29982527734SSukumar Swaminathan 			    "ADD CODE to RESUME RPIs node=%p did=%06x chan=%d",
30082527734SSukumar Swaminathan 			    ndlp, ndlp->nlp_DID, channelno);
30182527734SSukumar Swaminathan 
30282527734SSukumar Swaminathan 			goto done;
30382527734SSukumar Swaminathan 		}
304fcf3ce44SJohn Forte 
305fcf3ce44SJohn Forte 		/* Scan to see if any FCP2 devices are still closed */
306fcf3ce44SJohn Forte 		found = 0;
307fcf3ce44SJohn Forte 		rw_enter(&port->node_rwlock, RW_READER);
308fcf3ce44SJohn Forte 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
309fcf3ce44SJohn Forte 			nlp = port->node_table[i];
310fcf3ce44SJohn Forte 			while (nlp != NULL) {
311fcf3ce44SJohn Forte 				if ((nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) &&
31282527734SSukumar Swaminathan 				    (nlp->nlp_flag[hba->channel_fcp] &
31382527734SSukumar Swaminathan 				    NLP_CLOSED)) {
314fcf3ce44SJohn Forte 					found = 1;
315fcf3ce44SJohn Forte 					break;
316291a2b48SSukumar Swaminathan 
317fcf3ce44SJohn Forte 				}
318fcf3ce44SJohn Forte 				nlp = nlp->nlp_list_next;
319fcf3ce44SJohn Forte 			}
320fcf3ce44SJohn Forte 
321fcf3ce44SJohn Forte 			if (found) {
322fcf3ce44SJohn Forte 				break;
323fcf3ce44SJohn Forte 			}
324fcf3ce44SJohn Forte 		}
325fcf3ce44SJohn Forte 
326fcf3ce44SJohn Forte 		rw_exit(&port->node_rwlock);
327fcf3ce44SJohn Forte 
328fcf3ce44SJohn Forte 		if (!found) {
329fcf3ce44SJohn Forte 			/* Clear link attention */
330291a2b48SSukumar Swaminathan 			if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
33182527734SSukumar Swaminathan 			    MEM_MBOX, 1))) {
332fcf3ce44SJohn Forte 				mutex_enter(&EMLXS_PORT_LOCK);
333fcf3ce44SJohn Forte 
334fcf3ce44SJohn Forte 				/*
335291a2b48SSukumar Swaminathan 				 * If state is not FC_LINK_UP, then either the
336291a2b48SSukumar Swaminathan 				 * link has gone down or a FC_CLEAR_LA has
337291a2b48SSukumar Swaminathan 				 * already been issued
338fcf3ce44SJohn Forte 				 */
339fcf3ce44SJohn Forte 				if (hba->state != FC_LINK_UP) {
340fcf3ce44SJohn Forte 					mutex_exit(&EMLXS_PORT_LOCK);
341fcf3ce44SJohn Forte 					(void) emlxs_mem_put(hba, MEM_MBOX,
342fcf3ce44SJohn Forte 					    (uint8_t *)mbox);
343fcf3ce44SJohn Forte 					goto done;
344fcf3ce44SJohn Forte 				}
345291a2b48SSukumar Swaminathan 
34682527734SSukumar Swaminathan 				EMLXS_STATE_CHANGE_LOCKED(hba, FC_CLEAR_LA);
347fcf3ce44SJohn Forte 				hba->discovery_timer = 0;
348fcf3ce44SJohn Forte 				mutex_exit(&EMLXS_PORT_LOCK);
349fcf3ce44SJohn Forte 
35082527734SSukumar Swaminathan 				emlxs_mb_clear_la(hba, mbox);
351fcf3ce44SJohn Forte 
35282527734SSukumar Swaminathan 				rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba,
35382527734SSukumar Swaminathan 				    mbox, MBX_NOWAIT, 0);
35482527734SSukumar Swaminathan 				if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
355fcf3ce44SJohn Forte 					(void) emlxs_mem_put(hba, MEM_MBOX,
356fcf3ce44SJohn Forte 					    (uint8_t *)mbox);
357fcf3ce44SJohn Forte 				}
358fcf3ce44SJohn Forte 			} else {
359291a2b48SSukumar Swaminathan 				/* Close the node and try again */
360291a2b48SSukumar Swaminathan 				/* in a few seconds */
36182527734SSukumar Swaminathan 				emlxs_node_close(port, ndlp, channelno, 5);
362fcf3ce44SJohn Forte 				return;
363fcf3ce44SJohn Forte 			}
364fcf3ce44SJohn Forte 		}
365fcf3ce44SJohn Forte 	}
366291a2b48SSukumar Swaminathan 
367fcf3ce44SJohn Forte done:
368fcf3ce44SJohn Forte 
369fcf3ce44SJohn Forte 	/* Wake any sleeping threads */
370fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PKT_LOCK);
371fcf3ce44SJohn Forte 	cv_broadcast(&EMLXS_PKT_CV);
372fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PKT_LOCK);
373fcf3ce44SJohn Forte 
374fcf3ce44SJohn Forte 	return;
375fcf3ce44SJohn Forte 
37682527734SSukumar Swaminathan } /* emlxs_node_open() */
377fcf3ce44SJohn Forte 
378fcf3ce44SJohn Forte 
379fcf3ce44SJohn Forte static int
380fcf3ce44SJohn Forte emlxs_node_match_did(emlxs_port_t *port, NODELIST *ndlp, uint32_t did)
381fcf3ce44SJohn Forte {
382fcf3ce44SJohn Forte 	D_ID mydid;
383fcf3ce44SJohn Forte 	D_ID odid;
384fcf3ce44SJohn Forte 	D_ID ndid;
385fcf3ce44SJohn Forte 
386291a2b48SSukumar Swaminathan 	if (ndlp->nlp_DID == did)
387fcf3ce44SJohn Forte 		return (1);
388fcf3ce44SJohn Forte 
389fcf3ce44SJohn Forte 	/*
390fcf3ce44SJohn Forte 	 * Next check for area/domain == 0 match
391fcf3ce44SJohn Forte 	 */
392fcf3ce44SJohn Forte 	mydid.un.word = port->did;
393fcf3ce44SJohn Forte 	if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) {
394fcf3ce44SJohn Forte 		goto out;
395fcf3ce44SJohn Forte 	}
396291a2b48SSukumar Swaminathan 
397fcf3ce44SJohn Forte 	ndid.un.word = did;
398fcf3ce44SJohn Forte 	odid.un.word = ndlp->nlp_DID;
399fcf3ce44SJohn Forte 	if (ndid.un.b.id == odid.un.b.id) {
400fcf3ce44SJohn Forte 		if ((mydid.un.b.domain == ndid.un.b.domain) &&
401fcf3ce44SJohn Forte 		    (mydid.un.b.area == ndid.un.b.area)) {
402fcf3ce44SJohn Forte 			ndid.un.word = ndlp->nlp_DID;
403fcf3ce44SJohn Forte 			odid.un.word = did;
404291a2b48SSukumar Swaminathan 			if ((ndid.un.b.domain == 0) && (ndid.un.b.area == 0)) {
405fcf3ce44SJohn Forte 				return (1);
406fcf3ce44SJohn Forte 			}
407fcf3ce44SJohn Forte 			goto out;
408fcf3ce44SJohn Forte 		}
409291a2b48SSukumar Swaminathan 
410fcf3ce44SJohn Forte 		ndid.un.word = ndlp->nlp_DID;
411fcf3ce44SJohn Forte 		if ((mydid.un.b.domain == ndid.un.b.domain) &&
412fcf3ce44SJohn Forte 		    (mydid.un.b.area == ndid.un.b.area)) {
413fcf3ce44SJohn Forte 			odid.un.word = ndlp->nlp_DID;
414fcf3ce44SJohn Forte 			ndid.un.word = did;
415291a2b48SSukumar Swaminathan 			if ((ndid.un.b.domain == 0) && (ndid.un.b.area == 0)) {
416fcf3ce44SJohn Forte 				return (1);
417fcf3ce44SJohn Forte 			}
418fcf3ce44SJohn Forte 		}
419fcf3ce44SJohn Forte 	}
420291a2b48SSukumar Swaminathan 
421fcf3ce44SJohn Forte out:
422fcf3ce44SJohn Forte 
423fcf3ce44SJohn Forte 	return (0);
424fcf3ce44SJohn Forte 
42582527734SSukumar Swaminathan } /* End emlxs_node_match_did */
426fcf3ce44SJohn Forte 
427fcf3ce44SJohn Forte 
428fcf3ce44SJohn Forte 
429fcf3ce44SJohn Forte extern NODELIST *
430fcf3ce44SJohn Forte emlxs_node_find_mac(emlxs_port_t *port, uint8_t *mac)
431fcf3ce44SJohn Forte {
432fcf3ce44SJohn Forte 	NODELIST *nlp;
433fcf3ce44SJohn Forte 	uint32_t i;
434fcf3ce44SJohn Forte 
435fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
436fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
437fcf3ce44SJohn Forte 		nlp = port->node_table[i];
438fcf3ce44SJohn Forte 		while (nlp != NULL) {
439fcf3ce44SJohn Forte 			/*
440291a2b48SSukumar Swaminathan 			 * If portname matches mac address,
441291a2b48SSukumar Swaminathan 			 * return NODELIST entry
442fcf3ce44SJohn Forte 			 */
443fcf3ce44SJohn Forte 			if ((nlp->nlp_portname.IEEE[0] == mac[0])) {
44482527734SSukumar Swaminathan 				if ((nlp->nlp_DID != BCAST_DID) &&
44582527734SSukumar Swaminathan 				    ((nlp->nlp_DID & FABRIC_DID_MASK) ==
44682527734SSukumar Swaminathan 				    FABRIC_DID_MASK)) {
447291a2b48SSukumar Swaminathan 					nlp = (NODELIST *)nlp->nlp_list_next;
448fcf3ce44SJohn Forte 					continue;
449fcf3ce44SJohn Forte 				}
450291a2b48SSukumar Swaminathan 
451fcf3ce44SJohn Forte 				if ((nlp->nlp_portname.IEEE[1] == mac[1]) &&
452fcf3ce44SJohn Forte 				    (nlp->nlp_portname.IEEE[2] == mac[2]) &&
453fcf3ce44SJohn Forte 				    (nlp->nlp_portname.IEEE[3] == mac[3]) &&
454fcf3ce44SJohn Forte 				    (nlp->nlp_portname.IEEE[4] == mac[4]) &&
455fcf3ce44SJohn Forte 				    (nlp->nlp_portname.IEEE[5] == mac[5])) {
456fcf3ce44SJohn Forte 					rw_exit(&port->node_rwlock);
457fcf3ce44SJohn Forte 					return (nlp);
458fcf3ce44SJohn Forte 				}
459291a2b48SSukumar Swaminathan 
460fcf3ce44SJohn Forte 			}
461291a2b48SSukumar Swaminathan 
462291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
463fcf3ce44SJohn Forte 		}
464fcf3ce44SJohn Forte 	}
465fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
466fcf3ce44SJohn Forte 
467fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg,
468291a2b48SSukumar Swaminathan 	    "find: MAC=%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2],
469291a2b48SSukumar Swaminathan 	    mac[3], mac[4], mac[5]);
470fcf3ce44SJohn Forte 
471fcf3ce44SJohn Forte 	return (NULL);
472fcf3ce44SJohn Forte 
47382527734SSukumar Swaminathan } /* emlxs_node_find_mac() */
474fcf3ce44SJohn Forte 
475fcf3ce44SJohn Forte 
476fcf3ce44SJohn Forte extern NODELIST *
477fcf3ce44SJohn Forte emlxs_node_find_did(emlxs_port_t *port, uint32_t did)
478fcf3ce44SJohn Forte {
479fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
480fcf3ce44SJohn Forte 	NODELIST *nlp;
481fcf3ce44SJohn Forte 	uint32_t hash;
482fcf3ce44SJohn Forte 
483fcf3ce44SJohn Forte 	/* Check for invalid node ids  */
484291a2b48SSukumar Swaminathan 	if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) {
485291a2b48SSukumar Swaminathan 		return ((NODELIST *)0);
486291a2b48SSukumar Swaminathan 	}
487291a2b48SSukumar Swaminathan 
488291a2b48SSukumar Swaminathan 	if (did & 0xff000000) {
489291a2b48SSukumar Swaminathan 		return ((NODELIST *)0);
490fcf3ce44SJohn Forte 	}
491291a2b48SSukumar Swaminathan 
492fcf3ce44SJohn Forte 	/* Check for bcast node */
49382527734SSukumar Swaminathan 	if (did == BCAST_DID) {
494fcf3ce44SJohn Forte 		/* Use the base node here */
495fcf3ce44SJohn Forte 		return (&port->node_base);
496fcf3ce44SJohn Forte 	}
497fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT
498fcf3ce44SJohn Forte 	/* Check for menlo node */
499fcf3ce44SJohn Forte 	if (did == EMLXS_MENLO_DID) {
500fcf3ce44SJohn Forte 		/* Use the base node here */
501fcf3ce44SJohn Forte 		return (&port->node_base);
502fcf3ce44SJohn Forte 	}
503291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */
504fcf3ce44SJohn Forte 
505fcf3ce44SJohn Forte 	/* Check for host node */
506fcf3ce44SJohn Forte 	if (did == port->did && !(hba->flag & FC_LOOPBACK_MODE)) {
507fcf3ce44SJohn Forte 		/* Use the base node here */
508fcf3ce44SJohn Forte 		return (&port->node_base);
509fcf3ce44SJohn Forte 	}
510291a2b48SSukumar Swaminathan 
511fcf3ce44SJohn Forte 	/*
51282527734SSukumar Swaminathan 	 * Convert well known fabric addresses to the FABRIC_DID,
513291a2b48SSukumar Swaminathan 	 * since we don't login to some of them
514fcf3ce44SJohn Forte 	 */
515fcf3ce44SJohn Forte 	if ((did == SCR_DID)) {
51682527734SSukumar Swaminathan 		did = FABRIC_DID;
517fcf3ce44SJohn Forte 	}
518291a2b48SSukumar Swaminathan 
519fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
520fcf3ce44SJohn Forte 	hash = EMLXS_DID_HASH(did);
521fcf3ce44SJohn Forte 	nlp = port->node_table[hash];
522fcf3ce44SJohn Forte 	while (nlp != NULL) {
523fcf3ce44SJohn Forte 		/* Check for obvious match */
524fcf3ce44SJohn Forte 		if (nlp->nlp_DID == did) {
525fcf3ce44SJohn Forte 			rw_exit(&port->node_rwlock);
526fcf3ce44SJohn Forte 			return (nlp);
527fcf3ce44SJohn Forte 		}
528291a2b48SSukumar Swaminathan 
529fcf3ce44SJohn Forte 		/* Check for detailed match */
530fcf3ce44SJohn Forte 		else if (emlxs_node_match_did(port, nlp, did)) {
531fcf3ce44SJohn Forte 			rw_exit(&port->node_rwlock);
532fcf3ce44SJohn Forte 			return (nlp);
533fcf3ce44SJohn Forte 		}
534291a2b48SSukumar Swaminathan 
535291a2b48SSukumar Swaminathan 		nlp = (NODELIST *)nlp->nlp_list_next;
536fcf3ce44SJohn Forte 	}
537fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
538fcf3ce44SJohn Forte 
539291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: did=%x",
540291a2b48SSukumar Swaminathan 	    did);
541fcf3ce44SJohn Forte 
542fcf3ce44SJohn Forte 	/* no match found */
543291a2b48SSukumar Swaminathan 	return ((NODELIST *)0);
544fcf3ce44SJohn Forte 
54582527734SSukumar Swaminathan } /* emlxs_node_find_did() */
546fcf3ce44SJohn Forte 
547fcf3ce44SJohn Forte 
548fcf3ce44SJohn Forte extern NODELIST *
549fcf3ce44SJohn Forte emlxs_node_find_rpi(emlxs_port_t *port, uint32_t rpi)
550fcf3ce44SJohn Forte {
551fcf3ce44SJohn Forte 	NODELIST *nlp;
552fcf3ce44SJohn Forte 	uint32_t i;
553fcf3ce44SJohn Forte 
554fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
555fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
556fcf3ce44SJohn Forte 		nlp = port->node_table[i];
557fcf3ce44SJohn Forte 		while (nlp != NULL) {
558fcf3ce44SJohn Forte 			if (nlp->nlp_Rpi == rpi) {
559fcf3ce44SJohn Forte 				rw_exit(&port->node_rwlock);
560fcf3ce44SJohn Forte 				return (nlp);
561fcf3ce44SJohn Forte 			}
562291a2b48SSukumar Swaminathan 
563291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
564fcf3ce44SJohn Forte 		}
565fcf3ce44SJohn Forte 	}
566fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
567fcf3ce44SJohn Forte 
568291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: rpi=%x",
569291a2b48SSukumar Swaminathan 	    rpi);
570fcf3ce44SJohn Forte 
571fcf3ce44SJohn Forte 	/* no match found */
572291a2b48SSukumar Swaminathan 	return ((NODELIST *)0);
573fcf3ce44SJohn Forte 
57482527734SSukumar Swaminathan } /* emlxs_node_find_rpi() */
575fcf3ce44SJohn Forte 
576fcf3ce44SJohn Forte 
577fcf3ce44SJohn Forte extern NODELIST *
578fcf3ce44SJohn Forte emlxs_node_find_wwpn(emlxs_port_t *port, uint8_t *wwpn)
579fcf3ce44SJohn Forte {
580fcf3ce44SJohn Forte 	NODELIST *nlp;
581fcf3ce44SJohn Forte 	uint32_t i;
582fcf3ce44SJohn Forte 	uint32_t j;
583fcf3ce44SJohn Forte 	uint8_t *bptr1;
584fcf3ce44SJohn Forte 	uint8_t *bptr2;
585fcf3ce44SJohn Forte 
586fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
587fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
588fcf3ce44SJohn Forte 		nlp = port->node_table[i];
589fcf3ce44SJohn Forte 		while (nlp != NULL) {
590fcf3ce44SJohn Forte 			bptr1 = (uint8_t *)&nlp->nlp_portname;
591fcf3ce44SJohn Forte 			bptr1 += 7;
592fcf3ce44SJohn Forte 			bptr2 = (uint8_t *)wwpn;
593fcf3ce44SJohn Forte 			bptr2 += 7;
594fcf3ce44SJohn Forte 
595fcf3ce44SJohn Forte 			for (j = 0; j < 8; j++) {
596fcf3ce44SJohn Forte 				if (*bptr1-- != *bptr2--) {
597fcf3ce44SJohn Forte 					break;
598fcf3ce44SJohn Forte 				}
599fcf3ce44SJohn Forte 			}
600fcf3ce44SJohn Forte 
601fcf3ce44SJohn Forte 			if (j == 8) {
602fcf3ce44SJohn Forte 				rw_exit(&port->node_rwlock);
603fcf3ce44SJohn Forte 				return (nlp);
604fcf3ce44SJohn Forte 			}
605291a2b48SSukumar Swaminathan 
606291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
607fcf3ce44SJohn Forte 		}
608fcf3ce44SJohn Forte 	}
609fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
610fcf3ce44SJohn Forte 
611fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg,
612291a2b48SSukumar Swaminathan 	    "find: wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", wwpn[0], wwpn[1],
613291a2b48SSukumar Swaminathan 	    wwpn[2], wwpn[3], wwpn[4], wwpn[5], wwpn[6], wwpn[7]);
614fcf3ce44SJohn Forte 
615fcf3ce44SJohn Forte 	/* no match found */
616291a2b48SSukumar Swaminathan 	return ((NODELIST *)0);
617fcf3ce44SJohn Forte 
61882527734SSukumar Swaminathan } /* emlxs_node_find_wwpn() */
619fcf3ce44SJohn Forte 
620fcf3ce44SJohn Forte 
621fcf3ce44SJohn Forte extern NODELIST *
622291a2b48SSukumar Swaminathan emlxs_node_find_index(emlxs_port_t *port, uint32_t index,
623291a2b48SSukumar Swaminathan     uint32_t nports_only)
624fcf3ce44SJohn Forte {
625fcf3ce44SJohn Forte 	NODELIST *nlp;
626fcf3ce44SJohn Forte 	uint32_t i;
627fcf3ce44SJohn Forte 	uint32_t count;
628fcf3ce44SJohn Forte 
629fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
630fcf3ce44SJohn Forte 
631fcf3ce44SJohn Forte 	if (index > port->node_count - 1) {
632fcf3ce44SJohn Forte 		rw_exit(&port->node_rwlock);
633fcf3ce44SJohn Forte 		return (NULL);
634fcf3ce44SJohn Forte 	}
635291a2b48SSukumar Swaminathan 
636fcf3ce44SJohn Forte 	count = 0;
637fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
638fcf3ce44SJohn Forte 		nlp = port->node_table[i];
639fcf3ce44SJohn Forte 		while (nlp != NULL) {
640fcf3ce44SJohn Forte 			/* Skip fabric ports if requested */
641291a2b48SSukumar Swaminathan 			if (nports_only &&
642291a2b48SSukumar Swaminathan 			    (nlp->nlp_DID & 0xFFF000) == 0xFFF000) {
643291a2b48SSukumar Swaminathan 				nlp = (NODELIST *)nlp->nlp_list_next;
644fcf3ce44SJohn Forte 				continue;
645fcf3ce44SJohn Forte 			}
646291a2b48SSukumar Swaminathan 
647fcf3ce44SJohn Forte 			if (count == index) {
648fcf3ce44SJohn Forte 				rw_exit(&port->node_rwlock);
649fcf3ce44SJohn Forte 				return (nlp);
650fcf3ce44SJohn Forte 			}
651291a2b48SSukumar Swaminathan 
652291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
653fcf3ce44SJohn Forte 			count++;
654fcf3ce44SJohn Forte 		}
655fcf3ce44SJohn Forte 	}
656fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
657fcf3ce44SJohn Forte 
658291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: index=%d",
659291a2b48SSukumar Swaminathan 	    index);
660fcf3ce44SJohn Forte 
661fcf3ce44SJohn Forte 	/* no match found */
662291a2b48SSukumar Swaminathan 	return ((NODELIST *)0);
663fcf3ce44SJohn Forte 
66482527734SSukumar Swaminathan } /* emlxs_node_find_wwpn() */
665fcf3ce44SJohn Forte 
666fcf3ce44SJohn Forte 
667fcf3ce44SJohn Forte extern uint32_t
668fcf3ce44SJohn Forte emlxs_nport_count(emlxs_port_t *port)
669fcf3ce44SJohn Forte {
670fcf3ce44SJohn Forte 	NODELIST *nlp;
671fcf3ce44SJohn Forte 	uint32_t i;
672fcf3ce44SJohn Forte 	uint32_t nport_count = 0;
673fcf3ce44SJohn Forte 
674fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
675fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
676fcf3ce44SJohn Forte 		nlp = port->node_table[i];
677fcf3ce44SJohn Forte 		while (nlp != NULL) {
678fcf3ce44SJohn Forte 			if ((nlp->nlp_DID & 0xFFF000) != 0xFFF000) {
679fcf3ce44SJohn Forte 				nport_count++;
680fcf3ce44SJohn Forte 			}
681291a2b48SSukumar Swaminathan 
682291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
683fcf3ce44SJohn Forte 		}
684fcf3ce44SJohn Forte 	}
685fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
686fcf3ce44SJohn Forte 
687fcf3ce44SJohn Forte 	return (nport_count);
688fcf3ce44SJohn Forte 
68982527734SSukumar Swaminathan } /* emlxs_nport_count() */
690fcf3ce44SJohn Forte 
691fcf3ce44SJohn Forte 
692fcf3ce44SJohn Forte 
693fcf3ce44SJohn Forte extern void
694fcf3ce44SJohn Forte emlxs_node_destroy_all(emlxs_port_t *port)
695fcf3ce44SJohn Forte {
696fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
697fcf3ce44SJohn Forte 	NODELIST *next;
698fcf3ce44SJohn Forte 	NODELIST *ndlp;
69982527734SSukumar Swaminathan 	RPIobj_t *rp;
700fcf3ce44SJohn Forte 	uint8_t *wwn;
701fcf3ce44SJohn Forte 	uint32_t i;
702fcf3ce44SJohn Forte 
703fcf3ce44SJohn Forte 	/* Flush and free the nodes */
704fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_WRITER);
705fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
706fcf3ce44SJohn Forte 		ndlp = port->node_table[i];
707fcf3ce44SJohn Forte 		port->node_table[i] = 0;
708fcf3ce44SJohn Forte 		while (ndlp != NULL) {
709fcf3ce44SJohn Forte 			next = ndlp->nlp_list_next;
710fcf3ce44SJohn Forte 			ndlp->nlp_list_next = NULL;
711fcf3ce44SJohn Forte 			ndlp->nlp_list_prev = NULL;
712fcf3ce44SJohn Forte 			ndlp->nlp_active = 0;
713fcf3ce44SJohn Forte 
714fcf3ce44SJohn Forte 			if (port->node_count) {
715fcf3ce44SJohn Forte 				port->node_count--;
716fcf3ce44SJohn Forte 			}
717291a2b48SSukumar Swaminathan 
718fcf3ce44SJohn Forte 			wwn = (uint8_t *)&ndlp->nlp_portname;
719291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
720291a2b48SSukumar Swaminathan 			    &emlxs_node_destroy_msg, "did=%06x "
721291a2b48SSukumar Swaminathan 			    "rpi=%x wwpn=%02x%02x%02x%02x%02x%02x%02x%02x "
722291a2b48SSukumar Swaminathan 			    "count=%d", ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0],
723291a2b48SSukumar Swaminathan 			    wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6],
724291a2b48SSukumar Swaminathan 			    wwn[7], port->node_count);
725fcf3ce44SJohn Forte 
726fcf3ce44SJohn Forte 			(void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0);
727fcf3ce44SJohn Forte 
72882527734SSukumar Swaminathan 			/* Break Node/RPI binding */
72982527734SSukumar Swaminathan 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
73082527734SSukumar Swaminathan 				rp = EMLXS_NODE_TO_RPI(hba, ndlp);
73182527734SSukumar Swaminathan 				ndlp->RPIp = NULL;
73282527734SSukumar Swaminathan 
73382527734SSukumar Swaminathan 				if (rp) {
73482527734SSukumar Swaminathan 					rp->node = NULL;
73582527734SSukumar Swaminathan 					(void) emlxs_sli4_free_rpi(hba, rp);
73682527734SSukumar Swaminathan 				}
73782527734SSukumar Swaminathan 			}
73882527734SSukumar Swaminathan 
739fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_NLP, (uint8_t *)ndlp);
740fcf3ce44SJohn Forte 
741fcf3ce44SJohn Forte 			ndlp = next;
742fcf3ce44SJohn Forte 		}
743fcf3ce44SJohn Forte 	}
744fcf3ce44SJohn Forte 	port->node_count = 0;
745fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
746fcf3ce44SJohn Forte 
747fcf3ce44SJohn Forte 	/* Clean the base node */
748fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
749fcf3ce44SJohn Forte 	port->node_base.nlp_list_next = NULL;
750fcf3ce44SJohn Forte 	port->node_base.nlp_list_prev = NULL;
751fcf3ce44SJohn Forte 	port->node_base.nlp_active = 1;
752fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
753fcf3ce44SJohn Forte 
754fcf3ce44SJohn Forte 	/* Flush the base node */
755fcf3ce44SJohn Forte 	(void) emlxs_tx_node_flush(port, &port->node_base, 0, 1, 0);
756fcf3ce44SJohn Forte 	(void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0);
757fcf3ce44SJohn Forte 
758fcf3ce44SJohn Forte 	return;
759fcf3ce44SJohn Forte 
76082527734SSukumar Swaminathan } /* emlxs_node_destroy_all() */
761fcf3ce44SJohn Forte 
762fcf3ce44SJohn Forte 
763fcf3ce44SJohn Forte extern void
764fcf3ce44SJohn Forte emlxs_node_add(emlxs_port_t *port, NODELIST *ndlp)
765fcf3ce44SJohn Forte {
76682527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
767fcf3ce44SJohn Forte 	NODELIST *np;
768fcf3ce44SJohn Forte 	uint8_t *wwn;
769fcf3ce44SJohn Forte 	uint32_t hash;
77082527734SSukumar Swaminathan 	RPIobj_t *rp;
771fcf3ce44SJohn Forte 
772fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_WRITER);
773fcf3ce44SJohn Forte 	hash = EMLXS_DID_HASH(ndlp->nlp_DID);
774fcf3ce44SJohn Forte 	np = port->node_table[hash];
775fcf3ce44SJohn Forte 
776fcf3ce44SJohn Forte 	/*
777fcf3ce44SJohn Forte 	 * Insert node pointer to the head
778fcf3ce44SJohn Forte 	 */
779fcf3ce44SJohn Forte 	port->node_table[hash] = ndlp;
780fcf3ce44SJohn Forte 	if (!np) {
781fcf3ce44SJohn Forte 		ndlp->nlp_list_next = NULL;
782fcf3ce44SJohn Forte 	} else {
783fcf3ce44SJohn Forte 		ndlp->nlp_list_next = np;
784fcf3ce44SJohn Forte 	}
785fcf3ce44SJohn Forte 	port->node_count++;
786fcf3ce44SJohn Forte 
787fcf3ce44SJohn Forte 	wwn = (uint8_t *)&ndlp->nlp_portname;
788fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_msg,
789291a2b48SSukumar Swaminathan 	    "node=%p did=%06x rpi=%x wwpn=%02x%02x%02x%02x%02x%02x%02x%02x "
790291a2b48SSukumar Swaminathan 	    "count=%d", ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], wwn[1],
791291a2b48SSukumar Swaminathan 	    wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7], port->node_count);
792fcf3ce44SJohn Forte 
79382527734SSukumar Swaminathan 	/* Add Node/RPI binding */
79482527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
79582527734SSukumar Swaminathan 		rp = emlxs_sli4_find_rpi(hba, ndlp->nlp_Rpi);
79682527734SSukumar Swaminathan 
79782527734SSukumar Swaminathan 		if (rp) {
79882527734SSukumar Swaminathan 			rp->node = ndlp;
79982527734SSukumar Swaminathan 			ndlp->RPIp = rp;
80082527734SSukumar Swaminathan 		} else {
80182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_msg,
80282527734SSukumar Swaminathan 			    "Unable to find RPI! did=%x rpi=%x",
80382527734SSukumar Swaminathan 			    ndlp->nlp_DID, ndlp->nlp_Rpi);
80482527734SSukumar Swaminathan 		}
80582527734SSukumar Swaminathan 	}
80682527734SSukumar Swaminathan 
807fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
808fcf3ce44SJohn Forte 
809fcf3ce44SJohn Forte 	return;
810fcf3ce44SJohn Forte 
81182527734SSukumar Swaminathan } /* emlxs_node_add() */
812fcf3ce44SJohn Forte 
813fcf3ce44SJohn Forte 
814fcf3ce44SJohn Forte extern void
815fcf3ce44SJohn Forte emlxs_node_rm(emlxs_port_t *port, NODELIST *ndlp)
816fcf3ce44SJohn Forte {
817fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
818fcf3ce44SJohn Forte 	NODELIST *np;
819fcf3ce44SJohn Forte 	NODELIST *prevp;
82082527734SSukumar Swaminathan 	RPIobj_t *rp;
821fcf3ce44SJohn Forte 	uint8_t *wwn;
822fcf3ce44SJohn Forte 	uint32_t hash;
823fcf3ce44SJohn Forte 
824fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_WRITER);
825fcf3ce44SJohn Forte 	hash = EMLXS_DID_HASH(ndlp->nlp_DID);
826fcf3ce44SJohn Forte 	np = port->node_table[hash];
827fcf3ce44SJohn Forte 	prevp = NULL;
828fcf3ce44SJohn Forte 	while (np != NULL) {
829fcf3ce44SJohn Forte 		if (np->nlp_DID == ndlp->nlp_DID) {
830fcf3ce44SJohn Forte 			if (prevp == NULL) {
831fcf3ce44SJohn Forte 				port->node_table[hash] = np->nlp_list_next;
832fcf3ce44SJohn Forte 			} else {
833fcf3ce44SJohn Forte 				prevp->nlp_list_next = np->nlp_list_next;
834fcf3ce44SJohn Forte 			}
835fcf3ce44SJohn Forte 
836fcf3ce44SJohn Forte 			if (port->node_count) {
837fcf3ce44SJohn Forte 				port->node_count--;
838fcf3ce44SJohn Forte 			}
839291a2b48SSukumar Swaminathan 
840fcf3ce44SJohn Forte 			wwn = (uint8_t *)&ndlp->nlp_portname;
841291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
842291a2b48SSukumar Swaminathan 			    &emlxs_node_destroy_msg, "did=%06x "
843291a2b48SSukumar Swaminathan 			    "rpi=%x wwpn=%02x%02x%02x%02x%02x%02x%02x%02x "
844291a2b48SSukumar Swaminathan 			    "count=%d", ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0],
845291a2b48SSukumar Swaminathan 			    wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6],
846291a2b48SSukumar Swaminathan 			    wwn[7], port->node_count);
847fcf3ce44SJohn Forte 
848fcf3ce44SJohn Forte 			(void) emlxs_tx_node_flush(port, ndlp, 0, 1, 0);
849fcf3ce44SJohn Forte 
850fcf3ce44SJohn Forte 			ndlp->nlp_active = 0;
85182527734SSukumar Swaminathan 
85282527734SSukumar Swaminathan 			/* Break Node/RPI binding */
85382527734SSukumar Swaminathan 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
85482527734SSukumar Swaminathan 				rp = EMLXS_NODE_TO_RPI(hba, ndlp);
85582527734SSukumar Swaminathan 				ndlp->RPIp = NULL;
85682527734SSukumar Swaminathan 
85782527734SSukumar Swaminathan 				if (rp) {
85882527734SSukumar Swaminathan 					rp->node = NULL;
85982527734SSukumar Swaminathan 					(void) emlxs_sli4_free_rpi(hba, rp);
86082527734SSukumar Swaminathan 				}
86182527734SSukumar Swaminathan 			}
86282527734SSukumar Swaminathan 
863fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_NLP, (uint8_t *)ndlp);
864fcf3ce44SJohn Forte 
865fcf3ce44SJohn Forte 			break;
866fcf3ce44SJohn Forte 		}
867fcf3ce44SJohn Forte 		prevp = np;
868fcf3ce44SJohn Forte 		np = np->nlp_list_next;
869fcf3ce44SJohn Forte 	}
870fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
871fcf3ce44SJohn Forte 
872fcf3ce44SJohn Forte 	return;
873fcf3ce44SJohn Forte 
87482527734SSukumar Swaminathan } /* emlxs_node_rm() */
875