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.
24*82527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27*82527734SSukumar 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 */
35*82527734SSukumar Swaminathan /* Timeout not -1 will apply the timeout */
36fcf3ce44SJohn Forte extern void
37*82527734SSukumar 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;
42*82527734SSukumar Swaminathan 	CHANNEL *cp;
43fcf3ce44SJohn Forte 	NODELIST *prev;
44291a2b48SSukumar Swaminathan 	uint32_t offline = 0;
45fcf3ce44SJohn Forte 
46*82527734SSukumar Swaminathan 
47*82527734SSukumar Swaminathan 	/* If node is on a channel service queue, then remove it */
48*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
49fcf3ce44SJohn Forte 
50fcf3ce44SJohn Forte 	/* Return if node destroyed */
51fcf3ce44SJohn Forte 	if (!ndlp || !ndlp->nlp_active) {
52*82527734SSukumar 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 
67*82527734SSukumar 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 */
73*82527734SSukumar Swaminathan 	if (ndlp->nlp_flag[channelno] & NLP_CLOSED) {
74*82527734SSukumar Swaminathan 		if (ndlp->nlp_flag[channelno] & NLP_OFFLINE) {
75*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
76291a2b48SSukumar Swaminathan 			return;
77291a2b48SSukumar Swaminathan 		}
78291a2b48SSukumar Swaminathan 
79291a2b48SSukumar Swaminathan 		if (offline) {
80*82527734SSukumar Swaminathan 			ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
81*82527734SSukumar Swaminathan 			ndlp->nlp_flag[channelno] |= NLP_OFFLINE;
82*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
83291a2b48SSukumar Swaminathan 
84291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
85*82527734SSukumar Swaminathan 			    "node=%p did=%06x channel=%d. offline=%d set.",
86*82527734SSukumar Swaminathan 			    ndlp, ndlp->nlp_DID, channelno, timeout);
87291a2b48SSukumar Swaminathan 
88291a2b48SSukumar Swaminathan 		} else if (timeout) {
89*82527734SSukumar Swaminathan 			ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
90*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
91291a2b48SSukumar Swaminathan 
92291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
93*82527734SSukumar Swaminathan 			    "node=%p did=%06x channel=%d. timeout=%d set.",
94*82527734SSukumar Swaminathan 			    ndlp, ndlp->nlp_DID, channelno, timeout);
95291a2b48SSukumar Swaminathan 		} else {
96*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
97fcf3ce44SJohn Forte 		}
98fcf3ce44SJohn Forte 
99fcf3ce44SJohn Forte 		return;
100fcf3ce44SJohn Forte 	}
101291a2b48SSukumar Swaminathan 
102fcf3ce44SJohn Forte 	/* Set the node closed */
103*82527734SSukumar Swaminathan 	ndlp->nlp_flag[channelno] |= NLP_CLOSED;
104fcf3ce44SJohn Forte 
105291a2b48SSukumar Swaminathan 	if (offline) {
106*82527734SSukumar Swaminathan 		ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
107*82527734SSukumar Swaminathan 		ndlp->nlp_flag[channelno] |= NLP_OFFLINE;
108291a2b48SSukumar Swaminathan 
109291a2b48SSukumar Swaminathan 	} else if (timeout) {
110*82527734SSukumar Swaminathan 		ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
111fcf3ce44SJohn Forte 	}
112fcf3ce44SJohn Forte 
113*82527734SSukumar Swaminathan 
114*82527734SSukumar Swaminathan 	/*
115*82527734SSukumar Swaminathan 	 * ndlp->nlp_next[] and cp->nodeq list have to be updated
116*82527734SSukumar Swaminathan 	 * simulaneously
117*82527734SSukumar Swaminathan 	 */
118*82527734SSukumar Swaminathan 	if (ndlp->nlp_next[channelno]) {
119*82527734SSukumar Swaminathan 		/* Remove node from channel queue */
120*82527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
121fcf3ce44SJohn Forte 
122fcf3ce44SJohn Forte 		/* If this is the only node on list */
123*82527734SSukumar Swaminathan 		if (cp->nodeq.q_first == (void *)ndlp &&
124*82527734SSukumar Swaminathan 		    cp->nodeq.q_last == (void *)ndlp) {
125*82527734SSukumar Swaminathan 			cp->nodeq.q_last = NULL;
126*82527734SSukumar Swaminathan 			cp->nodeq.q_first = NULL;
127*82527734SSukumar Swaminathan 			cp->nodeq.q_cnt = 0;
128*82527734SSukumar Swaminathan 		} else if (cp->nodeq.q_first == (void *)ndlp) {
129*82527734SSukumar Swaminathan 			cp->nodeq.q_first = ndlp->nlp_next[channelno];
130*82527734SSukumar Swaminathan 			((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] =
131*82527734SSukumar Swaminathan 			    cp->nodeq.q_first;
132*82527734SSukumar Swaminathan 			cp->nodeq.q_cnt--;
133fcf3ce44SJohn Forte 		} else {	/* This is a little more difficult */
134291a2b48SSukumar Swaminathan 
135*82527734SSukumar Swaminathan 			/* Find the previous node in circular channel queue */
136fcf3ce44SJohn Forte 			prev = ndlp;
137*82527734SSukumar Swaminathan 			while (prev->nlp_next[channelno] != ndlp) {
138*82527734SSukumar Swaminathan 				prev = prev->nlp_next[channelno];
139fcf3ce44SJohn Forte 			}
140fcf3ce44SJohn Forte 
141*82527734SSukumar Swaminathan 			prev->nlp_next[channelno] = ndlp->nlp_next[channelno];
142fcf3ce44SJohn Forte 
143*82527734SSukumar Swaminathan 			if (cp->nodeq.q_last == (void *)ndlp) {
144*82527734SSukumar Swaminathan 				cp->nodeq.q_last = (void *)prev;
145fcf3ce44SJohn Forte 			}
146*82527734SSukumar Swaminathan 			cp->nodeq.q_cnt--;
147fcf3ce44SJohn Forte 
148fcf3ce44SJohn Forte 		}
149fcf3ce44SJohn Forte 
150fcf3ce44SJohn Forte 		/* Clear node */
151*82527734SSukumar Swaminathan 		ndlp->nlp_next[channelno] = NULL;
152fcf3ce44SJohn Forte 	}
153291a2b48SSukumar Swaminathan 
154*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
155728bdc9bSSukumar Swaminathan 
156291a2b48SSukumar Swaminathan 	return;
157291a2b48SSukumar Swaminathan 
158*82527734SSukumar Swaminathan } /* emlxs_node_close() */
159291a2b48SSukumar Swaminathan 
160291a2b48SSukumar Swaminathan 
161291a2b48SSukumar Swaminathan /* Called by emlxs_timer_check_nodes() */
162291a2b48SSukumar Swaminathan extern void
163*82527734SSukumar Swaminathan emlxs_node_timeout(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno)
164291a2b48SSukumar Swaminathan {
165291a2b48SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
166291a2b48SSukumar Swaminathan 
167*82527734SSukumar Swaminathan 	/* If node needs servicing, then add it to the channel queues */
168*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
169291a2b48SSukumar Swaminathan 
170291a2b48SSukumar Swaminathan 	/* Return if node destroyed */
171291a2b48SSukumar Swaminathan 	if (!ndlp || !ndlp->nlp_active) {
172*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
173291a2b48SSukumar Swaminathan 		return;
174291a2b48SSukumar Swaminathan 	}
175291a2b48SSukumar Swaminathan 
176291a2b48SSukumar Swaminathan 	/* Open the node if not offline */
177*82527734SSukumar Swaminathan 	if (!(ndlp->nlp_flag[channelno] & NLP_OFFLINE)) {
178*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
179291a2b48SSukumar Swaminathan 
180291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg,
181*82527734SSukumar Swaminathan 		    "node=%p did=%06x channel=%d Opening.", ndlp, ndlp->nlp_DID,
182*82527734SSukumar Swaminathan 		    channelno);
183291a2b48SSukumar Swaminathan 
184*82527734SSukumar Swaminathan 		emlxs_node_open(port, ndlp, channelno);
185291a2b48SSukumar Swaminathan 		return;
186728bdc9bSSukumar Swaminathan 	}
187fcf3ce44SJohn Forte 
188291a2b48SSukumar Swaminathan 	/* OFFLINE TIMEOUT OCCURRED! */
189291a2b48SSukumar Swaminathan 
190291a2b48SSukumar Swaminathan 	/* Clear the timer */
191*82527734SSukumar Swaminathan 	ndlp->nlp_tics[channelno] = 0;
192291a2b48SSukumar Swaminathan 
193*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
194291a2b48SSukumar Swaminathan 
195291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg,
196291a2b48SSukumar Swaminathan 	    "node=%p did=%06x %s. Flushing.", ndlp, ndlp->nlp_DID,
197*82527734SSukumar Swaminathan 	    channelno);
198291a2b48SSukumar Swaminathan 
199*82527734SSukumar Swaminathan 	/* Flush tx queue for this channel */
200*82527734SSukumar Swaminathan 	(void) emlxs_tx_node_flush(port, ndlp, &hba->chan[channelno], 0, 0);
201291a2b48SSukumar Swaminathan 
202*82527734SSukumar Swaminathan 	/* Flush chip queue for this channel */
203*82527734SSukumar Swaminathan 	(void) emlxs_chipq_node_flush(port, &hba->chan[channelno], ndlp, 0);
204291a2b48SSukumar Swaminathan 
205fcf3ce44SJohn Forte 	return;
206fcf3ce44SJohn Forte 
207*82527734SSukumar Swaminathan } /* emlxs_node_timeout() */
208fcf3ce44SJohn Forte 
209fcf3ce44SJohn Forte 
210fcf3ce44SJohn Forte extern void
211*82527734SSukumar Swaminathan emlxs_node_open(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno)
212fcf3ce44SJohn Forte {
213fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
214*82527734SSukumar Swaminathan 	CHANNEL *cp;
215fcf3ce44SJohn Forte 	uint32_t found;
216fcf3ce44SJohn Forte 	NODELIST *nlp;
217fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
218fcf3ce44SJohn Forte 	uint32_t i;
219*82527734SSukumar Swaminathan 	int rc;
220fcf3ce44SJohn Forte 
221*82527734SSukumar Swaminathan 	/* If node needs servicing, then add it to the channel queues */
222*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
223fcf3ce44SJohn Forte 
224fcf3ce44SJohn Forte 	/* Return if node destroyed */
225fcf3ce44SJohn Forte 	if (!ndlp || !ndlp->nlp_active) {
226*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
227fcf3ce44SJohn Forte 
228fcf3ce44SJohn Forte 		return;
229fcf3ce44SJohn Forte 	}
230291a2b48SSukumar Swaminathan 
231fcf3ce44SJohn Forte 	/* Return if node already open */
232*82527734SSukumar Swaminathan 	if (!(ndlp->nlp_flag[channelno] & NLP_CLOSED)) {
233*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
234fcf3ce44SJohn Forte 
235fcf3ce44SJohn Forte 		return;
236fcf3ce44SJohn Forte 	}
237fcf3ce44SJohn Forte 
238291a2b48SSukumar Swaminathan 	/* Set the node open (not closed) */
239*82527734SSukumar Swaminathan 	ndlp->nlp_flag[channelno] &= ~(NLP_CLOSED|NLP_OFFLINE);
240fcf3ce44SJohn Forte 
241fcf3ce44SJohn Forte 	/* Clear the timer */
242*82527734SSukumar Swaminathan 	ndlp->nlp_tics[channelno] = 0;
243fcf3ce44SJohn Forte 
244fcf3ce44SJohn Forte 	/*
245291a2b48SSukumar Swaminathan 	 * If the ptx or the tx queue needs servicing and
246*82527734SSukumar Swaminathan 	 * the node is not already on the channel queue
247fcf3ce44SJohn Forte 	 */
248*82527734SSukumar Swaminathan 	if ((ndlp->nlp_ptx[channelno].q_first ||
249*82527734SSukumar Swaminathan 	    ndlp->nlp_tx[channelno].q_first) && !ndlp->nlp_next[channelno]) {
250*82527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
251fcf3ce44SJohn Forte 
252*82527734SSukumar Swaminathan 		/* If so, then add it to the channel queue */
253*82527734SSukumar Swaminathan 		if (cp->nodeq.q_first) {
254*82527734SSukumar Swaminathan 			((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] =
255fcf3ce44SJohn Forte 			    (uint8_t *)ndlp;
256*82527734SSukumar Swaminathan 			ndlp->nlp_next[channelno] = cp->nodeq.q_first;
257fcf3ce44SJohn Forte 
258291a2b48SSukumar Swaminathan 			/* If this is not the base node then */
259291a2b48SSukumar Swaminathan 			/* add it to the tail */
260fcf3ce44SJohn Forte 			if (!ndlp->nlp_base) {
261*82527734SSukumar Swaminathan 				cp->nodeq.q_last = (uint8_t *)ndlp;
262fcf3ce44SJohn Forte 			} else {	/* Otherwise, add it to the head */
263291a2b48SSukumar Swaminathan 
264fcf3ce44SJohn Forte 				/* The command node always gets priority */
265*82527734SSukumar Swaminathan 				cp->nodeq.q_first = (uint8_t *)ndlp;
266fcf3ce44SJohn Forte 			}
267fcf3ce44SJohn Forte 
268*82527734SSukumar Swaminathan 			cp->nodeq.q_cnt++;
269fcf3ce44SJohn Forte 		} else {
270*82527734SSukumar Swaminathan 			cp->nodeq.q_first = (uint8_t *)ndlp;
271*82527734SSukumar Swaminathan 			cp->nodeq.q_last = (uint8_t *)ndlp;
272*82527734SSukumar Swaminathan 			ndlp->nlp_next[channelno] = ndlp;
273*82527734SSukumar Swaminathan 			cp->nodeq.q_cnt = 1;
274fcf3ce44SJohn Forte 		}
275fcf3ce44SJohn Forte 	}
276291a2b48SSukumar Swaminathan 
277*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
278fcf3ce44SJohn Forte 
279291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_opened_msg,
280*82527734SSukumar Swaminathan 	    "node=%p did=%06x channel=%d", ndlp, ndlp->nlp_DID, channelno);
281728bdc9bSSukumar Swaminathan 
282fcf3ce44SJohn Forte 	/* If link attention needs to be cleared */
283*82527734SSukumar Swaminathan 	if ((hba->state == FC_LINK_UP) && (channelno == hba->channel_fcp)) {
284*82527734SSukumar Swaminathan 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
285*82527734SSukumar Swaminathan 		/* re Think this code path. For SLI4 channel fcp == els */
286*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
287*82527734SSukumar Swaminathan 			    "ADD CODE to RESUME RPIs node=%p did=%06x chan=%d",
288*82527734SSukumar Swaminathan 			    ndlp, ndlp->nlp_DID, channelno);
289*82527734SSukumar Swaminathan 
290*82527734SSukumar Swaminathan 			goto done;
291*82527734SSukumar Swaminathan 		}
292fcf3ce44SJohn Forte 
293fcf3ce44SJohn Forte 		/* Scan to see if any FCP2 devices are still closed */
294fcf3ce44SJohn Forte 		found = 0;
295fcf3ce44SJohn Forte 		rw_enter(&port->node_rwlock, RW_READER);
296fcf3ce44SJohn Forte 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
297fcf3ce44SJohn Forte 			nlp = port->node_table[i];
298fcf3ce44SJohn Forte 			while (nlp != NULL) {
299fcf3ce44SJohn Forte 				if ((nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) &&
300*82527734SSukumar Swaminathan 				    (nlp->nlp_flag[hba->channel_fcp] &
301*82527734SSukumar Swaminathan 				    NLP_CLOSED)) {
302fcf3ce44SJohn Forte 					found = 1;
303fcf3ce44SJohn Forte 					break;
304291a2b48SSukumar Swaminathan 
305fcf3ce44SJohn Forte 				}
306fcf3ce44SJohn Forte 				nlp = nlp->nlp_list_next;
307fcf3ce44SJohn Forte 			}
308fcf3ce44SJohn Forte 
309fcf3ce44SJohn Forte 			if (found) {
310fcf3ce44SJohn Forte 				break;
311fcf3ce44SJohn Forte 			}
312fcf3ce44SJohn Forte 		}
313fcf3ce44SJohn Forte 
314fcf3ce44SJohn Forte 		rw_exit(&port->node_rwlock);
315fcf3ce44SJohn Forte 
316fcf3ce44SJohn Forte 		if (!found) {
317fcf3ce44SJohn Forte 			/* Clear link attention */
318291a2b48SSukumar Swaminathan 			if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
319*82527734SSukumar Swaminathan 			    MEM_MBOX, 1))) {
320fcf3ce44SJohn Forte 				mutex_enter(&EMLXS_PORT_LOCK);
321fcf3ce44SJohn Forte 
322fcf3ce44SJohn Forte 				/*
323291a2b48SSukumar Swaminathan 				 * If state is not FC_LINK_UP, then either the
324291a2b48SSukumar Swaminathan 				 * link has gone down or a FC_CLEAR_LA has
325291a2b48SSukumar Swaminathan 				 * already been issued
326fcf3ce44SJohn Forte 				 */
327fcf3ce44SJohn Forte 				if (hba->state != FC_LINK_UP) {
328fcf3ce44SJohn Forte 					mutex_exit(&EMLXS_PORT_LOCK);
329fcf3ce44SJohn Forte 					(void) emlxs_mem_put(hba, MEM_MBOX,
330fcf3ce44SJohn Forte 					    (uint8_t *)mbox);
331fcf3ce44SJohn Forte 					goto done;
332fcf3ce44SJohn Forte 				}
333291a2b48SSukumar Swaminathan 
334*82527734SSukumar Swaminathan 				EMLXS_STATE_CHANGE_LOCKED(hba, FC_CLEAR_LA);
335fcf3ce44SJohn Forte 				hba->discovery_timer = 0;
336fcf3ce44SJohn Forte 				mutex_exit(&EMLXS_PORT_LOCK);
337fcf3ce44SJohn Forte 
338*82527734SSukumar Swaminathan 				emlxs_mb_clear_la(hba, mbox);
339fcf3ce44SJohn Forte 
340*82527734SSukumar Swaminathan 				rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba,
341*82527734SSukumar Swaminathan 				    mbox, MBX_NOWAIT, 0);
342*82527734SSukumar Swaminathan 				if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
343fcf3ce44SJohn Forte 					(void) emlxs_mem_put(hba, MEM_MBOX,
344fcf3ce44SJohn Forte 					    (uint8_t *)mbox);
345fcf3ce44SJohn Forte 				}
346fcf3ce44SJohn Forte 			} else {
347291a2b48SSukumar Swaminathan 				/* Close the node and try again */
348291a2b48SSukumar Swaminathan 				/* in a few seconds */
349*82527734SSukumar Swaminathan 				emlxs_node_close(port, ndlp, channelno, 5);
350fcf3ce44SJohn Forte 				return;
351fcf3ce44SJohn Forte 			}
352fcf3ce44SJohn Forte 		}
353fcf3ce44SJohn Forte 	}
354291a2b48SSukumar Swaminathan 
355fcf3ce44SJohn Forte done:
356fcf3ce44SJohn Forte 
357fcf3ce44SJohn Forte 	/* Wake any sleeping threads */
358fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PKT_LOCK);
359fcf3ce44SJohn Forte 	cv_broadcast(&EMLXS_PKT_CV);
360fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PKT_LOCK);
361fcf3ce44SJohn Forte 
362fcf3ce44SJohn Forte 	return;
363fcf3ce44SJohn Forte 
364*82527734SSukumar Swaminathan } /* emlxs_node_open() */
365fcf3ce44SJohn Forte 
366fcf3ce44SJohn Forte 
367fcf3ce44SJohn Forte static int
368fcf3ce44SJohn Forte emlxs_node_match_did(emlxs_port_t *port, NODELIST *ndlp, uint32_t did)
369fcf3ce44SJohn Forte {
370fcf3ce44SJohn Forte 	D_ID mydid;
371fcf3ce44SJohn Forte 	D_ID odid;
372fcf3ce44SJohn Forte 	D_ID ndid;
373fcf3ce44SJohn Forte 
374291a2b48SSukumar Swaminathan 	if (ndlp->nlp_DID == did)
375fcf3ce44SJohn Forte 		return (1);
376fcf3ce44SJohn Forte 
377fcf3ce44SJohn Forte 	/*
378fcf3ce44SJohn Forte 	 * Next check for area/domain == 0 match
379fcf3ce44SJohn Forte 	 */
380fcf3ce44SJohn Forte 	mydid.un.word = port->did;
381fcf3ce44SJohn Forte 	if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) {
382fcf3ce44SJohn Forte 		goto out;
383fcf3ce44SJohn Forte 	}
384291a2b48SSukumar Swaminathan 
385fcf3ce44SJohn Forte 	ndid.un.word = did;
386fcf3ce44SJohn Forte 	odid.un.word = ndlp->nlp_DID;
387fcf3ce44SJohn Forte 	if (ndid.un.b.id == odid.un.b.id) {
388fcf3ce44SJohn Forte 		if ((mydid.un.b.domain == ndid.un.b.domain) &&
389fcf3ce44SJohn Forte 		    (mydid.un.b.area == ndid.un.b.area)) {
390fcf3ce44SJohn Forte 			ndid.un.word = ndlp->nlp_DID;
391fcf3ce44SJohn Forte 			odid.un.word = did;
392291a2b48SSukumar Swaminathan 			if ((ndid.un.b.domain == 0) && (ndid.un.b.area == 0)) {
393fcf3ce44SJohn Forte 				return (1);
394fcf3ce44SJohn Forte 			}
395fcf3ce44SJohn Forte 			goto out;
396fcf3ce44SJohn Forte 		}
397291a2b48SSukumar Swaminathan 
398fcf3ce44SJohn Forte 		ndid.un.word = ndlp->nlp_DID;
399fcf3ce44SJohn Forte 		if ((mydid.un.b.domain == ndid.un.b.domain) &&
400fcf3ce44SJohn Forte 		    (mydid.un.b.area == ndid.un.b.area)) {
401fcf3ce44SJohn Forte 			odid.un.word = ndlp->nlp_DID;
402fcf3ce44SJohn Forte 			ndid.un.word = did;
403291a2b48SSukumar Swaminathan 			if ((ndid.un.b.domain == 0) && (ndid.un.b.area == 0)) {
404fcf3ce44SJohn Forte 				return (1);
405fcf3ce44SJohn Forte 			}
406fcf3ce44SJohn Forte 		}
407fcf3ce44SJohn Forte 	}
408291a2b48SSukumar Swaminathan 
409fcf3ce44SJohn Forte out:
410fcf3ce44SJohn Forte 
411fcf3ce44SJohn Forte 	return (0);
412fcf3ce44SJohn Forte 
413*82527734SSukumar Swaminathan } /* End emlxs_node_match_did */
414fcf3ce44SJohn Forte 
415fcf3ce44SJohn Forte 
416fcf3ce44SJohn Forte 
417fcf3ce44SJohn Forte extern NODELIST *
418fcf3ce44SJohn Forte emlxs_node_find_mac(emlxs_port_t *port, uint8_t *mac)
419fcf3ce44SJohn Forte {
420fcf3ce44SJohn Forte 	NODELIST *nlp;
421fcf3ce44SJohn Forte 	uint32_t i;
422fcf3ce44SJohn Forte 
423fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
424fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
425fcf3ce44SJohn Forte 		nlp = port->node_table[i];
426fcf3ce44SJohn Forte 		while (nlp != NULL) {
427fcf3ce44SJohn Forte 			/*
428291a2b48SSukumar Swaminathan 			 * If portname matches mac address,
429291a2b48SSukumar Swaminathan 			 * return NODELIST entry
430fcf3ce44SJohn Forte 			 */
431fcf3ce44SJohn Forte 			if ((nlp->nlp_portname.IEEE[0] == mac[0])) {
432*82527734SSukumar Swaminathan 				if ((nlp->nlp_DID != BCAST_DID) &&
433*82527734SSukumar Swaminathan 				    ((nlp->nlp_DID & FABRIC_DID_MASK) ==
434*82527734SSukumar Swaminathan 				    FABRIC_DID_MASK)) {
435291a2b48SSukumar Swaminathan 					nlp = (NODELIST *)nlp->nlp_list_next;
436fcf3ce44SJohn Forte 					continue;
437fcf3ce44SJohn Forte 				}
438291a2b48SSukumar Swaminathan 
439fcf3ce44SJohn Forte 				if ((nlp->nlp_portname.IEEE[1] == mac[1]) &&
440fcf3ce44SJohn Forte 				    (nlp->nlp_portname.IEEE[2] == mac[2]) &&
441fcf3ce44SJohn Forte 				    (nlp->nlp_portname.IEEE[3] == mac[3]) &&
442fcf3ce44SJohn Forte 				    (nlp->nlp_portname.IEEE[4] == mac[4]) &&
443fcf3ce44SJohn Forte 				    (nlp->nlp_portname.IEEE[5] == mac[5])) {
444fcf3ce44SJohn Forte 					rw_exit(&port->node_rwlock);
445fcf3ce44SJohn Forte 					return (nlp);
446fcf3ce44SJohn Forte 				}
447291a2b48SSukumar Swaminathan 
448fcf3ce44SJohn Forte 			}
449291a2b48SSukumar Swaminathan 
450291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
451fcf3ce44SJohn Forte 		}
452fcf3ce44SJohn Forte 	}
453fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
454fcf3ce44SJohn Forte 
455fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg,
456291a2b48SSukumar Swaminathan 	    "find: MAC=%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2],
457291a2b48SSukumar Swaminathan 	    mac[3], mac[4], mac[5]);
458fcf3ce44SJohn Forte 
459fcf3ce44SJohn Forte 	return (NULL);
460fcf3ce44SJohn Forte 
461*82527734SSukumar Swaminathan } /* emlxs_node_find_mac() */
462fcf3ce44SJohn Forte 
463fcf3ce44SJohn Forte 
464fcf3ce44SJohn Forte extern NODELIST *
465fcf3ce44SJohn Forte emlxs_node_find_did(emlxs_port_t *port, uint32_t did)
466fcf3ce44SJohn Forte {
467fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
468fcf3ce44SJohn Forte 	NODELIST *nlp;
469fcf3ce44SJohn Forte 	uint32_t hash;
470fcf3ce44SJohn Forte 
471fcf3ce44SJohn Forte 	/* Check for invalid node ids  */
472291a2b48SSukumar Swaminathan 	if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) {
473291a2b48SSukumar Swaminathan 		return ((NODELIST *)0);
474291a2b48SSukumar Swaminathan 	}
475291a2b48SSukumar Swaminathan 
476291a2b48SSukumar Swaminathan 	if (did & 0xff000000) {
477291a2b48SSukumar Swaminathan 		return ((NODELIST *)0);
478fcf3ce44SJohn Forte 	}
479291a2b48SSukumar Swaminathan 
480fcf3ce44SJohn Forte 	/* Check for bcast node */
481*82527734SSukumar Swaminathan 	if (did == BCAST_DID) {
482fcf3ce44SJohn Forte 		/* Use the base node here */
483fcf3ce44SJohn Forte 		return (&port->node_base);
484fcf3ce44SJohn Forte 	}
485fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT
486fcf3ce44SJohn Forte 	/* Check for menlo node */
487fcf3ce44SJohn Forte 	if (did == EMLXS_MENLO_DID) {
488fcf3ce44SJohn Forte 		/* Use the base node here */
489fcf3ce44SJohn Forte 		return (&port->node_base);
490fcf3ce44SJohn Forte 	}
491291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */
492fcf3ce44SJohn Forte 
493fcf3ce44SJohn Forte 	/* Check for host node */
494fcf3ce44SJohn Forte 	if (did == port->did && !(hba->flag & FC_LOOPBACK_MODE)) {
495fcf3ce44SJohn Forte 		/* Use the base node here */
496fcf3ce44SJohn Forte 		return (&port->node_base);
497fcf3ce44SJohn Forte 	}
498291a2b48SSukumar Swaminathan 
499fcf3ce44SJohn Forte 	/*
500*82527734SSukumar Swaminathan 	 * Convert well known fabric addresses to the FABRIC_DID,
501291a2b48SSukumar Swaminathan 	 * since we don't login to some of them
502fcf3ce44SJohn Forte 	 */
503fcf3ce44SJohn Forte 	if ((did == SCR_DID)) {
504*82527734SSukumar Swaminathan 		did = FABRIC_DID;
505fcf3ce44SJohn Forte 	}
506291a2b48SSukumar Swaminathan 
507fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
508fcf3ce44SJohn Forte 	hash = EMLXS_DID_HASH(did);
509fcf3ce44SJohn Forte 	nlp = port->node_table[hash];
510fcf3ce44SJohn Forte 	while (nlp != NULL) {
511fcf3ce44SJohn Forte 		/* Check for obvious match */
512fcf3ce44SJohn Forte 		if (nlp->nlp_DID == did) {
513fcf3ce44SJohn Forte 			rw_exit(&port->node_rwlock);
514fcf3ce44SJohn Forte 			return (nlp);
515fcf3ce44SJohn Forte 		}
516291a2b48SSukumar Swaminathan 
517fcf3ce44SJohn Forte 		/* Check for detailed match */
518fcf3ce44SJohn Forte 		else if (emlxs_node_match_did(port, nlp, did)) {
519fcf3ce44SJohn Forte 			rw_exit(&port->node_rwlock);
520fcf3ce44SJohn Forte 			return (nlp);
521fcf3ce44SJohn Forte 		}
522291a2b48SSukumar Swaminathan 
523291a2b48SSukumar Swaminathan 		nlp = (NODELIST *)nlp->nlp_list_next;
524fcf3ce44SJohn Forte 	}
525fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
526fcf3ce44SJohn Forte 
527291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: did=%x",
528291a2b48SSukumar Swaminathan 	    did);
529fcf3ce44SJohn Forte 
530fcf3ce44SJohn Forte 	/* no match found */
531291a2b48SSukumar Swaminathan 	return ((NODELIST *)0);
532fcf3ce44SJohn Forte 
533*82527734SSukumar Swaminathan } /* emlxs_node_find_did() */
534fcf3ce44SJohn Forte 
535fcf3ce44SJohn Forte 
536fcf3ce44SJohn Forte extern NODELIST *
537fcf3ce44SJohn Forte emlxs_node_find_rpi(emlxs_port_t *port, uint32_t rpi)
538fcf3ce44SJohn Forte {
539fcf3ce44SJohn Forte 	NODELIST *nlp;
540fcf3ce44SJohn Forte 	uint32_t i;
541fcf3ce44SJohn Forte 
542fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
543fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
544fcf3ce44SJohn Forte 		nlp = port->node_table[i];
545fcf3ce44SJohn Forte 		while (nlp != NULL) {
546fcf3ce44SJohn Forte 			if (nlp->nlp_Rpi == rpi) {
547fcf3ce44SJohn Forte 				rw_exit(&port->node_rwlock);
548fcf3ce44SJohn Forte 				return (nlp);
549fcf3ce44SJohn Forte 			}
550291a2b48SSukumar Swaminathan 
551291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
552fcf3ce44SJohn Forte 		}
553fcf3ce44SJohn Forte 	}
554fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
555fcf3ce44SJohn Forte 
556291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: rpi=%x",
557291a2b48SSukumar Swaminathan 	    rpi);
558fcf3ce44SJohn Forte 
559fcf3ce44SJohn Forte 	/* no match found */
560291a2b48SSukumar Swaminathan 	return ((NODELIST *)0);
561fcf3ce44SJohn Forte 
562*82527734SSukumar Swaminathan } /* emlxs_node_find_rpi() */
563fcf3ce44SJohn Forte 
564fcf3ce44SJohn Forte 
565fcf3ce44SJohn Forte extern NODELIST *
566fcf3ce44SJohn Forte emlxs_node_find_wwpn(emlxs_port_t *port, uint8_t *wwpn)
567fcf3ce44SJohn Forte {
568fcf3ce44SJohn Forte 	NODELIST *nlp;
569fcf3ce44SJohn Forte 	uint32_t i;
570fcf3ce44SJohn Forte 	uint32_t j;
571fcf3ce44SJohn Forte 	uint8_t *bptr1;
572fcf3ce44SJohn Forte 	uint8_t *bptr2;
573fcf3ce44SJohn Forte 
574fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
575fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
576fcf3ce44SJohn Forte 		nlp = port->node_table[i];
577fcf3ce44SJohn Forte 		while (nlp != NULL) {
578fcf3ce44SJohn Forte 			bptr1 = (uint8_t *)&nlp->nlp_portname;
579fcf3ce44SJohn Forte 			bptr1 += 7;
580fcf3ce44SJohn Forte 			bptr2 = (uint8_t *)wwpn;
581fcf3ce44SJohn Forte 			bptr2 += 7;
582fcf3ce44SJohn Forte 
583fcf3ce44SJohn Forte 			for (j = 0; j < 8; j++) {
584fcf3ce44SJohn Forte 				if (*bptr1-- != *bptr2--) {
585fcf3ce44SJohn Forte 					break;
586fcf3ce44SJohn Forte 				}
587fcf3ce44SJohn Forte 			}
588fcf3ce44SJohn Forte 
589fcf3ce44SJohn Forte 			if (j == 8) {
590fcf3ce44SJohn Forte 				rw_exit(&port->node_rwlock);
591fcf3ce44SJohn Forte 				return (nlp);
592fcf3ce44SJohn Forte 			}
593291a2b48SSukumar Swaminathan 
594291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
595fcf3ce44SJohn Forte 		}
596fcf3ce44SJohn Forte 	}
597fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
598fcf3ce44SJohn Forte 
599fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg,
600291a2b48SSukumar Swaminathan 	    "find: wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", wwpn[0], wwpn[1],
601291a2b48SSukumar Swaminathan 	    wwpn[2], wwpn[3], wwpn[4], wwpn[5], wwpn[6], wwpn[7]);
602fcf3ce44SJohn Forte 
603fcf3ce44SJohn Forte 	/* no match found */
604291a2b48SSukumar Swaminathan 	return ((NODELIST *)0);
605fcf3ce44SJohn Forte 
606*82527734SSukumar Swaminathan } /* emlxs_node_find_wwpn() */
607fcf3ce44SJohn Forte 
608fcf3ce44SJohn Forte 
609fcf3ce44SJohn Forte extern NODELIST *
610291a2b48SSukumar Swaminathan emlxs_node_find_index(emlxs_port_t *port, uint32_t index,
611291a2b48SSukumar Swaminathan     uint32_t nports_only)
612fcf3ce44SJohn Forte {
613fcf3ce44SJohn Forte 	NODELIST *nlp;
614fcf3ce44SJohn Forte 	uint32_t i;
615fcf3ce44SJohn Forte 	uint32_t count;
616fcf3ce44SJohn Forte 
617fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
618fcf3ce44SJohn Forte 
619fcf3ce44SJohn Forte 	if (index > port->node_count - 1) {
620fcf3ce44SJohn Forte 		rw_exit(&port->node_rwlock);
621fcf3ce44SJohn Forte 		return (NULL);
622fcf3ce44SJohn Forte 	}
623291a2b48SSukumar Swaminathan 
624fcf3ce44SJohn Forte 	count = 0;
625fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
626fcf3ce44SJohn Forte 		nlp = port->node_table[i];
627fcf3ce44SJohn Forte 		while (nlp != NULL) {
628fcf3ce44SJohn Forte 			/* Skip fabric ports if requested */
629291a2b48SSukumar Swaminathan 			if (nports_only &&
630291a2b48SSukumar Swaminathan 			    (nlp->nlp_DID & 0xFFF000) == 0xFFF000) {
631291a2b48SSukumar Swaminathan 				nlp = (NODELIST *)nlp->nlp_list_next;
632fcf3ce44SJohn Forte 				continue;
633fcf3ce44SJohn Forte 			}
634291a2b48SSukumar Swaminathan 
635fcf3ce44SJohn Forte 			if (count == index) {
636fcf3ce44SJohn Forte 				rw_exit(&port->node_rwlock);
637fcf3ce44SJohn Forte 				return (nlp);
638fcf3ce44SJohn Forte 			}
639291a2b48SSukumar Swaminathan 
640291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
641fcf3ce44SJohn Forte 			count++;
642fcf3ce44SJohn Forte 		}
643fcf3ce44SJohn Forte 	}
644fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
645fcf3ce44SJohn Forte 
646291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: index=%d",
647291a2b48SSukumar Swaminathan 	    index);
648fcf3ce44SJohn Forte 
649fcf3ce44SJohn Forte 	/* no match found */
650291a2b48SSukumar Swaminathan 	return ((NODELIST *)0);
651fcf3ce44SJohn Forte 
652*82527734SSukumar Swaminathan } /* emlxs_node_find_wwpn() */
653fcf3ce44SJohn Forte 
654fcf3ce44SJohn Forte 
655fcf3ce44SJohn Forte extern uint32_t
656fcf3ce44SJohn Forte emlxs_nport_count(emlxs_port_t *port)
657fcf3ce44SJohn Forte {
658fcf3ce44SJohn Forte 	NODELIST *nlp;
659fcf3ce44SJohn Forte 	uint32_t i;
660fcf3ce44SJohn Forte 	uint32_t nport_count = 0;
661fcf3ce44SJohn Forte 
662fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
663fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
664fcf3ce44SJohn Forte 		nlp = port->node_table[i];
665fcf3ce44SJohn Forte 		while (nlp != NULL) {
666fcf3ce44SJohn Forte 			if ((nlp->nlp_DID & 0xFFF000) != 0xFFF000) {
667fcf3ce44SJohn Forte 				nport_count++;
668fcf3ce44SJohn Forte 			}
669291a2b48SSukumar Swaminathan 
670291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
671fcf3ce44SJohn Forte 		}
672fcf3ce44SJohn Forte 	}
673fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
674fcf3ce44SJohn Forte 
675fcf3ce44SJohn Forte 	return (nport_count);
676fcf3ce44SJohn Forte 
677*82527734SSukumar Swaminathan } /* emlxs_nport_count() */
678fcf3ce44SJohn Forte 
679fcf3ce44SJohn Forte 
680fcf3ce44SJohn Forte 
681fcf3ce44SJohn Forte extern void
682fcf3ce44SJohn Forte emlxs_node_destroy_all(emlxs_port_t *port)
683fcf3ce44SJohn Forte {
684fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
685fcf3ce44SJohn Forte 	NODELIST *next;
686fcf3ce44SJohn Forte 	NODELIST *ndlp;
687*82527734SSukumar Swaminathan 	RPIobj_t *rp;
688fcf3ce44SJohn Forte 	uint8_t *wwn;
689fcf3ce44SJohn Forte 	uint32_t i;
690fcf3ce44SJohn Forte 
691fcf3ce44SJohn Forte 	/* Flush and free the nodes */
692fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_WRITER);
693fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
694fcf3ce44SJohn Forte 		ndlp = port->node_table[i];
695fcf3ce44SJohn Forte 		port->node_table[i] = 0;
696fcf3ce44SJohn Forte 		while (ndlp != NULL) {
697fcf3ce44SJohn Forte 			next = ndlp->nlp_list_next;
698fcf3ce44SJohn Forte 			ndlp->nlp_list_next = NULL;
699fcf3ce44SJohn Forte 			ndlp->nlp_list_prev = NULL;
700fcf3ce44SJohn Forte 			ndlp->nlp_active = 0;
701fcf3ce44SJohn Forte 
702fcf3ce44SJohn Forte 			if (port->node_count) {
703fcf3ce44SJohn Forte 				port->node_count--;
704fcf3ce44SJohn Forte 			}
705291a2b48SSukumar Swaminathan 
706fcf3ce44SJohn Forte 			wwn = (uint8_t *)&ndlp->nlp_portname;
707291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
708291a2b48SSukumar Swaminathan 			    &emlxs_node_destroy_msg, "did=%06x "
709291a2b48SSukumar Swaminathan 			    "rpi=%x wwpn=%02x%02x%02x%02x%02x%02x%02x%02x "
710291a2b48SSukumar Swaminathan 			    "count=%d", ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0],
711291a2b48SSukumar Swaminathan 			    wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6],
712291a2b48SSukumar Swaminathan 			    wwn[7], port->node_count);
713fcf3ce44SJohn Forte 
714fcf3ce44SJohn Forte 			(void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0);
715fcf3ce44SJohn Forte 
716*82527734SSukumar Swaminathan 			/* Break Node/RPI binding */
717*82527734SSukumar Swaminathan 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
718*82527734SSukumar Swaminathan 				rp = EMLXS_NODE_TO_RPI(hba, ndlp);
719*82527734SSukumar Swaminathan 				ndlp->RPIp = NULL;
720*82527734SSukumar Swaminathan 
721*82527734SSukumar Swaminathan 				if (rp) {
722*82527734SSukumar Swaminathan 					rp->node = NULL;
723*82527734SSukumar Swaminathan 					(void) emlxs_sli4_free_rpi(hba, rp);
724*82527734SSukumar Swaminathan 				}
725*82527734SSukumar Swaminathan 			}
726*82527734SSukumar Swaminathan 
727fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_NLP, (uint8_t *)ndlp);
728fcf3ce44SJohn Forte 
729fcf3ce44SJohn Forte 			ndlp = next;
730fcf3ce44SJohn Forte 		}
731fcf3ce44SJohn Forte 	}
732fcf3ce44SJohn Forte 	port->node_count = 0;
733fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
734fcf3ce44SJohn Forte 
735fcf3ce44SJohn Forte 	/* Clean the base node */
736fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
737fcf3ce44SJohn Forte 	port->node_base.nlp_list_next = NULL;
738fcf3ce44SJohn Forte 	port->node_base.nlp_list_prev = NULL;
739fcf3ce44SJohn Forte 	port->node_base.nlp_active = 1;
740fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
741fcf3ce44SJohn Forte 
742fcf3ce44SJohn Forte 	/* Flush the base node */
743fcf3ce44SJohn Forte 	(void) emlxs_tx_node_flush(port, &port->node_base, 0, 1, 0);
744fcf3ce44SJohn Forte 	(void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0);
745fcf3ce44SJohn Forte 
746fcf3ce44SJohn Forte 	return;
747fcf3ce44SJohn Forte 
748*82527734SSukumar Swaminathan } /* emlxs_node_destroy_all() */
749fcf3ce44SJohn Forte 
750fcf3ce44SJohn Forte 
751fcf3ce44SJohn Forte extern void
752fcf3ce44SJohn Forte emlxs_node_add(emlxs_port_t *port, NODELIST *ndlp)
753fcf3ce44SJohn Forte {
754*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
755fcf3ce44SJohn Forte 	NODELIST *np;
756fcf3ce44SJohn Forte 	uint8_t *wwn;
757fcf3ce44SJohn Forte 	uint32_t hash;
758*82527734SSukumar Swaminathan 	RPIobj_t *rp;
759fcf3ce44SJohn Forte 
760fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_WRITER);
761fcf3ce44SJohn Forte 	hash = EMLXS_DID_HASH(ndlp->nlp_DID);
762fcf3ce44SJohn Forte 	np = port->node_table[hash];
763fcf3ce44SJohn Forte 
764fcf3ce44SJohn Forte 	/*
765fcf3ce44SJohn Forte 	 * Insert node pointer to the head
766fcf3ce44SJohn Forte 	 */
767fcf3ce44SJohn Forte 	port->node_table[hash] = ndlp;
768fcf3ce44SJohn Forte 	if (!np) {
769fcf3ce44SJohn Forte 		ndlp->nlp_list_next = NULL;
770fcf3ce44SJohn Forte 	} else {
771fcf3ce44SJohn Forte 		ndlp->nlp_list_next = np;
772fcf3ce44SJohn Forte 	}
773fcf3ce44SJohn Forte 	port->node_count++;
774fcf3ce44SJohn Forte 
775fcf3ce44SJohn Forte 	wwn = (uint8_t *)&ndlp->nlp_portname;
776fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_msg,
777291a2b48SSukumar Swaminathan 	    "node=%p did=%06x rpi=%x wwpn=%02x%02x%02x%02x%02x%02x%02x%02x "
778291a2b48SSukumar Swaminathan 	    "count=%d", ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], wwn[1],
779291a2b48SSukumar Swaminathan 	    wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7], port->node_count);
780fcf3ce44SJohn Forte 
781*82527734SSukumar Swaminathan 	/* Add Node/RPI binding */
782*82527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
783*82527734SSukumar Swaminathan 		rp = emlxs_sli4_find_rpi(hba, ndlp->nlp_Rpi);
784*82527734SSukumar Swaminathan 
785*82527734SSukumar Swaminathan 		if (rp) {
786*82527734SSukumar Swaminathan 			rp->node = ndlp;
787*82527734SSukumar Swaminathan 			ndlp->RPIp = rp;
788*82527734SSukumar Swaminathan 		} else {
789*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_msg,
790*82527734SSukumar Swaminathan 			    "Unable to find RPI! did=%x rpi=%x",
791*82527734SSukumar Swaminathan 			    ndlp->nlp_DID, ndlp->nlp_Rpi);
792*82527734SSukumar Swaminathan 		}
793*82527734SSukumar Swaminathan 	}
794*82527734SSukumar Swaminathan 
795fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
796fcf3ce44SJohn Forte 
797fcf3ce44SJohn Forte 	return;
798fcf3ce44SJohn Forte 
799*82527734SSukumar Swaminathan } /* emlxs_node_add() */
800fcf3ce44SJohn Forte 
801fcf3ce44SJohn Forte 
802fcf3ce44SJohn Forte extern void
803fcf3ce44SJohn Forte emlxs_node_rm(emlxs_port_t *port, NODELIST *ndlp)
804fcf3ce44SJohn Forte {
805fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
806fcf3ce44SJohn Forte 	NODELIST *np;
807fcf3ce44SJohn Forte 	NODELIST *prevp;
808*82527734SSukumar Swaminathan 	RPIobj_t *rp;
809fcf3ce44SJohn Forte 	uint8_t *wwn;
810fcf3ce44SJohn Forte 	uint32_t hash;
811fcf3ce44SJohn Forte 
812fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_WRITER);
813fcf3ce44SJohn Forte 	hash = EMLXS_DID_HASH(ndlp->nlp_DID);
814fcf3ce44SJohn Forte 	np = port->node_table[hash];
815fcf3ce44SJohn Forte 	prevp = NULL;
816fcf3ce44SJohn Forte 	while (np != NULL) {
817fcf3ce44SJohn Forte 		if (np->nlp_DID == ndlp->nlp_DID) {
818fcf3ce44SJohn Forte 			if (prevp == NULL) {
819fcf3ce44SJohn Forte 				port->node_table[hash] = np->nlp_list_next;
820fcf3ce44SJohn Forte 			} else {
821fcf3ce44SJohn Forte 				prevp->nlp_list_next = np->nlp_list_next;
822fcf3ce44SJohn Forte 			}
823fcf3ce44SJohn Forte 
824fcf3ce44SJohn Forte 			if (port->node_count) {
825fcf3ce44SJohn Forte 				port->node_count--;
826fcf3ce44SJohn Forte 			}
827291a2b48SSukumar Swaminathan 
828fcf3ce44SJohn Forte 			wwn = (uint8_t *)&ndlp->nlp_portname;
829291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
830291a2b48SSukumar Swaminathan 			    &emlxs_node_destroy_msg, "did=%06x "
831291a2b48SSukumar Swaminathan 			    "rpi=%x wwpn=%02x%02x%02x%02x%02x%02x%02x%02x "
832291a2b48SSukumar Swaminathan 			    "count=%d", ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0],
833291a2b48SSukumar Swaminathan 			    wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6],
834291a2b48SSukumar Swaminathan 			    wwn[7], port->node_count);
835fcf3ce44SJohn Forte 
836fcf3ce44SJohn Forte 			(void) emlxs_tx_node_flush(port, ndlp, 0, 1, 0);
837fcf3ce44SJohn Forte 
838fcf3ce44SJohn Forte 			ndlp->nlp_active = 0;
839*82527734SSukumar Swaminathan 
840*82527734SSukumar Swaminathan 			/* Break Node/RPI binding */
841*82527734SSukumar Swaminathan 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
842*82527734SSukumar Swaminathan 				rp = EMLXS_NODE_TO_RPI(hba, ndlp);
843*82527734SSukumar Swaminathan 				ndlp->RPIp = NULL;
844*82527734SSukumar Swaminathan 
845*82527734SSukumar Swaminathan 				if (rp) {
846*82527734SSukumar Swaminathan 					rp->node = NULL;
847*82527734SSukumar Swaminathan 					(void) emlxs_sli4_free_rpi(hba, rp);
848*82527734SSukumar Swaminathan 				}
849*82527734SSukumar Swaminathan 			}
850*82527734SSukumar Swaminathan 
851fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_NLP, (uint8_t *)ndlp);
852fcf3ce44SJohn Forte 
853fcf3ce44SJohn Forte 			break;
854fcf3ce44SJohn Forte 		}
855fcf3ce44SJohn Forte 		prevp = np;
856fcf3ce44SJohn Forte 		np = np->nlp_list_next;
857fcf3ce44SJohn Forte 	}
858fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
859fcf3ce44SJohn Forte 
860fcf3ce44SJohn Forte 	return;
861fcf3ce44SJohn Forte 
862*82527734SSukumar Swaminathan } /* emlxs_node_rm() */
863