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