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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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