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 /* 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
emlxs_ip_handle_event(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)3482527734SSukumar Swaminathan emlxs_ip_handle_event(emlxs_hba_t *hba, CHANNEL *cp, 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",
5282527734SSukumar Swaminathan 		    (uint32_t)cmd->ULPCOMMAND, (uint32_t)cmd->ULPIOTAG,
5382527734SSukumar Swaminathan 		    cmd->ULPSTATUS, cmd->un.ulpWord[4]);
54fcf3ce44SJohn Forte 
55fcf3ce44SJohn Forte 		return (EIO);
56fcf3ce44SJohn Forte 	}
57291a2b48SSukumar Swaminathan 
5882527734SSukumar Swaminathan 	if (cp->channelno != hba->channel_ip) {
59fcf3ce44SJohn Forte 		HBASTATS.IpStray++;
60fcf3ce44SJohn Forte 
61fcf3ce44SJohn Forte 		return (0);
62fcf3ce44SJohn Forte 	}
63291a2b48SSukumar Swaminathan 
64fcf3ce44SJohn Forte 	port = sbp->iocbq.port;
65fcf3ce44SJohn Forte 
6682527734SSukumar Swaminathan 	switch (cmd->ULPCOMMAND) {
67fcf3ce44SJohn Forte 		/*
68291a2b48SSukumar 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 "
7882527734SSukumar Swaminathan 		    "[%08x,%08x]", cmd->ULPCOMMAND, cmd->ULPSTATUS,
79fcf3ce44SJohn Forte 		    cmd->un.ulpWord[4], cmd->un.ulpWord[5]);
80fcf3ce44SJohn Forte 
8182527734SSukumar Swaminathan 		emlxs_pkt_complete(sbp, cmd->ULPSTATUS,
82fcf3ce44SJohn Forte 		    cmd->un.grsp.perr.statLocalError, 1);
83fcf3ce44SJohn Forte 
84fcf3ce44SJohn Forte 		break;
85fcf3ce44SJohn Forte 
86fcf3ce44SJohn Forte 		/*
87291a2b48SSukumar Swaminathan 		 * Error: Abnormal XMIT SEQUENCE command completion
88291a2b48SSukumar 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,
97291a2b48SSukumar Swaminathan 		    "XMIT SEQUENCE CR completion error: cmd=%x status=0x%x "
9882527734SSukumar Swaminathan 		    "[%08x,%08x]", cmd->ULPCOMMAND, cmd->ULPSTATUS,
99291a2b48SSukumar Swaminathan 		    cmd->un.ulpWord[4], cmd->un.ulpWord[5]);
100fcf3ce44SJohn Forte 
10182527734SSukumar Swaminathan 		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]",
11782527734SSukumar Swaminathan 		    cmd->ULPCOMMAND, cmd->ULPSTATUS, cmd->un.ulpWord[4],
118fcf3ce44SJohn Forte 		    cmd->un.ulpWord[5]);
119fcf3ce44SJohn Forte 
12082527734SSukumar Swaminathan 		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,
134291a2b48SSukumar Swaminathan 		    "XMIT SEQUENCE CR completion: cmd=%x status=0x%x"
13582527734SSukumar Swaminathan 		    "[%08x,%08x]", cmd->ULPCOMMAND, cmd->ULPSTATUS,
136fcf3ce44SJohn Forte 		    cmd->un.ulpWord[4], cmd->un.ulpWord[5]);
137fcf3ce44SJohn Forte 
13882527734SSukumar Swaminathan 		if (cmd->ULPSTATUS) {
139fcf3ce44SJohn Forte 			HBASTATS.IpSeqError++;
140fcf3ce44SJohn Forte 
14182527734SSukumar Swaminathan 			if ((cmd->ULPSTATUS == IOSTAT_LOCAL_REJECT) &&
142fcf3ce44SJohn Forte 			    ((cmd->un.ulpWord[4] & 0xff) == IOERR_NO_XRI)) {
143291a2b48SSukumar Swaminathan 				ndlp = (NODELIST *)sbp->node;
14482527734SSukumar Swaminathan 				if ((cmd->ULPCONTEXT == ndlp->nlp_Xri) &&
14582527734SSukumar Swaminathan 				    !(ndlp->nlp_flag[hba->channel_ip] &
146fcf3ce44SJohn Forte 				    NLP_RPI_XRI)) {
147fcf3ce44SJohn Forte 					ndlp->nlp_Xri = 0;
14882527734SSukumar Swaminathan 					(void) emlxs_create_xri(port, cp, ndlp);
149fcf3ce44SJohn Forte 				}
150fcf3ce44SJohn Forte 			}
151fcf3ce44SJohn Forte 		} else {
152fcf3ce44SJohn Forte 			HBASTATS.IpSeqGood++;
153fcf3ce44SJohn Forte 		}
154fcf3ce44SJohn Forte 
15582527734SSukumar Swaminathan 		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,
16582527734SSukumar Swaminathan 		    "Invalid iocb: cmd=0x%x", cmd->ULPCOMMAND);
166fcf3ce44SJohn Forte 
167fcf3ce44SJohn Forte 		break;
168fcf3ce44SJohn Forte 
16982527734SSukumar Swaminathan 	}	/* switch(cmd->ULPCOMMAND) */
170fcf3ce44SJohn Forte 
171fcf3ce44SJohn Forte 
172fcf3ce44SJohn Forte 	return (0);
173fcf3ce44SJohn Forte 
17482527734SSukumar Swaminathan } /* emlxs_ip_handle_event() */
175fcf3ce44SJohn Forte 
176fcf3ce44SJohn Forte 
177fcf3ce44SJohn Forte extern int32_t
emlxs_ip_handle_unsol_req(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)17882527734SSukumar Swaminathan emlxs_ip_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, 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 
200*8f23e9faSHans Rosenfeld 		if (!(port->flag & EMLXS_INI_BOUND) ||
201fcf3ce44SJohn Forte 		    !(port->flag & EMLXS_PORT_IP_UP)) {
202fcf3ce44SJohn Forte 			continue;
203fcf3ce44SJohn Forte 		}
204fcf3ce44SJohn Forte 
205291a2b48SSukumar Swaminathan 		ubp =
206291a2b48SSukumar Swaminathan 		    (fc_unsol_buf_t *)emlxs_ub_get(port, size,
207291a2b48SSukumar Swaminathan 		    FC_TYPE_IS8802_SNAP, 0);
208fcf3ce44SJohn Forte 
209291a2b48SSukumar Swaminathan 		if (!ubp) {
210fcf3ce44SJohn Forte 			/* Theoretically we should never get here. */
211291a2b48SSukumar Swaminathan 			/* There should be one DMA buffer for every ub */
212291a2b48SSukumar 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",
21782527734SSukumar Swaminathan 			    PADDR(cmd->un.cont64[0].addrHigh,
218fcf3ce44SJohn Forte 			    cmd->un.cont64[0].addrLow));
219fcf3ce44SJohn Forte 
220fcf3ce44SJohn Forte 			continue;
221fcf3ce44SJohn Forte 		}
222291a2b48SSukumar Swaminathan 
223fcf3ce44SJohn Forte 		bcopy(mp->virt, ubp->ub_buffer, size);
224fcf3ce44SJohn Forte 
225fcf3ce44SJohn Forte 		ub_priv = ubp->ub_fca_private;
226291a2b48SSukumar 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) &&
23482527734SSukumar Swaminathan 			    !(ndlp->nlp_flag[hba->channel_ip] & NLP_RPI_XRI)) {
23582527734SSukumar Swaminathan 				(void) emlxs_create_xri(port, cp, ndlp);
236fcf3ce44SJohn Forte 			}
237fcf3ce44SJohn Forte 		}
238291a2b48SSukumar Swaminathan 
239fcf3ce44SJohn Forte 		/*
240291a2b48SSukumar Swaminathan 		 * If no node is found, then check if this is a
241291a2b48SSukumar Swaminathan 		 * broadcast frame
242fcf3ce44SJohn Forte 		 */
243fcf3ce44SJohn Forte 		else if (cmd->un.xrseq.w5.hcsw.Fctl & BC) {
244fcf3ce44SJohn Forte 			sid = cmd->un.ulpWord[4] & 0x00ffffff;
245291a2b48SSukumar Swaminathan 		}
246291a2b48SSukumar Swaminathan 
247291a2b48SSukumar Swaminathan 		else {
248291a2b48SSukumar Swaminathan 			/* We have to drop this frame because we do not have */
249291a2b48SSukumar 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 
254a9800bebSGarrett D'Amore 			(void) emlxs_fca_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;
27382527734SSukumar Swaminathan 		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 	}
286291a2b48SSukumar Swaminathan 
287fcf3ce44SJohn Forte 	if (IpBcastReceived) {
288fcf3ce44SJohn Forte 		HBASTATS.IpBcastReceived++;
289fcf3ce44SJohn Forte 	}
290291a2b48SSukumar Swaminathan 
291fcf3ce44SJohn Forte 	if (IpSeqReceived) {
292fcf3ce44SJohn Forte 		HBASTATS.IpSeqReceived++;
293fcf3ce44SJohn Forte 	}
294291a2b48SSukumar Swaminathan 
295fcf3ce44SJohn Forte 	return (0);
296fcf3ce44SJohn Forte 
29782527734SSukumar Swaminathan } /* emlxs_ip_handle_unsol_req() */
298fcf3ce44SJohn Forte 
299fcf3ce44SJohn Forte 
300fcf3ce44SJohn Forte extern int32_t
emlxs_ip_handle_rcv_seq_list(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)30182527734SSukumar Swaminathan emlxs_ip_handle_rcv_seq_list(emlxs_hba_t *hba, CHANNEL *cp, 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 	HBQE_t *hbqE;
308fcf3ce44SJohn Forte 	uint32_t hbq_id;
309fcf3ce44SJohn Forte 	uint32_t hbqe_tag;
31082527734SSukumar Swaminathan 	RING *rp;
311fcf3ce44SJohn Forte 
312fcf3ce44SJohn Forte 	/*
313fcf3ce44SJohn Forte 	 * No action required for now.
314fcf3ce44SJohn Forte 	 */
315fcf3ce44SJohn Forte 	cmd = &iocbq->iocb;
31682527734SSukumar Swaminathan 	rp = &hba->sli.sli3.ring[cp->channelno];
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 "
32282527734SSukumar Swaminathan 	    "w4=0x%x channelno=0x%x", cmd->ULPCOMMAND, cmd->ULPIOTAG,
32382527734SSukumar Swaminathan 	    cmd->ULPSTATUS, cmd->un.ulpWord[4], cp->channelno);
324fcf3ce44SJohn Forte 
32582527734SSukumar Swaminathan 	if (cmd->ULPSTATUS) {
326fcf3ce44SJohn Forte 		goto out;
327fcf3ce44SJohn Forte 	}
32882527734SSukumar Swaminathan 
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 
33682527734SSukumar Swaminathan 		hbq = &hba->sli.sli3.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 {
34382527734SSukumar Swaminathan 			mp = hba->sli.sli3.hbq_table
34482527734SSukumar Swaminathan 			    [hbq_id].HBQ_PostBufs[hbqe_tag];
345fcf3ce44SJohn Forte 		}
34682527734SSukumar Swaminathan 	} else {
347fcf3ce44SJohn Forte 		/* Check for valid buffer */
348fcf3ce44SJohn Forte 		if (!(cmd->un.cont64[0].tus.f.bdeFlags & BUFF_TYPE_INVALID)) {
349291a2b48SSukumar Swaminathan 			bdeAddr =
35082527734SSukumar Swaminathan 			    PADDR(cmd->un.cont64[0].addrHigh,
351fcf3ce44SJohn Forte 			    cmd->un.cont64[0].addrLow);
352fcf3ce44SJohn Forte 			mp = emlxs_mem_get_vaddr(hba, rp, bdeAddr);
353fcf3ce44SJohn Forte 		}
354fcf3ce44SJohn Forte 	}
355fcf3ce44SJohn Forte 
356fcf3ce44SJohn Forte out:
357fcf3ce44SJohn Forte 
358fcf3ce44SJohn Forte 	if (hba->flag & FC_HBQ_ENABLED) {
359fcf3ce44SJohn Forte 		emlxs_update_HBQ_index(hba, hbq_id);
36082527734SSukumar Swaminathan 	} else {
361fcf3ce44SJohn Forte 		if (mp) {
362a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, MEM_IPBUF, (void *)mp);
363fcf3ce44SJohn Forte 		}
364fcf3ce44SJohn Forte 		(void) emlxs_post_buffer(hba, rp, 1);
365fcf3ce44SJohn Forte 	}
366fcf3ce44SJohn Forte 
367fcf3ce44SJohn Forte 	HBASTATS.IpDropped++;
368fcf3ce44SJohn Forte 
369fcf3ce44SJohn Forte 	return (0);
370fcf3ce44SJohn Forte 
37182527734SSukumar Swaminathan } /* emlxs_ip_handle_rcv_seq_list() */
372fcf3ce44SJohn Forte 
373fcf3ce44SJohn Forte 
374fcf3ce44SJohn Forte 
375fcf3ce44SJohn Forte /*
376fcf3ce44SJohn Forte  * Process a create_xri command completion.
377fcf3ce44SJohn Forte  */
378fcf3ce44SJohn Forte extern int32_t
emlxs_handle_create_xri(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)37982527734SSukumar Swaminathan emlxs_handle_create_xri(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
380fcf3ce44SJohn Forte {
381fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
382fcf3ce44SJohn Forte 	IOCB *cmd;
383fcf3ce44SJohn Forte 	NODELIST *ndlp;
384fcf3ce44SJohn Forte 	fc_packet_t *pkt;
385fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
386*8f23e9faSHans Rosenfeld 	int32_t rval = 0;
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,
394*8f23e9faSHans Rosenfeld 		    "create_xri: cmd=0x%x iotag=0x%x status=0x%x w4=0x%x. "
395*8f23e9faSHans Rosenfeld 		    "NULL sbp found.",
39682527734SSukumar Swaminathan 		    cmd->ULPCOMMAND, cmd->ULPIOTAG, cmd->ULPSTATUS,
397fcf3ce44SJohn Forte 		    cmd->un.ulpWord[4]);
398fcf3ce44SJohn Forte 
399fcf3ce44SJohn Forte 		return (EIO);
400fcf3ce44SJohn Forte 	}
401291a2b48SSukumar Swaminathan 
402fcf3ce44SJohn Forte 	/* check for first xmit completion in sequence */
403fcf3ce44SJohn Forte 	ndlp = (NODELIST *)sbp->node;
404fcf3ce44SJohn Forte 
405*8f23e9faSHans Rosenfeld 	if (!ndlp) {
406*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_bad_ip_completion_msg,
407*8f23e9faSHans Rosenfeld 		    "create_xri: cmd=0x%x iotag=0x%x status=0x%x w4=0x%x. "
408*8f23e9faSHans Rosenfeld 		    "NULL node found.",
409*8f23e9faSHans Rosenfeld 		    cmd->ULPCOMMAND, cmd->ULPIOTAG, cmd->ULPSTATUS,
410*8f23e9faSHans Rosenfeld 		    cmd->un.ulpWord[4]);
411*8f23e9faSHans Rosenfeld 
412*8f23e9faSHans Rosenfeld 		rval = EIO;
413*8f23e9faSHans Rosenfeld 		goto done;
414*8f23e9faSHans Rosenfeld 	}
415*8f23e9faSHans Rosenfeld 
41682527734SSukumar Swaminathan 	if (cmd->ULPSTATUS) {
417fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_bad_ip_completion_msg,
418*8f23e9faSHans Rosenfeld 		    "create_xri: cmd=0x%x iotag=0x%x status=0x%x w4=0x%x. "
419*8f23e9faSHans Rosenfeld 		    "Completion error.",
42082527734SSukumar Swaminathan 		    cmd->ULPCOMMAND, cmd->ULPIOTAG, cmd->ULPSTATUS,
421fcf3ce44SJohn Forte 		    cmd->un.ulpWord[4]);
422fcf3ce44SJohn Forte 
42382527734SSukumar Swaminathan 		mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
42482527734SSukumar Swaminathan 		ndlp->nlp_flag[cp->channelno] &= ~NLP_RPI_XRI;
42582527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
426fcf3ce44SJohn Forte 
427*8f23e9faSHans Rosenfeld 		rval = EIO;
428*8f23e9faSHans Rosenfeld 		goto done;
429fcf3ce44SJohn Forte 	}
430291a2b48SSukumar Swaminathan 
43182527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
43282527734SSukumar Swaminathan 	ndlp->nlp_Xri = cmd->ULPCONTEXT;
43382527734SSukumar Swaminathan 	ndlp->nlp_flag[cp->channelno] &= ~NLP_RPI_XRI;
43482527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
435fcf3ce44SJohn Forte 
436fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
437fcf3ce44SJohn Forte 	    "create_xri completed: DID=0x%x Xri=0x%x iotag=0x%x",
43882527734SSukumar Swaminathan 	    ndlp->nlp_DID, ndlp->nlp_Xri, cmd->ULPIOTAG);
439fcf3ce44SJohn Forte 
440*8f23e9faSHans Rosenfeld done:
441fcf3ce44SJohn Forte 	pkt = sbp->pkt;
442*8f23e9faSHans Rosenfeld 	if (pkt) {
443*8f23e9faSHans Rosenfeld 		emlxs_pkt_free(pkt);
444*8f23e9faSHans Rosenfeld 	}
445fcf3ce44SJohn Forte 
446*8f23e9faSHans Rosenfeld 	return (rval);
447fcf3ce44SJohn Forte 
44882527734SSukumar Swaminathan } /* emlxs_handle_create_xri()  */
449fcf3ce44SJohn Forte 
450fcf3ce44SJohn Forte 
451fcf3ce44SJohn Forte /*
452291a2b48SSukumar Swaminathan  * Issue an iocb command to create an exchange with the remote Nport
453291a2b48SSukumar Swaminathan  * specified by the NODELIST entry.
454fcf3ce44SJohn Forte  */
455fcf3ce44SJohn Forte extern int32_t
emlxs_create_xri(emlxs_port_t * port,CHANNEL * cp,NODELIST * ndlp)45682527734SSukumar Swaminathan emlxs_create_xri(emlxs_port_t *port, CHANNEL *cp, NODELIST *ndlp)
457fcf3ce44SJohn Forte {
458fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
459fcf3ce44SJohn Forte 	IOCB *icmd;
460fcf3ce44SJohn Forte 	IOCBQ *iocbq;
461fcf3ce44SJohn Forte 	fc_packet_t *pkt;
462fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
463fcf3ce44SJohn Forte 	uint16_t iotag;
464fcf3ce44SJohn Forte 
465fcf3ce44SJohn Forte 	/* Check if an XRI has already been requested */
46682527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
46782527734SSukumar Swaminathan 	if (ndlp->nlp_Xri != 0 ||
46882527734SSukumar Swaminathan 	    (ndlp->nlp_flag[cp->channelno] & NLP_RPI_XRI)) {
46982527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
470fcf3ce44SJohn Forte 		return (0);
471fcf3ce44SJohn Forte 	}
47282527734SSukumar Swaminathan 	ndlp->nlp_flag[cp->channelno] |= NLP_RPI_XRI;
47382527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
474fcf3ce44SJohn Forte 
475fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, 0, 0, 0, KM_NOSLEEP))) {
476fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
477fcf3ce44SJohn Forte 		    "create_xri failed: Unable to allocate pkt. did=0x%x",
478fcf3ce44SJohn Forte 		    ndlp->nlp_DID);
479fcf3ce44SJohn Forte 
480fcf3ce44SJohn Forte 		goto fail;
481fcf3ce44SJohn Forte 	}
482291a2b48SSukumar Swaminathan 
483fcf3ce44SJohn Forte 	sbp = (emlxs_buf_t *)pkt->pkt_fca_private;
484fcf3ce44SJohn Forte 	iocbq = &sbp->iocbq;
485fcf3ce44SJohn Forte 
48682527734SSukumar Swaminathan 	/* Clear the PACKET_ULP_OWNED flag */
48782527734SSukumar Swaminathan 	sbp->pkt_flags &= ~PACKET_ULP_OWNED;
48882527734SSukumar Swaminathan 
489fcf3ce44SJohn Forte 	/* Get the iotag by registering the packet */
49082527734SSukumar Swaminathan 	iotag = emlxs_register_pkt(cp, sbp);
491fcf3ce44SJohn Forte 
492fcf3ce44SJohn Forte 	if (!iotag) {
493fcf3ce44SJohn Forte 		/*
494fcf3ce44SJohn Forte 		 * No more command slots available, retry later
495fcf3ce44SJohn Forte 		 */
496fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
497fcf3ce44SJohn Forte 
498fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
499fcf3ce44SJohn Forte 		    "create_xri failed: Unable to allocate IOTAG. did=0x%x",
500fcf3ce44SJohn Forte 		    ndlp->nlp_DID);
501fcf3ce44SJohn Forte 
502fcf3ce44SJohn Forte 		goto fail;
503fcf3ce44SJohn Forte 	}
504291a2b48SSukumar Swaminathan 
505fcf3ce44SJohn Forte 	icmd = &iocbq->iocb;
50682527734SSukumar Swaminathan 	icmd->ULPIOTAG = iotag;
50782527734SSukumar Swaminathan 	icmd->ULPCONTEXT = ndlp->nlp_Rpi;
50882527734SSukumar Swaminathan 	icmd->ULPLE = 1;
50982527734SSukumar Swaminathan 	icmd->ULPCOMMAND = CMD_CREATE_XRI_CR;
51082527734SSukumar Swaminathan 	icmd->ULPOWNER = OWN_CHIP;
511fcf3ce44SJohn Forte 
512fcf3ce44SJohn Forte 	/* Initalize iocbq */
513fcf3ce44SJohn Forte 	iocbq->port = (void *)port;
514fcf3ce44SJohn Forte 	iocbq->node = (void *)ndlp;
51582527734SSukumar Swaminathan 	iocbq->channel = (void *)cp;
516fcf3ce44SJohn Forte 
517fcf3ce44SJohn Forte 	mutex_enter(&sbp->mtx);
518fcf3ce44SJohn Forte 	sbp->node = (void *)ndlp;
51982527734SSukumar Swaminathan 	sbp->channel = cp;
520fcf3ce44SJohn Forte 	mutex_exit(&sbp->mtx);
521fcf3ce44SJohn Forte 
522fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ip_detail_msg,
523291a2b48SSukumar Swaminathan 	    "create_xri sent: DID=0x%x Xri=0x%x iotag=0x%x", ndlp->nlp_DID,
524291a2b48SSukumar Swaminathan 	    ndlp->nlp_Xri, iotag);
525fcf3ce44SJohn Forte 
52682527734SSukumar Swaminathan 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
527fcf3ce44SJohn Forte 
528fcf3ce44SJohn Forte 	return (0);
529fcf3ce44SJohn Forte 
530fcf3ce44SJohn Forte fail:
531fcf3ce44SJohn Forte 
532fcf3ce44SJohn Forte 	/* Clear the XRI flag */
53382527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
53482527734SSukumar Swaminathan 	ndlp->nlp_flag[cp->channelno] &= ~NLP_RPI_XRI;
53582527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
536fcf3ce44SJohn Forte 
537fcf3ce44SJohn Forte 	return (1);
538fcf3ce44SJohn Forte 
53982527734SSukumar Swaminathan } /* emlxs_create_xri() */