1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte 
22*fcf3ce44SJohn Forte /*
23*fcf3ce44SJohn Forte  * Copyright 2008 Emulex.  All rights reserved.
24*fcf3ce44SJohn Forte  * Use is subject to License terms.
25*fcf3ce44SJohn Forte  */
26*fcf3ce44SJohn Forte 
27*fcf3ce44SJohn Forte 
28*fcf3ce44SJohn Forte #include "emlxs.h"
29*fcf3ce44SJohn Forte 
30*fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31*fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_IP_C);
32*fcf3ce44SJohn Forte 
33*fcf3ce44SJohn Forte 
34*fcf3ce44SJohn Forte extern int32_t
35*fcf3ce44SJohn Forte emlxs_ip_handle_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq)
36*fcf3ce44SJohn Forte {
37*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
38*fcf3ce44SJohn Forte 	IOCB *cmd;
39*fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
40*fcf3ce44SJohn Forte 	NODELIST *ndlp;
41*fcf3ce44SJohn Forte 
42*fcf3ce44SJohn Forte 	cmd = &iocbq->iocb;
43*fcf3ce44SJohn Forte 
44*fcf3ce44SJohn Forte 	HBASTATS.IpEvent++;
45*fcf3ce44SJohn Forte 
46*fcf3ce44SJohn Forte 	sbp = (emlxs_buf_t *)iocbq->sbp;
47*fcf3ce44SJohn Forte 
48*fcf3ce44SJohn Forte 	if (!sbp) {
49*fcf3ce44SJohn Forte 		HBASTATS.IpStray++;
50*fcf3ce44SJohn Forte 
51*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ip_completion_msg,
52*fcf3ce44SJohn Forte 		    "cmd=0x%x iotag=0x%x status=0x%x perr=0x%x",
53*fcf3ce44SJohn Forte 		    (uint32_t)cmd->ulpCommand, (uint32_t)cmd->ulpIoTag,
54*fcf3ce44SJohn Forte 		    cmd->ulpStatus, cmd->un.ulpWord[4]);
55*fcf3ce44SJohn Forte 
56*fcf3ce44SJohn Forte 		return (EIO);
57*fcf3ce44SJohn Forte 	}
58*fcf3ce44SJohn Forte 	if (rp->ringno != FC_IP_RING) {
59*fcf3ce44SJohn Forte 		HBASTATS.IpStray++;
60*fcf3ce44SJohn Forte 
61*fcf3ce44SJohn Forte 		return (0);
62*fcf3ce44SJohn Forte 	}
63*fcf3ce44SJohn Forte 	port = sbp->iocbq.port;
64*fcf3ce44SJohn Forte 
65*fcf3ce44SJohn Forte 	switch (cmd->ulpCommand) {
66*fcf3ce44SJohn Forte 		/*
67*fcf3ce44SJohn Forte 		 *  Error:  Abnormal BCAST (Local error)
68*fcf3ce44SJohn Forte 		 */
69*fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST_CN:
70*fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST64_CN:
71*fcf3ce44SJohn Forte 
72*fcf3ce44SJohn Forte 		HBASTATS.IpBcastCompleted++;
73*fcf3ce44SJohn Forte 		HBASTATS.IpBcastError++;
74*fcf3ce44SJohn Forte 
75*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
76*fcf3ce44SJohn Forte 		    "XMIT BCAST completion error cmd=0x%x status=0x%x "
77*fcf3ce44SJohn Forte 		    "[%08x,%08x]", cmd->ulpCommand, cmd->ulpStatus,
78*fcf3ce44SJohn Forte 		    cmd->un.ulpWord[4], cmd->un.ulpWord[5]);
79*fcf3ce44SJohn Forte 
80*fcf3ce44SJohn Forte 		emlxs_pkt_complete(sbp, cmd->ulpStatus,
81*fcf3ce44SJohn Forte 		    cmd->un.grsp.perr.statLocalError, 1);
82*fcf3ce44SJohn Forte 
83*fcf3ce44SJohn Forte 		break;
84*fcf3ce44SJohn Forte 
85*fcf3ce44SJohn Forte 		/*
86*fcf3ce44SJohn Forte 		 *  Error:  Abnormal XMIT SEQUENCE (Local error)
87*fcf3ce44SJohn Forte 		 */
88*fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE_CR:
89*fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE64_CR:
90*fcf3ce44SJohn Forte 
91*fcf3ce44SJohn Forte 		HBASTATS.IpSeqCompleted++;
92*fcf3ce44SJohn Forte 		HBASTATS.IpSeqError++;
93*fcf3ce44SJohn Forte 
94*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
95*fcf3ce44SJohn Forte 		    "XMIT SEQUENCE CR completion error: "
96*fcf3ce44SJohn Forte 		    "cmd=%x status=0x%x [%08x,%08x]", cmd->ulpCommand,
97*fcf3ce44SJohn Forte 		    cmd->ulpStatus, cmd->un.ulpWord[4], cmd->un.ulpWord[5]);
98*fcf3ce44SJohn Forte 
99*fcf3ce44SJohn Forte 		emlxs_pkt_complete(sbp, cmd->ulpStatus,
100*fcf3ce44SJohn Forte 		    cmd->un.grsp.perr.statLocalError, 1);
101*fcf3ce44SJohn Forte 
102*fcf3ce44SJohn Forte 		break;
103*fcf3ce44SJohn Forte 
104*fcf3ce44SJohn Forte 		/*
105*fcf3ce44SJohn Forte 		 * Normal BCAST completion
106*fcf3ce44SJohn Forte 		 */
107*fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST_CX:
108*fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST64_CX:
109*fcf3ce44SJohn Forte 
110*fcf3ce44SJohn Forte 		HBASTATS.IpBcastCompleted++;
111*fcf3ce44SJohn Forte 		HBASTATS.IpBcastGood++;
112*fcf3ce44SJohn Forte 
113*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
114*fcf3ce44SJohn Forte 		    "XMIT BCAST CN completion: cmd=%x status=0x%x [%08x,%08x]",
115*fcf3ce44SJohn Forte 		    cmd->ulpCommand, cmd->ulpStatus, cmd->un.ulpWord[4],
116*fcf3ce44SJohn Forte 		    cmd->un.ulpWord[5]);
117*fcf3ce44SJohn Forte 
118*fcf3ce44SJohn Forte 		emlxs_pkt_complete(sbp, cmd->ulpStatus,
119*fcf3ce44SJohn Forte 		    cmd->un.grsp.perr.statLocalError, 1);
120*fcf3ce44SJohn Forte 
121*fcf3ce44SJohn Forte 		break;
122*fcf3ce44SJohn Forte 
123*fcf3ce44SJohn Forte 		/*
124*fcf3ce44SJohn Forte 		 * Normal XMIT SEQUENCE completion
125*fcf3ce44SJohn Forte 		 */
126*fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE_CX:
127*fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE64_CX:
128*fcf3ce44SJohn Forte 
129*fcf3ce44SJohn Forte 		HBASTATS.IpSeqCompleted++;
130*fcf3ce44SJohn Forte 
131*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
132*fcf3ce44SJohn Forte 		    "XMIT SEQUENCE CR completion: cmd=%x status=0x%x "
133*fcf3ce44SJohn Forte 		    "[%08x,%08x]", cmd->ulpCommand, cmd->ulpStatus,
134*fcf3ce44SJohn Forte 		    cmd->un.ulpWord[4], cmd->un.ulpWord[5]);
135*fcf3ce44SJohn Forte 
136*fcf3ce44SJohn Forte 		if (cmd->ulpStatus) {
137*fcf3ce44SJohn Forte 			HBASTATS.IpSeqError++;
138*fcf3ce44SJohn Forte 
139*fcf3ce44SJohn Forte 			if ((cmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
140*fcf3ce44SJohn Forte 			    ((cmd->un.ulpWord[4] & 0xff) == IOERR_NO_XRI)) {
141*fcf3ce44SJohn Forte 				ndlp = (NODELIST *) sbp->node;
142*fcf3ce44SJohn Forte 				if ((cmd->ulpContext == ndlp->nlp_Xri) &&
143*fcf3ce44SJohn Forte 				    !(ndlp->nlp_flag[FC_IP_RING] &
144*fcf3ce44SJohn Forte 				    NLP_RPI_XRI)) {
145*fcf3ce44SJohn Forte 					ndlp->nlp_Xri = 0;
146*fcf3ce44SJohn Forte 					(void) emlxs_create_xri(port, rp, ndlp);
147*fcf3ce44SJohn Forte 				}
148*fcf3ce44SJohn Forte 			}
149*fcf3ce44SJohn Forte 		} else {
150*fcf3ce44SJohn Forte 			HBASTATS.IpSeqGood++;
151*fcf3ce44SJohn Forte 		}
152*fcf3ce44SJohn Forte 
153*fcf3ce44SJohn Forte 		emlxs_pkt_complete(sbp, cmd->ulpStatus,
154*fcf3ce44SJohn Forte 		    cmd->un.grsp.perr.statLocalError, 1);
155*fcf3ce44SJohn Forte 
156*fcf3ce44SJohn Forte 		break;
157*fcf3ce44SJohn Forte 
158*fcf3ce44SJohn Forte 	default:
159*fcf3ce44SJohn Forte 
160*fcf3ce44SJohn Forte 		HBASTATS.IpStray++;
161*fcf3ce44SJohn Forte 
162*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_invalid_ip_msg,
163*fcf3ce44SJohn Forte 		    "Invalid iocb: cmd=0x%x", cmd->ulpCommand);
164*fcf3ce44SJohn Forte 
165*fcf3ce44SJohn Forte 		break;
166*fcf3ce44SJohn Forte 
167*fcf3ce44SJohn Forte 	}	/* switch(cmd->ulpCommand) */
168*fcf3ce44SJohn Forte 
169*fcf3ce44SJohn Forte 
170*fcf3ce44SJohn Forte 	return (0);
171*fcf3ce44SJohn Forte 
172*fcf3ce44SJohn Forte } /* emlxs_ip_handle_event() */
173*fcf3ce44SJohn Forte 
174*fcf3ce44SJohn Forte 
175*fcf3ce44SJohn Forte extern int32_t
176*fcf3ce44SJohn Forte emlxs_ip_handle_unsol_req(emlxs_port_t *port, RING *rp, IOCBQ *iocbq,
177*fcf3ce44SJohn Forte     MATCHMAP *mp, uint32_t size)
178*fcf3ce44SJohn Forte {
179*fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
180*fcf3ce44SJohn Forte 	fc_unsol_buf_t *ubp;
181*fcf3ce44SJohn Forte 	IOCB *cmd;
182*fcf3ce44SJohn Forte 	NETHDR *nd;
183*fcf3ce44SJohn Forte 	NODELIST *ndlp;
184*fcf3ce44SJohn Forte 	uint8_t *mac;
185*fcf3ce44SJohn Forte 	emlxs_ub_priv_t *ub_priv;
186*fcf3ce44SJohn Forte 	uint32_t sid;
187*fcf3ce44SJohn Forte 	uint32_t i;
188*fcf3ce44SJohn Forte 	uint32_t IpDropped = 1;
189*fcf3ce44SJohn Forte 	uint32_t IpBcastReceived = 0;
190*fcf3ce44SJohn Forte 	uint32_t IpSeqReceived = 0;
191*fcf3ce44SJohn Forte 
192*fcf3ce44SJohn Forte 	cmd = &iocbq->iocb;
193*fcf3ce44SJohn Forte 	ubp = NULL;
194*fcf3ce44SJohn Forte 
195*fcf3ce44SJohn Forte 	for (i = 0; i < MAX_VPORTS; i++) {
196*fcf3ce44SJohn Forte 		port = &VPORT(i);
197*fcf3ce44SJohn Forte 
198*fcf3ce44SJohn Forte 		if (!(port->flag & EMLXS_PORT_BOUND) ||
199*fcf3ce44SJohn Forte 		    !(port->flag & EMLXS_PORT_IP_UP)) {
200*fcf3ce44SJohn Forte 			continue;
201*fcf3ce44SJohn Forte 		}
202*fcf3ce44SJohn Forte 		ubp = (fc_unsol_buf_t *)
203*fcf3ce44SJohn Forte 		    emlxs_ub_get(port, size, FC_TYPE_IS8802_SNAP, 0);
204*fcf3ce44SJohn Forte 
205*fcf3ce44SJohn Forte 		if (!ubp) {
206*fcf3ce44SJohn Forte 
207*fcf3ce44SJohn Forte 			/* Theoretically we should never get here. */
208*fcf3ce44SJohn Forte 			/*
209*fcf3ce44SJohn Forte 			 * There should be one DMA buffer for every ub
210*fcf3ce44SJohn Forte 			 * buffer.  If we are out of ub buffers
211*fcf3ce44SJohn Forte 			 */
212*fcf3ce44SJohn Forte 			/* then some how this matching has been corrupted */
213*fcf3ce44SJohn Forte 
214*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ip_dropped_msg,
215*fcf3ce44SJohn Forte 			    "Buffer not found. paddr=%lx",
216*fcf3ce44SJohn Forte 			    getPaddr(cmd->un.cont64[0].addrHigh,
217*fcf3ce44SJohn Forte 			    cmd->un.cont64[0].addrLow));
218*fcf3ce44SJohn Forte 
219*fcf3ce44SJohn Forte 			continue;
220*fcf3ce44SJohn Forte 		}
221*fcf3ce44SJohn Forte 		bcopy(mp->virt, ubp->ub_buffer, size);
222*fcf3ce44SJohn Forte 
223*fcf3ce44SJohn Forte 		ub_priv = ubp->ub_fca_private;
224*fcf3ce44SJohn Forte 		nd = (NETHDR *) ubp->ub_buffer;
225*fcf3ce44SJohn Forte 		mac = nd->fc_srcname.IEEE;
226*fcf3ce44SJohn Forte 		ndlp = emlxs_node_find_mac(port, mac);
227*fcf3ce44SJohn Forte 
228*fcf3ce44SJohn Forte 		if (ndlp) {
229*fcf3ce44SJohn Forte 			sid = ndlp->nlp_DID;
230*fcf3ce44SJohn Forte 
231*fcf3ce44SJohn Forte 			if ((ndlp->nlp_Xri == 0) &&
232*fcf3ce44SJohn Forte 			    !(ndlp->nlp_flag[FC_IP_RING] & NLP_RPI_XRI)) {
233*fcf3ce44SJohn Forte 				(void) emlxs_create_xri(port, rp, ndlp);
234*fcf3ce44SJohn Forte 			}
235*fcf3ce44SJohn Forte 		}
236*fcf3ce44SJohn Forte 		/*
237*fcf3ce44SJohn Forte 		 * If no node is found, then check if this is a broadcast
238*fcf3ce44SJohn Forte 		 * frame
239*fcf3ce44SJohn Forte 		 */
240*fcf3ce44SJohn Forte 		else if (cmd->un.xrseq.w5.hcsw.Fctl & BC) {
241*fcf3ce44SJohn Forte 			sid = cmd->un.ulpWord[4] & 0x00ffffff;
242*fcf3ce44SJohn Forte 		} else {
243*fcf3ce44SJohn Forte 			/*
244*fcf3ce44SJohn Forte 			 * We have to drop this frame because we do not have
245*fcf3ce44SJohn Forte 			 * the S_ID of the request
246*fcf3ce44SJohn Forte 			 */
247*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ip_dropped_msg,
248*fcf3ce44SJohn Forte 			    "Node not found. mac=%02x%02x%02x%02x%02x%02x",
249*fcf3ce44SJohn Forte 			    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
250*fcf3ce44SJohn Forte 
251*fcf3ce44SJohn Forte 			(void) emlxs_ub_release((opaque_t)port, 1,
252*fcf3ce44SJohn Forte 			    &ubp->ub_token);
253*fcf3ce44SJohn Forte 
254*fcf3ce44SJohn Forte 			continue;
255*fcf3ce44SJohn Forte 		}
256*fcf3ce44SJohn Forte 
257*fcf3ce44SJohn Forte 		if (cmd->un.xrseq.w5.hcsw.Fctl & BC) {
258*fcf3ce44SJohn Forte 			IpBcastReceived++;
259*fcf3ce44SJohn Forte 		} else {
260*fcf3ce44SJohn Forte 			IpSeqReceived++;
261*fcf3ce44SJohn Forte 		}
262*fcf3ce44SJohn Forte 
263*fcf3ce44SJohn Forte 		/*
264*fcf3ce44SJohn Forte 		 * Setup frame header
265*fcf3ce44SJohn Forte 		 */
266*fcf3ce44SJohn Forte 		ubp->ub_frame.r_ctl = cmd->un.xrseq.w5.hcsw.Rctl;
267*fcf3ce44SJohn Forte 		ubp->ub_frame.type = cmd->un.xrseq.w5.hcsw.Type;
268*fcf3ce44SJohn Forte 		ubp->ub_frame.s_id = sid;
269*fcf3ce44SJohn Forte 		ubp->ub_frame.ox_id = ub_priv->token;
270*fcf3ce44SJohn Forte 		ubp->ub_frame.rx_id = cmd->ulpContext;
271*fcf3ce44SJohn Forte 		ubp->ub_class = FC_TRAN_CLASS3;
272*fcf3ce44SJohn Forte 
273*fcf3ce44SJohn Forte 		emlxs_ub_callback(port, ubp);
274*fcf3ce44SJohn Forte 		IpDropped = 0;
275*fcf3ce44SJohn Forte 	}
276*fcf3ce44SJohn Forte 	port = &PPORT;
277*fcf3ce44SJohn Forte 
278*fcf3ce44SJohn Forte out:
279*fcf3ce44SJohn Forte 
280*fcf3ce44SJohn Forte 	if (IpDropped) {
281*fcf3ce44SJohn Forte 		HBASTATS.IpDropped++;
282*fcf3ce44SJohn Forte 	}
283*fcf3ce44SJohn Forte 	if (IpBcastReceived) {
284*fcf3ce44SJohn Forte 		HBASTATS.IpBcastReceived++;
285*fcf3ce44SJohn Forte 	}
286*fcf3ce44SJohn Forte 	if (IpSeqReceived) {
287*fcf3ce44SJohn Forte 		HBASTATS.IpSeqReceived++;
288*fcf3ce44SJohn Forte 	}
289*fcf3ce44SJohn Forte 	return (0);
290*fcf3ce44SJohn Forte 
291*fcf3ce44SJohn Forte } /* emlxs_ip_handle_unsol_req() */
292*fcf3ce44SJohn Forte 
293*fcf3ce44SJohn Forte 
294*fcf3ce44SJohn Forte extern int32_t
295*fcf3ce44SJohn Forte emlxs_ip_handle_rcv_seq_list(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq)
296*fcf3ce44SJohn Forte {
297*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
298*fcf3ce44SJohn Forte 	IOCB *cmd;
299*fcf3ce44SJohn Forte 	uint64_t bdeAddr;
300*fcf3ce44SJohn Forte 	MATCHMAP *mp = NULL;
301*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
302*fcf3ce44SJohn Forte 	HBQE_t *hbqE;
303*fcf3ce44SJohn Forte 	uint32_t hbq_id;
304*fcf3ce44SJohn Forte 	uint32_t hbqe_tag;
305*fcf3ce44SJohn Forte #endif	/* SLI3_SUPPORT */
306*fcf3ce44SJohn Forte 
307*fcf3ce44SJohn Forte 	/*
308*fcf3ce44SJohn Forte 	 * No action required for now.
309*fcf3ce44SJohn Forte 	 */
310*fcf3ce44SJohn Forte 	cmd = &iocbq->iocb;
311*fcf3ce44SJohn Forte 
312*fcf3ce44SJohn Forte 	HBASTATS.IpRcvEvent++;
313*fcf3ce44SJohn Forte 
314*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
315*fcf3ce44SJohn Forte 	    "Receive sequence list: cmd=0x%x iotag=0x%x status=0x%x "
316*fcf3ce44SJohn Forte 	    "w4=0x%x ringno=0x%x", cmd->ulpCommand, cmd->ulpIoTag,
317*fcf3ce44SJohn Forte 	    cmd->ulpStatus, cmd->un.ulpWord[4], rp->ringno);
318*fcf3ce44SJohn Forte 
319*fcf3ce44SJohn Forte 	if (cmd->ulpStatus) {
320*fcf3ce44SJohn Forte 		goto out;
321*fcf3ce44SJohn Forte 	}
322*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
323*fcf3ce44SJohn Forte 	hbqE = (HBQE_t *)&iocbq->iocb;
324*fcf3ce44SJohn Forte 	hbq_id = hbqE->unt.ext.HBQ_tag;
325*fcf3ce44SJohn Forte 	hbqe_tag = hbqE->unt.ext.HBQE_tag;
326*fcf3ce44SJohn Forte 
327*fcf3ce44SJohn Forte 	if (hba->flag & FC_HBQ_ENABLED) {
328*fcf3ce44SJohn Forte 		HBQ_INIT_t *hbq;
329*fcf3ce44SJohn Forte 
330*fcf3ce44SJohn Forte 		hbq = &hba->hbq_table[hbq_id];
331*fcf3ce44SJohn Forte 
332*fcf3ce44SJohn Forte 		HBASTATS.IpUbPosted--;
333*fcf3ce44SJohn Forte 
334*fcf3ce44SJohn Forte 		if (hbqe_tag >= hbq->HBQ_numEntries) {
335*fcf3ce44SJohn Forte 			mp = NULL;
336*fcf3ce44SJohn Forte 		} else {
337*fcf3ce44SJohn Forte 			mp = hba->hbq_table[hbq_id].HBQ_PostBufs[hbqe_tag];
338*fcf3ce44SJohn Forte 		}
339*fcf3ce44SJohn Forte 	} else
340*fcf3ce44SJohn Forte #endif	/* SLI3_SUPPORT */
341*fcf3ce44SJohn Forte 	{
342*fcf3ce44SJohn Forte 		/* Check for valid buffer */
343*fcf3ce44SJohn Forte 		if (!(cmd->un.cont64[0].tus.f.bdeFlags & BUFF_TYPE_INVALID)) {
344*fcf3ce44SJohn Forte 			bdeAddr = getPaddr(cmd->un.cont64[0].addrHigh,
345*fcf3ce44SJohn Forte 			    cmd->un.cont64[0].addrLow);
346*fcf3ce44SJohn Forte 			mp = emlxs_mem_get_vaddr(hba, rp, bdeAddr);
347*fcf3ce44SJohn Forte 		}
348*fcf3ce44SJohn Forte 	}
349*fcf3ce44SJohn Forte 
350*fcf3ce44SJohn Forte out:
351*fcf3ce44SJohn Forte 
352*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
353*fcf3ce44SJohn Forte 	if (hba->flag & FC_HBQ_ENABLED) {
354*fcf3ce44SJohn Forte 		emlxs_update_HBQ_index(hba, hbq_id);
355*fcf3ce44SJohn Forte 	} else
356*fcf3ce44SJohn Forte #endif	/* SLI3_SUPPORT */
357*fcf3ce44SJohn Forte 	{
358*fcf3ce44SJohn Forte 		if (mp) {
359*fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_IPBUF, (uint8_t *)mp);
360*fcf3ce44SJohn Forte 		}
361*fcf3ce44SJohn Forte 		(void) emlxs_post_buffer(hba, rp, 1);
362*fcf3ce44SJohn Forte 	}
363*fcf3ce44SJohn Forte 
364*fcf3ce44SJohn Forte 	HBASTATS.IpDropped++;
365*fcf3ce44SJohn Forte 
366*fcf3ce44SJohn Forte 	return (0);
367*fcf3ce44SJohn Forte 
368*fcf3ce44SJohn Forte } /* emlxs_ip_handle_rcv_seq_list() */
369*fcf3ce44SJohn Forte 
370*fcf3ce44SJohn Forte 
371*fcf3ce44SJohn Forte 
372*fcf3ce44SJohn Forte /*
373*fcf3ce44SJohn Forte  * Process a create_xri command completion.
374*fcf3ce44SJohn Forte  */
375*fcf3ce44SJohn Forte extern int32_t
376*fcf3ce44SJohn Forte emlxs_handle_create_xri(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq)
377*fcf3ce44SJohn Forte {
378*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
379*fcf3ce44SJohn Forte 	IOCB *cmd;
380*fcf3ce44SJohn Forte 	NODELIST *ndlp;
381*fcf3ce44SJohn Forte 	fc_packet_t *pkt;
382*fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
383*fcf3ce44SJohn Forte 
384*fcf3ce44SJohn Forte 	cmd = &iocbq->iocb;
385*fcf3ce44SJohn Forte 
386*fcf3ce44SJohn Forte 	sbp = (emlxs_buf_t *)iocbq->sbp;
387*fcf3ce44SJohn Forte 
388*fcf3ce44SJohn Forte 	if (!sbp) {
389*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ip_completion_msg,
390*fcf3ce44SJohn Forte 		    "create_xri: cmd=0x%x iotag=0x%x status=0x%x w4=0x%x",
391*fcf3ce44SJohn Forte 		    cmd->ulpCommand, cmd->ulpIoTag, cmd->ulpStatus,
392*fcf3ce44SJohn Forte 		    cmd->un.ulpWord[4]);
393*fcf3ce44SJohn Forte 
394*fcf3ce44SJohn Forte 		return (EIO);
395*fcf3ce44SJohn Forte 	}
396*fcf3ce44SJohn Forte 	/* check for first xmit completion in sequence */
397*fcf3ce44SJohn Forte 	ndlp = (NODELIST *)sbp->node;
398*fcf3ce44SJohn Forte 
399*fcf3ce44SJohn Forte 	if (cmd->ulpStatus) {
400*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_bad_ip_completion_msg,
401*fcf3ce44SJohn Forte 		    "create_xri: cmd=0x%x iotag=0x%x status=0x%x w4=0x%x",
402*fcf3ce44SJohn Forte 		    cmd->ulpCommand, cmd->ulpIoTag, cmd->ulpStatus,
403*fcf3ce44SJohn Forte 		    cmd->un.ulpWord[4]);
404*fcf3ce44SJohn Forte 
405*fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_RINGTX_LOCK);
406*fcf3ce44SJohn Forte 		ndlp->nlp_flag[rp->ringno] &= ~NLP_RPI_XRI;
407*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_RINGTX_LOCK);
408*fcf3ce44SJohn Forte 
409*fcf3ce44SJohn Forte 		return (EIO);
410*fcf3ce44SJohn Forte 	}
411*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_RINGTX_LOCK);
412*fcf3ce44SJohn Forte 	ndlp->nlp_Xri = cmd->ulpContext;
413*fcf3ce44SJohn Forte 	ndlp->nlp_flag[rp->ringno] &= ~NLP_RPI_XRI;
414*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_RINGTX_LOCK);
415*fcf3ce44SJohn Forte 
416*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
417*fcf3ce44SJohn Forte 	    "create_xri completed: DID=0x%x Xri=0x%x iotag=0x%x",
418*fcf3ce44SJohn Forte 	    ndlp->nlp_DID, ndlp->nlp_Xri, cmd->ulpIoTag);
419*fcf3ce44SJohn Forte 
420*fcf3ce44SJohn Forte 	pkt = sbp->pkt;
421*fcf3ce44SJohn Forte 	emlxs_pkt_free(pkt);
422*fcf3ce44SJohn Forte 
423*fcf3ce44SJohn Forte 	return (0);
424*fcf3ce44SJohn Forte 
425*fcf3ce44SJohn Forte } /* emlxs_handle_create_xri()  */
426*fcf3ce44SJohn Forte 
427*fcf3ce44SJohn Forte 
428*fcf3ce44SJohn Forte /*
429*fcf3ce44SJohn Forte  * Issue an iocb command to create an exchange with
430*fcf3ce44SJohn Forte  * the remote Nport specified by the NODELIST entry.
431*fcf3ce44SJohn Forte  */
432*fcf3ce44SJohn Forte extern int32_t
433*fcf3ce44SJohn Forte emlxs_create_xri(emlxs_port_t *port, RING *rp, NODELIST *ndlp)
434*fcf3ce44SJohn Forte {
435*fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
436*fcf3ce44SJohn Forte 	IOCB *icmd;
437*fcf3ce44SJohn Forte 	IOCBQ *iocbq;
438*fcf3ce44SJohn Forte 	fc_packet_t *pkt;
439*fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
440*fcf3ce44SJohn Forte 	uint16_t iotag;
441*fcf3ce44SJohn Forte 
442*fcf3ce44SJohn Forte 	/* Check if an XRI has already been requested */
443*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_RINGTX_LOCK);
444*fcf3ce44SJohn Forte 	if (ndlp->nlp_Xri != 0 || (ndlp->nlp_flag[rp->ringno] & NLP_RPI_XRI)) {
445*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_RINGTX_LOCK);
446*fcf3ce44SJohn Forte 		return (0);
447*fcf3ce44SJohn Forte 	}
448*fcf3ce44SJohn Forte 	ndlp->nlp_flag[rp->ringno] |= NLP_RPI_XRI;
449*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_RINGTX_LOCK);
450*fcf3ce44SJohn Forte 
451*fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, 0, 0, 0, KM_NOSLEEP))) {
452*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
453*fcf3ce44SJohn Forte 		    "create_xri failed: Unable to allocate pkt. did=0x%x",
454*fcf3ce44SJohn Forte 		    ndlp->nlp_DID);
455*fcf3ce44SJohn Forte 
456*fcf3ce44SJohn Forte 		goto fail;
457*fcf3ce44SJohn Forte 	}
458*fcf3ce44SJohn Forte 	sbp = (emlxs_buf_t *)pkt->pkt_fca_private;
459*fcf3ce44SJohn Forte 	iocbq = &sbp->iocbq;
460*fcf3ce44SJohn Forte 
461*fcf3ce44SJohn Forte 	/* Get the iotag by registering the packet */
462*fcf3ce44SJohn Forte 	iotag = emlxs_register_pkt(rp, sbp);
463*fcf3ce44SJohn Forte 
464*fcf3ce44SJohn Forte 	if (!iotag) {
465*fcf3ce44SJohn Forte 		/*
466*fcf3ce44SJohn Forte 		 * No more command slots available, retry later
467*fcf3ce44SJohn Forte 		 */
468*fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
469*fcf3ce44SJohn Forte 
470*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
471*fcf3ce44SJohn Forte 		    "create_xri failed: Unable to allocate IOTAG. did=0x%x",
472*fcf3ce44SJohn Forte 		    ndlp->nlp_DID);
473*fcf3ce44SJohn Forte 
474*fcf3ce44SJohn Forte 		goto fail;
475*fcf3ce44SJohn Forte 	}
476*fcf3ce44SJohn Forte 	icmd = &iocbq->iocb;
477*fcf3ce44SJohn Forte 	icmd->ulpIoTag = iotag;
478*fcf3ce44SJohn Forte 	icmd->ulpContext = ndlp->nlp_Rpi;
479*fcf3ce44SJohn Forte 	icmd->ulpLe = 1;
480*fcf3ce44SJohn Forte 	icmd->ulpCommand = CMD_CREATE_XRI_CR;
481*fcf3ce44SJohn Forte 	icmd->ulpOwner = OWN_CHIP;
482*fcf3ce44SJohn Forte 
483*fcf3ce44SJohn Forte 	/* Initalize iocbq */
484*fcf3ce44SJohn Forte 	iocbq->port = (void *)port;
485*fcf3ce44SJohn Forte 	iocbq->node = (void *)ndlp;
486*fcf3ce44SJohn Forte 	iocbq->ring = (void *)rp;
487*fcf3ce44SJohn Forte 
488*fcf3ce44SJohn Forte 	mutex_enter(&sbp->mtx);
489*fcf3ce44SJohn Forte 	sbp->node = (void *)ndlp;
490*fcf3ce44SJohn Forte 	sbp->ring = rp;
491*fcf3ce44SJohn Forte 	mutex_exit(&sbp->mtx);
492*fcf3ce44SJohn Forte 
493*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
494*fcf3ce44SJohn Forte 	    "create_xri sent: DID=0x%x Xri=0x%x iotag=0x%x",
495*fcf3ce44SJohn Forte 	    ndlp->nlp_DID, ndlp->nlp_Xri, iotag);
496*fcf3ce44SJohn Forte 
497*fcf3ce44SJohn Forte 	emlxs_issue_iocb_cmd(hba, rp, iocbq);
498*fcf3ce44SJohn Forte 
499*fcf3ce44SJohn Forte 	return (0);
500*fcf3ce44SJohn Forte 
501*fcf3ce44SJohn Forte fail:
502*fcf3ce44SJohn Forte 
503*fcf3ce44SJohn Forte 	/* Clear the XRI flag */
504*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_RINGTX_LOCK);
505*fcf3ce44SJohn Forte 	ndlp->nlp_flag[rp->ringno] &= ~NLP_RPI_XRI;
506*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_RINGTX_LOCK);
507*fcf3ce44SJohn Forte 
508*fcf3ce44SJohn Forte 	return (1);
509*fcf3ce44SJohn Forte 
510*fcf3ce44SJohn Forte } /* emlxs_create_xri() */
511