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  *
8*8f23e9faSHans Rosenfeld  * You can obtain a copy of the license at
9*8f23e9faSHans Rosenfeld  * http://www.opensource.org/licenses/cddl1.txt.
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 /*
23*8f23e9faSHans Rosenfeld  * Copyright (c) 2004-2011 Emulex. All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27291a2b48SSukumar Swaminathan #include <emlxs.h>
28fcf3ce44SJohn Forte 
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_NODE_C);
32fcf3ce44SJohn Forte 
33*8f23e9faSHans Rosenfeld static void	emlxs_node_add(emlxs_port_t *, NODELIST *);
34*8f23e9faSHans Rosenfeld static int	emlxs_node_match_did(emlxs_port_t *, NODELIST *, uint32_t);
35*8f23e9faSHans Rosenfeld 
36291a2b48SSukumar Swaminathan /* Timeout == -1 will enable the offline timer */
3782527734SSukumar Swaminathan /* Timeout not -1 will apply the timeout */
38fcf3ce44SJohn Forte extern void
emlxs_node_close(emlxs_port_t * port,NODELIST * ndlp,uint32_t channelno,int32_t timeout)3982527734SSukumar Swaminathan emlxs_node_close(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno,
40291a2b48SSukumar Swaminathan     int32_t timeout)
41fcf3ce44SJohn Forte {
42fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
43291a2b48SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
4482527734SSukumar Swaminathan 	CHANNEL *cp;
45fcf3ce44SJohn Forte 	NODELIST *prev;
46291a2b48SSukumar Swaminathan 	uint32_t offline = 0;
47fcf3ce44SJohn Forte 
4882527734SSukumar Swaminathan 
4982527734SSukumar Swaminathan 	/* If node is on a channel service queue, then remove it */
5082527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
51fcf3ce44SJohn Forte 
52fcf3ce44SJohn Forte 	/* Return if node destroyed */
53fcf3ce44SJohn Forte 	if (!ndlp || !ndlp->nlp_active) {
5482527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
55fcf3ce44SJohn Forte 
56fcf3ce44SJohn Forte 		return;
57fcf3ce44SJohn Forte 	}
58291a2b48SSukumar Swaminathan 
59291a2b48SSukumar Swaminathan 	/* Check offline support */
60291a2b48SSukumar Swaminathan 	if (timeout == -1) {
61291a2b48SSukumar Swaminathan 		if (cfg[CFG_OFFLINE_TIMEOUT].current) {
62291a2b48SSukumar Swaminathan 			timeout = cfg[CFG_OFFLINE_TIMEOUT].current;
63291a2b48SSukumar Swaminathan 			offline = 1;
64291a2b48SSukumar Swaminathan 		} else {
65291a2b48SSukumar Swaminathan 			timeout = 0;
66291a2b48SSukumar Swaminathan 		}
67291a2b48SSukumar Swaminathan 	}
68291a2b48SSukumar Swaminathan 
6982527734SSukumar Swaminathan 	if (channelno == hba->channel_ip) {
70fcf3ce44SJohn Forte 		/* Clear IP XRI */
71fcf3ce44SJohn Forte 		ndlp->nlp_Xri = 0;
72fcf3ce44SJohn Forte 	}
73291a2b48SSukumar Swaminathan 
74fcf3ce44SJohn Forte 	/* Check if node is already closed */
7582527734SSukumar Swaminathan 	if (ndlp->nlp_flag[channelno] & NLP_CLOSED) {
7682527734SSukumar Swaminathan 		if (ndlp->nlp_flag[channelno] & NLP_OFFLINE) {
7782527734SSukumar Swaminathan 			mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
78291a2b48SSukumar Swaminathan 			return;
79291a2b48SSukumar Swaminathan 		}
80291a2b48SSukumar Swaminathan 
81291a2b48SSukumar Swaminathan 		if (offline) {
8282527734SSukumar Swaminathan 			ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
8382527734SSukumar Swaminathan 			ndlp->nlp_flag[channelno] |= NLP_OFFLINE;
8482527734SSukumar Swaminathan 			mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
85291a2b48SSukumar Swaminathan 
86291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
87fe199829SSukumar Swaminathan 			    "node=%p did=%06x channel=%d. offline=%d update.",
8882527734SSukumar Swaminathan 			    ndlp, ndlp->nlp_DID, channelno, timeout);
89291a2b48SSukumar Swaminathan 
90291a2b48SSukumar Swaminathan 		} else if (timeout) {
9182527734SSukumar Swaminathan 			ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
9282527734SSukumar Swaminathan 			mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
93291a2b48SSukumar Swaminathan 
94291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
95fe199829SSukumar Swaminathan 			    "node=%p did=%06x channel=%d. timeout=%d update.",
9682527734SSukumar Swaminathan 			    ndlp, ndlp->nlp_DID, channelno, timeout);
97291a2b48SSukumar Swaminathan 		} else {
9882527734SSukumar Swaminathan 			mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
99fcf3ce44SJohn Forte 		}
100fcf3ce44SJohn Forte 
101fcf3ce44SJohn Forte 		return;
102fcf3ce44SJohn Forte 	}
103291a2b48SSukumar Swaminathan 
104fcf3ce44SJohn Forte 	/* Set the node closed */
10582527734SSukumar Swaminathan 	ndlp->nlp_flag[channelno] |= NLP_CLOSED;
106fcf3ce44SJohn Forte 
107291a2b48SSukumar Swaminathan 	if (offline) {
10882527734SSukumar Swaminathan 		ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
10982527734SSukumar Swaminathan 		ndlp->nlp_flag[channelno] |= NLP_OFFLINE;
110291a2b48SSukumar Swaminathan 
111fe199829SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
112fe199829SSukumar Swaminathan 		    "node=%p did=%06x channel=%d. offline=%d set.",
113fe199829SSukumar Swaminathan 		    ndlp, ndlp->nlp_DID, channelno, timeout);
114fe199829SSukumar Swaminathan 
115291a2b48SSukumar Swaminathan 	} else if (timeout) {
11682527734SSukumar Swaminathan 		ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
117fe199829SSukumar Swaminathan 
118fe199829SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
119fe199829SSukumar Swaminathan 		    "node=%p did=%06x channel=%d. timeout=%d set.",
120fe199829SSukumar Swaminathan 		    ndlp, ndlp->nlp_DID, channelno, timeout);
121fe199829SSukumar Swaminathan 	} else {
122fe199829SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
123fe199829SSukumar Swaminathan 		    "node=%p did=%06x channel=%d.",
124fe199829SSukumar Swaminathan 		    ndlp, ndlp->nlp_DID, channelno);
125fcf3ce44SJohn Forte 	}
126fcf3ce44SJohn Forte 
12782527734SSukumar Swaminathan 
12882527734SSukumar Swaminathan 	/*
12982527734SSukumar Swaminathan 	 * ndlp->nlp_next[] and cp->nodeq list have to be updated
13082527734SSukumar Swaminathan 	 * simulaneously
13182527734SSukumar Swaminathan 	 */
13282527734SSukumar Swaminathan 	if (ndlp->nlp_next[channelno]) {
13382527734SSukumar Swaminathan 		/* Remove node from channel queue */
13482527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
135fcf3ce44SJohn Forte 
136fcf3ce44SJohn Forte 		/* If this is the only node on list */
13782527734SSukumar Swaminathan 		if (cp->nodeq.q_first == (void *)ndlp &&
13882527734SSukumar Swaminathan 		    cp->nodeq.q_last == (void *)ndlp) {
13982527734SSukumar Swaminathan 			cp->nodeq.q_last = NULL;
14082527734SSukumar Swaminathan 			cp->nodeq.q_first = NULL;
14182527734SSukumar Swaminathan 			cp->nodeq.q_cnt = 0;
14282527734SSukumar Swaminathan 		} else if (cp->nodeq.q_first == (void *)ndlp) {
14382527734SSukumar Swaminathan 			cp->nodeq.q_first = ndlp->nlp_next[channelno];
14482527734SSukumar Swaminathan 			((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] =
14582527734SSukumar Swaminathan 			    cp->nodeq.q_first;
14682527734SSukumar Swaminathan 			cp->nodeq.q_cnt--;
147fcf3ce44SJohn Forte 		} else {	/* This is a little more difficult */
148291a2b48SSukumar Swaminathan 
14982527734SSukumar Swaminathan 			/* Find the previous node in circular channel queue */
150fcf3ce44SJohn Forte 			prev = ndlp;
15182527734SSukumar Swaminathan 			while (prev->nlp_next[channelno] != ndlp) {
15282527734SSukumar Swaminathan 				prev = prev->nlp_next[channelno];
153fcf3ce44SJohn Forte 			}
154fcf3ce44SJohn Forte 
15582527734SSukumar Swaminathan 			prev->nlp_next[channelno] = ndlp->nlp_next[channelno];
156fcf3ce44SJohn Forte 
15782527734SSukumar Swaminathan 			if (cp->nodeq.q_last == (void *)ndlp) {
15882527734SSukumar Swaminathan 				cp->nodeq.q_last = (void *)prev;
159fcf3ce44SJohn Forte 			}
16082527734SSukumar Swaminathan 			cp->nodeq.q_cnt--;
161fcf3ce44SJohn Forte 
162fcf3ce44SJohn Forte 		}
163fcf3ce44SJohn Forte 
164fcf3ce44SJohn Forte 		/* Clear node */
16582527734SSukumar Swaminathan 		ndlp->nlp_next[channelno] = NULL;
166fcf3ce44SJohn Forte 	}
167291a2b48SSukumar Swaminathan 
16882527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
169728bdc9bSSukumar Swaminathan 
170291a2b48SSukumar Swaminathan 	return;
171291a2b48SSukumar Swaminathan 
17282527734SSukumar Swaminathan } /* emlxs_node_close() */
173291a2b48SSukumar Swaminathan 
174291a2b48SSukumar Swaminathan 
175291a2b48SSukumar Swaminathan /* Called by emlxs_timer_check_nodes() */
176291a2b48SSukumar Swaminathan extern void
emlxs_node_timeout(emlxs_port_t * port,NODELIST * ndlp,uint32_t channelno)17782527734SSukumar Swaminathan emlxs_node_timeout(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno)
178291a2b48SSukumar Swaminathan {
179291a2b48SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
180291a2b48SSukumar Swaminathan 
18182527734SSukumar Swaminathan 	/* If node needs servicing, then add it to the channel queues */
18282527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
183291a2b48SSukumar Swaminathan 
184291a2b48SSukumar Swaminathan 	/* Return if node destroyed */
185291a2b48SSukumar Swaminathan 	if (!ndlp || !ndlp->nlp_active) {
18682527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
187291a2b48SSukumar Swaminathan 		return;
188291a2b48SSukumar Swaminathan 	}
189291a2b48SSukumar Swaminathan 
190291a2b48SSukumar Swaminathan 	/* Open the node if not offline */
19182527734SSukumar Swaminathan 	if (!(ndlp->nlp_flag[channelno] & NLP_OFFLINE)) {
19282527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
193291a2b48SSukumar Swaminathan 
194291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg,
19582527734SSukumar Swaminathan 		    "node=%p did=%06x channel=%d Opening.", ndlp, ndlp->nlp_DID,
19682527734SSukumar Swaminathan 		    channelno);
197291a2b48SSukumar Swaminathan 
19882527734SSukumar Swaminathan 		emlxs_node_open(port, ndlp, channelno);
199291a2b48SSukumar Swaminathan 		return;
200728bdc9bSSukumar Swaminathan 	}
201fcf3ce44SJohn Forte 
202291a2b48SSukumar Swaminathan 	/* OFFLINE TIMEOUT OCCURRED! */
203291a2b48SSukumar Swaminathan 
204291a2b48SSukumar Swaminathan 	/* Clear the timer */
20582527734SSukumar Swaminathan 	ndlp->nlp_tics[channelno] = 0;
206291a2b48SSukumar Swaminathan 
20782527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
208291a2b48SSukumar Swaminathan 
209291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg,
210a9800bebSGarrett D'Amore 	    "node=%p did=%06x channel=%d. Flushing.", ndlp, ndlp->nlp_DID,
21182527734SSukumar Swaminathan 	    channelno);
212291a2b48SSukumar Swaminathan 
21382527734SSukumar Swaminathan 	/* Flush tx queue for this channel */
21482527734SSukumar Swaminathan 	(void) emlxs_tx_node_flush(port, ndlp, &hba->chan[channelno], 0, 0);
215291a2b48SSukumar Swaminathan 
21682527734SSukumar Swaminathan 	/* Flush chip queue for this channel */
21782527734SSukumar Swaminathan 	(void) emlxs_chipq_node_flush(port, &hba->chan[channelno], ndlp, 0);
218291a2b48SSukumar Swaminathan 
219fcf3ce44SJohn Forte 	return;
220fcf3ce44SJohn Forte 
22182527734SSukumar Swaminathan } /* emlxs_node_timeout() */
222fcf3ce44SJohn Forte 
223fcf3ce44SJohn Forte 
224fcf3ce44SJohn Forte extern void
emlxs_node_open(emlxs_port_t * port,NODELIST * ndlp,uint32_t channelno)22582527734SSukumar Swaminathan emlxs_node_open(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno)
226fcf3ce44SJohn Forte {
227fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
22882527734SSukumar Swaminathan 	CHANNEL *cp;
229fcf3ce44SJohn Forte 	uint32_t found;
230fcf3ce44SJohn Forte 	NODELIST *nlp;
231fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
232fcf3ce44SJohn Forte 	uint32_t i;
23382527734SSukumar Swaminathan 	int rc;
234fcf3ce44SJohn Forte 
23582527734SSukumar Swaminathan 	/* If node needs servicing, then add it to the channel queues */
23682527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
237fcf3ce44SJohn Forte 
238fcf3ce44SJohn Forte 	/* Return if node destroyed */
239fcf3ce44SJohn Forte 	if (!ndlp || !ndlp->nlp_active) {
24082527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
241fcf3ce44SJohn Forte 
242fcf3ce44SJohn Forte 		return;
243fcf3ce44SJohn Forte 	}
244291a2b48SSukumar Swaminathan 
245fcf3ce44SJohn Forte 	/* Return if node already open */
24682527734SSukumar Swaminathan 	if (!(ndlp->nlp_flag[channelno] & NLP_CLOSED)) {
24782527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
248fcf3ce44SJohn Forte 
249fcf3ce44SJohn Forte 		return;
250fcf3ce44SJohn Forte 	}
251fcf3ce44SJohn Forte 
252291a2b48SSukumar Swaminathan 	/* Set the node open (not closed) */
25382527734SSukumar Swaminathan 	ndlp->nlp_flag[channelno] &= ~(NLP_CLOSED|NLP_OFFLINE);
254fcf3ce44SJohn Forte 
255fcf3ce44SJohn Forte 	/* Clear the timer */
25682527734SSukumar Swaminathan 	ndlp->nlp_tics[channelno] = 0;
257fcf3ce44SJohn Forte 
258fcf3ce44SJohn Forte 	/*
259291a2b48SSukumar Swaminathan 	 * If the ptx or the tx queue needs servicing and
26082527734SSukumar Swaminathan 	 * the node is not already on the channel queue
261fcf3ce44SJohn Forte 	 */
26282527734SSukumar Swaminathan 	if ((ndlp->nlp_ptx[channelno].q_first ||
26382527734SSukumar Swaminathan 	    ndlp->nlp_tx[channelno].q_first) && !ndlp->nlp_next[channelno]) {
26482527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
265fcf3ce44SJohn Forte 
26682527734SSukumar Swaminathan 		/* If so, then add it to the channel queue */
26782527734SSukumar Swaminathan 		if (cp->nodeq.q_first) {
26882527734SSukumar Swaminathan 			((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] =
269fcf3ce44SJohn Forte 			    (uint8_t *)ndlp;
27082527734SSukumar Swaminathan 			ndlp->nlp_next[channelno] = cp->nodeq.q_first;
271fcf3ce44SJohn Forte 
272291a2b48SSukumar Swaminathan 			/* If this is not the base node then */
273291a2b48SSukumar Swaminathan 			/* add it to the tail */
274fcf3ce44SJohn Forte 			if (!ndlp->nlp_base) {
27582527734SSukumar Swaminathan 				cp->nodeq.q_last = (uint8_t *)ndlp;
276fcf3ce44SJohn Forte 			} else {	/* Otherwise, add it to the head */
277291a2b48SSukumar Swaminathan 
278fcf3ce44SJohn Forte 				/* The command node always gets priority */
27982527734SSukumar Swaminathan 				cp->nodeq.q_first = (uint8_t *)ndlp;
280fcf3ce44SJohn Forte 			}
281fcf3ce44SJohn Forte 
28282527734SSukumar Swaminathan 			cp->nodeq.q_cnt++;
283fcf3ce44SJohn Forte 		} else {
28482527734SSukumar Swaminathan 			cp->nodeq.q_first = (uint8_t *)ndlp;
28582527734SSukumar Swaminathan 			cp->nodeq.q_last = (uint8_t *)ndlp;
28682527734SSukumar Swaminathan 			ndlp->nlp_next[channelno] = ndlp;
28782527734SSukumar Swaminathan 			cp->nodeq.q_cnt = 1;
288fcf3ce44SJohn Forte 		}
289fcf3ce44SJohn Forte 	}
290291a2b48SSukumar Swaminathan 
29182527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
292fcf3ce44SJohn Forte 
293291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_opened_msg,
294*8f23e9faSHans Rosenfeld 	    "node=%p did=%06x rpi=%d channel=%d", ndlp, ndlp->nlp_DID,
295a9800bebSGarrett D'Amore 	    ndlp->nlp_Rpi, channelno);
296728bdc9bSSukumar Swaminathan 
297fcf3ce44SJohn Forte 	/* If link attention needs to be cleared */
29882527734SSukumar Swaminathan 	if ((hba->state == FC_LINK_UP) && (channelno == hba->channel_fcp)) {
29982527734SSukumar Swaminathan 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
30082527734SSukumar Swaminathan 			goto done;
30182527734SSukumar Swaminathan 		}
302fcf3ce44SJohn Forte 
303fcf3ce44SJohn Forte 		/* Scan to see if any FCP2 devices are still closed */
304fcf3ce44SJohn Forte 		found = 0;
305fcf3ce44SJohn Forte 		rw_enter(&port->node_rwlock, RW_READER);
306fcf3ce44SJohn Forte 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
307fcf3ce44SJohn Forte 			nlp = port->node_table[i];
308fcf3ce44SJohn Forte 			while (nlp != NULL) {
309fcf3ce44SJohn Forte 				if ((nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) &&
31082527734SSukumar Swaminathan 				    (nlp->nlp_flag[hba->channel_fcp] &
31182527734SSukumar Swaminathan 				    NLP_CLOSED)) {
312fcf3ce44SJohn Forte 					found = 1;
313fcf3ce44SJohn Forte 					break;
314291a2b48SSukumar Swaminathan 
315fcf3ce44SJohn Forte 				}
316fcf3ce44SJohn Forte 				nlp = nlp->nlp_list_next;
317fcf3ce44SJohn Forte 			}
318fcf3ce44SJohn Forte 
319fcf3ce44SJohn Forte 			if (found) {
320fcf3ce44SJohn Forte 				break;
321fcf3ce44SJohn Forte 			}
322fcf3ce44SJohn Forte 		}
323fcf3ce44SJohn Forte 
324fcf3ce44SJohn Forte 		rw_exit(&port->node_rwlock);
325fcf3ce44SJohn Forte 
326fcf3ce44SJohn Forte 		if (!found) {
327fcf3ce44SJohn Forte 			/* Clear link attention */
328291a2b48SSukumar Swaminathan 			if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
329*8f23e9faSHans Rosenfeld 			    MEM_MBOX))) {
330fcf3ce44SJohn Forte 				mutex_enter(&EMLXS_PORT_LOCK);
331fcf3ce44SJohn Forte 
332fcf3ce44SJohn Forte 				/*
333291a2b48SSukumar Swaminathan 				 * If state is not FC_LINK_UP, then either the
334291a2b48SSukumar Swaminathan 				 * link has gone down or a FC_CLEAR_LA has
335291a2b48SSukumar Swaminathan 				 * already been issued
336fcf3ce44SJohn Forte 				 */
337fcf3ce44SJohn Forte 				if (hba->state != FC_LINK_UP) {
338fcf3ce44SJohn Forte 					mutex_exit(&EMLXS_PORT_LOCK);
339a9800bebSGarrett D'Amore 					emlxs_mem_put(hba, MEM_MBOX,
340a9800bebSGarrett D'Amore 					    (void *)mbox);
341fcf3ce44SJohn Forte 					goto done;
342fcf3ce44SJohn Forte 				}
343291a2b48SSukumar Swaminathan 
34482527734SSukumar Swaminathan 				EMLXS_STATE_CHANGE_LOCKED(hba, FC_CLEAR_LA);
345fcf3ce44SJohn Forte 				hba->discovery_timer = 0;
346fcf3ce44SJohn Forte 				mutex_exit(&EMLXS_PORT_LOCK);
347fcf3ce44SJohn Forte 
34882527734SSukumar Swaminathan 				emlxs_mb_clear_la(hba, mbox);
349fcf3ce44SJohn Forte 
35082527734SSukumar Swaminathan 				rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba,
35182527734SSukumar Swaminathan 				    mbox, MBX_NOWAIT, 0);
35282527734SSukumar Swaminathan 				if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
353a9800bebSGarrett D'Amore 					emlxs_mem_put(hba, MEM_MBOX,
354a9800bebSGarrett D'Amore 					    (void *)mbox);
355fcf3ce44SJohn Forte 				}
356fcf3ce44SJohn Forte 			} else {
357291a2b48SSukumar Swaminathan 				/* Close the node and try again */
358291a2b48SSukumar Swaminathan 				/* in a few seconds */
35982527734SSukumar Swaminathan 				emlxs_node_close(port, ndlp, channelno, 5);
360fcf3ce44SJohn Forte 				return;
361fcf3ce44SJohn Forte 			}
362fcf3ce44SJohn Forte 		}
363fcf3ce44SJohn Forte 	}
364291a2b48SSukumar Swaminathan 
365fcf3ce44SJohn Forte done:
366fcf3ce44SJohn Forte 
367fcf3ce44SJohn Forte 	/* Wake any sleeping threads */
368fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PKT_LOCK);
369fcf3ce44SJohn Forte 	cv_broadcast(&EMLXS_PKT_CV);
370fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PKT_LOCK);
371fcf3ce44SJohn Forte 
372fcf3ce44SJohn Forte 	return;
373fcf3ce44SJohn Forte 
37482527734SSukumar Swaminathan } /* emlxs_node_open() */
375fcf3ce44SJohn Forte 
376fcf3ce44SJohn Forte 
377fcf3ce44SJohn Forte static int
emlxs_node_match_did(emlxs_port_t * port,NODELIST * ndlp,uint32_t did)378fcf3ce44SJohn Forte emlxs_node_match_did(emlxs_port_t *port, NODELIST *ndlp, uint32_t did)
379fcf3ce44SJohn Forte {
380fcf3ce44SJohn Forte 	D_ID mydid;
381fcf3ce44SJohn Forte 	D_ID odid;
382fcf3ce44SJohn Forte 	D_ID ndid;
383fcf3ce44SJohn Forte 
384291a2b48SSukumar Swaminathan 	if (ndlp->nlp_DID == did)
385fcf3ce44SJohn Forte 		return (1);
386fcf3ce44SJohn Forte 
387fcf3ce44SJohn Forte 	/*
388fcf3ce44SJohn Forte 	 * Next check for area/domain == 0 match
389fcf3ce44SJohn Forte 	 */
390fcf3ce44SJohn Forte 	mydid.un.word = port->did;
391fcf3ce44SJohn Forte 	if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) {
392fcf3ce44SJohn Forte 		goto out;
393fcf3ce44SJohn Forte 	}
394291a2b48SSukumar Swaminathan 
395fcf3ce44SJohn Forte 	ndid.un.word = did;
396fcf3ce44SJohn Forte 	odid.un.word = ndlp->nlp_DID;
397fcf3ce44SJohn Forte 	if (ndid.un.b.id == odid.un.b.id) {
398fcf3ce44SJohn Forte 		if ((mydid.un.b.domain == ndid.un.b.domain) &&
399fcf3ce44SJohn Forte 		    (mydid.un.b.area == ndid.un.b.area)) {
400fcf3ce44SJohn Forte 			ndid.un.word = ndlp->nlp_DID;
401fcf3ce44SJohn Forte 			odid.un.word = did;
402291a2b48SSukumar Swaminathan 			if ((ndid.un.b.domain == 0) && (ndid.un.b.area == 0)) {
403fcf3ce44SJohn Forte 				return (1);
404fcf3ce44SJohn Forte 			}
405fcf3ce44SJohn Forte 			goto out;
406fcf3ce44SJohn Forte 		}
407291a2b48SSukumar Swaminathan 
408fcf3ce44SJohn Forte 		ndid.un.word = ndlp->nlp_DID;
409fcf3ce44SJohn Forte 		if ((mydid.un.b.domain == ndid.un.b.domain) &&
410fcf3ce44SJohn Forte 		    (mydid.un.b.area == ndid.un.b.area)) {
411fcf3ce44SJohn Forte 			odid.un.word = ndlp->nlp_DID;
412fcf3ce44SJohn Forte 			ndid.un.word = did;
413291a2b48SSukumar Swaminathan 			if ((ndid.un.b.domain == 0) && (ndid.un.b.area == 0)) {
414fcf3ce44SJohn Forte 				return (1);
415fcf3ce44SJohn Forte 			}
416fcf3ce44SJohn Forte 		}
417fcf3ce44SJohn Forte 	}
418291a2b48SSukumar Swaminathan 
419fcf3ce44SJohn Forte out:
420fcf3ce44SJohn Forte 
421fcf3ce44SJohn Forte 	return (0);
422fcf3ce44SJohn Forte 
423*8f23e9faSHans Rosenfeld } /* emlxs_node_match_did() */
424fcf3ce44SJohn Forte 
425fcf3ce44SJohn Forte 
426fcf3ce44SJohn Forte 
427fcf3ce44SJohn Forte extern NODELIST *
emlxs_node_find_mac(emlxs_port_t * port,uint8_t * mac)428fcf3ce44SJohn Forte emlxs_node_find_mac(emlxs_port_t *port, uint8_t *mac)
429fcf3ce44SJohn Forte {
430fcf3ce44SJohn Forte 	NODELIST *nlp;
431fcf3ce44SJohn Forte 	uint32_t i;
432fcf3ce44SJohn Forte 
433fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
434fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
435fcf3ce44SJohn Forte 		nlp = port->node_table[i];
436fcf3ce44SJohn Forte 		while (nlp != NULL) {
437fcf3ce44SJohn Forte 			/*
438291a2b48SSukumar Swaminathan 			 * If portname matches mac address,
439291a2b48SSukumar Swaminathan 			 * return NODELIST entry
440fcf3ce44SJohn Forte 			 */
441fcf3ce44SJohn Forte 			if ((nlp->nlp_portname.IEEE[0] == mac[0])) {
44282527734SSukumar Swaminathan 				if ((nlp->nlp_DID != BCAST_DID) &&
44382527734SSukumar Swaminathan 				    ((nlp->nlp_DID & FABRIC_DID_MASK) ==
44482527734SSukumar Swaminathan 				    FABRIC_DID_MASK)) {
445291a2b48SSukumar Swaminathan 					nlp = (NODELIST *)nlp->nlp_list_next;
446fcf3ce44SJohn Forte 					continue;
447fcf3ce44SJohn Forte 				}
448291a2b48SSukumar Swaminathan 
449fcf3ce44SJohn Forte 				if ((nlp->nlp_portname.IEEE[1] == mac[1]) &&
450fcf3ce44SJohn Forte 				    (nlp->nlp_portname.IEEE[2] == mac[2]) &&
451fcf3ce44SJohn Forte 				    (nlp->nlp_portname.IEEE[3] == mac[3]) &&
452fcf3ce44SJohn Forte 				    (nlp->nlp_portname.IEEE[4] == mac[4]) &&
453fcf3ce44SJohn Forte 				    (nlp->nlp_portname.IEEE[5] == mac[5])) {
454fcf3ce44SJohn Forte 					rw_exit(&port->node_rwlock);
455fcf3ce44SJohn Forte 					return (nlp);
456fcf3ce44SJohn Forte 				}
457291a2b48SSukumar Swaminathan 
458fcf3ce44SJohn Forte 			}
459291a2b48SSukumar Swaminathan 
460291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
461fcf3ce44SJohn Forte 		}
462fcf3ce44SJohn Forte 	}
463fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
464fcf3ce44SJohn Forte 
465fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg,
466291a2b48SSukumar Swaminathan 	    "find: MAC=%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2],
467291a2b48SSukumar Swaminathan 	    mac[3], mac[4], mac[5]);
468fcf3ce44SJohn Forte 
469fcf3ce44SJohn Forte 	return (NULL);
470fcf3ce44SJohn Forte 
47182527734SSukumar Swaminathan } /* emlxs_node_find_mac() */
472fcf3ce44SJohn Forte 
473fcf3ce44SJohn Forte 
474fcf3ce44SJohn Forte extern NODELIST *
emlxs_node_find_did(emlxs_port_t * port,uint32_t did,uint32_t lock)475*8f23e9faSHans Rosenfeld emlxs_node_find_did(emlxs_port_t *port, uint32_t did, uint32_t lock)
476fcf3ce44SJohn Forte {
477fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
478fcf3ce44SJohn Forte 	NODELIST *nlp;
479fcf3ce44SJohn Forte 	uint32_t hash;
480fcf3ce44SJohn Forte 
481fcf3ce44SJohn Forte 	/* Check for invalid node ids  */
482291a2b48SSukumar Swaminathan 	if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) {
483291a2b48SSukumar Swaminathan 		return ((NODELIST *)0);
484291a2b48SSukumar Swaminathan 	}
485291a2b48SSukumar Swaminathan 
486291a2b48SSukumar Swaminathan 	if (did & 0xff000000) {
487291a2b48SSukumar Swaminathan 		return ((NODELIST *)0);
488fcf3ce44SJohn Forte 	}
489291a2b48SSukumar Swaminathan 
490fcf3ce44SJohn Forte 	/* Check for bcast node */
49182527734SSukumar Swaminathan 	if (did == BCAST_DID) {
492fcf3ce44SJohn Forte 		/* Use the base node here */
493fcf3ce44SJohn Forte 		return (&port->node_base);
494fcf3ce44SJohn Forte 	}
495fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT
496fcf3ce44SJohn Forte 	/* Check for menlo node */
497fcf3ce44SJohn Forte 	if (did == EMLXS_MENLO_DID) {
498fcf3ce44SJohn Forte 		/* Use the base node here */
499fcf3ce44SJohn Forte 		return (&port->node_base);
500fcf3ce44SJohn Forte 	}
501291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */
502fcf3ce44SJohn Forte 
503fcf3ce44SJohn Forte 	/* Check for host node */
504fcf3ce44SJohn Forte 	if (did == port->did && !(hba->flag & FC_LOOPBACK_MODE)) {
505fcf3ce44SJohn Forte 		/* Use the base node here */
506fcf3ce44SJohn Forte 		return (&port->node_base);
507fcf3ce44SJohn Forte 	}
508291a2b48SSukumar Swaminathan 
509fcf3ce44SJohn Forte 	/*
51082527734SSukumar Swaminathan 	 * Convert well known fabric addresses to the FABRIC_DID,
511291a2b48SSukumar Swaminathan 	 * since we don't login to some of them
512fcf3ce44SJohn Forte 	 */
513fcf3ce44SJohn Forte 	if ((did == SCR_DID)) {
51482527734SSukumar Swaminathan 		did = FABRIC_DID;
515fcf3ce44SJohn Forte 	}
516291a2b48SSukumar Swaminathan 
517*8f23e9faSHans Rosenfeld 	if (lock) {
518*8f23e9faSHans Rosenfeld 		rw_enter(&port->node_rwlock, RW_READER);
519*8f23e9faSHans Rosenfeld 	}
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) {
525*8f23e9faSHans Rosenfeld 			if (lock) {
526*8f23e9faSHans Rosenfeld 				rw_exit(&port->node_rwlock);
527*8f23e9faSHans Rosenfeld 			}
528fcf3ce44SJohn Forte 			return (nlp);
529fcf3ce44SJohn Forte 		}
530291a2b48SSukumar Swaminathan 
531fcf3ce44SJohn Forte 		/* Check for detailed match */
532fcf3ce44SJohn Forte 		else if (emlxs_node_match_did(port, nlp, did)) {
533*8f23e9faSHans Rosenfeld 			if (lock) {
534*8f23e9faSHans Rosenfeld 				rw_exit(&port->node_rwlock);
535*8f23e9faSHans Rosenfeld 			}
536fcf3ce44SJohn Forte 			return (nlp);
537fcf3ce44SJohn Forte 		}
538291a2b48SSukumar Swaminathan 
539291a2b48SSukumar Swaminathan 		nlp = (NODELIST *)nlp->nlp_list_next;
540fcf3ce44SJohn Forte 	}
541*8f23e9faSHans Rosenfeld 
542*8f23e9faSHans Rosenfeld 	if (lock) {
543*8f23e9faSHans Rosenfeld 		rw_exit(&port->node_rwlock);
544*8f23e9faSHans Rosenfeld 	}
545fcf3ce44SJohn Forte 
546291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: did=%x",
547291a2b48SSukumar Swaminathan 	    did);
548fcf3ce44SJohn Forte 
549fcf3ce44SJohn Forte 	/* no match found */
550291a2b48SSukumar Swaminathan 	return ((NODELIST *)0);
551fcf3ce44SJohn Forte 
55282527734SSukumar Swaminathan } /* emlxs_node_find_did() */
553fcf3ce44SJohn Forte 
554fcf3ce44SJohn Forte 
555fcf3ce44SJohn Forte extern NODELIST *
emlxs_node_find_rpi(emlxs_port_t * port,uint32_t rpi)556fcf3ce44SJohn Forte emlxs_node_find_rpi(emlxs_port_t *port, uint32_t rpi)
557fcf3ce44SJohn Forte {
558fcf3ce44SJohn Forte 	NODELIST *nlp;
559fcf3ce44SJohn Forte 	uint32_t i;
560fcf3ce44SJohn Forte 
561fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
562fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
563fcf3ce44SJohn Forte 		nlp = port->node_table[i];
564fcf3ce44SJohn Forte 		while (nlp != NULL) {
565fcf3ce44SJohn Forte 			if (nlp->nlp_Rpi == rpi) {
566fcf3ce44SJohn Forte 				rw_exit(&port->node_rwlock);
567fcf3ce44SJohn Forte 				return (nlp);
568fcf3ce44SJohn Forte 			}
569291a2b48SSukumar Swaminathan 
570291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
571fcf3ce44SJohn Forte 		}
572fcf3ce44SJohn Forte 	}
573fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
574fcf3ce44SJohn Forte 
575*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: rpi=%d",
576291a2b48SSukumar Swaminathan 	    rpi);
577fcf3ce44SJohn Forte 
578fcf3ce44SJohn Forte 	/* no match found */
579291a2b48SSukumar Swaminathan 	return ((NODELIST *)0);
580fcf3ce44SJohn Forte 
58182527734SSukumar Swaminathan } /* emlxs_node_find_rpi() */
582fcf3ce44SJohn Forte 
583fcf3ce44SJohn Forte 
584fcf3ce44SJohn Forte extern NODELIST *
emlxs_node_find_wwpn(emlxs_port_t * port,uint8_t * wwpn,uint32_t lock)585*8f23e9faSHans Rosenfeld emlxs_node_find_wwpn(emlxs_port_t *port, uint8_t *wwpn, uint32_t lock)
586fcf3ce44SJohn Forte {
587fcf3ce44SJohn Forte 	NODELIST *nlp;
588fcf3ce44SJohn Forte 	uint32_t i;
589fcf3ce44SJohn Forte 	uint32_t j;
590fcf3ce44SJohn Forte 	uint8_t *bptr1;
591fcf3ce44SJohn Forte 	uint8_t *bptr2;
592fcf3ce44SJohn Forte 
593*8f23e9faSHans Rosenfeld 	if (lock) {
594*8f23e9faSHans Rosenfeld 		rw_enter(&port->node_rwlock, RW_READER);
595*8f23e9faSHans Rosenfeld 	}
596*8f23e9faSHans Rosenfeld 
597fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
598fcf3ce44SJohn Forte 		nlp = port->node_table[i];
599fcf3ce44SJohn Forte 		while (nlp != NULL) {
600fcf3ce44SJohn Forte 			bptr1 = (uint8_t *)&nlp->nlp_portname;
601fcf3ce44SJohn Forte 			bptr1 += 7;
602fcf3ce44SJohn Forte 			bptr2 = (uint8_t *)wwpn;
603fcf3ce44SJohn Forte 			bptr2 += 7;
604fcf3ce44SJohn Forte 
605fcf3ce44SJohn Forte 			for (j = 0; j < 8; j++) {
606fcf3ce44SJohn Forte 				if (*bptr1-- != *bptr2--) {
607fcf3ce44SJohn Forte 					break;
608fcf3ce44SJohn Forte 				}
609fcf3ce44SJohn Forte 			}
610fcf3ce44SJohn Forte 
611fcf3ce44SJohn Forte 			if (j == 8) {
612*8f23e9faSHans Rosenfeld 				if (lock) {
613*8f23e9faSHans Rosenfeld 					rw_exit(&port->node_rwlock);
614*8f23e9faSHans Rosenfeld 				}
615fcf3ce44SJohn Forte 				return (nlp);
616fcf3ce44SJohn Forte 			}
617291a2b48SSukumar Swaminathan 
618291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
619fcf3ce44SJohn Forte 		}
620fcf3ce44SJohn Forte 	}
621*8f23e9faSHans Rosenfeld 
622*8f23e9faSHans Rosenfeld 	if (lock) {
623*8f23e9faSHans Rosenfeld 		rw_exit(&port->node_rwlock);
624*8f23e9faSHans Rosenfeld 	}
625fcf3ce44SJohn Forte 
626fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg,
627291a2b48SSukumar Swaminathan 	    "find: wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", wwpn[0], wwpn[1],
628291a2b48SSukumar Swaminathan 	    wwpn[2], wwpn[3], wwpn[4], wwpn[5], wwpn[6], wwpn[7]);
629fcf3ce44SJohn Forte 
630fcf3ce44SJohn Forte 	/* no match found */
631291a2b48SSukumar Swaminathan 	return ((NODELIST *)0);
632fcf3ce44SJohn Forte 
63382527734SSukumar Swaminathan } /* emlxs_node_find_wwpn() */
634fcf3ce44SJohn Forte 
635fcf3ce44SJohn Forte 
636fcf3ce44SJohn Forte extern NODELIST *
emlxs_node_find_index(emlxs_port_t * port,uint32_t index,uint32_t nports_only)637291a2b48SSukumar Swaminathan emlxs_node_find_index(emlxs_port_t *port, uint32_t index,
638291a2b48SSukumar Swaminathan     uint32_t nports_only)
639fcf3ce44SJohn Forte {
640fcf3ce44SJohn Forte 	NODELIST *nlp;
641fcf3ce44SJohn Forte 	uint32_t i;
642fcf3ce44SJohn Forte 	uint32_t count;
643fcf3ce44SJohn Forte 
644fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
645fcf3ce44SJohn Forte 
646fcf3ce44SJohn Forte 	if (index > port->node_count - 1) {
647fcf3ce44SJohn Forte 		rw_exit(&port->node_rwlock);
648fcf3ce44SJohn Forte 		return (NULL);
649fcf3ce44SJohn Forte 	}
650291a2b48SSukumar Swaminathan 
651fcf3ce44SJohn Forte 	count = 0;
652fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
653fcf3ce44SJohn Forte 		nlp = port->node_table[i];
654fcf3ce44SJohn Forte 		while (nlp != NULL) {
655fcf3ce44SJohn Forte 			/* Skip fabric ports if requested */
656291a2b48SSukumar Swaminathan 			if (nports_only &&
657291a2b48SSukumar Swaminathan 			    (nlp->nlp_DID & 0xFFF000) == 0xFFF000) {
658291a2b48SSukumar Swaminathan 				nlp = (NODELIST *)nlp->nlp_list_next;
659fcf3ce44SJohn Forte 				continue;
660fcf3ce44SJohn Forte 			}
661291a2b48SSukumar Swaminathan 
662fcf3ce44SJohn Forte 			if (count == index) {
663fcf3ce44SJohn Forte 				rw_exit(&port->node_rwlock);
664fcf3ce44SJohn Forte 				return (nlp);
665fcf3ce44SJohn Forte 			}
666291a2b48SSukumar Swaminathan 
667291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
668fcf3ce44SJohn Forte 			count++;
669fcf3ce44SJohn Forte 		}
670fcf3ce44SJohn Forte 	}
671fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
672fcf3ce44SJohn Forte 
673291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: index=%d",
674291a2b48SSukumar Swaminathan 	    index);
675fcf3ce44SJohn Forte 
676fcf3ce44SJohn Forte 	/* no match found */
677291a2b48SSukumar Swaminathan 	return ((NODELIST *)0);
678fcf3ce44SJohn Forte 
679a9800bebSGarrett D'Amore } /* emlxs_node_find_index() */
680fcf3ce44SJohn Forte 
681fcf3ce44SJohn Forte 
682fcf3ce44SJohn Forte extern uint32_t
emlxs_nport_count(emlxs_port_t * port)683fcf3ce44SJohn Forte emlxs_nport_count(emlxs_port_t *port)
684fcf3ce44SJohn Forte {
685fcf3ce44SJohn Forte 	NODELIST *nlp;
686fcf3ce44SJohn Forte 	uint32_t i;
687fcf3ce44SJohn Forte 	uint32_t nport_count = 0;
688fcf3ce44SJohn Forte 
689fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
690fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
691fcf3ce44SJohn Forte 		nlp = port->node_table[i];
692fcf3ce44SJohn Forte 		while (nlp != NULL) {
693fcf3ce44SJohn Forte 			if ((nlp->nlp_DID & 0xFFF000) != 0xFFF000) {
694fcf3ce44SJohn Forte 				nport_count++;
695fcf3ce44SJohn Forte 			}
696291a2b48SSukumar Swaminathan 
697291a2b48SSukumar Swaminathan 			nlp = (NODELIST *)nlp->nlp_list_next;
698fcf3ce44SJohn Forte 		}
699fcf3ce44SJohn Forte 	}
700fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
701fcf3ce44SJohn Forte 
702fcf3ce44SJohn Forte 	return (nport_count);
703fcf3ce44SJohn Forte 
70482527734SSukumar Swaminathan } /* emlxs_nport_count() */
705fcf3ce44SJohn Forte 
706fcf3ce44SJohn Forte 
707fcf3ce44SJohn Forte 
708fcf3ce44SJohn Forte extern void
emlxs_node_destroy_all(emlxs_port_t * port)709fcf3ce44SJohn Forte emlxs_node_destroy_all(emlxs_port_t *port)
710fcf3ce44SJohn Forte {
711fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
712fcf3ce44SJohn Forte 	NODELIST *next;
713fcf3ce44SJohn Forte 	NODELIST *ndlp;
714a9800bebSGarrett D'Amore 	RPIobj_t *rpip;
715fcf3ce44SJohn Forte 	uint8_t *wwn;
716fcf3ce44SJohn Forte 	uint32_t i;
717fcf3ce44SJohn Forte 
718fcf3ce44SJohn Forte 	/* Flush and free the nodes */
719fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_WRITER);
720fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
721fcf3ce44SJohn Forte 		ndlp = port->node_table[i];
722fcf3ce44SJohn Forte 		port->node_table[i] = 0;
723fcf3ce44SJohn Forte 		while (ndlp != NULL) {
724fcf3ce44SJohn Forte 			next = ndlp->nlp_list_next;
725fcf3ce44SJohn Forte 			ndlp->nlp_list_next = NULL;
726fcf3ce44SJohn Forte 			ndlp->nlp_list_prev = NULL;
727fcf3ce44SJohn Forte 			ndlp->nlp_active = 0;
728fcf3ce44SJohn Forte 
729fcf3ce44SJohn Forte 			if (port->node_count) {
730fcf3ce44SJohn Forte 				port->node_count--;
731fcf3ce44SJohn Forte 			}
732291a2b48SSukumar Swaminathan 
733fcf3ce44SJohn Forte 			wwn = (uint8_t *)&ndlp->nlp_portname;
734291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
735291a2b48SSukumar Swaminathan 			    &emlxs_node_destroy_msg, "did=%06x "
736*8f23e9faSHans Rosenfeld 			    "rpi=%d wwpn=%02x%02x%02x%02x%02x%02x%02x%02x "
737291a2b48SSukumar Swaminathan 			    "count=%d", ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0],
738291a2b48SSukumar Swaminathan 			    wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6],
739291a2b48SSukumar Swaminathan 			    wwn[7], port->node_count);
740fcf3ce44SJohn Forte 
741fcf3ce44SJohn Forte 			(void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0);
742fcf3ce44SJohn Forte 
74382527734SSukumar Swaminathan 			/* Break Node/RPI binding */
744a9800bebSGarrett D'Amore 			if (ndlp->rpip) {
745a9800bebSGarrett D'Amore 				rpip = ndlp->rpip;
74682527734SSukumar Swaminathan 
747a9800bebSGarrett D'Amore 				ndlp->rpip = NULL;
748a9800bebSGarrett D'Amore 				rpip->node = NULL;
749a9800bebSGarrett D'Amore 
750a9800bebSGarrett D'Amore 				(void) emlxs_rpi_free_notify(port, rpip);
75182527734SSukumar Swaminathan 			}
75282527734SSukumar Swaminathan 
753a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, MEM_NLP, (void *)ndlp);
754fcf3ce44SJohn Forte 
755fcf3ce44SJohn Forte 			ndlp = next;
756fcf3ce44SJohn Forte 		}
757fcf3ce44SJohn Forte 	}
758fcf3ce44SJohn Forte 	port->node_count = 0;
759fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
760fcf3ce44SJohn Forte 
761fcf3ce44SJohn Forte 	/* Clean the base node */
762fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
763fcf3ce44SJohn Forte 	port->node_base.nlp_list_next = NULL;
764fcf3ce44SJohn Forte 	port->node_base.nlp_list_prev = NULL;
765fcf3ce44SJohn Forte 	port->node_base.nlp_active = 1;
766fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
767fcf3ce44SJohn Forte 
768fcf3ce44SJohn Forte 	/* Flush the base node */
769fcf3ce44SJohn Forte 	(void) emlxs_tx_node_flush(port, &port->node_base, 0, 1, 0);
770fcf3ce44SJohn Forte 	(void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0);
771fcf3ce44SJohn Forte 
772fcf3ce44SJohn Forte 	return;
773fcf3ce44SJohn Forte 
77482527734SSukumar Swaminathan } /* emlxs_node_destroy_all() */
775fcf3ce44SJohn Forte 
776fcf3ce44SJohn Forte 
777a9800bebSGarrett D'Amore extern NODELIST *
emlxs_node_create(emlxs_port_t * port,uint32_t did,uint32_t rpi,SERV_PARM * sp)778a9800bebSGarrett D'Amore emlxs_node_create(emlxs_port_t *port, uint32_t did, uint32_t rpi, SERV_PARM *sp)
779a9800bebSGarrett D'Amore {
780a9800bebSGarrett D'Amore 	emlxs_hba_t *hba = HBA;
781*8f23e9faSHans Rosenfeld 	NODELIST *ndlp, *ndlp_wwn;
782a9800bebSGarrett D'Amore 	uint8_t *wwn;
783a9800bebSGarrett D'Amore 	emlxs_vvl_fmt_t vvl;
784a9800bebSGarrett D'Amore 	RPIobj_t *rpip;
785a9800bebSGarrett D'Amore 
786*8f23e9faSHans Rosenfeld 	rw_enter(&port->node_rwlock, RW_WRITER);
787*8f23e9faSHans Rosenfeld 
788*8f23e9faSHans Rosenfeld 	ndlp = emlxs_node_find_did(port, did, 0);
789*8f23e9faSHans Rosenfeld 	ndlp_wwn = emlxs_node_find_wwpn(port, (uint8_t *)&sp->portName, 0);
790*8f23e9faSHans Rosenfeld 
791*8f23e9faSHans Rosenfeld 	/* Zero out the stale node worldwide names */
792*8f23e9faSHans Rosenfeld 	if (ndlp_wwn && (ndlp != ndlp_wwn)) {
793*8f23e9faSHans Rosenfeld 		bzero((uint8_t *)&ndlp_wwn->nlp_nodename, sizeof (NAME_TYPE));
794*8f23e9faSHans Rosenfeld 		bzero((uint8_t *)&ndlp_wwn->nlp_portname, sizeof (NAME_TYPE));
795*8f23e9faSHans Rosenfeld 	}
796a9800bebSGarrett D'Amore 
797a9800bebSGarrett D'Amore 	/* Update the node */
798a9800bebSGarrett D'Amore 	if (ndlp) {
799a9800bebSGarrett D'Amore 		ndlp->nlp_Rpi = (uint16_t)rpi;
800a9800bebSGarrett D'Amore 		ndlp->nlp_DID = did;
801a9800bebSGarrett D'Amore 
802a9800bebSGarrett D'Amore 		bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm,
803a9800bebSGarrett D'Amore 		    sizeof (SERV_PARM));
804a9800bebSGarrett D'Amore 
805a9800bebSGarrett D'Amore 		bcopy((uint8_t *)&sp->nodeName,
806a9800bebSGarrett D'Amore 		    (uint8_t *)&ndlp->nlp_nodename,
807a9800bebSGarrett D'Amore 		    sizeof (NAME_TYPE));
808a9800bebSGarrett D'Amore 
809a9800bebSGarrett D'Amore 		bcopy((uint8_t *)&sp->portName,
810a9800bebSGarrett D'Amore 		    (uint8_t *)&ndlp->nlp_portname,
811a9800bebSGarrett D'Amore 		    sizeof (NAME_TYPE));
812a9800bebSGarrett D'Amore 
813a9800bebSGarrett D'Amore 		/* Add Node/RPI binding */
814a9800bebSGarrett D'Amore 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
815a9800bebSGarrett D'Amore 			rpip = emlxs_rpi_find(port, rpi);
816a9800bebSGarrett D'Amore 
817a9800bebSGarrett D'Amore 			if (rpip) {
818a9800bebSGarrett D'Amore 				rpip->node = ndlp;
819a9800bebSGarrett D'Amore 				ndlp->rpip = rpip;
820a9800bebSGarrett D'Amore 			} else {
821a9800bebSGarrett D'Amore 				ndlp->rpip = NULL;
822a9800bebSGarrett D'Amore 
823a9800bebSGarrett D'Amore 				EMLXS_MSGF(EMLXS_CONTEXT,
824a9800bebSGarrett D'Amore 				    &emlxs_node_create_msg,
825*8f23e9faSHans Rosenfeld 				    "Unable to find RPI. did=%x rpi=%d",
826a9800bebSGarrett D'Amore 				    did, rpi);
827a9800bebSGarrett D'Amore 			}
828a9800bebSGarrett D'Amore 		} else {
829a9800bebSGarrett D'Amore 			ndlp->rpip = NULL;
830a9800bebSGarrett D'Amore 		}
831a9800bebSGarrett D'Amore 
832a9800bebSGarrett D'Amore 		wwn = (uint8_t *)&ndlp->nlp_portname;
833a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_update_msg,
834*8f23e9faSHans Rosenfeld 		    "node=%p did=%06x rpi=%d "
835a9800bebSGarrett D'Amore 		    "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x",
836a9800bebSGarrett D'Amore 		    ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0],
837a9800bebSGarrett D'Amore 		    wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
838a9800bebSGarrett D'Amore 
839a9800bebSGarrett D'Amore 		goto done;
840a9800bebSGarrett D'Amore 	}
841a9800bebSGarrett D'Amore 
842a9800bebSGarrett D'Amore 	/* Allocate a new node */
843*8f23e9faSHans Rosenfeld 	ndlp = (NODELIST *)emlxs_mem_get(hba, MEM_NLP);
844a9800bebSGarrett D'Amore 
845a9800bebSGarrett D'Amore 	if (ndlp) {
846a9800bebSGarrett D'Amore 		ndlp->nlp_Rpi = (uint16_t)rpi;
847a9800bebSGarrett D'Amore 		ndlp->nlp_DID = did;
848a9800bebSGarrett D'Amore 
849a9800bebSGarrett D'Amore 		bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm,
850a9800bebSGarrett D'Amore 		    sizeof (SERV_PARM));
851a9800bebSGarrett D'Amore 
852a9800bebSGarrett D'Amore 		bcopy((uint8_t *)&sp->nodeName,
853a9800bebSGarrett D'Amore 		    (uint8_t *)&ndlp->nlp_nodename,
854a9800bebSGarrett D'Amore 		    sizeof (NAME_TYPE));
855a9800bebSGarrett D'Amore 
856a9800bebSGarrett D'Amore 		bcopy((uint8_t *)&sp->portName,
857a9800bebSGarrett D'Amore 		    (uint8_t *)&ndlp->nlp_portname,
858a9800bebSGarrett D'Amore 		    sizeof (NAME_TYPE));
859a9800bebSGarrett D'Amore 
860a9800bebSGarrett D'Amore 		ndlp->nlp_active = 1;
861a9800bebSGarrett D'Amore 		ndlp->nlp_flag[hba->channel_ct]  |= NLP_CLOSED;
862a9800bebSGarrett D'Amore 		ndlp->nlp_flag[hba->channel_els] |= NLP_CLOSED;
863a9800bebSGarrett D'Amore 		ndlp->nlp_flag[hba->channel_fcp] |= NLP_CLOSED;
864a9800bebSGarrett D'Amore 		ndlp->nlp_flag[hba->channel_ip]  |= NLP_CLOSED;
865a9800bebSGarrett D'Amore 
866a9800bebSGarrett D'Amore 		/* Add Node/RPI binding */
867a9800bebSGarrett D'Amore 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
868a9800bebSGarrett D'Amore 			rpip = emlxs_rpi_find(port, rpi);
869a9800bebSGarrett D'Amore 
870a9800bebSGarrett D'Amore 			if (rpip) {
871a9800bebSGarrett D'Amore 				rpip->node = ndlp;
872a9800bebSGarrett D'Amore 				ndlp->rpip = rpip;
873a9800bebSGarrett D'Amore 			} else {
874a9800bebSGarrett D'Amore 				ndlp->rpip = NULL;
875a9800bebSGarrett D'Amore 
876a9800bebSGarrett D'Amore 				EMLXS_MSGF(EMLXS_CONTEXT,
877a9800bebSGarrett D'Amore 				    &emlxs_node_create_msg,
878*8f23e9faSHans Rosenfeld 				    "Unable to find RPI. did=%x rpi=%d",
879a9800bebSGarrett D'Amore 				    did, rpi);
880a9800bebSGarrett D'Amore 			}
881a9800bebSGarrett D'Amore 		} else {
882a9800bebSGarrett D'Amore 			ndlp->rpip = NULL;
883a9800bebSGarrett D'Amore 		}
884*8f23e9faSHans Rosenfeld 
885*8f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT
886*8f23e9faSHans Rosenfeld 		emlxs_node_throttle_set(port, ndlp);
887*8f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */
888a9800bebSGarrett D'Amore 
889a9800bebSGarrett D'Amore 		/* Add the node */
890a9800bebSGarrett D'Amore 		emlxs_node_add(port, ndlp);
891a9800bebSGarrett D'Amore 
892a9800bebSGarrett D'Amore 		goto done;
893a9800bebSGarrett D'Amore 	}
894a9800bebSGarrett D'Amore 
895*8f23e9faSHans Rosenfeld 	rw_exit(&port->node_rwlock);
896a9800bebSGarrett D'Amore 	wwn = (uint8_t *)&sp->portName;
897a9800bebSGarrett D'Amore 	EMLXS_MSGF(EMLXS_CONTEXT,
898a9800bebSGarrett D'Amore 	    &emlxs_node_create_failed_msg,
899a9800bebSGarrett D'Amore 	    "Unable to allocate node. did=%06x "
900a9800bebSGarrett D'Amore 	    "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x",
901a9800bebSGarrett D'Amore 	    did, wwn[0], wwn[1], wwn[2],
902a9800bebSGarrett D'Amore 	    wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
903a9800bebSGarrett D'Amore 
904a9800bebSGarrett D'Amore 	return (NULL);
905a9800bebSGarrett D'Amore 
906a9800bebSGarrett D'Amore done:
907*8f23e9faSHans Rosenfeld 	rw_exit(&port->node_rwlock);
908a9800bebSGarrett D'Amore 	if (sp->VALID_VENDOR_VERSION) {
909a9800bebSGarrett D'Amore 		bcopy((caddr_t *)&sp->vendorVersion[0],
910a9800bebSGarrett D'Amore 		    (caddr_t *)&vvl, sizeof (emlxs_vvl_fmt_t));
911a9800bebSGarrett D'Amore 
912a9800bebSGarrett D'Amore 		vvl.un0.word0 = LE_SWAP32(vvl.un0.word0);
913a9800bebSGarrett D'Amore 		vvl.un1.word1 = LE_SWAP32(vvl.un1.word1);
914a9800bebSGarrett D'Amore 
915a9800bebSGarrett D'Amore 		if ((vvl.un0.w0.oui == 0x0000C9) &&
916a9800bebSGarrett D'Amore 		    (vvl.un1.w1.vport)) {
917a9800bebSGarrett D'Amore 			ndlp->nlp_fcp_info |= NLP_EMLX_VPORT;
918a9800bebSGarrett D'Amore 		}
919a9800bebSGarrett D'Amore 	}
920a9800bebSGarrett D'Amore 
921a9800bebSGarrett D'Amore 	/* Open the node */
922a9800bebSGarrett D'Amore 	emlxs_node_open(port, ndlp, hba->channel_ct);
923a9800bebSGarrett D'Amore 	emlxs_node_open(port, ndlp, hba->channel_els);
924a9800bebSGarrett D'Amore 	emlxs_node_open(port, ndlp, hba->channel_ip);
925a9800bebSGarrett D'Amore 	emlxs_node_open(port, ndlp, hba->channel_fcp);
926a9800bebSGarrett D'Amore 
927*8f23e9faSHans Rosenfeld 	EMLXS_SET_DFC_STATE(ndlp, NODE_LOGIN);
928*8f23e9faSHans Rosenfeld 
929a9800bebSGarrett D'Amore 	return (ndlp);
930a9800bebSGarrett D'Amore 
931a9800bebSGarrett D'Amore } /* emlxs_node_create() */
932a9800bebSGarrett D'Amore 
933a9800bebSGarrett D'Amore 
934*8f23e9faSHans Rosenfeld /* node_rwlock must be held when calling this routine */
935*8f23e9faSHans Rosenfeld static void
emlxs_node_add(emlxs_port_t * port,NODELIST * ndlp)936fcf3ce44SJohn Forte emlxs_node_add(emlxs_port_t *port, NODELIST *ndlp)
937fcf3ce44SJohn Forte {
938fcf3ce44SJohn Forte 	NODELIST *np;
939fcf3ce44SJohn Forte 	uint8_t *wwn;
940fcf3ce44SJohn Forte 	uint32_t hash;
941fcf3ce44SJohn Forte 
942fcf3ce44SJohn Forte 	hash = EMLXS_DID_HASH(ndlp->nlp_DID);
943fcf3ce44SJohn Forte 	np = port->node_table[hash];
944fcf3ce44SJohn Forte 
945fcf3ce44SJohn Forte 	/*
946fcf3ce44SJohn Forte 	 * Insert node pointer to the head
947fcf3ce44SJohn Forte 	 */
948fcf3ce44SJohn Forte 	port->node_table[hash] = ndlp;
949fcf3ce44SJohn Forte 	if (!np) {
950fcf3ce44SJohn Forte 		ndlp->nlp_list_next = NULL;
951fcf3ce44SJohn Forte 	} else {
952fcf3ce44SJohn Forte 		ndlp->nlp_list_next = np;
953fcf3ce44SJohn Forte 	}
954fcf3ce44SJohn Forte 	port->node_count++;
955fcf3ce44SJohn Forte 
956fcf3ce44SJohn Forte 	wwn = (uint8_t *)&ndlp->nlp_portname;
957fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_msg,
958*8f23e9faSHans Rosenfeld 	    "node=%p did=%06x rpi=%d wwpn=%02x%02x%02x%02x%02x%02x%02x%02x "
959291a2b48SSukumar Swaminathan 	    "count=%d", ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], wwn[1],
960291a2b48SSukumar Swaminathan 	    wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7], port->node_count);
961fcf3ce44SJohn Forte 
962fcf3ce44SJohn Forte 	return;
963fcf3ce44SJohn Forte 
96482527734SSukumar Swaminathan } /* emlxs_node_add() */
965fcf3ce44SJohn Forte 
966fcf3ce44SJohn Forte 
967fcf3ce44SJohn Forte extern void
emlxs_node_rm(emlxs_port_t * port,NODELIST * ndlp)968fcf3ce44SJohn Forte emlxs_node_rm(emlxs_port_t *port, NODELIST *ndlp)
969fcf3ce44SJohn Forte {
970fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
971fcf3ce44SJohn Forte 	NODELIST *np;
972fcf3ce44SJohn Forte 	NODELIST *prevp;
973a9800bebSGarrett D'Amore 	RPIobj_t *rpip;
974fcf3ce44SJohn Forte 	uint8_t *wwn;
975fcf3ce44SJohn Forte 	uint32_t hash;
976fcf3ce44SJohn Forte 
977fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_WRITER);
978fcf3ce44SJohn Forte 	hash = EMLXS_DID_HASH(ndlp->nlp_DID);
979fcf3ce44SJohn Forte 	np = port->node_table[hash];
980fcf3ce44SJohn Forte 	prevp = NULL;
981fcf3ce44SJohn Forte 	while (np != NULL) {
982fcf3ce44SJohn Forte 		if (np->nlp_DID == ndlp->nlp_DID) {
983fcf3ce44SJohn Forte 			if (prevp == NULL) {
984fcf3ce44SJohn Forte 				port->node_table[hash] = np->nlp_list_next;
985fcf3ce44SJohn Forte 			} else {
986fcf3ce44SJohn Forte 				prevp->nlp_list_next = np->nlp_list_next;
987fcf3ce44SJohn Forte 			}
988fcf3ce44SJohn Forte 
989fcf3ce44SJohn Forte 			if (port->node_count) {
990fcf3ce44SJohn Forte 				port->node_count--;
991fcf3ce44SJohn Forte 			}
992291a2b48SSukumar Swaminathan 
993fcf3ce44SJohn Forte 			wwn = (uint8_t *)&ndlp->nlp_portname;
994291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
995291a2b48SSukumar Swaminathan 			    &emlxs_node_destroy_msg, "did=%06x "
996*8f23e9faSHans Rosenfeld 			    "rpi=%d wwpn=%02x%02x%02x%02x%02x%02x%02x%02x "
997291a2b48SSukumar Swaminathan 			    "count=%d", ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0],
998291a2b48SSukumar Swaminathan 			    wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6],
999291a2b48SSukumar Swaminathan 			    wwn[7], port->node_count);
1000fcf3ce44SJohn Forte 
1001fcf3ce44SJohn Forte 			(void) emlxs_tx_node_flush(port, ndlp, 0, 1, 0);
1002fcf3ce44SJohn Forte 
1003fcf3ce44SJohn Forte 			ndlp->nlp_active = 0;
100482527734SSukumar Swaminathan 
100582527734SSukumar Swaminathan 			/* Break Node/RPI binding */
1006a9800bebSGarrett D'Amore 			if (ndlp->rpip) {
1007a9800bebSGarrett D'Amore 				rpip = ndlp->rpip;
100882527734SSukumar Swaminathan 
1009a9800bebSGarrett D'Amore 				ndlp->rpip = NULL;
1010a9800bebSGarrett D'Amore 				rpip->node = NULL;
1011a9800bebSGarrett D'Amore 
1012a9800bebSGarrett D'Amore 				(void) emlxs_rpi_free_notify(port, rpip);
101382527734SSukumar Swaminathan 			}
101482527734SSukumar Swaminathan 
1015a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, MEM_NLP, (void *)ndlp);
1016fcf3ce44SJohn Forte 
1017fcf3ce44SJohn Forte 			break;
1018fcf3ce44SJohn Forte 		}
1019fcf3ce44SJohn Forte 		prevp = np;
1020fcf3ce44SJohn Forte 		np = np->nlp_list_next;
1021fcf3ce44SJohn Forte 	}
1022fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
1023fcf3ce44SJohn Forte 
1024fcf3ce44SJohn Forte 	return;
1025fcf3ce44SJohn Forte 
102682527734SSukumar Swaminathan } /* emlxs_node_rm() */
1027*8f23e9faSHans Rosenfeld 
1028*8f23e9faSHans Rosenfeld 
1029*8f23e9faSHans Rosenfeld extern void
emlxs_node_throttle_set(emlxs_port_t * port,NODELIST * ndlp)1030*8f23e9faSHans Rosenfeld emlxs_node_throttle_set(emlxs_port_t *port, NODELIST *ndlp)
1031*8f23e9faSHans Rosenfeld {
1032*8f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
1033*8f23e9faSHans Rosenfeld 	emlxs_config_t *cfg = &CFG;
1034*8f23e9faSHans Rosenfeld 	char prop[64];
1035*8f23e9faSHans Rosenfeld 	char buf1[32];
1036*8f23e9faSHans Rosenfeld 	uint32_t throttle;
1037*8f23e9faSHans Rosenfeld 
1038*8f23e9faSHans Rosenfeld 	/* Set global default */
1039*8f23e9faSHans Rosenfeld 	throttle = (ndlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE)?
1040*8f23e9faSHans Rosenfeld 	    cfg[CFG_TGT_DEPTH].current:0;
1041*8f23e9faSHans Rosenfeld 
1042*8f23e9faSHans Rosenfeld 	/* Check per wwpn default */
1043*8f23e9faSHans Rosenfeld 	(void) snprintf(prop, sizeof (prop), "w%s-depth",
1044*8f23e9faSHans Rosenfeld 	    emlxs_wwn_xlate(buf1, sizeof (buf1),
1045*8f23e9faSHans Rosenfeld 	    (uint8_t *)&ndlp->nlp_portname));
1046*8f23e9faSHans Rosenfeld 
1047*8f23e9faSHans Rosenfeld 	throttle = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY,
1048*8f23e9faSHans Rosenfeld 	    (void *)hba->dip, DDI_PROP_DONTPASS, prop, throttle);
1049*8f23e9faSHans Rosenfeld 
1050*8f23e9faSHans Rosenfeld 	/* Check per driver/wwpn default */
1051*8f23e9faSHans Rosenfeld 	(void) snprintf(prop, sizeof (prop), "%s%d-w%s-depth", DRIVER_NAME,
1052*8f23e9faSHans Rosenfeld 	    hba->ddiinst, emlxs_wwn_xlate(buf1, sizeof (buf1),
1053*8f23e9faSHans Rosenfeld 	    (uint8_t *)&ndlp->nlp_portname));
1054*8f23e9faSHans Rosenfeld 
1055*8f23e9faSHans Rosenfeld 	throttle = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY,
1056*8f23e9faSHans Rosenfeld 	    (void *)hba->dip, DDI_PROP_DONTPASS, prop, throttle);
1057*8f23e9faSHans Rosenfeld 
1058*8f23e9faSHans Rosenfeld 	/* Check limit */
1059*8f23e9faSHans Rosenfeld 	throttle = MIN(throttle, MAX_NODE_THROTTLE);
1060*8f23e9faSHans Rosenfeld 
1061*8f23e9faSHans Rosenfeld 	ndlp->io_throttle = throttle;
1062*8f23e9faSHans Rosenfeld 
1063*8f23e9faSHans Rosenfeld 	return;
1064*8f23e9faSHans Rosenfeld 
1065*8f23e9faSHans Rosenfeld } /* emlxs_node_throttle_set() */
1066