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 /*
23*a9800bebSGarrett D'Amore  * Copyright 2010 Emulex.  All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
2782527734SSukumar Swaminathan 
28291a2b48SSukumar Swaminathan #include <emlxs.h>
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_IP_C);
32fcf3ce44SJohn Forte 
33fcf3ce44SJohn Forte 
34fcf3ce44SJohn Forte extern int32_t
3582527734SSukumar Swaminathan emlxs_ip_handle_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
36fcf3ce44SJohn Forte {
37fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
38fcf3ce44SJohn Forte 	IOCB *cmd;
39fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
40fcf3ce44SJohn Forte 	NODELIST *ndlp;
41fcf3ce44SJohn Forte 
42fcf3ce44SJohn Forte 	cmd = &iocbq->iocb;
43fcf3ce44SJohn Forte 
44fcf3ce44SJohn Forte 	HBASTATS.IpEvent++;
45fcf3ce44SJohn Forte 
46fcf3ce44SJohn Forte 	sbp = (emlxs_buf_t *)iocbq->sbp;
47fcf3ce44SJohn Forte 
48fcf3ce44SJohn Forte 	if (!sbp) {
49fcf3ce44SJohn Forte 		HBASTATS.IpStray++;
50fcf3ce44SJohn Forte 
51fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ip_completion_msg,
52fcf3ce44SJohn Forte 		    "cmd=0x%x iotag=0x%x status=0x%x perr=0x%x",
5382527734SSukumar Swaminathan 		    (uint32_t)cmd->ULPCOMMAND, (uint32_t)cmd->ULPIOTAG,
5482527734SSukumar Swaminathan 		    cmd->ULPSTATUS, cmd->un.ulpWord[4]);
55fcf3ce44SJohn Forte 
56fcf3ce44SJohn Forte 		return (EIO);
57fcf3ce44SJohn Forte 	}
58291a2b48SSukumar Swaminathan 
5982527734SSukumar Swaminathan 	if (cp->channelno != hba->channel_ip) {
60fcf3ce44SJohn Forte 		HBASTATS.IpStray++;
61fcf3ce44SJohn Forte 
62fcf3ce44SJohn Forte 		return (0);
63fcf3ce44SJohn Forte 	}
64291a2b48SSukumar Swaminathan 
65fcf3ce44SJohn Forte 	port = sbp->iocbq.port;
66fcf3ce44SJohn Forte 
6782527734SSukumar Swaminathan 	switch (cmd->ULPCOMMAND) {
68fcf3ce44SJohn Forte 		/*
69291a2b48SSukumar Swaminathan 		 * Error: Abnormal BCAST command completion  (Local error)
70fcf3ce44SJohn Forte 		 */
71fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST_CN:
72fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST64_CN:
73fcf3ce44SJohn Forte 
74fcf3ce44SJohn Forte 		HBASTATS.IpBcastCompleted++;
75fcf3ce44SJohn Forte 		HBASTATS.IpBcastError++;
76fcf3ce44SJohn Forte 
77fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
78fcf3ce44SJohn Forte 		    "XMIT BCAST completion error cmd=0x%x status=0x%x "
7982527734SSukumar Swaminathan 		    "[%08x,%08x]", cmd->ULPCOMMAND, cmd->ULPSTATUS,
80fcf3ce44SJohn Forte 		    cmd->un.ulpWord[4], cmd->un.ulpWord[5]);
81fcf3ce44SJohn Forte 
8282527734SSukumar Swaminathan 		emlxs_pkt_complete(sbp, cmd->ULPSTATUS,
83fcf3ce44SJohn Forte 		    cmd->un.grsp.perr.statLocalError, 1);
84fcf3ce44SJohn Forte 
85fcf3ce44SJohn Forte 		break;
86fcf3ce44SJohn Forte 
87fcf3ce44SJohn Forte 		/*
88291a2b48SSukumar Swaminathan 		 * Error: Abnormal XMIT SEQUENCE command completion
89291a2b48SSukumar Swaminathan 		 * (Local error)
90fcf3ce44SJohn Forte 		 */
91fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE_CR:
92fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE64_CR:
93fcf3ce44SJohn Forte 
94fcf3ce44SJohn Forte 		HBASTATS.IpSeqCompleted++;
95fcf3ce44SJohn Forte 		HBASTATS.IpSeqError++;
96fcf3ce44SJohn Forte 
97fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
98291a2b48SSukumar Swaminathan 		    "XMIT SEQUENCE CR completion error: cmd=%x status=0x%x "
9982527734SSukumar Swaminathan 		    "[%08x,%08x]", cmd->ULPCOMMAND, cmd->ULPSTATUS,
100291a2b48SSukumar Swaminathan 		    cmd->un.ulpWord[4], cmd->un.ulpWord[5]);
101fcf3ce44SJohn Forte 
10282527734SSukumar Swaminathan 		emlxs_pkt_complete(sbp, cmd->ULPSTATUS,
103fcf3ce44SJohn Forte 		    cmd->un.grsp.perr.statLocalError, 1);
104fcf3ce44SJohn Forte 
105fcf3ce44SJohn Forte 		break;
106fcf3ce44SJohn Forte 
107fcf3ce44SJohn Forte 		/*
108fcf3ce44SJohn Forte 		 * Normal BCAST completion
109fcf3ce44SJohn Forte 		 */
110fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST_CX:
111fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST64_CX:
112fcf3ce44SJohn Forte 
113fcf3ce44SJohn Forte 		HBASTATS.IpBcastCompleted++;
114fcf3ce44SJohn Forte 		HBASTATS.IpBcastGood++;
115fcf3ce44SJohn Forte 
116fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
117fcf3ce44SJohn Forte 		    "XMIT BCAST CN completion: cmd=%x status=0x%x [%08x,%08x]",
11882527734SSukumar Swaminathan 		    cmd->ULPCOMMAND, cmd->ULPSTATUS, cmd->un.ulpWord[4],
119fcf3ce44SJohn Forte 		    cmd->un.ulpWord[5]);
120fcf3ce44SJohn Forte 
12182527734SSukumar Swaminathan 		emlxs_pkt_complete(sbp, cmd->ULPSTATUS,
122fcf3ce44SJohn Forte 		    cmd->un.grsp.perr.statLocalError, 1);
123fcf3ce44SJohn Forte 
124fcf3ce44SJohn Forte 		break;
125fcf3ce44SJohn Forte 
126fcf3ce44SJohn Forte 		/*
127fcf3ce44SJohn Forte 		 * Normal XMIT SEQUENCE completion
128fcf3ce44SJohn Forte 		 */
129fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE_CX:
130fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE64_CX:
131fcf3ce44SJohn Forte 
132fcf3ce44SJohn Forte 		HBASTATS.IpSeqCompleted++;
133fcf3ce44SJohn Forte 
134fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
135291a2b48SSukumar Swaminathan 		    "XMIT SEQUENCE CR completion: cmd=%x status=0x%x"
13682527734SSukumar Swaminathan 		    "[%08x,%08x]", cmd->ULPCOMMAND, cmd->ULPSTATUS,
137fcf3ce44SJohn Forte 		    cmd->un.ulpWord[4], cmd->un.ulpWord[5]);
138fcf3ce44SJohn Forte 
13982527734SSukumar Swaminathan 		if (cmd->ULPSTATUS) {
140fcf3ce44SJohn Forte 			HBASTATS.IpSeqError++;
141fcf3ce44SJohn Forte 
14282527734SSukumar Swaminathan 			if ((cmd->ULPSTATUS == IOSTAT_LOCAL_REJECT) &&
143fcf3ce44SJohn Forte 			    ((cmd->un.ulpWord[4] & 0xff) == IOERR_NO_XRI)) {
144291a2b48SSukumar Swaminathan 				ndlp = (NODELIST *)sbp->node;
14582527734SSukumar Swaminathan 				if ((cmd->ULPCONTEXT == ndlp->nlp_Xri) &&
14682527734SSukumar Swaminathan 				    !(ndlp->nlp_flag[hba->channel_ip] &
147fcf3ce44SJohn Forte 				    NLP_RPI_XRI)) {
148fcf3ce44SJohn Forte 					ndlp->nlp_Xri = 0;
14982527734SSukumar Swaminathan 					(void) emlxs_create_xri(port, cp, ndlp);
150fcf3ce44SJohn Forte 				}
151fcf3ce44SJohn Forte 			}
152fcf3ce44SJohn Forte 		} else {
153fcf3ce44SJohn Forte 			HBASTATS.IpSeqGood++;
154fcf3ce44SJohn Forte 		}
155fcf3ce44SJohn Forte 
15682527734SSukumar Swaminathan 		emlxs_pkt_complete(sbp, cmd->ULPSTATUS,
157fcf3ce44SJohn Forte 		    cmd->un.grsp.perr.statLocalError, 1);
158fcf3ce44SJohn Forte 
159fcf3ce44SJohn Forte 		break;
160fcf3ce44SJohn Forte 
161fcf3ce44SJohn Forte 	default:
162fcf3ce44SJohn Forte 
163fcf3ce44SJohn Forte 		HBASTATS.IpStray++;
164fcf3ce44SJohn Forte 
165fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_invalid_ip_msg,
16682527734SSukumar Swaminathan 		    "Invalid iocb: cmd=0x%x", cmd->ULPCOMMAND);
167fcf3ce44SJohn Forte 
168fcf3ce44SJohn Forte 		break;
169fcf3ce44SJohn Forte 
17082527734SSukumar Swaminathan 	}	/* switch(cmd->ULPCOMMAND) */
171fcf3ce44SJohn Forte 
172fcf3ce44SJohn Forte 
173fcf3ce44SJohn Forte 	return (0);
174fcf3ce44SJohn Forte 
17582527734SSukumar Swaminathan } /* emlxs_ip_handle_event() */
176fcf3ce44SJohn Forte 
177fcf3ce44SJohn Forte 
178fcf3ce44SJohn Forte extern int32_t
17982527734SSukumar Swaminathan emlxs_ip_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
180fcf3ce44SJohn Forte     MATCHMAP *mp, uint32_t size)
181fcf3ce44SJohn Forte {
182fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
183fcf3ce44SJohn Forte 	fc_unsol_buf_t *ubp;
184fcf3ce44SJohn Forte 	IOCB *cmd;
185fcf3ce44SJohn Forte 	NETHDR *nd;
186fcf3ce44SJohn Forte 	NODELIST *ndlp;
187fcf3ce44SJohn Forte 	uint8_t *mac;
188fcf3ce44SJohn Forte 	emlxs_ub_priv_t *ub_priv;
189fcf3ce44SJohn Forte 	uint32_t sid;
190fcf3ce44SJohn Forte 	uint32_t i;
191fcf3ce44SJohn Forte 	uint32_t IpDropped = 1;
192fcf3ce44SJohn Forte 	uint32_t IpBcastReceived = 0;
193fcf3ce44SJohn Forte 	uint32_t IpSeqReceived = 0;
194fcf3ce44SJohn Forte 
195fcf3ce44SJohn Forte 	cmd = &iocbq->iocb;
196fcf3ce44SJohn Forte 	ubp = NULL;
197fcf3ce44SJohn Forte 
198fcf3ce44SJohn Forte 	for (i = 0; i < MAX_VPORTS; i++) {
199fcf3ce44SJohn Forte 		port = &VPORT(i);
200fcf3ce44SJohn Forte 
201fcf3ce44SJohn Forte 		if (!(port->flag & EMLXS_PORT_BOUND) ||
202fcf3ce44SJohn Forte 		    !(port->flag & EMLXS_PORT_IP_UP)) {
203fcf3ce44SJohn Forte 			continue;
204fcf3ce44SJohn Forte 		}
205fcf3ce44SJohn Forte 
206291a2b48SSukumar Swaminathan 		ubp =
207291a2b48SSukumar Swaminathan 		    (fc_unsol_buf_t *)emlxs_ub_get(port, size,
208291a2b48SSukumar Swaminathan 		    FC_TYPE_IS8802_SNAP, 0);
209fcf3ce44SJohn Forte 
210291a2b48SSukumar Swaminathan 		if (!ubp) {
211fcf3ce44SJohn Forte 			/* Theoretically we should never get here. */
212291a2b48SSukumar Swaminathan 			/* There should be one DMA buffer for every ub */
213291a2b48SSukumar Swaminathan 			/* buffer. If we are out of ub buffers */
214fcf3ce44SJohn Forte 			/* then some how this matching has been corrupted */
215fcf3ce44SJohn Forte 
216fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ip_dropped_msg,
217fcf3ce44SJohn Forte 			    "Buffer not found. paddr=%lx",
21882527734SSukumar Swaminathan 			    PADDR(cmd->un.cont64[0].addrHigh,
219fcf3ce44SJohn Forte 			    cmd->un.cont64[0].addrLow));
220fcf3ce44SJohn Forte 
221fcf3ce44SJohn Forte 			continue;
222fcf3ce44SJohn Forte 		}
223291a2b48SSukumar Swaminathan 
224fcf3ce44SJohn Forte 		bcopy(mp->virt, ubp->ub_buffer, size);
225fcf3ce44SJohn Forte 
226fcf3ce44SJohn Forte 		ub_priv = ubp->ub_fca_private;
227291a2b48SSukumar Swaminathan 		nd = (NETHDR *)ubp->ub_buffer;
228fcf3ce44SJohn Forte 		mac = nd->fc_srcname.IEEE;
229fcf3ce44SJohn Forte 		ndlp = emlxs_node_find_mac(port, mac);
230fcf3ce44SJohn Forte 
231fcf3ce44SJohn Forte 		if (ndlp) {
232fcf3ce44SJohn Forte 			sid = ndlp->nlp_DID;
233fcf3ce44SJohn Forte 
234fcf3ce44SJohn Forte 			if ((ndlp->nlp_Xri == 0) &&
23582527734SSukumar Swaminathan 			    !(ndlp->nlp_flag[hba->channel_ip] & NLP_RPI_XRI)) {
23682527734SSukumar Swaminathan 				(void) emlxs_create_xri(port, cp, ndlp);
237fcf3ce44SJohn Forte 			}
238fcf3ce44SJohn Forte 		}
239291a2b48SSukumar Swaminathan 
240fcf3ce44SJohn Forte 		/*
241291a2b48SSukumar Swaminathan 		 * If no node is found, then check if this is a
242291a2b48SSukumar Swaminathan 		 * broadcast frame
243fcf3ce44SJohn Forte 		 */
244fcf3ce44SJohn Forte 		else if (cmd->un.xrseq.w5.hcsw.Fctl & BC) {
245fcf3ce44SJohn Forte 			sid = cmd->un.ulpWord[4] & 0x00ffffff;
246291a2b48SSukumar Swaminathan 		}
247291a2b48SSukumar Swaminathan 
248291a2b48SSukumar Swaminathan 		else {
249291a2b48SSukumar Swaminathan 			/* We have to drop this frame because we do not have */
250291a2b48SSukumar Swaminathan 			/* the S_ID of the request */
251fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ip_dropped_msg,
252fcf3ce44SJohn Forte 			    "Node not found. mac=%02x%02x%02x%02x%02x%02x",
253fcf3ce44SJohn Forte 			    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
254fcf3ce44SJohn Forte 
255*a9800bebSGarrett D'Amore 			(void) emlxs_fca_ub_release((opaque_t)port, 1,
256fcf3ce44SJohn Forte 			    &ubp->ub_token);
257fcf3ce44SJohn Forte 
258fcf3ce44SJohn Forte 			continue;
259fcf3ce44SJohn Forte 		}
260fcf3ce44SJohn Forte 
261fcf3ce44SJohn Forte 		if (cmd->un.xrseq.w5.hcsw.Fctl & BC) {
262fcf3ce44SJohn Forte 			IpBcastReceived++;
263fcf3ce44SJohn Forte 		} else {
264fcf3ce44SJohn Forte 			IpSeqReceived++;
265fcf3ce44SJohn Forte 		}
266fcf3ce44SJohn Forte 
267fcf3ce44SJohn Forte 		/*
268fcf3ce44SJohn Forte 		 * Setup frame header
269fcf3ce44SJohn Forte 		 */
270fcf3ce44SJohn Forte 		ubp->ub_frame.r_ctl = cmd->un.xrseq.w5.hcsw.Rctl;
271fcf3ce44SJohn Forte 		ubp->ub_frame.type = cmd->un.xrseq.w5.hcsw.Type;
272fcf3ce44SJohn Forte 		ubp->ub_frame.s_id = sid;
273fcf3ce44SJohn Forte 		ubp->ub_frame.ox_id = ub_priv->token;
27482527734SSukumar Swaminathan 		ubp->ub_frame.rx_id = cmd->ULPCONTEXT;
275fcf3ce44SJohn Forte 		ubp->ub_class = FC_TRAN_CLASS3;
276fcf3ce44SJohn Forte 
277fcf3ce44SJohn Forte 		emlxs_ub_callback(port, ubp);
278fcf3ce44SJohn Forte 		IpDropped = 0;
279fcf3ce44SJohn Forte 	}
280fcf3ce44SJohn Forte 	port = &PPORT;
281fcf3ce44SJohn Forte 
282fcf3ce44SJohn Forte out:
283fcf3ce44SJohn Forte 
284fcf3ce44SJohn Forte 	if (IpDropped) {
285fcf3ce44SJohn Forte 		HBASTATS.IpDropped++;
286fcf3ce44SJohn Forte 	}
287291a2b48SSukumar Swaminathan 
288fcf3ce44SJohn Forte 	if (IpBcastReceived) {
289fcf3ce44SJohn Forte 		HBASTATS.IpBcastReceived++;
290fcf3ce44SJohn Forte 	}
291291a2b48SSukumar Swaminathan 
292fcf3ce44SJohn Forte 	if (IpSeqReceived) {
293fcf3ce44SJohn Forte 		HBASTATS.IpSeqReceived++;
294fcf3ce44SJohn Forte 	}
295291a2b48SSukumar Swaminathan 
296fcf3ce44SJohn Forte 	return (0);
297fcf3ce44SJohn Forte 
29882527734SSukumar Swaminathan } /* emlxs_ip_handle_unsol_req() */
299fcf3ce44SJohn Forte 
300fcf3ce44SJohn Forte 
301fcf3ce44SJohn Forte extern int32_t
30282527734SSukumar Swaminathan emlxs_ip_handle_rcv_seq_list(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
303fcf3ce44SJohn Forte {
304fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
305fcf3ce44SJohn Forte 	IOCB *cmd;
306fcf3ce44SJohn Forte 	uint64_t bdeAddr;
307fcf3ce44SJohn Forte 	MATCHMAP *mp = NULL;
308fcf3ce44SJohn Forte 	HBQE_t *hbqE;
309fcf3ce44SJohn Forte 	uint32_t hbq_id;
310fcf3ce44SJohn Forte 	uint32_t hbqe_tag;
31182527734SSukumar Swaminathan 	RING *rp;
312fcf3ce44SJohn Forte 
313fcf3ce44SJohn Forte 	/*
314fcf3ce44SJohn Forte 	 * No action required for now.
315fcf3ce44SJohn Forte 	 */
316fcf3ce44SJohn Forte 	cmd = &iocbq->iocb;
31782527734SSukumar Swaminathan 	rp = &hba->sli.sli3.ring[cp->channelno];
318fcf3ce44SJohn Forte 
319fcf3ce44SJohn Forte 	HBASTATS.IpRcvEvent++;
320fcf3ce44SJohn Forte 
321fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
322fcf3ce44SJohn Forte 	    "Receive sequence list: cmd=0x%x iotag=0x%x status=0x%x "
32382527734SSukumar Swaminathan 	    "w4=0x%x channelno=0x%x", cmd->ULPCOMMAND, cmd->ULPIOTAG,
32482527734SSukumar Swaminathan 	    cmd->ULPSTATUS, cmd->un.ulpWord[4], cp->channelno);
325fcf3ce44SJohn Forte 
32682527734SSukumar Swaminathan 	if (cmd->ULPSTATUS) {
327fcf3ce44SJohn Forte 		goto out;
328fcf3ce44SJohn Forte 	}
32982527734SSukumar Swaminathan 
330fcf3ce44SJohn Forte 	hbqE = (HBQE_t *)&iocbq->iocb;
331fcf3ce44SJohn Forte 	hbq_id = hbqE->unt.ext.HBQ_tag;
332fcf3ce44SJohn Forte 	hbqe_tag = hbqE->unt.ext.HBQE_tag;
333fcf3ce44SJohn Forte 
334fcf3ce44SJohn Forte 	if (hba->flag & FC_HBQ_ENABLED) {
335fcf3ce44SJohn Forte 		HBQ_INIT_t *hbq;
336fcf3ce44SJohn Forte 
33782527734SSukumar Swaminathan 		hbq = &hba->sli.sli3.hbq_table[hbq_id];
338fcf3ce44SJohn Forte 
339fcf3ce44SJohn Forte 		HBASTATS.IpUbPosted--;
340fcf3ce44SJohn Forte 
341fcf3ce44SJohn Forte 		if (hbqe_tag >= hbq->HBQ_numEntries) {
342fcf3ce44SJohn Forte 			mp = NULL;
343fcf3ce44SJohn Forte 		} else {
34482527734SSukumar Swaminathan 			mp = hba->sli.sli3.hbq_table
34582527734SSukumar Swaminathan 			    [hbq_id].HBQ_PostBufs[hbqe_tag];
346fcf3ce44SJohn Forte 		}
34782527734SSukumar Swaminathan 	} else {
348fcf3ce44SJohn Forte 		/* Check for valid buffer */
349fcf3ce44SJohn Forte 		if (!(cmd->un.cont64[0].tus.f.bdeFlags & BUFF_TYPE_INVALID)) {
350291a2b48SSukumar Swaminathan 			bdeAddr =
35182527734SSukumar Swaminathan 			    PADDR(cmd->un.cont64[0].addrHigh,
352fcf3ce44SJohn Forte 			    cmd->un.cont64[0].addrLow);
353fcf3ce44SJohn Forte 			mp = emlxs_mem_get_vaddr(hba, rp, bdeAddr);
354fcf3ce44SJohn Forte 		}
355fcf3ce44SJohn Forte 	}
356fcf3ce44SJohn Forte 
357fcf3ce44SJohn Forte out:
358fcf3ce44SJohn Forte 
359fcf3ce44SJohn Forte 	if (hba->flag & FC_HBQ_ENABLED) {
360fcf3ce44SJohn Forte 		emlxs_update_HBQ_index(hba, hbq_id);
36182527734SSukumar Swaminathan 	} else {
362fcf3ce44SJohn Forte 		if (mp) {
363*a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, MEM_IPBUF, (void *)mp);
364fcf3ce44SJohn Forte 		}
365fcf3ce44SJohn Forte 		(void) emlxs_post_buffer(hba, rp, 1);
366fcf3ce44SJohn Forte 	}
367fcf3ce44SJohn Forte 
368fcf3ce44SJohn Forte 	HBASTATS.IpDropped++;
369fcf3ce44SJohn Forte 
370fcf3ce44SJohn Forte 	return (0);
371fcf3ce44SJohn Forte 
37282527734SSukumar Swaminathan } /* emlxs_ip_handle_rcv_seq_list() */
373fcf3ce44SJohn Forte 
374fcf3ce44SJohn Forte 
375fcf3ce44SJohn Forte 
376fcf3ce44SJohn Forte /*
377fcf3ce44SJohn Forte  * Process a create_xri command completion.
378fcf3ce44SJohn Forte  */
379fcf3ce44SJohn Forte extern int32_t
38082527734SSukumar Swaminathan emlxs_handle_create_xri(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
381fcf3ce44SJohn Forte {
382fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
383fcf3ce44SJohn Forte 	IOCB *cmd;
384fcf3ce44SJohn Forte 	NODELIST *ndlp;
385fcf3ce44SJohn Forte 	fc_packet_t *pkt;
386fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
387fcf3ce44SJohn Forte 
388fcf3ce44SJohn Forte 	cmd = &iocbq->iocb;
389fcf3ce44SJohn Forte 
390fcf3ce44SJohn Forte 	sbp = (emlxs_buf_t *)iocbq->sbp;
391fcf3ce44SJohn Forte 
392fcf3ce44SJohn Forte 	if (!sbp) {
393fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ip_completion_msg,
394fcf3ce44SJohn Forte 		    "create_xri: cmd=0x%x iotag=0x%x status=0x%x w4=0x%x",
39582527734SSukumar Swaminathan 		    cmd->ULPCOMMAND, cmd->ULPIOTAG, cmd->ULPSTATUS,
396fcf3ce44SJohn Forte 		    cmd->un.ulpWord[4]);
397fcf3ce44SJohn Forte 
398fcf3ce44SJohn Forte 		return (EIO);
399fcf3ce44SJohn Forte 	}
400291a2b48SSukumar Swaminathan 
401fcf3ce44SJohn Forte 	/* check for first xmit completion in sequence */
402fcf3ce44SJohn Forte 	ndlp = (NODELIST *)sbp->node;
403fcf3ce44SJohn Forte 
40482527734SSukumar Swaminathan 	if (cmd->ULPSTATUS) {
405fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_bad_ip_completion_msg,
406fcf3ce44SJohn Forte 		    "create_xri: cmd=0x%x iotag=0x%x status=0x%x w4=0x%x",
40782527734SSukumar Swaminathan 		    cmd->ULPCOMMAND, cmd->ULPIOTAG, cmd->ULPSTATUS,
408fcf3ce44SJohn Forte 		    cmd->un.ulpWord[4]);
409fcf3ce44SJohn Forte 
41082527734SSukumar Swaminathan 		mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
41182527734SSukumar Swaminathan 		ndlp->nlp_flag[cp->channelno] &= ~NLP_RPI_XRI;
41282527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
413fcf3ce44SJohn Forte 
414fcf3ce44SJohn Forte 		return (EIO);
415fcf3ce44SJohn Forte 	}
416291a2b48SSukumar Swaminathan 
41782527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
41882527734SSukumar Swaminathan 	ndlp->nlp_Xri = cmd->ULPCONTEXT;
41982527734SSukumar Swaminathan 	ndlp->nlp_flag[cp->channelno] &= ~NLP_RPI_XRI;
42082527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
421fcf3ce44SJohn Forte 
422fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
423fcf3ce44SJohn Forte 	    "create_xri completed: DID=0x%x Xri=0x%x iotag=0x%x",
42482527734SSukumar Swaminathan 	    ndlp->nlp_DID, ndlp->nlp_Xri, cmd->ULPIOTAG);
425fcf3ce44SJohn Forte 
426fcf3ce44SJohn Forte 	pkt = sbp->pkt;
427fcf3ce44SJohn Forte 	emlxs_pkt_free(pkt);
428fcf3ce44SJohn Forte 
429fcf3ce44SJohn Forte 	return (0);
430fcf3ce44SJohn Forte 
43182527734SSukumar Swaminathan } /* emlxs_handle_create_xri()  */
432fcf3ce44SJohn Forte 
433fcf3ce44SJohn Forte 
434fcf3ce44SJohn Forte /*
435291a2b48SSukumar Swaminathan  * Issue an iocb command to create an exchange with the remote Nport
436291a2b48SSukumar Swaminathan  * specified by the NODELIST entry.
437fcf3ce44SJohn Forte  */
438fcf3ce44SJohn Forte extern int32_t
43982527734SSukumar Swaminathan emlxs_create_xri(emlxs_port_t *port, CHANNEL *cp, NODELIST *ndlp)
440fcf3ce44SJohn Forte {
441fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
442fcf3ce44SJohn Forte 	IOCB *icmd;
443fcf3ce44SJohn Forte 	IOCBQ *iocbq;
444fcf3ce44SJohn Forte 	fc_packet_t *pkt;
445fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
446fcf3ce44SJohn Forte 	uint16_t iotag;
447fcf3ce44SJohn Forte 
448fcf3ce44SJohn Forte 	/* Check if an XRI has already been requested */
44982527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
45082527734SSukumar Swaminathan 	if (ndlp->nlp_Xri != 0 ||
45182527734SSukumar Swaminathan 	    (ndlp->nlp_flag[cp->channelno] & NLP_RPI_XRI)) {
45282527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
453fcf3ce44SJohn Forte 		return (0);
454fcf3ce44SJohn Forte 	}
45582527734SSukumar Swaminathan 	ndlp->nlp_flag[cp->channelno] |= NLP_RPI_XRI;
45682527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
457fcf3ce44SJohn Forte 
458fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, 0, 0, 0, KM_NOSLEEP))) {
459fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
460fcf3ce44SJohn Forte 		    "create_xri failed: Unable to allocate pkt. did=0x%x",
461fcf3ce44SJohn Forte 		    ndlp->nlp_DID);
462fcf3ce44SJohn Forte 
463fcf3ce44SJohn Forte 		goto fail;
464fcf3ce44SJohn Forte 	}
465291a2b48SSukumar Swaminathan 
466fcf3ce44SJohn Forte 	sbp = (emlxs_buf_t *)pkt->pkt_fca_private;
467fcf3ce44SJohn Forte 	iocbq = &sbp->iocbq;
468fcf3ce44SJohn Forte 
46982527734SSukumar Swaminathan 	/* Clear the PACKET_ULP_OWNED flag */
47082527734SSukumar Swaminathan 	sbp->pkt_flags &= ~PACKET_ULP_OWNED;
47182527734SSukumar Swaminathan 
472fcf3ce44SJohn Forte 	/* Get the iotag by registering the packet */
47382527734SSukumar Swaminathan 	iotag = emlxs_register_pkt(cp, sbp);
474fcf3ce44SJohn Forte 
475fcf3ce44SJohn Forte 	if (!iotag) {
476fcf3ce44SJohn Forte 		/*
477fcf3ce44SJohn Forte 		 * No more command slots available, retry later
478fcf3ce44SJohn Forte 		 */
479fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
480fcf3ce44SJohn Forte 
481fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
482fcf3ce44SJohn Forte 		    "create_xri failed: Unable to allocate IOTAG. did=0x%x",
483fcf3ce44SJohn Forte 		    ndlp->nlp_DID);
484fcf3ce44SJohn Forte 
485fcf3ce44SJohn Forte 		goto fail;
486fcf3ce44SJohn Forte 	}
487291a2b48SSukumar Swaminathan 
488fcf3ce44SJohn Forte 	icmd = &iocbq->iocb;
48982527734SSukumar Swaminathan 	icmd->ULPIOTAG = iotag;
49082527734SSukumar Swaminathan 	icmd->ULPCONTEXT = ndlp->nlp_Rpi;
49182527734SSukumar Swaminathan 	icmd->ULPLE = 1;
49282527734SSukumar Swaminathan 	icmd->ULPCOMMAND = CMD_CREATE_XRI_CR;
49382527734SSukumar Swaminathan 	icmd->ULPOWNER = OWN_CHIP;
494fcf3ce44SJohn Forte 
495fcf3ce44SJohn Forte 	/* Initalize iocbq */
496fcf3ce44SJohn Forte 	iocbq->port = (void *)port;
497fcf3ce44SJohn Forte 	iocbq->node = (void *)ndlp;
49882527734SSukumar Swaminathan 	iocbq->channel = (void *)cp;
499fcf3ce44SJohn Forte 
500fcf3ce44SJohn Forte 	mutex_enter(&sbp->mtx);
501fcf3ce44SJohn Forte 	sbp->node = (void *)ndlp;
50282527734SSukumar Swaminathan 	sbp->channel = cp;
503fcf3ce44SJohn Forte 	mutex_exit(&sbp->mtx);
504fcf3ce44SJohn Forte 
505fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
506291a2b48SSukumar Swaminathan 	    "create_xri sent: DID=0x%x Xri=0x%x iotag=0x%x", ndlp->nlp_DID,
507291a2b48SSukumar Swaminathan 	    ndlp->nlp_Xri, iotag);
508fcf3ce44SJohn Forte 
50982527734SSukumar Swaminathan 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
510fcf3ce44SJohn Forte 
511fcf3ce44SJohn Forte 	return (0);
512fcf3ce44SJohn Forte 
513fcf3ce44SJohn Forte fail:
514fcf3ce44SJohn Forte 
515fcf3ce44SJohn Forte 	/* Clear the XRI flag */
51682527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
51782527734SSukumar Swaminathan 	ndlp->nlp_flag[cp->channelno] &= ~NLP_RPI_XRI;
51882527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
519fcf3ce44SJohn Forte 
520fcf3ce44SJohn Forte 	return (1);
521fcf3ce44SJohn Forte 
52282527734SSukumar Swaminathan } /* emlxs_create_xri() */
523