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