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-2012 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_ELS_C);
31
32 static void emlxs_handle_sol_flogi(emlxs_port_t *port, emlxs_buf_t *sbp);
33 static void emlxs_handle_sol_fdisc(emlxs_port_t *port, emlxs_buf_t *sbp);
34 static void emlxs_handle_sol_plogi(emlxs_port_t *port, emlxs_buf_t *sbp);
35 static void emlxs_handle_sol_adisc(emlxs_port_t *port, emlxs_buf_t *sbp);
36 static void emlxs_handle_sol_logo(emlxs_port_t *port, emlxs_buf_t *sbp);
37 static void emlxs_handle_sol_prli(emlxs_port_t *port, emlxs_buf_t *sbp);
38
39 static void emlxs_handle_unsol_rscn(emlxs_port_t *port, CHANNEL *cp,
40 IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
41 static void emlxs_handle_unsol_flogi(emlxs_port_t *port, CHANNEL *cp,
42 IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
43 static void emlxs_handle_unsol_plogi(emlxs_port_t *port, CHANNEL *cp,
44 IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
45 static void emlxs_handle_unsol_logo(emlxs_port_t *port, CHANNEL *cp,
46 IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
47 static void emlxs_handle_unsol_adisc(emlxs_port_t *port, CHANNEL *cp,
48 IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
49 static void emlxs_handle_unsol_prli(emlxs_port_t *port, CHANNEL *cp,
50 IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
51 static void emlxs_handle_unsol_prlo(emlxs_port_t *port, CHANNEL *cp,
52 IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
53 static void emlxs_handle_unsol_auth(emlxs_port_t *port, CHANNEL *cp,
54 IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
55 static void emlxs_handle_unsol_gen_cmd(emlxs_port_t *port, CHANNEL *cp,
56 IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
57 static void emlxs_handle_unsol_echo(emlxs_port_t *port, CHANNEL *cp,
58 IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
59 static void emlxs_handle_unsol_rtv(emlxs_port_t *port, CHANNEL *cp,
60 IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
61 static void emlxs_handle_unsol_rls(emlxs_port_t *port, CHANNEL *cp,
62 IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
63 static void emlxs_handle_acc(emlxs_port_t *port, emlxs_buf_t *sbp,
64 IOCBQ *iocbq, uint32_t flag);
65 static void emlxs_handle_reject(emlxs_port_t *port, emlxs_buf_t *sbp,
66 IOCBQ *iocbq, uint32_t flag);
67
68 #if (EMLXS_MODREV < EMLXS_MODREV4)
69 static void emlxs_send_rsnn(emlxs_port_t *port);
70
71 #endif /* < EMLXS_MODREV4 */
72
73
74
75 /* Routine Declaration - Local */
76 /* End Routine Declaration - Local */
77
78 /*
79 * emlxs_els_handle_event
80 *
81 * Description: Process an ELS Response Ring cmpl
82 *
83 */
84 extern int
emlxs_els_handle_event(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)85 emlxs_els_handle_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
86 {
87 emlxs_port_t *port = &PPORT;
88 IOCB *iocb;
89 emlxs_buf_t *sbp;
90 fc_packet_t *pkt;
91 uint32_t *lp0;
92 uint32_t command;
93 NODELIST *ndlp;
94 uint32_t did;
95 ELS_PKT *els;
96
97 iocb = &iocbq->iocb;
98
99 HBASTATS.ElsEvent++;
100
101 sbp = (emlxs_buf_t *)iocbq->sbp;
102
103 if (!sbp) {
104 /*
105 * completion with missing xmit command
106 */
107 HBASTATS.ElsStray++;
108
109 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_els_completion_msg,
110 "iocbq=%p cmd=0x%x iotag=0x%x status=0x%x perr=0x%x",
111 iocbq, (uint32_t)iocb->ULPCOMMAND,
112 (uint32_t)iocb->ULPIOTAG, iocb->ULPSTATUS,
113 iocb->un.ulpWord[4]);
114
115 return (1);
116 }
117
118 if (cp->channelno != hba->channel_els) {
119 HBASTATS.ElsStray++;
120
121 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_els_completion_msg,
122 "Not ELS channel: channel=%d iocbq=%p cmd=0x%x iotag=0x%x "
123 "status=0x%x perr=0x%x", cp->channelno, iocbq,
124 (uint32_t)iocb->ULPCOMMAND, (uint32_t)iocb->ULPIOTAG,
125 iocb->ULPSTATUS, iocb->un.ulpWord[4]);
126
127 return (1);
128 }
129
130 port = sbp->iocbq.port;
131 pkt = PRIV2PKT(sbp);
132 lp0 = (uint32_t *)pkt->pkt_cmd;
133 command = *lp0 & ELS_CMD_MASK;
134 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
135
136 /* Check if a response buffer was provided */
137 if (pkt->pkt_rsplen) {
138 EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0, pkt->pkt_rsplen,
139 DDI_DMA_SYNC_FORKERNEL);
140 }
141
142 switch (iocb->ULPCOMMAND) {
143 /*
144 * ELS Reply completion
145 */
146 case CMD_XMIT_ELS_RSP_CX:
147 case CMD_XMIT_ELS_RSP64_CX:
148
149 HBASTATS.ElsRspCompleted++;
150
151 if (command == ELS_CMD_ACC) {
152 emlxs_handle_acc(port, sbp, iocbq, 1);
153 } else {
154 emlxs_handle_reject(port, sbp, iocbq, 1);
155 }
156
157 break;
158
159 /*
160 * ELS command completion
161 */
162 case CMD_ELS_REQUEST_CR:
163 case CMD_ELS_REQUEST64_CR:
164 case CMD_ELS_REQUEST_CX:
165 case CMD_ELS_REQUEST64_CX:
166
167 HBASTATS.ElsCmdCompleted++;
168
169 sbp->pkt_flags |= PACKET_ELS_RSP_VALID;
170
171 els = (ELS_PKT *)pkt->pkt_resp;
172
173 pkt->pkt_resp_resid =
174 pkt->pkt_rsplen - iocb->un.elsreq64.bdl.bdeSize;
175 pkt->pkt_data_resid = pkt->pkt_datalen;
176
177 pkt->pkt_resp_fhdr.d_id = pkt->pkt_cmd_fhdr.s_id;
178 pkt->pkt_resp_fhdr.s_id = pkt->pkt_cmd_fhdr.d_id;
179
180 if ((iocb->ULPSTATUS == 0) && (els->elsCode == 0x02)) {
181 HBASTATS.ElsCmdGood++;
182
183 if (!(sbp->pkt_flags & PACKET_ALLOCATED)) {
184 /*
185 * ULP patch - ULP expects
186 * resp_resid = 0 on success
187 */
188 pkt->pkt_resp_resid = 0;
189 }
190
191 switch (command) {
192 case ELS_CMD_FDISC: /* Fabric login */
193 emlxs_handle_sol_fdisc(port, sbp);
194
195 break;
196
197 case ELS_CMD_FLOGI: /* Fabric login */
198 emlxs_handle_sol_flogi(port, sbp);
199
200 break;
201
202 case ELS_CMD_PLOGI: /* NPort login */
203 emlxs_handle_sol_plogi(port, sbp);
204
205 break;
206
207 case ELS_CMD_ADISC: /* Adisc */
208 emlxs_handle_sol_adisc(port, sbp);
209
210 break;
211
212 case ELS_CMD_LOGO: /* Logout */
213 emlxs_handle_sol_logo(port, sbp);
214
215 break;
216
217 case ELS_CMD_PRLI: /* Process Log In */
218 emlxs_handle_sol_prli(port, sbp);
219
220 break;
221
222 default:
223 EMLXS_MSGF(EMLXS_CONTEXT,
224 &emlxs_els_completion_msg, "%s: did=%x",
225 emlxs_elscmd_xlate(command), did);
226
227 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
228
229 break;
230 }
231
232 } else {
233 HBASTATS.ElsCmdError++;
234
235 /* Look for LS_REJECT */
236 if (iocb->ULPSTATUS == IOSTAT_LS_RJT) {
237 pkt->pkt_state = FC_PKT_LS_RJT;
238 pkt->pkt_action = FC_ACTION_RETRYABLE;
239 pkt->pkt_reason = iocb->un.grsp.perr.statRsn;
240 pkt->pkt_expln = iocb->un.grsp.perr.statBaExp;
241 sbp->pkt_flags |= PACKET_STATE_VALID;
242
243 #ifdef SAN_DIAG_SUPPORT
244 ndlp = emlxs_node_find_did(port, did, 1);
245 if (ndlp) {
246 emlxs_log_sd_lsrjt_event(port,
247 (HBA_WWN *)&ndlp->nlp_portname,
248 command, pkt->pkt_reason,
249 pkt->pkt_expln);
250 }
251 #endif
252
253 EMLXS_MSGF(EMLXS_CONTEXT,
254 &emlxs_els_completion_msg,
255 "%s Rejected: did=%x rsn=%x exp=%x",
256 emlxs_elscmd_xlate(command), did,
257 pkt->pkt_reason, pkt->pkt_expln);
258 } else if (iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) {
259 EMLXS_MSGF(EMLXS_CONTEXT,
260 &emlxs_bad_els_completion_msg,
261 "%s: did=%x Local Reject. %s",
262 emlxs_elscmd_xlate(command), did,
263 emlxs_error_xlate(iocb->un.grsp.perr.
264 statLocalError));
265 } else {
266 EMLXS_MSGF(EMLXS_CONTEXT,
267 &emlxs_bad_els_completion_msg,
268 "%s: did=%x %s (%02x%02x%02x%02x)",
269 emlxs_elscmd_xlate(command), did,
270 emlxs_state_xlate(iocb->ULPSTATUS),
271 iocb->un.grsp.perr.statAction,
272 iocb->un.grsp.perr.statRsn,
273 iocb->un.grsp.perr.statBaExp,
274 iocb->un.grsp.perr.statLocalError);
275 }
276
277 switch (command) {
278 case ELS_CMD_PLOGI: /* NPort login failed */
279 ndlp = emlxs_node_find_did(port, did, 1);
280
281 if (ndlp && ndlp->nlp_active) {
282 /* Open the node again */
283 emlxs_node_open(port, ndlp,
284 hba->channel_fcp);
285 emlxs_node_open(port, ndlp,
286 hba->channel_ip);
287 #ifdef DHCHAP_SUPPORT
288 if (pkt->pkt_state == FC_PKT_LS_RJT) {
289 emlxs_dhc_state(port, ndlp,
290 NODE_STATE_NOCHANGE,
291 pkt->pkt_reason,
292 pkt->pkt_expln);
293 }
294 #endif /* DHCHAP_SUPPORT */
295 }
296
297 break;
298
299
300 case ELS_CMD_PRLI: /* Process Log In failed */
301 ndlp = emlxs_node_find_did(port, did, 1);
302
303 if (ndlp && ndlp->nlp_active) {
304 /* Open the node again */
305 emlxs_node_open(port, ndlp,
306 hba->channel_fcp);
307 }
308
309 break;
310
311 case ELS_CMD_FDISC: /* Fabric login */
312 case ELS_CMD_FLOGI: /* Fabric login */
313 if (pkt->pkt_state == FC_PKT_LS_RJT) {
314 /* This will cause ULP to retry */
315 /* FLOGI requests */
316 pkt->pkt_reason = FC_REASON_QFULL;
317 pkt->pkt_expln = 0;
318
319 #ifdef DHCHAP_SUPPORT
320 ndlp = emlxs_node_find_did(port,
321 did, 1);
322 if (ndlp && ndlp->nlp_active) {
323 emlxs_dhc_state(port, ndlp,
324 NODE_STATE_NOCHANGE,
325 pkt->pkt_reason,
326 pkt->pkt_expln);
327 }
328 #endif /* DHCHAP_SUPPORT */
329 }
330
331 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
332 /* Preset the state for deferred cmpl */
333 emlxs_set_pkt_state(sbp,
334 iocb->ULPSTATUS,
335 iocb->un.grsp.perr.statLocalError,
336 1);
337
338 if (emlxs_vpi_logi_failed_notify(
339 sbp->port, sbp) == 0) {
340 /* Defer completion */
341 return (0);
342 }
343 }
344
345 break;
346
347 default:
348 break;
349 }
350
351 emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
352 iocb->un.grsp.perr.statLocalError, 1);
353 }
354
355 break;
356
357 default:
358
359 HBASTATS.ElsStray++;
360
361 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_invalid_els_msg,
362 "Invalid iocb: cmd=0x%x", iocb->ULPCOMMAND);
363
364 emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
365 iocb->un.grsp.perr.statLocalError, 1);
366
367 break;
368 } /* switch(iocb->ULPCOMMAND) */
369
370 return (0);
371
372 } /* emlxs_els_handle_event() */
373
374
375 extern int
emlxs_els_handle_unsol_req(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)376 emlxs_els_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
377 MATCHMAP *mp, uint32_t size)
378 {
379 emlxs_hba_t *hba = HBA;
380 uint32_t cmd_code;
381 IOCB *iocb;
382
383 HBASTATS.ElsCmdReceived++;
384
385 iocb = &iocbq->iocb;
386 cmd_code = *((uint32_t *)mp->virt) & ELS_CMD_MASK;
387
388 if (!(port->flag & EMLXS_PORT_BOUND)) {
389 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
390 "%s: sid=%x. Port not bound: Rejecting.",
391 emlxs_elscmd_xlate(cmd_code),
392 iocbq->iocb.un.elsreq.remoteID);
393
394 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
395 cmd_code, LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
396
397 return (0);
398 }
399
400 switch (cmd_code) {
401 case ELS_CMD_RSCN:
402 HBASTATS.ElsRscnReceived++;
403 emlxs_handle_unsol_rscn(port, cp, iocbq, mp, size);
404 break;
405
406 case ELS_CMD_FLOGI:
407 HBASTATS.ElsFlogiReceived++;
408 emlxs_handle_unsol_flogi(port, cp, iocbq, mp, size);
409 break;
410
411 case ELS_CMD_PLOGI:
412 HBASTATS.ElsPlogiReceived++;
413 emlxs_handle_unsol_plogi(port, cp, iocbq, mp, size);
414 break;
415
416 case ELS_CMD_PRLI:
417 HBASTATS.ElsPrliReceived++;
418 emlxs_handle_unsol_prli(port, cp, iocbq, mp, size);
419 break;
420
421 case ELS_CMD_PRLO:
422 HBASTATS.ElsPrloReceived++;
423 emlxs_handle_unsol_prlo(port, cp, iocbq, mp, size);
424 break;
425
426 case ELS_CMD_LOGO:
427 HBASTATS.ElsLogoReceived++;
428 emlxs_handle_unsol_logo(port, cp, iocbq, mp, size);
429 break;
430
431 case ELS_CMD_ADISC:
432 HBASTATS.ElsAdiscReceived++;
433 emlxs_handle_unsol_adisc(port, cp, iocbq, mp, size);
434 break;
435
436 case ELS_CMD_AUTH:
437 HBASTATS.ElsAuthReceived++;
438 emlxs_handle_unsol_auth(port, cp, iocbq, mp, size);
439 break;
440
441 case ELS_CMD_TEST:
442 HBASTATS.ElsTestReceived++;
443 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
444 "%s: sid=%x. Dropping.",
445 emlxs_elscmd_xlate(cmd_code),
446 iocbq->iocb.un.elsreq.remoteID);
447
448 /* drop it */
449 emlxs_close_els_exchange(hba, port, iocb->ULPCONTEXT);
450 break;
451
452 case ELS_CMD_ESTC:
453 HBASTATS.ElsEstcReceived++;
454 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
455 "%s: sid=%x. Dropping.",
456 emlxs_elscmd_xlate(cmd_code),
457 iocbq->iocb.un.elsreq.remoteID);
458
459 /* drop it */
460 emlxs_close_els_exchange(hba, port, iocb->ULPCONTEXT);
461 break;
462
463 case ELS_CMD_FARPR:
464 HBASTATS.ElsFarprReceived++;
465
466 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
467 "%s: sid=%x. Dropping.",
468 emlxs_elscmd_xlate(cmd_code),
469 iocbq->iocb.un.elsreq.remoteID);
470
471 /* drop it */
472 emlxs_close_els_exchange(hba, port, iocb->ULPCONTEXT);
473 break;
474
475 case ELS_CMD_ECHO:
476 HBASTATS.ElsEchoReceived++;
477 emlxs_handle_unsol_echo(port, cp, iocbq, mp, size);
478 break;
479
480 case ELS_CMD_RLS:
481 HBASTATS.ElsRlsReceived++;
482 emlxs_handle_unsol_rls(port, cp, iocbq, mp, size);
483 break;
484
485 case ELS_CMD_RTV:
486 HBASTATS.ElsRtvReceived++;
487 emlxs_handle_unsol_rtv(port, cp, iocbq, mp, size);
488 break;
489
490 case ELS_CMD_ABTX:
491 case ELS_CMD_RCS:
492 case ELS_CMD_RES:
493 case ELS_CMD_RSS:
494 case ELS_CMD_RSI:
495 case ELS_CMD_ESTS:
496 case ELS_CMD_RRQ:
497 case ELS_CMD_REC:
498 HBASTATS.ElsGenReceived++;
499
500 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
501 "%s: sid=%x. Rejecting.",
502 emlxs_elscmd_xlate(cmd_code),
503 iocbq->iocb.un.elsreq.remoteID);
504
505 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
506 LSRJT_CMD_UNSUPPORTED, LSEXP_NOTHING_MORE);
507 break;
508
509 default:
510 HBASTATS.ElsGenReceived++;
511 emlxs_handle_unsol_gen_cmd(port, cp, iocbq, mp, size);
512 break;
513 }
514
515 return (0);
516
517 } /* emlxs_els_handle_unsol_req() */
518
519
520 static uint32_t
emlxs_els_delay_discovery(emlxs_port_t * port,emlxs_buf_t * sbp)521 emlxs_els_delay_discovery(emlxs_port_t *port, emlxs_buf_t *sbp)
522 {
523 emlxs_hba_t *hba = HBA;
524 emlxs_config_t *cfg;
525 SERV_PARM *parm;
526
527 cfg = &CFG;
528 if (!cfg[CFG_DELAY_DISCOVERY].current) {
529 return (0);
530 }
531
532 parm = &port->fabric_sparam;
533 if (((port->prev_did != port->did) ||
534 bcmp(&port->prev_fabric_sparam.portName,
535 &port->fabric_sparam.portName, 8)) &&
536 !(parm->cmn.CLEAN_ADDRESS_BIT)) {
537
538 /* If this is the first time, check config parameter */
539 if (port->prev_did || cfg[CFG_DELAY_DISCOVERY].current == 2) {
540
541 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
542 "Clean Address delay: sid=%x prev=%x RATOV %d",
543 port->did, port->prev_did, hba->fc_ratov);
544
545 port->clean_address_sbp = sbp;
546 port->clean_address_timer =
547 hba->timer_tics + hba->fc_ratov;
548
549 return (1);
550 }
551 }
552 return (0);
553
554 } /* emlxs_els_delay_discovery() */
555
556
557 static void
emlxs_handle_sol_flogi(emlxs_port_t * port,emlxs_buf_t * sbp)558 emlxs_handle_sol_flogi(emlxs_port_t *port, emlxs_buf_t *sbp)
559 {
560 emlxs_hba_t *hba = HBA;
561 emlxs_config_t *cfg = &CFG;
562 emlxs_port_t *vport;
563 SERV_PARM *sp;
564 fc_packet_t *pkt;
565 MAILBOXQ *mbox;
566 uint32_t did;
567 IOCBQ *iocbq;
568 IOCB *iocb;
569 char buffer[64];
570 uint32_t i;
571 int rc;
572 uint16_t altBbCredit;
573
574 pkt = PRIV2PKT(sbp);
575 sp = (SERV_PARM *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t));
576 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
577 iocbq = &sbp->iocbq;
578 iocb = &iocbq->iocb;
579
580 mutex_enter(&EMLXS_PORT_LOCK);
581
582 /* Save the fabric service parameters and did */
583 bcopy((void *)sp, (void *)&port->fabric_sparam, sizeof (SERV_PARM));
584
585 /* Save E_D_TOV ticks in nanoseconds */
586 if (sp->cmn.edtovResolution) {
587 hba->fc_edtov = (LE_SWAP32(sp->cmn.e_d_tov) + 999999) / 1000000;
588 } else {
589 hba->fc_edtov = LE_SWAP32(sp->cmn.e_d_tov);
590 }
591
592 /* Save R_A_TOV ticks */
593 hba->fc_ratov = (LE_SWAP32(sp->cmn.w2.r_a_tov) + 999) / 1000;
594
595 if (sp->cmn.fPort) {
596 hba->flag |= FC_FABRIC_ATTACHED;
597 hba->flag &= ~FC_PT_TO_PT;
598
599 port->did = iocb->un.elsreq.myID;
600 pkt->pkt_resp_fhdr.s_id = LE_SWAP24_LO(FABRIC_DID);
601 pkt->pkt_resp_fhdr.d_id = LE_SWAP24_LO(port->did);
602
603 /*
604 * If we are a N-port connected to a Fabric,
605 * fixup sparam's so logins to devices on remote
606 * loops work.
607 */
608 altBbCredit = (hba->topology != TOPOLOGY_LOOP)? 1:0;
609 hba->sparam.cmn.altBbCredit = altBbCredit;
610
611 /* Set this bit in all the port sparam copies */
612 for (i = 0; i < MAX_VPORTS; i++) {
613 vport = &VPORT(i);
614
615 if (!(vport->flag & EMLXS_PORT_BOUND)) {
616 continue;
617 }
618
619 vport->sparam.cmn.altBbCredit = altBbCredit;
620 }
621
622 if (sp->cmn.rspMultipleNPort) {
623 hba->flag |= FC_NPIV_SUPPORTED;
624
625 if (cfg[CFG_NPIV_DELAY].current) {
626 /*
627 * PATCH: for NPIV support on
628 * Brocade switch firmware 5.10b
629 */
630 if ((hba->flag & FC_NPIV_ENABLED) &&
631 ((sp->nodeName.IEEE[0] == 0x00) &&
632 (sp->nodeName.IEEE[1] == 0x05) &&
633 (sp->nodeName.IEEE[2] == 0x1e))) {
634 hba->flag |= FC_NPIV_DELAY_REQUIRED;
635 }
636 }
637 } else {
638 hba->flag |= FC_NPIV_UNSUPPORTED;
639 }
640
641 if (!(hba->flag & FC_NPIV_ENABLED)) {
642 (void) strlcpy(buffer, "npiv:Disabled ",
643 sizeof (buffer));
644 } else if (hba->flag & FC_NPIV_SUPPORTED) {
645 (void) strlcpy(buffer, "npiv:Supported ",
646 sizeof (buffer));
647 } else {
648 (void) strlcpy(buffer, "npiv:Unsupported ",
649 sizeof (buffer));
650 }
651
652 #ifdef DHCHAP_SUPPORT
653 if (!sp->cmn.fcsp_support) {
654 (void) strlcat(buffer, "fcsp:Unsupported",
655 sizeof (buffer));
656 } else if (cfg[CFG_AUTH_ENABLE].current &&
657 (port->vpi == 0 || cfg[CFG_AUTH_NPIV].current)) {
658 (void) strlcat(buffer, "fcsp:Supported",
659 sizeof (buffer));
660 } else {
661 (void) strlcat(buffer, "fcsp:Disabled",
662 sizeof (buffer));
663 }
664 #endif /* DHCHAP_SUPPORT */
665
666 mutex_exit(&EMLXS_PORT_LOCK);
667
668 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
669 "FLOGI: did=%x sid=%x prev=%x %s",
670 did, port->did, port->prev_did, buffer);
671
672 /* Update our service parms */
673 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
674 /* Update our service parms */
675 if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
676 MEM_MBOX))) {
677 emlxs_mb_config_link(hba, mbox);
678
679 rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox,
680 MBX_NOWAIT, 0);
681 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
682 emlxs_mem_put(hba, MEM_MBOX,
683 (void *)mbox);
684 }
685 }
686 }
687
688 /* Preset the state for the reg_did */
689 emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1);
690
691 if (emlxs_els_delay_discovery(port, sbp)) {
692 /* Deferred registration of this pkt until */
693 /* Clean Address timeout */
694 return;
695 }
696
697 if (EMLXS_SLI_REG_DID(port, FABRIC_DID, &port->fabric_sparam,
698 sbp, NULL, NULL) == 0) {
699 /* Deferred completion of this pkt until */
700 /* login is complete */
701 return;
702 }
703
704 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
705 IOERR_NO_RESOURCES, 1);
706
707 } else { /* No switch */
708
709 hba->flag &= ~FC_FABRIC_ATTACHED;
710 hba->flag |= FC_PT_TO_PT;
711
712 hba->flag &= ~FC_NPIV_SUPPORTED;
713 (void) strlcpy(buffer, "npiv:Disabled.", sizeof (buffer));
714
715 if (emlxs_wwn_cmp((uint8_t *)&sp->portName,
716 (uint8_t *)&port->wwpn) > 0) {
717 (void) strlcat(buffer, " P2P Master.",
718 sizeof (buffer));
719 } else {
720 (void) strlcat(buffer, " P2P Slave.",
721 sizeof (buffer));
722 }
723
724 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
725 "FLOGI: did=%x sid=%x %s", did, port->did, buffer);
726
727 mutex_exit(&EMLXS_PORT_LOCK);
728
729 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
730 /* Preset the state for the reg_did */
731 emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1);
732
733 if (EMLXS_SLI_REG_DID(port, FABRIC_DID,
734 &port->fabric_sparam, sbp, NULL, NULL) == 0) {
735 /* Deferred completion of this pkt until */
736 /* login is complete */
737 return;
738 }
739
740 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
741 IOERR_NO_RESOURCES, 1);
742
743 } else {
744 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
745 }
746 }
747
748 return;
749
750 } /* emlxs_handle_sol_flogi() */
751
752
753 static void
emlxs_handle_sol_fdisc(emlxs_port_t * port,emlxs_buf_t * sbp)754 emlxs_handle_sol_fdisc(emlxs_port_t *port, emlxs_buf_t *sbp)
755 {
756 emlxs_hba_t *hba = HBA;
757 emlxs_config_t *cfg = &CFG;
758 SERV_PARM *sp;
759 fc_packet_t *pkt;
760 uint32_t did;
761 IOCBQ *iocbq;
762 IOCB *iocb;
763 char buffer[64];
764
765 pkt = PRIV2PKT(sbp);
766 sp = (SERV_PARM *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t));
767 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
768 iocbq = &sbp->iocbq;
769 iocb = &iocbq->iocb;
770
771 mutex_enter(&EMLXS_PORT_LOCK);
772
773 /* Save the fabric service parameters and did */
774 port->did = iocb->un.elsreq.myID;
775 bcopy((void *)sp, (void *)&port->fabric_sparam, sizeof (SERV_PARM));
776
777 pkt->pkt_resp_fhdr.d_id = LE_SWAP24_LO(port->did);
778
779 mutex_exit(&EMLXS_PORT_LOCK);
780
781 buffer[0] = 0;
782
783 #ifdef DHCHAP_SUPPORT
784 if (!sp->cmn.fcsp_support) {
785 (void) strlcat(buffer, "fcsp:Unsupported",
786 sizeof (buffer));
787 } else if (cfg[CFG_AUTH_ENABLE].current && cfg[CFG_AUTH_NPIV].current) {
788 (void) strlcat(buffer, "fcsp:Supported",
789 sizeof (buffer));
790 } else {
791 (void) strlcat(buffer, "fcsp:Disabled",
792 sizeof (buffer));
793 }
794 #endif /* DHCHAP_SUPPORT */
795
796 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
797 "FDISC: did=%x sid=%x %s", did, port->did, buffer);
798
799 /* Preset the state for the reg_did */
800 emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1);
801
802 if (emlxs_els_delay_discovery(port, sbp)) {
803 /* Deferred registration of this pkt until */
804 /* Clean Address timeout */
805 return;
806 }
807
808 if (EMLXS_SLI_REG_DID(port, FABRIC_DID, &port->fabric_sparam, sbp,
809 NULL, NULL) == 0) {
810 /*
811 * Deferred completion of this pkt until login is complete
812 */
813 return;
814 }
815
816 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, IOERR_NO_RESOURCES, 1);
817
818 return;
819
820 } /* emlxs_handle_sol_fdisc() */
821
822
823 static void
emlxs_handle_sol_plogi(emlxs_port_t * port,emlxs_buf_t * sbp)824 emlxs_handle_sol_plogi(emlxs_port_t *port, emlxs_buf_t *sbp)
825 {
826 emlxs_hba_t *hba = HBA;
827 emlxs_config_t *cfg = &CFG;
828 SERV_PARM *sp;
829 fc_packet_t *pkt;
830 uint32_t did;
831 uint32_t sid;
832 NODELIST *ndlp;
833 char buffer[64];
834
835 pkt = PRIV2PKT(sbp);
836 sp = (SERV_PARM *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t));
837 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
838 sid = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.s_id);
839
840 buffer[0] = 0;
841
842 #ifdef DHCHAP_SUPPORT
843 if (!sp->cmn.fcsp_support) {
844 (void) strlcat(buffer, "fcsp:Unsupported",
845 sizeof (buffer));
846 } else if (cfg[CFG_AUTH_ENABLE].current && cfg[CFG_AUTH_E2E].current &&
847 (port->vpi == 0 || cfg[CFG_AUTH_NPIV].current)) {
848 (void) strlcat(buffer, "fcsp:Supported",
849 sizeof (buffer));
850 } else {
851 (void) strlcat(buffer, "fcsp:Disabled",
852 sizeof (buffer));
853 }
854 #endif /* DHCHAP_SUPPORT */
855
856 if (hba->flag & FC_PT_TO_PT) {
857 mutex_enter(&EMLXS_PORT_LOCK);
858
859 port->did = sid;
860 port->rdid = did;
861
862 /* Save E_D_TOV ticks in nanoseconds */
863 if (sp->cmn.edtovResolution) {
864 hba->fc_edtov =
865 (LE_SWAP32(sp->cmn.e_d_tov) + 999999) / 1000000;
866 } else {
867 hba->fc_edtov = LE_SWAP32(sp->cmn.e_d_tov);
868 }
869
870 /* Only E_D_TOV is valid for PLOGI in pt2pt mode */
871
872 mutex_exit(&EMLXS_PORT_LOCK);
873 }
874
875 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
876 "PLOGI: sid=%x did=%x %s", sid, did, buffer);
877
878 /* Preset the pkt state for reg_did */
879 emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1);
880
881 /*
882 * Do register login to Firmware before calling packet completion
883 */
884 if (EMLXS_SLI_REG_DID(port, did, sp, sbp, NULL, NULL) == 0) {
885 /*
886 * Deferred completion of this pkt until login is complete
887 */
888 return;
889 }
890
891 ndlp = emlxs_node_find_did(port, did, 1);
892
893 if (ndlp && ndlp->nlp_active) {
894 /* Open the node again */
895 emlxs_node_open(port, ndlp, hba->channel_fcp);
896 emlxs_node_open(port, ndlp, hba->channel_ip);
897 }
898
899 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, IOERR_NO_RESOURCES, 1);
900
901 return;
902
903 } /* emlxs_handle_sol_plogi() */
904
905
906 static void
emlxs_handle_sol_adisc(emlxs_port_t * port,emlxs_buf_t * sbp)907 emlxs_handle_sol_adisc(emlxs_port_t *port, emlxs_buf_t *sbp)
908 {
909 emlxs_hba_t *hba = HBA;
910 fc_packet_t *pkt;
911 uint32_t did;
912 NODELIST *ndlp;
913
914 pkt = PRIV2PKT(sbp);
915 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
916
917 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg, "ADISC: did=%x",
918 did);
919
920 ndlp = emlxs_node_find_did(port, did, 1);
921
922 if (ndlp && ndlp->nlp_active) {
923 /* Open the node again */
924 emlxs_node_open(port, ndlp, hba->channel_fcp);
925 emlxs_node_open(port, ndlp, hba->channel_ip);
926
927 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
928
929 emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1);
930
931 if (emlxs_rpi_resume_notify(port,
932 ndlp->rpip, sbp) == 0) {
933 /*
934 * Delay ADISC cmpl to ULP till
935 * after RESUME_RPI
936 */
937 return;
938 }
939 }
940 }
941
942 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
943
944 return;
945
946 } /* emlxs_handle_sol_adisc() */
947
948
949 static void
emlxs_handle_sol_prli(emlxs_port_t * port,emlxs_buf_t * sbp)950 emlxs_handle_sol_prli(emlxs_port_t *port, emlxs_buf_t *sbp)
951 {
952 emlxs_hba_t *hba = HBA;
953 emlxs_config_t *cfg = &CFG;
954 fc_packet_t *pkt;
955 NODELIST *ndlp;
956 uint32_t did;
957 PRLI *npr;
958 uint32_t task_retry_id;
959
960 pkt = PRIV2PKT(sbp);
961 npr = (PRLI *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t));
962 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
963
964 ndlp = emlxs_node_find_did(port, did, 1);
965
966 if (ndlp && ndlp->nlp_active) {
967 /* Check for FCP support */
968 if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) &&
969 (npr->prliType == PRLI_FCP_TYPE)) {
970 /* Clear FCP2 support if no ADISC support requested */
971 if (cfg[CFG_ADISC_SUPPORT].current == 0) {
972 npr->ConfmComplAllowed = 0;
973 npr->TaskRetryIdReq = 0;
974 npr->Retry = 0;
975 }
976
977 /* Check for target */
978 if (npr->targetFunc) {
979 ndlp->nlp_fcp_info |= NLP_FCP_TGT_DEVICE;
980 } else {
981 ndlp->nlp_fcp_info &= ~NLP_FCP_TGT_DEVICE;
982 }
983 #ifdef NODE_THROTTLE_SUPPORT
984 emlxs_node_throttle_set(port, ndlp);
985 #endif /* NODE_THROTTLE_SUPPORT */
986
987 /* Check for initiator */
988 if (npr->initiatorFunc) {
989 ndlp->nlp_fcp_info |= NLP_FCP_INI_DEVICE;
990 } else {
991 ndlp->nlp_fcp_info &= ~NLP_FCP_INI_DEVICE;
992 }
993
994 /* If TRI support is not required then force */
995 /* the task_retry_id value to one */
996 if (cfg[CFG_TRI_REQUIRED].current == 0) {
997 task_retry_id = 1;
998 } else {
999 task_retry_id = npr->TaskRetryIdReq;
1000 }
1001
1002 /* Check for FCP2 target support */
1003 /* Retry and TaskRetryId bits are both required here */
1004 if (npr->targetFunc && npr->Retry && task_retry_id) {
1005 ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
1006 } else {
1007 ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
1008 }
1009 }
1010
1011 /* Open the node again */
1012 emlxs_node_open(port, ndlp, hba->channel_fcp);
1013
1014 EMLXS_SET_DFC_STATE(ndlp, NODE_ALLOC);
1015
1016 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
1017 "PRLI: did=%x info=%02x", did, ndlp->nlp_fcp_info);
1018
1019 /*
1020 * Report PRLI completion
1021 */
1022 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
1023
1024 } else {
1025 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
1026 "PRLI: did=%x: Node not found. Failing.", did);
1027
1028 /*
1029 * Report PRLI failed
1030 */
1031 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
1032 IOERR_INVALID_RPI, 1);
1033 }
1034 return;
1035
1036 } /* emlxs_handle_sol_prli() */
1037
1038
1039 static void
emlxs_handle_sol_logo(emlxs_port_t * port,emlxs_buf_t * sbp)1040 emlxs_handle_sol_logo(emlxs_port_t *port, emlxs_buf_t *sbp)
1041 {
1042 emlxs_hba_t *hba = HBA;
1043 fc_packet_t *pkt;
1044 uint32_t did;
1045 NODELIST *ndlp;
1046
1047 pkt = PRIV2PKT(sbp);
1048 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
1049
1050 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg, "LOGO: did=%x",
1051 did);
1052
1053 ndlp = emlxs_node_find_did(port, did, 1);
1054
1055 if (ndlp && ndlp->nlp_active) {
1056 EMLXS_SET_DFC_STATE(ndlp, NODE_LOGOUT);
1057
1058 if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) &&
1059 (ndlp->nlp_DID == FABRIC_DID)) {
1060 (void) emlxs_vpi_logo_cmpl_notify(port);
1061 } else {
1062 /* Close the node for any further normal IO */
1063 emlxs_node_close(port, ndlp, hba->channel_fcp, 60);
1064 emlxs_node_close(port, ndlp, hba->channel_ip, 60);
1065
1066 /* Flush tx queues */
1067 (void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0);
1068
1069 /* Flush chip queues */
1070 (void) emlxs_chipq_node_flush(port, 0, ndlp, 0);
1071 }
1072 }
1073
1074 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
1075
1076 if ((hba->sli_mode == EMLXS_HBA_SLI3_MODE) &&
1077 (ndlp->nlp_DID == FABRIC_DID)) {
1078 port->flag &= ~EMLXS_PORT_FLOGI_CMPL;
1079 }
1080
1081 return;
1082
1083 } /* emlxs_handle_sol_logo() */
1084
1085
1086 /* ARGSUSED */
1087 static void
emlxs_handle_unsol_rscn(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)1088 emlxs_handle_unsol_rscn(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1089 MATCHMAP *mp, uint32_t size)
1090 {
1091 uint32_t *lp;
1092 fc_unsol_buf_t *ubp;
1093 uint8_t *bp;
1094 IOCB *iocb;
1095 uint32_t count;
1096 uint32_t sid;
1097 emlxs_ub_priv_t *ub_priv;
1098
1099 iocb = &iocbq->iocb;
1100 bp = mp->virt;
1101 lp = (uint32_t *)bp + 1;
1102 sid = iocb->un.elsreq.remoteID;
1103
1104 /* Log the legacy rscn event for physical port only */
1105 if (port->vpi == 0) {
1106 emlxs_log_rscn_event(port, bp, size);
1107 }
1108
1109 /* Log the vport rscn event for all ports */
1110 emlxs_log_vportrscn_event(port, bp, size);
1111
1112 count = ((size - 4) / 4);
1113
1114 ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size,
1115 FC_TYPE_EXTENDED_LS, 1);
1116
1117 if (ubp == NULL) {
1118 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
1119 "RSCN rcvd: sid=%x %d page(s): %08X, %08X. Rejecting.",
1120 sid, count, LE_SWAP32(*lp),
1121 ((count > 1) ? LE_SWAP32(*(lp + 1)) : 0));
1122
1123 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1124 ELS_CMD_RSCN, LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
1125
1126 goto drop_it;
1127 }
1128
1129 bcopy(bp, ubp->ub_buffer, size);
1130 ub_priv = ubp->ub_fca_private;
1131 ub_priv->cmd = ELS_CMD_RSCN;
1132
1133 /*
1134 * Setup frame header
1135 */
1136 ubp->ub_frame.r_ctl = FC_ELS_REQ;
1137 ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
1138 ubp->ub_frame.s_id = LE_SWAP24_LO(iocb->un.elsreq.remoteID);
1139 ubp->ub_frame.d_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
1140 ubp->ub_frame.ox_id = ub_priv->token;
1141 ubp->ub_frame.rx_id = iocb->ULPCONTEXT;
1142 ubp->ub_class = FC_TRAN_CLASS3;
1143
1144 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1145 "RSCN: sid=%x %d page(s): %08X, %08X buffer=%p token=%x.", sid,
1146 count, LE_SWAP32(*lp),
1147 ((count > 1) ? LE_SWAP32(*(lp + 1)) : 0), ubp, ub_priv->token);
1148
1149 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
1150 emlxs_swap_els_ub(ubp);
1151 #endif /* EMLXS_MODREV2X */
1152
1153 emlxs_ub_callback(port, ubp);
1154
1155 drop_it:
1156
1157 return;
1158
1159 } /* emlxs_handle_unsol_rscn() */
1160
1161
1162 /* This is shared by FCT driver */
1163 extern uint32_t
emlxs_process_unsol_flogi(emlxs_port_t * port,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size,char * buffer,size_t len)1164 emlxs_process_unsol_flogi(emlxs_port_t *port, IOCBQ *iocbq, MATCHMAP *mp,
1165 uint32_t size, char *buffer, size_t len)
1166 {
1167 emlxs_hba_t *hba = HBA;
1168 emlxs_config_t *cfg = &CFG;
1169 uint8_t *bp;
1170 IOCB *iocb;
1171 uint32_t sid;
1172 SERV_PARM *sp;
1173
1174 iocb = &iocbq->iocb;
1175 sid = iocb->un.elsreq.remoteID;
1176
1177 /* Check payload size */
1178 if (size < (sizeof (SERV_PARM) + 4)) {
1179 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1180 "FLOGI: sid=%x. Payload too small. %d<%d Rejecting.", sid,
1181 size, (sizeof (SERV_PARM) + 4));
1182
1183 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1184 ELS_CMD_FLOGI, LSRJT_PROTOCOL_ERR, LSEXP_NOTHING_MORE);
1185
1186 return (1);
1187 }
1188
1189 bp = mp->virt;
1190 sp = (SERV_PARM *)(bp + sizeof (uint32_t));
1191
1192 mutex_enter(&EMLXS_PORT_LOCK);
1193
1194 hba->flag &= ~FC_FABRIC_ATTACHED;
1195 hba->flag |= FC_PT_TO_PT;
1196
1197 bcopy((void *)sp, (void *)&port->fabric_sparam, sizeof (SERV_PARM));
1198
1199 /* Save E_D_TOV ticks in nanoseconds */
1200 if (sp->cmn.edtovResolution) {
1201 hba->fc_edtov =
1202 (LE_SWAP32(sp->cmn.e_d_tov) + 999999) / 1000000;
1203 } else {
1204 hba->fc_edtov = LE_SWAP32(sp->cmn.e_d_tov);
1205 }
1206
1207 /* Typically the FLOGI ACC rsp has the R_A_TOV value both sides use */
1208
1209 hba->flag &= ~FC_NPIV_SUPPORTED;
1210 (void) strlcpy(buffer, "npiv:Disabled.", len);
1211
1212 if (emlxs_wwn_cmp((uint8_t *)&sp->portName,
1213 (uint8_t *)&port->wwpn) > 0) {
1214 (void) strlcat(buffer, " P2P Master.", len);
1215 } else {
1216 (void) strlcat(buffer, " P2P Slave.", len);
1217 }
1218
1219 #ifdef DHCHAP_SUPPORT
1220 if (!sp->cmn.fcsp_support) {
1221 (void) strlcat(buffer, " fcsp:Unsupported", len);
1222 } else if (cfg[CFG_AUTH_ENABLE].current &&
1223 (port->vpi == 0 || cfg[CFG_AUTH_NPIV].current)) {
1224 (void) strlcat(buffer, " fcsp:Supported", len);
1225 } else {
1226 (void) strlcat(buffer, " fcsp:Disabled", len);
1227 }
1228 #endif /* DHCHAP_SUPPORT */
1229
1230 mutex_exit(&EMLXS_PORT_LOCK);
1231
1232 return (0);
1233
1234 } /* emlxs_process_unsol_flogi() */
1235
1236
1237 /* ARGSUSED */
1238 static void
emlxs_handle_unsol_flogi(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)1239 emlxs_handle_unsol_flogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1240 MATCHMAP *mp, uint32_t size)
1241 {
1242 uint8_t *bp;
1243 fc_unsol_buf_t *ubp;
1244 IOCB *iocb;
1245 uint32_t sid;
1246 emlxs_ub_priv_t *ub_priv;
1247 char buffer[64];
1248
1249 buffer[0] = 0;
1250
1251 /* Perform processing of FLOGI payload */
1252 if (emlxs_process_unsol_flogi(port, iocbq, mp, size, buffer,
1253 sizeof (buffer))) {
1254 return;
1255 }
1256
1257 iocb = &iocbq->iocb;
1258 sid = iocb->un.elsreq.remoteID;
1259 bp = mp->virt;
1260 size = sizeof (SERV_PARM) + 4;
1261
1262 ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size,
1263 FC_TYPE_EXTENDED_LS, 0);
1264
1265 if (ubp == NULL) {
1266 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
1267 "FLOGI rcvd: sid=%x. Rejecting.", sid);
1268
1269 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1270 ELS_CMD_FLOGI, LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
1271
1272 goto drop_it;
1273 }
1274
1275 /*
1276 * Setup unsolicited buffer and pass it up
1277 */
1278 bcopy(bp, ubp->ub_buffer, size);
1279 ub_priv = ubp->ub_fca_private;
1280 ub_priv->cmd = ELS_CMD_FLOGI;
1281
1282 /*
1283 * Setup frame header
1284 */
1285 ubp->ub_frame.r_ctl = FC_ELS_REQ;
1286 ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
1287 ubp->ub_frame.s_id = LE_SWAP24_LO(iocb->un.elsreq.remoteID);
1288 ubp->ub_frame.d_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
1289 ubp->ub_frame.ox_id = ub_priv->token;
1290 ubp->ub_frame.rx_id = iocb->ULPCONTEXT;
1291 ubp->ub_class = FC_TRAN_CLASS3;
1292
1293 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1294 "FLOGI: sid=%x buffer=%p token=%x %s", sid, ubp, ub_priv->token,
1295 buffer);
1296
1297 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
1298 emlxs_swap_els_ub(ubp);
1299 #endif /* EMLXS_MODREV2X */
1300
1301 emlxs_ub_callback(port, ubp);
1302
1303 drop_it:
1304
1305 return;
1306
1307 } /* emlxs_handle_unsol_flogi() */
1308
1309
1310
1311 /* This is shared by FCT driver */
1312 extern uint32_t
emlxs_process_unsol_plogi(emlxs_port_t * port,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size,char * buffer,size_t len)1313 emlxs_process_unsol_plogi(emlxs_port_t *port, IOCBQ *iocbq, MATCHMAP *mp,
1314 uint32_t size, char *buffer, size_t len)
1315 {
1316 emlxs_hba_t *hba = HBA;
1317 emlxs_config_t *cfg = &CFG;
1318 uint8_t *bp;
1319 IOCB *iocb;
1320 uint32_t sid;
1321 uint32_t did;
1322 SERV_PARM *sp;
1323 MAILBOXQ *mbox;
1324 emlxs_vvl_fmt_t vvl;
1325 int rc;
1326
1327 iocb = &iocbq->iocb;
1328 did = iocb->un.elsreq.myID;
1329 sid = iocb->un.elsreq.remoteID;
1330
1331 if (size < (sizeof (SERV_PARM) + 4)) {
1332 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1333 "PLOGI: sid=%x. Payload too small. %d<%d Rejecting.", sid,
1334 size, (sizeof (SERV_PARM) + 4));
1335
1336 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1337 ELS_CMD_PLOGI, LSRJT_PROTOCOL_ERR, LSEXP_NOTHING_MORE);
1338
1339 return (1);
1340 }
1341
1342 bp = mp->virt;
1343 sp = (SERV_PARM *)(bp + sizeof (uint32_t));
1344
1345 bzero((char *)&vvl, sizeof (emlxs_vvl_fmt_t));
1346
1347 if (sp->VALID_VENDOR_VERSION) {
1348
1349 bcopy((caddr_t *)&sp->vendorVersion[0],
1350 (caddr_t *)&vvl, sizeof (emlxs_vvl_fmt_t));
1351 vvl.un0.word0 = LE_SWAP32(vvl.un0.word0);
1352 vvl.un1.word1 = LE_SWAP32(vvl.un1.word1);
1353 }
1354
1355 if ((port->mode == MODE_INITIATOR) &&
1356 (port->flag & EMLXS_PORT_RESTRICTED)) {
1357 uint32_t reject_it = 0;
1358
1359 /* If remote port is the virtual port, then reject it */
1360 if ((vvl.un0.w0.oui == 0x0000C9) && (vvl.un1.w1.vport)) {
1361 reject_it = 1;
1362 }
1363
1364 /* If we are a virtual port and the remote device */
1365 /* is not a switch, then reject it */
1366 else if (port->vpi && ((sid & FABRIC_DID_MASK) !=
1367 FABRIC_DID_MASK)) {
1368 reject_it = 1;
1369 }
1370
1371 if (reject_it) {
1372 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1373 "PLOGI rcvd: sid=%x. Restricted. Rejecting.",
1374 sid);
1375
1376 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1377 ELS_CMD_PLOGI, LSRJT_UNABLE_TPC,
1378 LSEXP_NOTHING_MORE);
1379
1380 /* Clear temporary RPI in firmware */
1381 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
1382 (void) EMLXS_SLI_REG_DID(port, sid, sp,
1383 NULL, NULL, (IOCBQ *)1);
1384 }
1385
1386 return (1);
1387 }
1388 }
1389
1390 #ifdef DHCHAP_SUPPORT
1391 if (emlxs_dhc_verify_login(port, sid, sp)) {
1392 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1393 "PLOGI: sid=%x. FCSP disabled. Rejecting.", sid);
1394
1395 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1396 ELS_CMD_PLOGI, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
1397
1398 return (1);
1399 }
1400
1401 if (!sp->cmn.fcsp_support) {
1402 (void) strlcat(buffer, "fcsp:Unsupported", len);
1403 } else if (cfg[CFG_AUTH_ENABLE].current && cfg[CFG_AUTH_E2E].current &&
1404 (port->vpi == 0 || cfg[CFG_AUTH_NPIV].current)) {
1405 (void) strlcat(buffer, "fcsp:Supported", len);
1406 } else {
1407 (void) strlcat(buffer, "fcsp:Disabled", len);
1408 }
1409 #endif /* DHCHAP_SUPPORT */
1410
1411 /* Check if this was a point to point Plogi */
1412 if (hba->flag & FC_PT_TO_PT) {
1413 mutex_enter(&EMLXS_PORT_LOCK);
1414
1415 port->did = did;
1416 port->rdid = sid;
1417
1418 /* Save E_D_TOV ticks in nanoseconds */
1419 if (sp->cmn.edtovResolution) {
1420 hba->fc_edtov =
1421 (LE_SWAP32(sp->cmn.e_d_tov) + 999999) / 1000000;
1422 } else {
1423 hba->fc_edtov = LE_SWAP32(sp->cmn.e_d_tov);
1424 }
1425
1426 /* Only E_D_TOV is valid for PLOGI in pt2pt mode */
1427
1428 mutex_exit(&EMLXS_PORT_LOCK);
1429
1430 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
1431 /* Update our service parms */
1432 if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
1433 MEM_MBOX))) {
1434 emlxs_mb_config_link(hba, mbox);
1435
1436 rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox,
1437 MBX_NOWAIT, 0);
1438 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
1439 emlxs_mem_put(hba, MEM_MBOX,
1440 (void *)mbox);
1441 }
1442
1443 }
1444 }
1445 }
1446
1447 return (0);
1448
1449 } /* emlxs_process_unsol_plogi() */
1450
1451
1452 /* ARGSUSED */
1453 static void
emlxs_handle_unsol_plogi(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)1454 emlxs_handle_unsol_plogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1455 MATCHMAP *mp, uint32_t size)
1456 {
1457 emlxs_hba_t *hba = HBA;
1458 fc_unsol_buf_t *ubp;
1459 uint8_t *bp;
1460 IOCB *iocb;
1461 uint32_t sid;
1462 uint32_t did;
1463 emlxs_ub_priv_t *ub_priv;
1464 SERV_PARM *sp;
1465 char buffer[64];
1466
1467 buffer[0] = 0;
1468
1469 /* Perform processing of PLOGI payload */
1470 if (emlxs_process_unsol_plogi(port, iocbq, mp, size, buffer,
1471 sizeof (buffer))) {
1472 return;
1473 }
1474
1475 iocb = &iocbq->iocb;
1476 sid = iocb->un.elsreq.remoteID;
1477 did = iocb->un.elsreq.myID;
1478 bp = mp->virt;
1479 sp = (SERV_PARM *)(bp + sizeof (uint32_t));
1480 size = sizeof (SERV_PARM) + 4;
1481
1482 #ifdef SAN_DIAG_SUPPORT
1483 emlxs_log_sd_basic_els_event(port, SD_ELS_SUBCATEGORY_PLOGI_RCV,
1484 (HBA_WWN *)&sp->portName, (HBA_WWN *)&sp->nodeName);
1485 #endif
1486
1487 ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size,
1488 FC_TYPE_EXTENDED_LS, 0);
1489
1490 if (ubp == NULL) {
1491 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
1492 "PLOGI rcvd: sid=%x. Rejecting.", sid);
1493
1494 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1495 ELS_CMD_PLOGI, LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
1496
1497 goto drop_it;
1498 }
1499
1500 /*
1501 * Setup unsolicited buffer and pass it up
1502 */
1503 bcopy(bp, ubp->ub_buffer, size);
1504 ub_priv = ubp->ub_fca_private;
1505 ub_priv->cmd = ELS_CMD_PLOGI;
1506
1507 /*
1508 * Setup frame header
1509 */
1510 ubp->ub_frame.r_ctl = FC_ELS_REQ;
1511 ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
1512 ubp->ub_frame.s_id = LE_SWAP24_LO(iocb->un.elsreq.remoteID);
1513 ubp->ub_frame.d_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
1514 ubp->ub_frame.ox_id = ub_priv->token;
1515 ubp->ub_frame.rx_id = iocb->ULPCONTEXT;
1516 ubp->ub_class = FC_TRAN_CLASS3;
1517
1518 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1519 "PLOGI: sid=%x did=%x buffer=%p token=%x %s", sid, did, ubp,
1520 ub_priv->token, buffer);
1521
1522 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
1523 emlxs_swap_els_ub(ubp);
1524 #endif /* EMLXS_MODREV2X */
1525
1526 /* Create a new node and defer callback */
1527 if (EMLXS_SLI_REG_DID(port, sid, sp, NULL, ubp, NULL) == 0) {
1528 /*
1529 * Defer completion of this pkt until login is complete
1530 */
1531 goto drop_it;
1532 }
1533
1534 emlxs_ub_callback(port, ubp);
1535
1536 drop_it:
1537
1538 return;
1539
1540 } /* emlxs_handle_unsol_plogi() */
1541
1542
1543 /* ARGSUSED */
1544 static void
emlxs_handle_unsol_prli(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)1545 emlxs_handle_unsol_prli(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1546 MATCHMAP *mp, uint32_t size)
1547 {
1548 emlxs_hba_t *hba = HBA;
1549 emlxs_config_t *cfg = &CFG;
1550 IOCB *iocb;
1551 uint32_t sid;
1552 NODELIST *ndlp;
1553 PRLI *npr;
1554 fc_unsol_buf_t *ubp;
1555 emlxs_ub_priv_t *ub_priv;
1556 uint32_t task_retry_id;
1557
1558 iocb = &iocbq->iocb;
1559 sid = iocb->un.elsreq.remoteID;
1560 ndlp = emlxs_node_find_did(port, sid, 1);
1561
1562 if (!ndlp || !ndlp->nlp_active) {
1563 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1564 "PRLI: sid=%x: Node not found. Rejecting.", sid);
1565
1566 /* Auto reply to PRLI's */
1567 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1568 ELS_CMD_PRLI, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
1569
1570 goto drop_it;
1571 }
1572
1573 /* If node exists then save FCP2 support */
1574 npr = (PRLI *)((caddr_t)mp->virt + sizeof (uint32_t));
1575
1576 /* Check for FCP2 support */
1577 if ((npr->prliType == PRLI_FCP_TYPE) && npr->targetFunc) {
1578 /* Clear FCP2 support if no ADISC support is requested */
1579 if (cfg[CFG_ADISC_SUPPORT].current == 0) {
1580 npr->ConfmComplAllowed = 0;
1581 npr->TaskRetryIdReq = 0;
1582 npr->Retry = 0;
1583 }
1584
1585 /* Check for target */
1586 if (npr->targetFunc) {
1587 ndlp->nlp_fcp_info |= NLP_FCP_TGT_DEVICE;
1588 } else {
1589 ndlp->nlp_fcp_info &= ~NLP_FCP_TGT_DEVICE;
1590 }
1591 #ifdef NODE_THROTTLE_SUPPORT
1592 emlxs_node_throttle_set(port, ndlp);
1593 #endif /* NODE_THROTTLE_SUPPORT */
1594
1595 /* Check for initiator */
1596 if (npr->initiatorFunc) {
1597 ndlp->nlp_fcp_info |= NLP_FCP_INI_DEVICE;
1598 } else {
1599 ndlp->nlp_fcp_info &= ~NLP_FCP_INI_DEVICE;
1600 }
1601
1602 /* If TRI support is not required then force */
1603 /* the task_retry_id value to one */
1604 if (cfg[CFG_TRI_REQUIRED].current == 0) {
1605 task_retry_id = 1;
1606 } else {
1607 task_retry_id = npr->TaskRetryIdReq;
1608 }
1609
1610 /* Check for FCP2 target support */
1611 /* Retry and TaskRetryId bits are both required here */
1612 if (npr->targetFunc && npr->Retry && task_retry_id) {
1613 ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
1614 } else {
1615 ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
1616 }
1617 }
1618
1619 #ifdef ULP_PATCH3
1620 if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH3) {
1621 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1622 "PRLI: sid=%x. Accepting.", sid);
1623
1624 /* Auto reply to PRLI's */
1625 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC,
1626 ELS_CMD_PRLI, 0, 0);
1627 goto drop_it;
1628 }
1629 #endif /* ULP_PATCH3 */
1630
1631 /* Tell ULP about it */
1632 ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size,
1633 FC_TYPE_EXTENDED_LS, 0);
1634
1635 if (ubp == NULL) {
1636 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
1637 "PRLI rcvd: sid=%x. Rejecting.", sid);
1638
1639 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1640 ELS_CMD_PRLI, LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
1641
1642 goto drop_it;
1643 }
1644
1645 /*
1646 * Setup unsolicited buffer and pass it up
1647 */
1648 bcopy(mp->virt, ubp->ub_buffer, size);
1649 ub_priv = ubp->ub_fca_private;
1650 ub_priv->cmd = ELS_CMD_PRLI;
1651
1652 /*
1653 * Setup frame header
1654 */
1655 ubp->ub_frame.r_ctl = FC_ELS_REQ;
1656 ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
1657 ubp->ub_frame.s_id = LE_SWAP24_LO(iocb->un.elsreq.remoteID);
1658 ubp->ub_frame.d_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
1659 ubp->ub_frame.ox_id = ub_priv->token;
1660 ubp->ub_frame.rx_id = iocb->ULPCONTEXT;
1661 ubp->ub_class = FC_TRAN_CLASS3;
1662
1663 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1664 "PRLI: sid=%x buffer=%p token=%x info=%02x", sid, ubp,
1665 ub_priv->token, ndlp->nlp_fcp_info);
1666
1667 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
1668 emlxs_swap_els_ub(ubp);
1669 #endif /* EMLXS_MODREV2X */
1670
1671 emlxs_ub_callback(port, ubp);
1672
1673 drop_it:
1674
1675 return;
1676
1677 } /* emlxs_handle_unsol_prli() */
1678
1679
1680 /* ARGSUSED */
1681 static void
emlxs_handle_unsol_auth(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)1682 emlxs_handle_unsol_auth(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1683 MATCHMAP *mp, uint32_t size)
1684 {
1685 IOCB *iocb;
1686 uint32_t sid;
1687 NODELIST *ndlp;
1688
1689 iocb = &iocbq->iocb;
1690 sid = iocb->un.elsreq.remoteID;
1691
1692 #ifdef DHCHAP_SUPPORT
1693 ndlp = emlxs_node_find_did(port, sid, 1);
1694
1695 if (!ndlp || !ndlp->nlp_active) {
1696 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1697 "AUTH: sid=%x: Node not found. Rejecting.", sid);
1698
1699 /* Auto reply to AUTH_ELS's */
1700 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1701 ELS_CMD_AUTH, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
1702
1703 goto drop_it;
1704 }
1705
1706 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, "AUTH: sid=%x", sid);
1707
1708 (void) emlxs_dhchap_state_machine(port, cp, iocbq, mp, ndlp,
1709 NODE_EVENT_RCV_AUTH_MSG);
1710 #else
1711
1712 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1713 "AUTH: sid=%x: Rejecting.", sid);
1714 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, ELS_CMD_AUTH,
1715 LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
1716
1717 #endif /* DHCAHP_SUPPORT */
1718
1719 drop_it:
1720
1721 return;
1722
1723 } /* emlxs_handle_unsol_auth() */
1724
1725
1726 /* ARGSUSED */
1727 static void
emlxs_handle_unsol_adisc(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)1728 emlxs_handle_unsol_adisc(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1729 MATCHMAP *mp, uint32_t size)
1730 {
1731 IOCB *iocb;
1732 #ifdef SAN_DIAG_SUPPORT
1733 NODELIST *ndlp;
1734 #endif
1735 uint32_t sid;
1736
1737 iocb = &iocbq->iocb;
1738 sid = iocb->un.elsreq.remoteID;
1739
1740 #ifdef SAN_DIAG_SUPPORT
1741 ndlp = emlxs_node_find_did(port, sid, 1);
1742
1743 if (ndlp) {
1744 emlxs_log_sd_basic_els_event(port, SD_ELS_SUBCATEGORY_ADISC_RCV,
1745 (HBA_WWN *)&ndlp->nlp_portname,
1746 (HBA_WWN *)&ndlp->nlp_nodename);
1747 }
1748 #endif
1749
1750 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1751 "ADISC: sid=%x: Accepting.", sid);
1752 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, ELS_CMD_ADISC, 0, 0);
1753
1754 return;
1755
1756 } /* emlxs_handle_unsol_adisc() */
1757
1758
1759 /* ARGSUSED */
1760 static void
emlxs_handle_unsol_prlo(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)1761 emlxs_handle_unsol_prlo(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1762 MATCHMAP *mp, uint32_t size)
1763 {
1764 emlxs_hba_t *hba = HBA;
1765 emlxs_config_t *cfg = &CFG;
1766 IOCB *iocb;
1767 uint32_t sid;
1768 fc_unsol_buf_t *ubp;
1769 emlxs_ub_priv_t *ub_priv;
1770 NODELIST *ndlp;
1771
1772 iocb = &iocbq->iocb;
1773 sid = iocb->un.elsreq.remoteID;
1774
1775 /* Get the node */
1776 ndlp = emlxs_node_find_did(port, sid, 1);
1777
1778 #ifdef SAN_DIAG_SUPPORT
1779 if (ndlp) {
1780 emlxs_log_sd_prlo_event(port, (HBA_WWN *)&ndlp->nlp_portname);
1781 }
1782 #endif
1783
1784 #ifdef ULP_PATCH4
1785 if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH4) {
1786 #ifdef ULP_PATCH6
1787 if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH6) {
1788 /* Check if this is a SCSI target */
1789 if (ndlp && (ndlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE)) {
1790 /* This is a SCSI target */
1791
1792 /* If only one node is present, then we can */
1793 /* conclude that we are direct attached */
1794 /* to a target */
1795 if (port->node_count == 1) {
1796 EMLXS_MSGF(EMLXS_CONTEXT,
1797 &emlxs_unsol_els_msg,
1798 "PRLO: sid=%x. Accepting and " \
1799 "reseting link.",
1800 sid);
1801
1802 /* Send Acc */
1803 (void) emlxs_els_reply(port, iocbq,
1804 ELS_CMD_ACC, ELS_CMD_PRLO, 0, 0);
1805
1806 /* Spawn a thread to reset the link */
1807 emlxs_thread_spawn(hba,
1808 emlxs_reset_link_thread,
1809 NULL, NULL);
1810
1811 goto drop_it;
1812
1813 }
1814 /* Check if fabric is present */
1815 else if (hba->flag & FC_FABRIC_ATTACHED) {
1816 /* Auto reply to PRLO */
1817 EMLXS_MSGF(EMLXS_CONTEXT,
1818 &emlxs_unsol_els_msg,
1819 "PRLO: sid=%x. Accepting and " \
1820 "generating RSCN.",
1821 sid);
1822
1823 /* Send Acc */
1824 (void) emlxs_els_reply(port, iocbq,
1825 ELS_CMD_ACC, ELS_CMD_PRLO, 0, 0);
1826
1827 /* Generate an RSCN to wakeup ULP */
1828 (void) emlxs_generate_rscn(port, sid);
1829
1830 goto drop_it;
1831 }
1832 }
1833 }
1834 #endif /* ULP_PATCH6 */
1835
1836 /* Auto reply to PRLO */
1837 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1838 "PRLO: sid=%x. Accepting.", sid);
1839
1840 /* Send Acc */
1841 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC,
1842 ELS_CMD_PRLO, 0, 0);
1843
1844 goto drop_it;
1845 }
1846 #endif /* ULP_PATCH4 */
1847
1848 /* Tell ULP about it */
1849
1850 ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size,
1851 FC_TYPE_EXTENDED_LS, 0);
1852
1853 if (ubp == NULL) {
1854 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
1855 "PRLO recvd: sid=%x. Rejecting.", sid);
1856
1857 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1858 ELS_CMD_PRLO, LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
1859
1860 goto drop_it;
1861 }
1862
1863 /*
1864 * Setup unsolicited buffer and pass it up
1865 */
1866 bcopy(mp->virt, ubp->ub_buffer, size);
1867 ub_priv = ubp->ub_fca_private;
1868 ub_priv->cmd = ELS_CMD_PRLO;
1869
1870 /*
1871 * Setup frame header
1872 */
1873 ubp->ub_frame.r_ctl = FC_ELS_REQ;
1874 ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
1875 ubp->ub_frame.s_id = LE_SWAP24_LO(iocb->un.elsreq.remoteID);
1876 ubp->ub_frame.d_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
1877 ubp->ub_frame.ox_id = ub_priv->token;
1878 ubp->ub_frame.rx_id = iocb->ULPCONTEXT;
1879 ubp->ub_class = FC_TRAN_CLASS3;
1880
1881 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1882 "PRLO: sid=%x buffeiocbr=%p token=%x.", sid, ubp, ub_priv->token);
1883
1884 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
1885 emlxs_swap_els_ub(ubp);
1886 #endif /* EMLXS_MODREV2X */
1887
1888 emlxs_ub_callback(port, ubp);
1889
1890 drop_it:
1891
1892 return;
1893
1894 } /* emlxs_handle_unsol_prlo() */
1895
1896
1897 /* ARGSUSED */
1898 static void
emlxs_handle_unsol_logo(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)1899 emlxs_handle_unsol_logo(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1900 MATCHMAP *mp, uint32_t size)
1901 {
1902 emlxs_hba_t *hba = HBA;
1903 emlxs_config_t *cfg = &CFG;
1904 fc_unsol_buf_t *ubp;
1905 IOCB *iocb;
1906 uint32_t sid;
1907 emlxs_ub_priv_t *ub_priv;
1908 uint32_t reply_sent = 0;
1909 NODELIST *ndlp;
1910
1911 iocb = &iocbq->iocb;
1912 sid = iocb->un.elsreq.remoteID;
1913
1914 ndlp = emlxs_node_find_did(port, sid, 1);
1915
1916 #ifdef SAN_DIAG_SUPPORT
1917 if (ndlp) {
1918 emlxs_log_sd_basic_els_event(port, SD_ELS_SUBCATEGORY_LOGO_RCV,
1919 (HBA_WWN *)&ndlp->nlp_portname,
1920 (HBA_WWN *)((uint32_t *)mp->virt + 2));
1921 }
1922 #endif
1923
1924 EMLXS_SET_DFC_STATE(ndlp, NODE_LOGOUT);
1925
1926 #ifdef ULP_PATCH6
1927 if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH6) {
1928 /* Check if this is a SCSI target */
1929 if (ndlp && (ndlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE)) {
1930 /* This is a SCSI target */
1931
1932 /* If only one node is present, then we can */
1933 /* conclude that we are direct attached to a target */
1934 if (port->node_count == 1) {
1935 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1936 "LOGO: sid=%x. Accepting and "\
1937 "reseting link.", sid);
1938
1939 (void) emlxs_els_reply(port, iocbq,
1940 ELS_CMD_ACC, ELS_CMD_LOGO, 0, 0);
1941
1942 /* Spawn a thread to reset the link */
1943 emlxs_thread_spawn(hba, emlxs_reset_link_thread,
1944 NULL, NULL);
1945
1946 goto drop_it;
1947 }
1948 /* Check if fabric node is present */
1949 else if (hba->flag & FC_FABRIC_ATTACHED) {
1950 /* Send reply ourselves */
1951 /* We will block all attempts */
1952 /* for ULP to reply to a LOGO */
1953 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1954 "LOGO: sid=%x. Accepting and " \
1955 "generating RSCN.", sid);
1956
1957 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC,
1958 ELS_CMD_LOGO, 0, 0);
1959
1960 /* Generate an RSCN to wakeup ULP */
1961 if (emlxs_generate_rscn(port, sid)
1962 == FC_SUCCESS) {
1963 goto drop_it;
1964 }
1965
1966 reply_sent = 1;
1967 }
1968 }
1969 }
1970 #endif /* ULP_PATCH6 */
1971
1972 ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size,
1973 FC_TYPE_EXTENDED_LS, 1);
1974
1975 if (ubp == NULL) {
1976 if (!reply_sent) {
1977 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
1978 "LOGO rcvd: sid=%x. Rejecting.", sid);
1979
1980 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1981 ELS_CMD_LOGO, LSRJT_LOGICAL_BSY,
1982 LSEXP_OUT_OF_RESOURCE);
1983 }
1984
1985 goto drop_it;
1986
1987 }
1988
1989 /* Setup unsolicited buffer and pass it up */
1990 bcopy(mp->virt, ubp->ub_buffer, size);
1991 ub_priv = ubp->ub_fca_private;
1992 ub_priv->cmd = ELS_CMD_LOGO;
1993
1994 /* Setup frame header */
1995 ubp->ub_frame.r_ctl = FC_ELS_REQ;
1996 ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
1997 ubp->ub_frame.s_id = LE_SWAP24_LO(iocb->un.elsreq.remoteID);
1998 ubp->ub_frame.d_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
1999 ubp->ub_frame.ox_id = ub_priv->token;
2000 ubp->ub_frame.rx_id = iocb->ULPCONTEXT;
2001 ubp->ub_class = FC_TRAN_CLASS3;
2002
2003 #ifdef ULP_PATCH2
2004 if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH2) {
2005 if (!reply_sent) {
2006 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2007 "LOGO: sid=%x buffer=%p token=%x. Accepting.",
2008 sid, ubp, ub_priv->token);
2009
2010 ub_priv->flags |= EMLXS_UB_REPLY;
2011
2012 /* Send Acc */
2013 /* Send reply ourselves because ULP */
2014 /* doesn't always reply to these */
2015 /* We ll block attempts for ULP to reply to a LOGO */
2016 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC,
2017 ELS_CMD_LOGO, 0, 0);
2018 reply_sent = 1;
2019 }
2020 }
2021 #endif /* ULP_PATCH2 */
2022
2023 if (!reply_sent) {
2024 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2025 "LOGO: sid=%x buffer=%p token=%x.", sid, ubp,
2026 ub_priv->token);
2027 }
2028
2029 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
2030 emlxs_swap_els_ub(ubp);
2031 #endif /* EMLXS_MODREV2X */
2032
2033 /* Unregister the node */
2034 if ((sid & FABRIC_DID_MASK) == FABRIC_DID_MASK) {
2035 if (ndlp) {
2036 if (EMLXS_SLI_UNREG_NODE(port, ndlp, NULL,
2037 ubp, NULL) == 0) {
2038 /*
2039 * Deferred completion of this ubp
2040 * until unreg login is complete
2041 */
2042 return;
2043 }
2044 }
2045 }
2046
2047 emlxs_ub_callback(port, ubp);
2048
2049 drop_it:
2050
2051 return;
2052
2053 } /* emlxs_handle_unsol_logo() */
2054
2055
2056
2057 /* ARGSUSED */
2058 static void
emlxs_handle_unsol_gen_cmd(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)2059 emlxs_handle_unsol_gen_cmd(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
2060 MATCHMAP *mp, uint32_t size)
2061 {
2062 uint8_t *bp;
2063 fc_unsol_buf_t *ubp;
2064 IOCB *iocb;
2065 uint32_t *lp;
2066 uint32_t cmd;
2067 uint32_t sid;
2068 emlxs_ub_priv_t *ub_priv;
2069
2070 iocb = &iocbq->iocb;
2071 sid = iocb->un.elsreq.remoteID;
2072
2073 bp = mp->virt;
2074 lp = (uint32_t *)bp;
2075 cmd = *lp & ELS_CMD_MASK;
2076
2077 ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size,
2078 FC_TYPE_EXTENDED_LS, 0);
2079
2080 if (ubp == NULL) {
2081 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
2082 "%s rcvd: sid=%x: Rejecting.", emlxs_elscmd_xlate(cmd),
2083 sid);
2084
2085 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd,
2086 LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
2087
2088 goto drop_it;
2089 }
2090
2091 bcopy(bp, ubp->ub_buffer, size);
2092 ub_priv = ubp->ub_fca_private;
2093 ub_priv->cmd = cmd;
2094
2095 /* Setup frame header */
2096 ubp->ub_frame.r_ctl = FC_ELS_REQ;
2097 ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
2098 ubp->ub_frame.s_id = LE_SWAP24_LO(iocb->un.elsreq.remoteID);
2099 ubp->ub_frame.d_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
2100 ubp->ub_frame.ox_id = ub_priv->token;
2101 ubp->ub_frame.rx_id = iocb->ULPCONTEXT;
2102 ubp->ub_class = FC_TRAN_CLASS3;
2103
2104 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2105 "%s: sid=%x buffer=%p token=%x.", emlxs_elscmd_xlate(cmd), sid,
2106 ubp, ub_priv->token);
2107
2108 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
2109 emlxs_swap_els_ub(ubp);
2110 #endif /* EMLXS_MODREV2X */
2111
2112 emlxs_ub_callback(port, ubp);
2113
2114 drop_it:
2115
2116 return;
2117
2118 } /* emlxs_handle_unsol_gen_cmd() */
2119
2120
2121 /* ARGSUSED */
2122 static void
emlxs_handle_unsol_echo(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)2123 emlxs_handle_unsol_echo(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
2124 MATCHMAP *mp, uint32_t size)
2125 {
2126 emlxs_hba_t *hba = HBA;
2127 uint8_t *bp;
2128 IOCB *iocb;
2129 uint32_t *lp;
2130 uint32_t sid;
2131 fc_packet_t *pkt;
2132 uint32_t cmd;
2133
2134 iocb = &iocbq->iocb;
2135 sid = iocb->un.elsreq.remoteID;
2136
2137 bp = mp->virt;
2138 lp = (uint32_t *)bp;
2139 cmd = *lp & ELS_CMD_MASK;
2140
2141 if (!(pkt = emlxs_pkt_alloc(port,
2142 size, 0, 0, KM_NOSLEEP))) {
2143 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2144 "ECHO: sid=%x. Unable to allocate pkt. Rejecting.",
2145 sid);
2146
2147 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
2148 ELS_CMD_ECHO, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
2149 return;
2150 }
2151
2152 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2153 "ECHO: sid=%x. Accepting.",
2154 sid);
2155
2156 /* Common initialization */
2157 pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2158 pkt->pkt_timeout = (2 * hba->fc_ratov);
2159
2160 if ((uint32_t)iocb->ULPCLASS == CLASS2) {
2161 pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
2162 pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
2163 }
2164
2165 /* Build the fc header */
2166 pkt->pkt_cmd_fhdr.d_id =
2167 LE_SWAP24_LO(iocb->un.elsreq.remoteID);
2168 pkt->pkt_cmd_fhdr.r_ctl =
2169 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
2170 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
2171 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2172 pkt->pkt_cmd_fhdr.f_ctl =
2173 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2174 pkt->pkt_cmd_fhdr.seq_id = 0;
2175 pkt->pkt_cmd_fhdr.df_ctl = 0;
2176 pkt->pkt_cmd_fhdr.seq_cnt = 0;
2177 pkt->pkt_cmd_fhdr.ox_id = (cmd >> ELS_CMD_SHIFT) & 0xff;
2178 pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT;
2179 pkt->pkt_cmd_fhdr.ro = 0;
2180
2181 /* Build the response */
2182 *lp = ELS_CMD_ACC;
2183 bcopy(lp, pkt->pkt_cmd, size);
2184
2185 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2186 /* Free the pkt */
2187 emlxs_pkt_free(pkt);
2188 emlxs_abort_els_exchange(hba, port, iocb->ULPCONTEXT);
2189 }
2190
2191 return;
2192
2193 } /* emlxs_handle_unsol_echo() */
2194
2195
2196 /* ARGSUSED */
2197 static void
emlxs_handle_unsol_rtv(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)2198 emlxs_handle_unsol_rtv(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
2199 MATCHMAP *mp, uint32_t size)
2200 {
2201 emlxs_hba_t *hba = HBA;
2202 uint8_t *bp;
2203 IOCB *iocb;
2204 uint32_t *lp;
2205 uint32_t sid;
2206 fc_packet_t *pkt;
2207 uint32_t cmd;
2208 SERV_PARM *sp;
2209
2210 iocb = &iocbq->iocb;
2211 sid = iocb->un.elsreq.remoteID;
2212
2213 bp = mp->virt;
2214 lp = (uint32_t *)bp;
2215 cmd = *lp & ELS_CMD_MASK;
2216
2217 if (!(pkt = emlxs_pkt_alloc(port,
2218 (4 * sizeof (uint32_t)), 0, 0, KM_NOSLEEP))) {
2219 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2220 "RTV: sid=%x. Unable to allocate pkt. Rejecting.",
2221 sid);
2222
2223 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
2224 ELS_CMD_RTV, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
2225 return;
2226 }
2227
2228 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2229 "RTV: sid=%x. Accepting.",
2230 emlxs_elscmd_xlate(cmd),
2231 sid);
2232
2233 /* Common initialization */
2234 pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2235 pkt->pkt_timeout = (2 * hba->fc_ratov);
2236
2237 if ((uint32_t)iocb->ULPCLASS == CLASS2) {
2238 pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
2239 pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
2240 }
2241
2242 /* Build the fc header */
2243 pkt->pkt_cmd_fhdr.d_id =
2244 LE_SWAP24_LO(iocb->un.elsreq.remoteID);
2245 pkt->pkt_cmd_fhdr.r_ctl =
2246 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
2247 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
2248 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2249 pkt->pkt_cmd_fhdr.f_ctl =
2250 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2251 pkt->pkt_cmd_fhdr.seq_id = 0;
2252 pkt->pkt_cmd_fhdr.df_ctl = 0;
2253 pkt->pkt_cmd_fhdr.seq_cnt = 0;
2254 pkt->pkt_cmd_fhdr.ox_id = (cmd >> ELS_CMD_SHIFT) & 0xff;
2255 pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT;
2256 pkt->pkt_cmd_fhdr.ro = 0;
2257
2258 /* Build the response */
2259 sp = (SERV_PARM *)&port->fabric_sparam;
2260 lp = (uint32_t *)pkt->pkt_cmd;
2261 lp[0] = ELS_CMD_ACC;
2262 lp[1] = LE_SWAP32(sp->cmn.w2.r_a_tov);
2263 lp[2] = LE_SWAP32(sp->cmn.e_d_tov);
2264 lp[3] = sp->cmn.edtovResolution << 26;
2265
2266 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2267 /* Free the pkt */
2268 emlxs_pkt_free(pkt);
2269 emlxs_abort_els_exchange(hba, port, iocb->ULPCONTEXT);
2270 }
2271
2272 return;
2273
2274 } /* emlxs_handle_unsol_rtv() */
2275
2276
2277 /* ARGSUSED */
2278 static void
emlxs_rls_rsp_thread(emlxs_hba_t * hba,void * arg1,void * arg2)2279 emlxs_rls_rsp_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2280 {
2281 emlxs_port_t *port = (emlxs_port_t *)arg1;
2282 fc_packet_t *pkt = (fc_packet_t *)arg2;
2283 MAILBOXQ *mbq = NULL;
2284 MAILBOX *mb;
2285 la_els_rls_acc_t *rls;
2286 uint32_t rval;
2287
2288 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2289 "RLS: sid=%x. Accepting.",
2290 LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id));
2291
2292 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
2293 goto dropit;
2294 }
2295 mb = (MAILBOX *)mbq;
2296
2297 /* Read current link status */
2298 emlxs_mb_read_lnk_stat(hba, mbq);
2299 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
2300
2301 if (rval != MBX_SUCCESS) {
2302 goto dropit;
2303 }
2304
2305 /* Build the response */
2306 rls = (la_els_rls_acc_t *)pkt->pkt_cmd;
2307 rls->ls_code.ls_code = 0x02;
2308 rls->rls_link_params.rls_link_fail =
2309 mb->un.varRdLnk.linkFailureCnt;
2310 rls->rls_link_params.rls_sync_loss =
2311 mb->un.varRdLnk.lossSyncCnt;
2312 rls->rls_link_params.rls_sig_loss =
2313 mb->un.varRdLnk.lossSignalCnt;
2314 rls->rls_link_params.rls_prim_seq_err =
2315 mb->un.varRdLnk.primSeqErrCnt;
2316 rls->rls_link_params.rls_invalid_word =
2317 mb->un.varRdLnk.invalidXmitWord;
2318 rls->rls_link_params.rls_invalid_crc =
2319 mb->un.varRdLnk.crcCnt;
2320
2321 LE_SWAP32_BUFFER((uint8_t *)rls, sizeof (la_els_rls_acc_t));
2322
2323 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
2324 mbq = NULL;
2325
2326 if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) {
2327 goto dropit;
2328 }
2329
2330 return;
2331
2332 dropit:
2333
2334 emlxs_abort_els_exchange(hba, port, pkt->pkt_cmd_fhdr.rx_id);
2335
2336 emlxs_pkt_free(pkt);
2337
2338 if (mbq) {
2339 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
2340 }
2341
2342 return;
2343
2344 } /* emlxs_rls_rsp_thread() */
2345
2346
2347 /* ARGSUSED */
2348 static void
emlxs_handle_unsol_rls(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)2349 emlxs_handle_unsol_rls(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
2350 MATCHMAP *mp, uint32_t size)
2351 {
2352 emlxs_hba_t *hba = HBA;
2353 uint8_t *bp;
2354 IOCB *iocb;
2355 uint32_t *lp;
2356 uint32_t sid;
2357 fc_packet_t *pkt;
2358 uint32_t cmd;
2359
2360 iocb = &iocbq->iocb;
2361 sid = iocb->un.elsreq.remoteID;
2362
2363 bp = mp->virt;
2364 lp = (uint32_t *)bp;
2365 cmd = *lp++ & ELS_CMD_MASK;
2366
2367 if (!(pkt = emlxs_pkt_alloc(port,
2368 sizeof (la_els_rls_acc_t), 0, 0, KM_NOSLEEP))) {
2369 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2370 "RLS: sid=%x. Unable to allocate pkt. Rejecting.",
2371 sid);
2372
2373 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
2374 ELS_CMD_RLS, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
2375 return;
2376 }
2377
2378 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2379 "RLS: sid=%x. Scheduling response.",
2380 sid);
2381
2382 /* Common initialization */
2383 pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2384 pkt->pkt_timeout = (2 * hba->fc_ratov);
2385
2386 if ((uint32_t)iocb->ULPCLASS == CLASS2) {
2387 pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
2388 pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
2389 }
2390
2391 /* Build the fc header */
2392 pkt->pkt_cmd_fhdr.d_id =
2393 LE_SWAP24_LO(iocb->un.elsreq.remoteID);
2394 pkt->pkt_cmd_fhdr.r_ctl =
2395 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
2396 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
2397 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2398 pkt->pkt_cmd_fhdr.f_ctl =
2399 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2400 pkt->pkt_cmd_fhdr.seq_id = 0;
2401 pkt->pkt_cmd_fhdr.df_ctl = 0;
2402 pkt->pkt_cmd_fhdr.seq_cnt = 0;
2403 pkt->pkt_cmd_fhdr.ox_id = (cmd >> ELS_CMD_SHIFT) & 0xff;
2404 pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT;
2405 pkt->pkt_cmd_fhdr.ro = 0;
2406
2407 /* We must spawn a separate thread to send the */
2408 /* read link status mailbox command becasue we are */
2409 /* normally in a hardware interrupt context here. */
2410 emlxs_thread_spawn(hba, emlxs_rls_rsp_thread,
2411 (void *)port, (void *)pkt);
2412
2413 return;
2414
2415 } /* emlxs_handle_unsol_rls() */
2416
2417
2418 /* This handles the reply completions to unsolicited cmds */
2419 /* ARGSUSED */
2420 static void
emlxs_handle_acc(emlxs_port_t * port,emlxs_buf_t * sbp,IOCBQ * iocbq,uint32_t flag)2421 emlxs_handle_acc(emlxs_port_t *port, emlxs_buf_t *sbp, IOCBQ *iocbq,
2422 uint32_t flag)
2423 {
2424 emlxs_hba_t *hba = HBA;
2425 fc_packet_t *pkt;
2426 IOCB *iocb;
2427 uint32_t did;
2428 NODELIST *ndlp;
2429 uint32_t ucmd;
2430 uint32_t cmd;
2431 uint32_t *lp;
2432
2433 iocb = &iocbq->iocb;
2434 pkt = PRIV2PKT(sbp);
2435 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
2436 ucmd = pkt->pkt_cmd_fhdr.ox_id << ELS_CMD_SHIFT;
2437 lp = (uint32_t *)pkt->pkt_cmd;
2438 cmd = *lp & ELS_CMD_MASK;
2439
2440 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
2441 "%s %s: did=%x %s %s", emlxs_elscmd_xlate(ucmd),
2442 emlxs_elscmd_xlate(cmd), did, emlxs_state_xlate(iocb->ULPSTATUS),
2443 emlxs_error_xlate(iocb->un.grsp.perr.statLocalError));
2444
2445 switch (ucmd) {
2446 case ELS_CMD_PLOGI:
2447 case ELS_CMD_ADISC:
2448
2449 ndlp = emlxs_node_find_did(port, did, 1);
2450
2451 if (ndlp && ndlp->nlp_active) {
2452 /* Open the node again */
2453 emlxs_node_open(port, ndlp, hba->channel_fcp);
2454 emlxs_node_open(port, ndlp, hba->channel_ip);
2455 }
2456
2457 break;
2458
2459 case ELS_CMD_PRLI:
2460
2461 ndlp = emlxs_node_find_did(port, did, 1);
2462
2463 if (ndlp && ndlp->nlp_active) {
2464 EMLXS_SET_DFC_STATE(ndlp, NODE_ALLOC);
2465
2466 /* Open the node again */
2467 emlxs_node_open(port, ndlp, hba->channel_fcp);
2468 }
2469
2470 break;
2471 }
2472
2473 emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
2474 iocb->un.grsp.perr.statLocalError, 1);
2475
2476 return;
2477
2478 } /* emlxs_handle_acc() */
2479
2480
2481 /* This handles the reply completions to unsolicited cmds */
2482 /* ARGSUSED */
2483 static void
emlxs_handle_reject(emlxs_port_t * port,emlxs_buf_t * sbp,IOCBQ * iocbq,uint32_t flag)2484 emlxs_handle_reject(emlxs_port_t *port, emlxs_buf_t *sbp, IOCBQ *iocbq,
2485 uint32_t flag)
2486 {
2487 emlxs_hba_t *hba = HBA;
2488 fc_packet_t *pkt;
2489 NODELIST *ndlp;
2490 IOCB *iocb;
2491 uint32_t did;
2492 uint32_t ucmd;
2493 uint32_t cmd;
2494 uint32_t *lp;
2495
2496 iocb = &iocbq->iocb;
2497 pkt = PRIV2PKT(sbp);
2498 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
2499 ucmd = pkt->pkt_cmd_fhdr.ox_id << ELS_CMD_SHIFT;
2500 lp = (uint32_t *)pkt->pkt_cmd;
2501 cmd = *lp & ELS_CMD_MASK;
2502
2503 ndlp = emlxs_node_find_did(port, did, 1);
2504
2505 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
2506 "%s %s: did=%x %s %s", emlxs_elscmd_xlate(ucmd),
2507 emlxs_elscmd_xlate(cmd), did, emlxs_state_xlate(iocb->ULPSTATUS),
2508 emlxs_error_xlate(iocb->un.grsp.perr.statLocalError));
2509
2510 switch (ucmd) {
2511 case ELS_CMD_PLOGI:
2512
2513 if (ndlp && ndlp->nlp_active) {
2514 /* Open the node again */
2515 emlxs_node_open(port, ndlp, hba->channel_fcp);
2516 emlxs_node_open(port, ndlp, hba->channel_ip);
2517 }
2518
2519 break;
2520
2521 case ELS_CMD_PRLI:
2522
2523 if (ndlp && ndlp->nlp_active) {
2524 /* Open the node again */
2525 emlxs_node_open(port, ndlp, hba->channel_fcp);
2526 }
2527
2528 break;
2529 }
2530
2531 emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
2532 iocb->un.grsp.perr.statLocalError, 1);
2533
2534 return;
2535
2536 } /* emlxs_handle_reject() */
2537
2538
2539 /* ARGSUSED */
2540 extern int32_t
emlxs_els_reply(emlxs_port_t * port,IOCBQ * iocbq,uint32_t type,uint32_t type2,uint32_t reason,uint32_t explain)2541 emlxs_els_reply(emlxs_port_t *port, IOCBQ *iocbq, uint32_t type,
2542 uint32_t type2, uint32_t reason, uint32_t explain)
2543 {
2544 emlxs_hba_t *hba = HBA;
2545 emlxs_config_t *cfg = &CFG;
2546 fc_packet_t *pkt;
2547 ELS_PKT *els;
2548 IOCB *iocb;
2549
2550 iocb = &iocbq->iocb;
2551
2552 switch (type) {
2553 case ELS_CMD_ACC: /* Accept Response */
2554
2555 /* Allocate the pkt */
2556 switch (type2) {
2557 case ELS_CMD_FLOGI:
2558 pkt = emlxs_pkt_alloc(port,
2559 sizeof (uint32_t) + sizeof (SERV_PARM), 0,
2560 0, KM_NOSLEEP);
2561 break;
2562
2563 case ELS_CMD_ADISC:
2564 pkt = emlxs_pkt_alloc(port,
2565 sizeof (uint32_t) + sizeof (ADISC), 0, 0,
2566 KM_NOSLEEP);
2567 break;
2568
2569 case ELS_CMD_PRLI:
2570 pkt = emlxs_pkt_alloc(port,
2571 sizeof (uint32_t) + sizeof (PRLI), 0, 0,
2572 KM_NOSLEEP);
2573 break;
2574
2575 case ELS_CMD_PRLO:
2576 pkt = emlxs_pkt_alloc(port,
2577 sizeof (uint32_t) + sizeof (PRLO), 0, 0,
2578 KM_NOSLEEP);
2579 break;
2580
2581 case ELS_CMD_AUTH:
2582 default:
2583 pkt = emlxs_pkt_alloc(port, sizeof (uint32_t),
2584 0, 0, KM_NOSLEEP);
2585 break;
2586 }
2587
2588 if (!pkt) {
2589 goto dropit;
2590 }
2591
2592 /* Common initialization */
2593 pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2594 pkt->pkt_timeout = (2 * hba->fc_ratov);
2595
2596 if ((uint32_t)iocb->ULPCLASS == CLASS2) {
2597 pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
2598 pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
2599 }
2600
2601 /* Build the fc header */
2602 pkt->pkt_cmd_fhdr.d_id =
2603 LE_SWAP24_LO(iocb->un.elsreq.remoteID);
2604 pkt->pkt_cmd_fhdr.r_ctl =
2605 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
2606 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
2607 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2608 pkt->pkt_cmd_fhdr.f_ctl =
2609 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2610 pkt->pkt_cmd_fhdr.seq_id = 0;
2611 pkt->pkt_cmd_fhdr.df_ctl = 0;
2612 pkt->pkt_cmd_fhdr.seq_cnt = 0;
2613 pkt->pkt_cmd_fhdr.ox_id = (type2 >> ELS_CMD_SHIFT) & 0xff;
2614 pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT;
2615 pkt->pkt_cmd_fhdr.ro = 0;
2616
2617 /*
2618 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2619 * "%s ACC send. oxid=%x", emlxs_elscmd_xlate(type2),
2620 * pkt->pkt_cmd_fhdr.ox_id);
2621 */
2622
2623 /* Build the command */
2624 els = (ELS_PKT *)pkt->pkt_cmd;
2625 els->elsCode = 0x02;
2626
2627 /* Build the payload */
2628 switch (type2) {
2629 case ELS_CMD_ADISC:
2630
2631 els->un.adisc.hardAL_PA =
2632 (uint8_t)cfg[CFG_ASSIGN_ALPA].current;
2633 bcopy(&port->wwnn, &els->un.adisc.nodeName,
2634 sizeof (NAME_TYPE));
2635 bcopy(&port->wwpn, &els->un.adisc.portName,
2636 sizeof (NAME_TYPE));
2637 els->un.adisc.DID = LE_SWAP24_LO(port->did);
2638
2639 break;
2640
2641 case ELS_CMD_PRLI:
2642
2643 els->elsByte1 = 0x10;
2644 els->elsByte2 = 0;
2645 els->elsByte3 = 0x14;
2646
2647 els->un.prli.prliType = PRLI_FCP_TYPE;
2648 els->un.prli.estabImagePair = 1;
2649 els->un.prli.acceptRspCode = PRLI_REQ_EXECUTED;
2650
2651 if (port->mode == MODE_INITIATOR) {
2652 els->un.prli.initiatorFunc = 1;
2653 }
2654
2655 if (port->mode == MODE_TARGET) {
2656 els->un.prli.targetFunc = 1;
2657 }
2658
2659 els->un.prli.readXferRdyDis = 1;
2660
2661 if ((hba->vpd.feaLevelHigh >= 0x02) &&
2662 (cfg[CFG_ADISC_SUPPORT].current != 0)) {
2663 els->un.prli.ConfmComplAllowed = 1;
2664 els->un.prli.Retry = 1;
2665 els->un.prli.TaskRetryIdReq = 1;
2666 } else {
2667 els->un.prli.ConfmComplAllowed = 0;
2668 els->un.prli.Retry = 0;
2669 els->un.prli.TaskRetryIdReq = 0;
2670 }
2671
2672 break;
2673
2674 case ELS_CMD_PRLO:
2675
2676 els->elsByte1 = 0x10;
2677 els->elsByte2 = 0;
2678 els->elsByte3 = 0x14;
2679
2680 els->un.prlo.prloType = PRLO_FCP_TYPE;
2681 els->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
2682
2683 break;
2684
2685
2686 } /* switch(type2) */
2687 break;
2688
2689 case ELS_CMD_LS_RJT: /* reject response */
2690
2691 if (!(pkt = emlxs_pkt_alloc(port,
2692 sizeof (uint32_t) + sizeof (LS_RJT), 0, 0, KM_NOSLEEP))) {
2693 goto dropit;
2694 }
2695
2696 pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2697 pkt->pkt_timeout = (2 * hba->fc_ratov);
2698
2699 if ((uint32_t)iocb->ULPCLASS == CLASS2) {
2700 pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
2701 pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
2702 }
2703
2704 /* Build the fc header */
2705 pkt->pkt_cmd_fhdr.d_id =
2706 LE_SWAP24_LO(iocb->un.elsreq.remoteID);
2707 pkt->pkt_cmd_fhdr.r_ctl =
2708 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
2709 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
2710 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2711 pkt->pkt_cmd_fhdr.f_ctl =
2712 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2713 pkt->pkt_cmd_fhdr.seq_id = 0;
2714 pkt->pkt_cmd_fhdr.df_ctl = 0;
2715 pkt->pkt_cmd_fhdr.seq_cnt = 0;
2716 pkt->pkt_cmd_fhdr.ox_id = (type2 >> ELS_CMD_SHIFT) & 0xff;
2717 pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT;
2718 pkt->pkt_cmd_fhdr.ro = 0;
2719
2720 /*
2721 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2722 * "%s LS_RJT send. oxid=%x", emlxs_elscmd_xlate(type2),
2723 * pkt->pkt_cmd_fhdr.ox_id);
2724 */
2725
2726 /* Build the command */
2727 els = (ELS_PKT *)pkt->pkt_cmd;
2728 els->elsCode = 0x01;
2729 els->un.lsRjt.un.b.lsRjtRsvd0 = 0;
2730 els->un.lsRjt.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2731 els->un.lsRjt.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
2732 els->un.lsRjt.un.b.vendorUnique = 0x01;
2733
2734 break;
2735
2736 default:
2737 return (1);
2738 }
2739
2740 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2741 /* Free the pkt */
2742 emlxs_pkt_free(pkt);
2743 goto dropit;
2744 }
2745
2746 return (0);
2747
2748 dropit:
2749
2750 emlxs_abort_els_exchange(hba, port, iocb->ULPCONTEXT);
2751 return (1);
2752
2753 } /* emlxs_els_reply() */
2754
2755
2756 #ifdef ULP_PATCH6
2757
2758 extern uint32_t
emlxs_generate_rscn(emlxs_port_t * port,uint32_t d_id)2759 emlxs_generate_rscn(emlxs_port_t *port, uint32_t d_id)
2760 {
2761 fc_unsol_buf_t *ubp;
2762 fc_rscn_t *rscn;
2763 emlxs_ub_priv_t *ub_priv;
2764 uint32_t *page;
2765
2766 ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, 8, FC_TYPE_EXTENDED_LS, 1);
2767
2768 if (ubp == NULL) {
2769 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
2770 "RSCN create: sid=0xfffffd 1 page(s): %08X, 00000000. "
2771 "Creation failed.", d_id);
2772
2773 return ((uint32_t)FC_FAILURE);
2774 }
2775
2776 /* Simulate an RSCN payload */
2777 rscn = (fc_rscn_t *)ubp->ub_buffer;
2778 rscn->rscn_code = 0x61;
2779 rscn->rscn_len = 0x04;
2780 rscn->rscn_payload_len = 0x0008;
2781 page = ((uint32_t *)rscn);
2782 page++;
2783 *page = d_id;
2784
2785 #ifdef EMLXS_I386
2786 /* Put payload in BE format */
2787 rscn->rscn_payload_len = LE_SWAP16(rscn->rscn_payload_len);
2788 *page = LE_SWAP32(d_id);
2789 #endif /* EMLXS_I386 */
2790
2791 ub_priv = ubp->ub_fca_private;
2792 ub_priv->cmd = ELS_CMD_RSCN;
2793 ub_priv->flags |= EMLXS_UB_INTERCEPT;
2794
2795 ubp->ub_frame.r_ctl = FC_ELS_REQ;
2796 ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
2797 ubp->ub_frame.s_id = 0xfffffd;
2798 ubp->ub_frame.d_id = LE_SWAP24_LO(port->did);
2799 ubp->ub_frame.ox_id = ub_priv->token;
2800 ubp->ub_frame.rx_id = 0xffff;
2801 ubp->ub_class = FC_TRAN_CLASS3;
2802
2803 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2804 "RSCN: sid=fffffd 1 page(s): %08X, 00000000 buffer=%p "
2805 "token=%x. Created.", d_id, ubp, ub_priv->token);
2806
2807 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
2808 emlxs_swap_els_ub(ubp);
2809 #endif /* EMLXS_MODREV2X */
2810
2811 emlxs_ub_callback(port, ubp);
2812
2813 return (FC_SUCCESS);
2814
2815 } /* emlxs_generate_rscn() */
2816
2817 #endif /* ULP_PATCH6 */
2818
2819
2820 #ifdef MENLO_SUPPORT
2821 extern int
emlxs_menlo_handle_event(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)2822 emlxs_menlo_handle_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2823 {
2824 emlxs_port_t *port = &PPORT;
2825 IOCB *iocb;
2826 emlxs_buf_t *sbp;
2827 fc_packet_t *pkt;
2828 uint32_t cmd_code = 0;
2829 uint32_t rsp_code = 0;
2830 menlo_cmd_t *cmd;
2831 uint32_t *rsp;
2832
2833 iocb = &iocbq->iocb;
2834
2835 HBASTATS.CtEvent++;
2836
2837 sbp = (emlxs_buf_t *)iocbq->sbp;
2838
2839 if (!sbp) {
2840 /*
2841 * completion with missing xmit command
2842 */
2843 HBASTATS.CtStray++;
2844
2845 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ct_completion_msg,
2846 "iocbq=%p cmd=0x%x iotag=0x%x status=0x%x perr=0x%x",
2847 iocbq, (uint32_t)iocb->ULPCOMMAND,
2848 (uint32_t)iocb->ULPIOTAG, iocb->ULPSTATUS,
2849 iocb->un.ulpWord[4]);
2850
2851 return (1);
2852 }
2853
2854 if (cp->channelno != hba->channel_ct) {
2855 HBASTATS.CtStray++;
2856
2857 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ct_completion_msg,
2858 "Invalid IO channel:%d iocbq=%p", cp->channelno, iocbq);
2859
2860 return (1);
2861 }
2862
2863 port = sbp->iocbq.port;
2864 pkt = PRIV2PKT(sbp);
2865
2866 cmd = (menlo_cmd_t *)pkt->pkt_cmd;
2867 cmd_code = BE_SWAP32(cmd->code);
2868
2869 /* Check if a response buffer was provided */
2870 if (pkt->pkt_rsplen) {
2871 EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0, pkt->pkt_rsplen,
2872 DDI_DMA_SYNC_FORKERNEL);
2873 }
2874
2875 switch (iocb->ULPCOMMAND) {
2876 /*
2877 * MENLO Command completion
2878 */
2879 case CMD_GEN_REQUEST64_CR:
2880 case CMD_GEN_REQUEST64_CX:
2881
2882 HBASTATS.CtCmdCompleted++;
2883
2884 sbp->pkt_flags |= PACKET_CT_RSP_VALID;
2885
2886 rsp = (uint32_t *)pkt->pkt_resp;
2887 rsp_code = *rsp;
2888 rsp_code = BE_SWAP32(rsp_code);
2889
2890 if (hba->sli_mode >= EMLXS_HBA_SLI3_MODE) {
2891 pkt->pkt_resp_resid =
2892 pkt->pkt_rsplen - iocb->unsli3.ext_iocb.rsplen;
2893 } else {
2894 pkt->pkt_resp_resid =
2895 pkt->pkt_rsplen - iocb->un.genreq64.bdl.bdeSize;
2896 }
2897
2898 pkt->pkt_data_resid = pkt->pkt_datalen;
2899 pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT;
2900
2901 if ((iocb->ULPSTATUS == 0) && (rsp_code == MENLO_RSP_SUCCESS)) {
2902 HBASTATS.CtCmdGood++;
2903
2904 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg,
2905 "%s: %s rxid=0x%x",
2906 emlxs_menlo_cmd_xlate(cmd_code),
2907 emlxs_menlo_rsp_xlate(rsp_code),
2908 iocb->ULPCONTEXT);
2909
2910 } else {
2911 HBASTATS.CtCmdError++;
2912
2913 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg,
2914 "%s: %s %s %s rxid=0x%x",
2915 emlxs_menlo_cmd_xlate(cmd_code),
2916 emlxs_menlo_rsp_xlate(rsp_code),
2917 emlxs_state_xlate(iocb->ULPSTATUS),
2918 emlxs_error_xlate(iocb->un.grsp.perr.
2919 statLocalError), iocb->ULPCONTEXT);
2920 }
2921
2922 emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
2923 iocb->un.grsp.perr.statLocalError, 1);
2924
2925 break;
2926
2927 default:
2928
2929 HBASTATS.CtStray++;
2930
2931 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_invalid_ct_msg,
2932 "Invalid iocb: cmd=0x%x", iocb->ULPCOMMAND);
2933
2934 emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
2935 iocb->un.grsp.perr.statLocalError, 1);
2936
2937 break;
2938
2939 } /* switch(iocb->ULPCOMMAND) */
2940
2941 return (0);
2942
2943 } /* emlxs_menlo_handle_event() */
2944
2945 #endif /* MENLO_SUPPORT */
2946
2947
2948 extern int
emlxs_ct_handle_event(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)2949 emlxs_ct_handle_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2950 {
2951 emlxs_port_t *port = &PPORT;
2952 IOCB *iocb;
2953 emlxs_buf_t *sbp;
2954 fc_packet_t *pkt;
2955 uint32_t *rsp;
2956 SLI_CT_REQUEST *CtRsp;
2957 SLI_CT_REQUEST *CtCmd;
2958 uint32_t cmd_code = 0;
2959 uint32_t rsp_code = 0;
2960
2961 iocb = &iocbq->iocb;
2962
2963 HBASTATS.CtEvent++;
2964
2965 sbp = (emlxs_buf_t *)iocbq->sbp;
2966
2967 if (!sbp) {
2968 /*
2969 * completion with missing xmit command
2970 */
2971 HBASTATS.CtStray++;
2972
2973 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ct_completion_msg,
2974 "iocbq=%p cmd=0x%x iotag=0x%x status=0x%x perr=0x%x",
2975 iocbq, (uint32_t)iocb->ULPCOMMAND,
2976 (uint32_t)iocb->ULPIOTAG, iocb->ULPSTATUS,
2977 iocb->un.ulpWord[4]);
2978
2979 return (1);
2980 }
2981
2982 if (cp->channelno != hba->channel_ct) {
2983 HBASTATS.CtStray++;
2984
2985 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ct_completion_msg,
2986 "Invalid channel: channel=%d iocbq=%p", cp->channelno,
2987 iocbq);
2988
2989 return (1);
2990 }
2991
2992 pkt = PRIV2PKT(sbp);
2993 port = sbp->iocbq.port;
2994 CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd;
2995 cmd_code = LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp);
2996
2997 if (cmd_code == SLI_CT_LOOPBACK) {
2998 HBASTATS.CtEvent--;
2999 return (emlxs_dfc_handle_event(hba, cp, iocbq));
3000 }
3001
3002 /* Check if a response buffer was provided */
3003 if (pkt->pkt_rsplen) {
3004 EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0, pkt->pkt_rsplen,
3005 DDI_DMA_SYNC_FORKERNEL);
3006 }
3007
3008 switch (iocb->ULPCOMMAND) {
3009 /*
3010 * CT Reply completion
3011 */
3012 case CMD_XMIT_SEQUENCE_CX:
3013 case CMD_XMIT_SEQUENCE64_CX:
3014
3015 HBASTATS.CtRspCompleted++;
3016
3017 switch (CtCmd->FsType) {
3018 case 0xFC: /* Name server */
3019 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg,
3020 "%s: %s %s", emlxs_ctcmd_xlate(cmd_code),
3021 emlxs_state_xlate(iocb->ULPSTATUS),
3022 emlxs_error_xlate(iocb->un.grsp.perr.
3023 statLocalError));
3024 break;
3025
3026 case 0xFA: /* Managment server */
3027 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg,
3028 "%s: %s %s", emlxs_mscmd_xlate(cmd_code),
3029 emlxs_state_xlate(iocb->ULPSTATUS),
3030 emlxs_error_xlate(iocb->un.grsp.perr.
3031 statLocalError));
3032 break;
3033
3034 case 0x0A: /* Emulex Remote server */
3035 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg,
3036 "%s: %s %s", emlxs_rmcmd_xlate(cmd_code),
3037 emlxs_state_xlate(iocb->ULPSTATUS),
3038 emlxs_error_xlate(iocb->un.grsp.perr.
3039 statLocalError));
3040 break;
3041
3042 default:
3043 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg,
3044 "%s: %s %s", emlxs_ctcmd_xlate(cmd_code),
3045 emlxs_state_xlate(iocb->ULPSTATUS),
3046 emlxs_error_xlate(iocb->un.grsp.perr.
3047 statLocalError));
3048 }
3049
3050 emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
3051 iocb->un.grsp.perr.statLocalError, 1);
3052
3053 break;
3054
3055 /*
3056 * CT Command completion
3057 */
3058 case CMD_GEN_REQUEST64_CR:
3059 case CMD_GEN_REQUEST64_CX:
3060
3061 HBASTATS.CtCmdCompleted++;
3062
3063 sbp->pkt_flags |= PACKET_CT_RSP_VALID;
3064
3065 rsp = (uint32_t *)pkt->pkt_resp;
3066 CtRsp = (SLI_CT_REQUEST *)pkt->pkt_resp;
3067 rsp_code = LE_SWAP16(CtRsp->CommandResponse.bits.CmdRsp);
3068
3069 if (hba->sli_mode >= EMLXS_HBA_SLI3_MODE) {
3070 pkt->pkt_resp_resid =
3071 pkt->pkt_rsplen - iocb->unsli3.ext_iocb.rsplen;
3072 } else {
3073 pkt->pkt_resp_resid =
3074 pkt->pkt_rsplen - iocb->un.genreq64.bdl.bdeSize;
3075 }
3076
3077 pkt->pkt_data_resid = pkt->pkt_datalen;
3078
3079 /*
3080 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg,
3081 * "INFO: pkt_resid=%d %d %d %x", pkt->pkt_resp_resid,
3082 * pkt->pkt_rsplen, iocb->un.genreq64.bdl.bdeSize,
3083 * iocb->un.genreq64.bdl.bdeFlags);
3084 */
3085
3086 if ((iocb->ULPSTATUS == 0) &&
3087 (rsp_code == SLI_CT_RESPONSE_FS_ACC)) {
3088 HBASTATS.CtCmdGood++;
3089
3090 if (!(sbp->pkt_flags & PACKET_ALLOCATED)) {
3091 /* ULP patch - ULP expects */
3092 /* resp_resid = 0 on success */
3093 pkt->pkt_resp_resid = 0;
3094 }
3095
3096 switch (CtCmd->FsType) {
3097 case 0xFC: /* Name server */
3098 EMLXS_MSGF(EMLXS_CONTEXT,
3099 &emlxs_ct_completion_msg,
3100 "%s: %s: Rsn=%x Exp=%x [%08x,%08x]",
3101 emlxs_ctcmd_xlate(cmd_code),
3102 emlxs_ctcmd_xlate(rsp_code),
3103 CtRsp->ReasonCode, CtRsp->Explanation,
3104 LE_SWAP32(rsp[4]), LE_SWAP32(rsp[5]));
3105
3106 #if (EMLXS_MODREV < EMLXS_MODREV4)
3107 if (cmd_code == SLI_CTNS_RNN_ID) {
3108 emlxs_send_rsnn(port);
3109 }
3110 #endif /* < EMLXS_MODREV4 */
3111
3112 break;
3113
3114 case 0xFA: /* Managment server */
3115 EMLXS_MSGF(EMLXS_CONTEXT,
3116 &emlxs_ct_completion_msg,
3117 "%s: %s: Rsn=%x Exp=%x [%08x,%08x]",
3118 emlxs_mscmd_xlate(cmd_code),
3119 emlxs_mscmd_xlate(rsp_code),
3120 CtRsp->ReasonCode, CtRsp->Explanation,
3121 LE_SWAP32(rsp[4]), LE_SWAP32(rsp[5]));
3122 break;
3123
3124 case 0x0A: /* Emulex Remote server */
3125 EMLXS_MSGF(EMLXS_CONTEXT,
3126 &emlxs_ct_completion_msg,
3127 "%s: %s: Rsn=%x Exp=%x [%08x,%08x]",
3128 emlxs_rmcmd_xlate(cmd_code),
3129 emlxs_rmcmd_xlate(rsp_code),
3130 CtRsp->ReasonCode, CtRsp->Explanation,
3131 LE_SWAP32(rsp[4]), LE_SWAP32(rsp[5]));
3132 break;
3133
3134 default:
3135 EMLXS_MSGF(EMLXS_CONTEXT,
3136 &emlxs_ct_completion_msg,
3137 "%s: %s: Rsn=%x Exp=%x [%08x,%08x]",
3138 emlxs_ctcmd_xlate(cmd_code),
3139 emlxs_ctcmd_xlate(rsp_code),
3140 CtRsp->ReasonCode, CtRsp->Explanation,
3141 LE_SWAP32(rsp[4]), LE_SWAP32(rsp[5]));
3142 }
3143 } else {
3144 HBASTATS.CtCmdError++;
3145
3146 if (rsp_code == SLI_CT_RESPONSE_FS_RJT) {
3147 pkt->pkt_state = FC_PKT_FS_RJT;
3148 pkt->pkt_action = FC_ACTION_RETRYABLE;
3149 pkt->pkt_reason = CtRsp->ReasonCode;
3150 pkt->pkt_expln = CtRsp->Explanation;
3151 sbp->pkt_flags |= PACKET_STATE_VALID;
3152
3153 EMLXS_MSGF(EMLXS_CONTEXT,
3154 &emlxs_ct_completion_msg,
3155 "%s: Rejected. rsn=%x exp=%x",
3156 emlxs_ctcmd_xlate(cmd_code),
3157 pkt->pkt_reason, pkt->pkt_expln);
3158 } else if (iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) {
3159 switch (CtCmd->FsType) {
3160 case 0xFC: /* Name server */
3161 EMLXS_MSGF(EMLXS_CONTEXT,
3162 &emlxs_ct_completion_msg,
3163 "%s: %s %s",
3164 emlxs_ctcmd_xlate(cmd_code),
3165 emlxs_state_xlate(iocb->
3166 ULPSTATUS),
3167 emlxs_error_xlate(iocb->un.grsp.
3168 perr.statLocalError));
3169 break;
3170
3171 case 0xFA: /* Managment server */
3172 EMLXS_MSGF(EMLXS_CONTEXT,
3173 &emlxs_ct_completion_msg,
3174 "%s: %s %s",
3175 emlxs_mscmd_xlate(cmd_code),
3176 emlxs_state_xlate(iocb->
3177 ULPSTATUS),
3178 emlxs_error_xlate(iocb->un.grsp.
3179 perr.statLocalError));
3180 break;
3181
3182 case 0x0A: /* Emulex Remote server */
3183 EMLXS_MSGF(EMLXS_CONTEXT,
3184 &emlxs_ct_completion_msg,
3185 "%s: %s %s",
3186 emlxs_rmcmd_xlate(cmd_code),
3187 emlxs_state_xlate(iocb->
3188 ULPSTATUS),
3189 emlxs_error_xlate(iocb->un.grsp.
3190 perr.statLocalError));
3191 break;
3192
3193 default:
3194 EMLXS_MSGF(EMLXS_CONTEXT,
3195 &emlxs_ct_completion_msg,
3196 "%s: %s %s",
3197 emlxs_ctcmd_xlate(cmd_code),
3198 emlxs_state_xlate(iocb->
3199 ULPSTATUS),
3200 emlxs_error_xlate(iocb->un.grsp.
3201 perr.statLocalError));
3202 }
3203 } else {
3204 switch (CtCmd->FsType) {
3205 case 0xFC: /* Name server */
3206 EMLXS_MSGF(EMLXS_CONTEXT,
3207 &emlxs_ct_completion_msg,
3208 "%s: %s (%02x%02x%02x%02x)",
3209 emlxs_ctcmd_xlate(cmd_code),
3210 emlxs_state_xlate(iocb->
3211 ULPSTATUS),
3212 iocb->un.grsp.perr.statAction,
3213 iocb->un.grsp.perr.statRsn,
3214 iocb->un.grsp.perr.statBaExp,
3215 iocb->un.grsp.perr.
3216 statLocalError);
3217 break;
3218
3219 case 0xFA: /* Managment server */
3220 EMLXS_MSGF(EMLXS_CONTEXT,
3221 &emlxs_ct_completion_msg,
3222 "%s: %s (%02x%02x%02x%02x)",
3223 emlxs_mscmd_xlate(cmd_code),
3224 emlxs_state_xlate(iocb->
3225 ULPSTATUS),
3226 iocb->un.grsp.perr.statAction,
3227 iocb->un.grsp.perr.statRsn,
3228 iocb->un.grsp.perr.statBaExp,
3229 iocb->un.grsp.perr.
3230 statLocalError);
3231 break;
3232
3233 case 0x0A: /* Emulex Remote server */
3234 EMLXS_MSGF(EMLXS_CONTEXT,
3235 &emlxs_ct_completion_msg,
3236 "%s: %s (%02x%02x%02x%02x)",
3237 emlxs_rmcmd_xlate(cmd_code),
3238 emlxs_state_xlate(iocb->
3239 ULPSTATUS),
3240 iocb->un.grsp.perr.statAction,
3241 iocb->un.grsp.perr.statRsn,
3242 iocb->un.grsp.perr.statBaExp,
3243 iocb->un.grsp.perr.
3244 statLocalError);
3245 break;
3246
3247 default:
3248 EMLXS_MSGF(EMLXS_CONTEXT,
3249 &emlxs_ct_completion_msg,
3250 "%s: %s (%02x%02x%02x%02x)",
3251 emlxs_ctcmd_xlate(cmd_code),
3252 emlxs_state_xlate(iocb->
3253 ULPSTATUS),
3254 iocb->un.grsp.perr.statAction,
3255 iocb->un.grsp.perr.statRsn,
3256 iocb->un.grsp.perr.statBaExp,
3257 iocb->un.grsp.perr.
3258 statLocalError);
3259 }
3260 }
3261 }
3262
3263 emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
3264 iocb->un.grsp.perr.statLocalError, 1);
3265
3266 break;
3267
3268 default:
3269
3270 HBASTATS.CtStray++;
3271
3272 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_invalid_ct_msg,
3273 "Invalid iocb: cmd=0x%x", iocb->ULPCOMMAND);
3274
3275 emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
3276 iocb->un.grsp.perr.statLocalError, 1);
3277
3278 break;
3279 } /* switch(iocb->ULPCOMMAND) */
3280
3281 return (0);
3282
3283 } /* emlxs_ct_handle_event() */
3284
3285
3286 extern int
emlxs_ct_handle_unsol_req(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)3287 emlxs_ct_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
3288 MATCHMAP *mp, uint32_t size)
3289 {
3290 emlxs_hba_t *hba = HBA;
3291 IOCB *iocb;
3292 SLI_CT_REQUEST *CtCmd;
3293 uint32_t cmd_code;
3294
3295 iocb = &iocbq->iocb;
3296
3297 CtCmd = (SLI_CT_REQUEST *)mp->virt;
3298 cmd_code = LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp);
3299
3300 if (cmd_code == SLI_CT_LOOPBACK) {
3301 int rval;
3302
3303 rval = emlxs_dfc_handle_unsol_req(port, cp, iocbq, mp, size);
3304
3305 return (rval);
3306 }
3307
3308 HBASTATS.CtCmdReceived++;
3309
3310 switch (CtCmd->FsType) {
3311 case 0xFC: /* Name server */
3312 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg,
3313 "%s: pl=%p size=%d rxid=%x", emlxs_ctcmd_xlate(cmd_code),
3314 CtCmd, size, iocb->ULPCONTEXT);
3315 break;
3316
3317 case 0xFA: /* Managment server */
3318 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg,
3319 "%s: pl=%p size=%d rxid=%x", emlxs_mscmd_xlate(cmd_code),
3320 CtCmd, size, iocb->ULPCONTEXT);
3321 break;
3322
3323 case 0x0A: /* Emulex Remote server */
3324 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg,
3325 "%s: pl=%p size=%d rxid=%x", emlxs_rmcmd_xlate(cmd_code),
3326 CtCmd, size, iocb->ULPCONTEXT);
3327 break;
3328
3329 default:
3330 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg,
3331 "%s: pl=%p size=%d rxid=%x", emlxs_ctcmd_xlate(cmd_code),
3332 CtCmd, size, iocb->ULPCONTEXT);
3333 }
3334
3335 if (emlxs_log_ct_event(port, (uint8_t *)mp->virt, size,
3336 iocb->ULPCONTEXT)) {
3337 /* Abort the exchange */
3338 emlxs_abort_ct_exchange(hba, port, iocb->ULPCONTEXT);
3339 }
3340
3341 return (0);
3342
3343 } /* emlxs_ct_handle_unsol_req() */
3344
3345
3346 #if (EMLXS_MODREV < EMLXS_MODREV4)
3347 static void
emlxs_send_rsnn(emlxs_port_t * port)3348 emlxs_send_rsnn(emlxs_port_t *port)
3349 {
3350 emlxs_hba_t *hba = HBA;
3351 fc_packet_t *pkt;
3352 SLI_CT_REQUEST *ct;
3353
3354 if (!(pkt = emlxs_pkt_alloc(port, sizeof (SLI_CT_REQUEST),
3355 sizeof (SLI_CT_REQUEST), 0, KM_NOSLEEP))) {
3356 return;
3357 }
3358
3359 pkt->pkt_tran_type = FC_PKT_EXCHANGE;
3360 pkt->pkt_timeout = (2 * hba->fc_ratov);
3361
3362 /* Build the fc header */
3363 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(NAMESERVER_DID);
3364 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL;
3365 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
3366 pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
3367 pkt->pkt_cmd_fhdr.f_ctl =
3368 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
3369 pkt->pkt_cmd_fhdr.seq_id = 0;
3370 pkt->pkt_cmd_fhdr.df_ctl = 0;
3371 pkt->pkt_cmd_fhdr.seq_cnt = 0;
3372 pkt->pkt_cmd_fhdr.ox_id = 0xffff;
3373 pkt->pkt_cmd_fhdr.rx_id = 0xffff;
3374 pkt->pkt_cmd_fhdr.ro = 0;
3375
3376 /* Build the command */
3377 ct = (SLI_CT_REQUEST *)pkt->pkt_cmd;
3378
3379 ct->RevisionId.bits.Revision = SLI_CT_REVISION;
3380 ct->RevisionId.bits.InId = 0;
3381
3382 ct->FsType = SLI_CT_DIRECTORY_SERVICE;
3383 ct->FsSubType = SLI_CT_DIRECTORY_NAME_SERVER;
3384
3385 ct->CommandResponse.bits.Size = 0;
3386 ct->CommandResponse.bits.CmdRsp = LE_SWAP16(SLI_CTNS_RSNN_NN);
3387
3388 bcopy((uint8_t *)&hba->wwnn, (char *)ct->un.rsnn.wwnn, 8);
3389
3390 ct->un.rsnn.snn_len = strlen(port->snn);
3391 bcopy(port->snn, (char *)ct->un.rsnn.snn, ct->un.rsnn.snn_len);
3392
3393 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg, "Sending RSNN_NN. [%s]",
3394 port->snn);
3395
3396 /* Send the pkt later in another thread */
3397 if (emlxs_pkt_send(pkt, 0) != FC_SUCCESS) {
3398 /* Free the pkt */
3399 emlxs_pkt_free(pkt);
3400 }
3401
3402 return;
3403
3404 } /* emlxs_send_rsnn() */
3405 #endif /* < EMLXS_MODREV4 */
3406
3407
3408
3409
3410 extern uint32_t
emlxs_ub_send_login_acc(emlxs_port_t * port,fc_unsol_buf_t * ubp)3411 emlxs_ub_send_login_acc(emlxs_port_t *port, fc_unsol_buf_t *ubp)
3412 {
3413 emlxs_hba_t *hba = HBA;
3414 fc_packet_t *pkt;
3415 ELS_PKT *els;
3416 uint32_t rval;
3417 emlxs_ub_priv_t *ub_priv;
3418
3419 ub_priv = ubp->ub_fca_private;
3420
3421 if (!(pkt = emlxs_pkt_alloc(port,
3422 sizeof (uint32_t) + sizeof (SERV_PARM), 0, 0, KM_NOSLEEP))) {
3423 return (1);
3424 }
3425
3426 /* Common initialization */
3427 pkt->pkt_tran_type = FC_PKT_OUTBOUND;
3428 pkt->pkt_timeout = (2 * hba->fc_ratov);
3429
3430 if ((uint32_t)ubp->ub_class == FC_TRAN_CLASS2) {
3431 pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
3432 pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
3433 }
3434
3435 /* Build the fc header */
3436 pkt->pkt_cmd_fhdr.d_id = ubp->ub_frame.s_id;
3437 pkt->pkt_cmd_fhdr.r_ctl =
3438 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
3439 pkt->pkt_cmd_fhdr.s_id = ubp->ub_frame.d_id;
3440 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3441 pkt->pkt_cmd_fhdr.f_ctl =
3442 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
3443 pkt->pkt_cmd_fhdr.seq_id = 0;
3444 pkt->pkt_cmd_fhdr.df_ctl = 0;
3445 pkt->pkt_cmd_fhdr.seq_cnt = 0;
3446 pkt->pkt_cmd_fhdr.ox_id = (ub_priv->cmd >> ELS_CMD_SHIFT) & 0xff;
3447 pkt->pkt_cmd_fhdr.rx_id = ubp->ub_frame.rx_id;
3448 pkt->pkt_cmd_fhdr.ro = 0;
3449
3450 /* Build the command */
3451 els = (ELS_PKT *)pkt->pkt_cmd;
3452 els->elsCode = 0x02;
3453 bcopy((void *)&port->sparam, (void *)&els->un.logi,
3454 sizeof (SERV_PARM));
3455
3456 if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) {
3457 /* Free the pkt */
3458 emlxs_pkt_free(pkt);
3459 } else {
3460 ub_priv->flags |= EMLXS_UB_INTERCEPT;
3461 }
3462
3463 return (rval);
3464
3465 } /* emlxs_ub_send_login_acc */
3466
3467
3468 extern void
emlxs_send_logo(emlxs_port_t * port,uint32_t d_id)3469 emlxs_send_logo(emlxs_port_t *port, uint32_t d_id)
3470 {
3471 emlxs_hba_t *hba = HBA;
3472 fc_packet_t *pkt;
3473 ELS_PKT *els;
3474
3475 if (!(hba->flag & FC_ONLINE_MODE)) {
3476 return;
3477 }
3478
3479 if (hba->state <= FC_LINK_DOWN) {
3480 return;
3481 }
3482
3483 if (!(pkt = emlxs_pkt_alloc(port,
3484 sizeof (uint32_t) + sizeof (LOGO),
3485 sizeof (uint32_t) + sizeof (LOGO), 0, KM_NOSLEEP))) {
3486 return;
3487 }
3488
3489 pkt->pkt_tran_type = FC_PKT_EXCHANGE;
3490 pkt->pkt_timeout = (2 * hba->fc_ratov);
3491
3492 /* Build the fc header */
3493 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(d_id);
3494 pkt->pkt_cmd_fhdr.r_ctl =
3495 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
3496 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
3497 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3498 pkt->pkt_cmd_fhdr.f_ctl =
3499 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
3500 pkt->pkt_cmd_fhdr.seq_id = 0;
3501 pkt->pkt_cmd_fhdr.df_ctl = 0;
3502 pkt->pkt_cmd_fhdr.seq_cnt = 0;
3503 pkt->pkt_cmd_fhdr.ox_id = 0xffff;
3504 pkt->pkt_cmd_fhdr.rx_id = 0xffff;
3505 pkt->pkt_cmd_fhdr.ro = 0;
3506
3507 /* Build the command */
3508 els = (ELS_PKT *)pkt->pkt_cmd;
3509 els->elsCode = 0x05;
3510 els->un.logo.un.nPortId32 = pkt->pkt_cmd_fhdr.s_id;
3511 bcopy((uint8_t *)&port->wwpn, (uint8_t *)&els->un.logo.portName,
3512 8);
3513
3514 /* Send the pkt now */
3515 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
3516 /* Free the pkt */
3517 emlxs_pkt_free(pkt);
3518 }
3519
3520 return;
3521
3522 } /* emlxs_send_logo() */
3523