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