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 emlxs_hba_t *hba = HBA; 1527 IOCB *iocb; 1528 uint32_t sid; 1529 #ifndef ULP_PATCH4 1530 fc_unsol_buf_t *ubp; 1531 emlxs_ub_priv_t *ub_priv; 1532 #endif 1533 1534 NODELIST *ndlp; 1535 1536 iocb = &iocbq->iocb; 1537 sid = iocb->un.elsreq.remoteID; 1538 1539 /* Get the node */ 1540 ndlp = emlxs_node_find_did(port, sid); 1541 1542 #ifdef SAN_DIAG_SUPPORT 1543 if (ndlp) { 1544 emlxs_log_sd_prlo_event(port, (HBA_WWN *)&ndlp->nlp_portname); 1545 } 1546 #endif 1547 1548 #ifdef ULP_PATCH4 1549 #ifdef ULP_PATCH6 1550 1551 /* Check if this is a SCSI target */ 1552 if (ndlp && (ndlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE)) { 1553 /* This is a SCSI target */ 1554 1555 /* If only one node is present, then we can */ 1556 /* conclude that we are direct attached to a target */ 1557 if (port->node_count == 1) { 1558 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 1559 "PRLO: sid=%x. Accepting and reseting link.", 1560 sid); 1561 1562 /* Send Acc */ 1563 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, 1564 ELS_CMD_PRLO, 0, 0); 1565 1566 /* Spawn a thread to reset the link */ 1567 emlxs_thread_spawn(hba, emlxs_reset_link_thread, 1568 NULL, NULL); 1569 1570 goto drop_it; 1571 1572 } 1573 /* Check if fabric is present */ 1574 else if (hba->flag & FC_FABRIC_ATTACHED) { 1575 /* Auto reply to PRLO */ 1576 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 1577 "PRLO: sid=%x. Accepting and generating RSCN.", 1578 sid); 1579 1580 /* Send Acc */ 1581 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, 1582 ELS_CMD_PRLO, 0, 0); 1583 1584 /* Generate an RSCN to wakeup ULP */ 1585 (void) emlxs_generate_rscn(port, sid); 1586 1587 goto drop_it; 1588 } 1589 1590 } 1591 /* SCSI target */ 1592 #endif /* ULP_PATCH6 */ 1593 1594 /* Auto reply to PRLO */ 1595 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 1596 "PRLO: sid=%x. Accepting.", sid); 1597 1598 /* Send Acc */ 1599 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, ELS_CMD_PRLO, 0, 0); 1600 1601 goto drop_it; 1602 1603 #else /* !ULP_PATCH4 */ 1604 1605 /* Tell ULP about it */ 1606 1607 ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size, FC_ELS_DATA, 0); 1608 1609 if (ubp == NULL) { 1610 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg, 1611 "PRLO recvd: sid=%x. Rejecting.", sid); 1612 1613 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, 1614 ELS_CMD_PRLO, LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE); 1615 1616 goto drop_it; 1617 } 1618 1619 /* 1620 * Setup unsolicited buffer and pass it up 1621 */ 1622 bcopy(mp->virt, ubp->ub_buffer, size); 1623 ub_priv = ubp->ub_fca_private; 1624 ub_priv->cmd = ELS_CMD_PRLO; 1625 1626 /* 1627 * Setup frame header 1628 */ 1629 ubp->ub_frame.r_ctl = FC_ELS_REQ; 1630 ubp->ub_frame.type = FC_ELS_DATA; 1631 ubp->ub_frame.s_id = SWAP_DATA24_LO(iocb->un.elsreq.remoteID); 1632 ubp->ub_frame.d_id = SWAP_DATA24_LO(iocb->un.elsreq.myID); 1633 ubp->ub_frame.ox_id = ub_priv->token; 1634 ubp->ub_frame.rx_id = iocb->ulpContext; 1635 ubp->ub_class = FC_TRAN_CLASS3; 1636 1637 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 1638 "PRLO: sid=%x buffeiocbr=%p token=%x.", sid, ubp, ub_priv->token); 1639 1640 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 1641 emlxs_swap_els_ub(ubp); 1642 #endif /* EMLXS_MODREV2X */ 1643 1644 emlxs_ub_callback(port, ubp); 1645 1646 #endif /* ULP_PATCH4 */ 1647 1648 drop_it: 1649 1650 return; 1651 1652 } /* emlxs_handle_unsol_prlo() */ 1653 1654 1655 /* ARGSUSED */ 1656 static void 1657 emlxs_handle_unsol_logo(emlxs_port_t *port, RING *rp, IOCBQ *iocbq, 1658 MATCHMAP *mp, uint32_t size) 1659 { 1660 emlxs_hba_t *hba = HBA; 1661 fc_unsol_buf_t *ubp; 1662 IOCB *iocb; 1663 uint32_t sid; 1664 emlxs_ub_priv_t *ub_priv; 1665 uint32_t reply_sent = 0; 1666 NODELIST *ndlp; 1667 1668 iocb = &iocbq->iocb; 1669 sid = iocb->un.elsreq.remoteID; 1670 1671 ndlp = emlxs_node_find_did(port, sid); 1672 1673 #ifdef SAN_DIAG_SUPPORT 1674 if (ndlp) { 1675 emlxs_log_sd_basic_els_event(port, SD_ELS_SUBCATEGORY_LOGO_RCV, 1676 (HBA_WWN *)&ndlp->nlp_portname, 1677 (HBA_WWN *)((uint32_t *)mp->virt + 2)); 1678 } 1679 #endif 1680 1681 #ifdef ULP_PATCH6 1682 1683 /* Check if this is a SCSI target */ 1684 if (ndlp && (ndlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE)) { 1685 /* This is a SCSI target */ 1686 1687 /* If only one node is present, then we can */ 1688 /* conclude that we are direct attached to a target */ 1689 if (port->node_count == 1) { 1690 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 1691 "LOGO: sid=%x. Accepting and reseting link.", 1692 sid); 1693 1694 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, 1695 ELS_CMD_LOGO, 0, 0); 1696 1697 /* Spawn a thread to reset the link */ 1698 emlxs_thread_spawn(hba, emlxs_reset_link_thread, 1699 NULL, NULL); 1700 1701 goto drop_it; 1702 } 1703 /* Check if fabric node is present */ 1704 else if (hba->flag & FC_FABRIC_ATTACHED) { 1705 /* Send reply ourselves */ 1706 /* We will block all attempts */ 1707 /* for ULP to reply to a LOGO */ 1708 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 1709 "LOGO: sid=%x. Accepting and generating RSCN.", 1710 sid); 1711 1712 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, 1713 ELS_CMD_LOGO, 0, 0); 1714 1715 /* Generate an RSCN to wakeup ULP */ 1716 if (emlxs_generate_rscn(port, sid) == FC_SUCCESS) { 1717 goto drop_it; 1718 } 1719 1720 reply_sent = 1; 1721 } 1722 1723 } 1724 /* SCSI target */ 1725 #endif /* ULP_PATCH6 */ 1726 1727 ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size, FC_ELS_DATA, 1); 1728 1729 if (ubp == NULL) { 1730 if (!reply_sent) { 1731 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg, 1732 "LOGO rcvd: sid=%x. Rejecting.", sid); 1733 1734 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, 1735 ELS_CMD_LOGO, LSRJT_LOGICAL_BSY, 1736 LSEXP_OUT_OF_RESOURCE); 1737 } 1738 1739 goto drop_it; 1740 1741 } 1742 1743 /* Setup unsolicited buffer and pass it up */ 1744 bcopy(mp->virt, ubp->ub_buffer, size); 1745 ub_priv = ubp->ub_fca_private; 1746 ub_priv->cmd = ELS_CMD_LOGO; 1747 1748 /* Setup frame header */ 1749 ubp->ub_frame.r_ctl = FC_ELS_REQ; 1750 ubp->ub_frame.type = FC_ELS_DATA; 1751 ubp->ub_frame.s_id = SWAP_DATA24_LO(iocb->un.elsreq.remoteID); 1752 ubp->ub_frame.d_id = SWAP_DATA24_LO(iocb->un.elsreq.myID); 1753 ubp->ub_frame.ox_id = ub_priv->token; 1754 ubp->ub_frame.rx_id = iocb->ulpContext; 1755 ubp->ub_class = FC_TRAN_CLASS3; 1756 1757 #ifdef ULP_PATCH2 1758 1759 if (!reply_sent) { 1760 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 1761 "LOGO: sid=%x buffer=%p token=%x. Accepting.", sid, ubp, 1762 ub_priv->token); 1763 1764 ub_priv->flags |= EMLXS_UB_REPLY; 1765 1766 /* Send Acc */ 1767 /* Send reply ourselves because ULP */ 1768 /* doesn't always reply to these */ 1769 /* We will block all attempts for ULP to reply to a LOGO */ 1770 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, 1771 ELS_CMD_LOGO, 0, 0); 1772 reply_sent = 1; 1773 } 1774 #else /* !ULP_PATCH2 */ 1775 1776 if (!reply_sent) { 1777 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 1778 "LOGO: sid=%x buffer=%p token=%x.", sid, ubp, 1779 ub_priv->token); 1780 } 1781 #endif /* ULP_PATCH2 */ 1782 1783 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 1784 emlxs_swap_els_ub(ubp); 1785 #endif /* EMLXS_MODREV2X */ 1786 1787 /* Clear the RPI */ 1788 if ((sid & Fabric_DID_MASK) == Fabric_DID_MASK) { 1789 if (emlxs_mb_unreg_did(port, sid, NULL, ubp, NULL) == 0) { 1790 /* 1791 * Deferred completion of this ubp 1792 * until unreg login is complete 1793 */ 1794 1795 return; 1796 } 1797 } 1798 1799 emlxs_ub_callback(port, ubp); 1800 1801 drop_it: 1802 1803 return; 1804 1805 } /* emlxs_handle_unsol_logo() */ 1806 1807 1808 1809 /* ARGSUSED */ 1810 static void 1811 emlxs_handle_unsol_gen_cmd(emlxs_port_t *port, RING *rp, IOCBQ *iocbq, 1812 MATCHMAP *mp, uint32_t size) 1813 { 1814 uint8_t *bp; 1815 fc_unsol_buf_t *ubp; 1816 IOCB *iocb; 1817 uint32_t *lp; 1818 uint32_t cmd; 1819 uint32_t sid; 1820 emlxs_ub_priv_t *ub_priv; 1821 1822 iocb = &iocbq->iocb; 1823 sid = iocb->un.elsreq.remoteID; 1824 1825 bp = mp->virt; 1826 lp = (uint32_t *)bp; 1827 cmd = *lp & ELS_CMD_MASK; 1828 1829 ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size, FC_ELS_DATA, 0); 1830 1831 if (ubp == NULL) { 1832 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg, 1833 "%s rcvd: sid=%x: Rejecting.", emlxs_elscmd_xlate(cmd), 1834 sid); 1835 1836 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd, 1837 LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE); 1838 1839 goto drop_it; 1840 } 1841 1842 bcopy(bp, ubp->ub_buffer, size); 1843 ub_priv = ubp->ub_fca_private; 1844 ub_priv->cmd = cmd; 1845 1846 /* Setup frame header */ 1847 ubp->ub_frame.r_ctl = FC_ELS_REQ; 1848 ubp->ub_frame.type = FC_ELS_DATA; 1849 ubp->ub_frame.s_id = SWAP_DATA24_LO(iocb->un.elsreq.remoteID); 1850 ubp->ub_frame.d_id = SWAP_DATA24_LO(iocb->un.elsreq.myID); 1851 ubp->ub_frame.ox_id = ub_priv->token; 1852 ubp->ub_frame.rx_id = iocb->ulpContext; 1853 ubp->ub_class = FC_TRAN_CLASS3; 1854 1855 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 1856 "%s: sid=%x buffer=%p token=%x.", emlxs_elscmd_xlate(cmd), sid, 1857 ubp, ub_priv->token); 1858 1859 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 1860 emlxs_swap_els_ub(ubp); 1861 #endif /* EMLXS_MODREV2X */ 1862 1863 emlxs_ub_callback(port, ubp); 1864 1865 drop_it: 1866 1867 return; 1868 1869 } /* emlxs_handle_unsol_gen_cmd() */ 1870 1871 1872 /* This handles the reply completions to unsolicited cmds */ 1873 /* ARGSUSED */ 1874 static void 1875 emlxs_handle_acc(emlxs_port_t *port, emlxs_buf_t *sbp, IOCBQ *iocbq, 1876 uint32_t flag) 1877 { 1878 fc_packet_t *pkt; 1879 IOCB *iocb; 1880 uint32_t did; 1881 NODELIST *ndlp; 1882 uint32_t ucmd; 1883 uint32_t cmd; 1884 uint32_t *lp; 1885 1886 iocb = &iocbq->iocb; 1887 pkt = PRIV2PKT(sbp); 1888 did = SWAP_DATA24_LO(pkt->pkt_cmd_fhdr.d_id); 1889 ucmd = pkt->pkt_cmd_fhdr.ox_id << ELS_CMD_SHIFT; 1890 lp = (uint32_t *)pkt->pkt_cmd; 1891 cmd = *lp & ELS_CMD_MASK; 1892 1893 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg, 1894 "%s %s: did=%x %s %s", emlxs_elscmd_xlate(ucmd), 1895 emlxs_elscmd_xlate(cmd), did, emlxs_state_xlate(iocb->ulpStatus), 1896 emlxs_error_xlate(iocb->un.grsp.perr.statLocalError)); 1897 1898 switch (ucmd) { 1899 case ELS_CMD_PLOGI: 1900 case ELS_CMD_ADISC: 1901 1902 ndlp = emlxs_node_find_did(port, did); 1903 1904 if (ndlp && ndlp->nlp_active) { 1905 /* Open the node again */ 1906 emlxs_node_open(port, ndlp, FC_FCP_RING); 1907 emlxs_node_open(port, ndlp, FC_IP_RING); 1908 } 1909 1910 break; 1911 1912 case ELS_CMD_PRLI: 1913 1914 ndlp = emlxs_node_find_did(port, did); 1915 1916 if (ndlp && ndlp->nlp_active) { 1917 /* Open the node again */ 1918 emlxs_node_open(port, ndlp, FC_FCP_RING); 1919 } 1920 1921 break; 1922 } 1923 1924 emlxs_pkt_complete(sbp, iocb->ulpStatus, 1925 iocb->un.grsp.perr.statLocalError, 1); 1926 1927 return; 1928 1929 } /* emlxs_handle_acc() */ 1930 1931 1932 /* This handles the reply completions to unsolicited cmds */ 1933 /* ARGSUSED */ 1934 static void 1935 emlxs_handle_reject(emlxs_port_t *port, emlxs_buf_t *sbp, IOCBQ *iocbq, 1936 uint32_t flag) 1937 { 1938 fc_packet_t *pkt; 1939 NODELIST *ndlp; 1940 IOCB *iocb; 1941 uint32_t did; 1942 uint32_t ucmd; 1943 uint32_t cmd; 1944 uint32_t *lp; 1945 1946 iocb = &iocbq->iocb; 1947 pkt = PRIV2PKT(sbp); 1948 did = SWAP_DATA24_LO(pkt->pkt_cmd_fhdr.d_id); 1949 ucmd = pkt->pkt_cmd_fhdr.ox_id << ELS_CMD_SHIFT; 1950 lp = (uint32_t *)pkt->pkt_cmd; 1951 cmd = *lp & ELS_CMD_MASK; 1952 1953 ndlp = emlxs_node_find_did(port, did); 1954 1955 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg, 1956 "%s %s: did=%x %s %s", emlxs_elscmd_xlate(ucmd), 1957 emlxs_elscmd_xlate(cmd), did, emlxs_state_xlate(iocb->ulpStatus), 1958 emlxs_error_xlate(iocb->un.grsp.perr.statLocalError)); 1959 1960 switch (ucmd) { 1961 case ELS_CMD_PLOGI: 1962 1963 if (ndlp && ndlp->nlp_active) { 1964 /* Open the node again */ 1965 emlxs_node_open(port, ndlp, FC_FCP_RING); 1966 emlxs_node_open(port, ndlp, FC_IP_RING); 1967 } 1968 1969 break; 1970 1971 case ELS_CMD_PRLI: 1972 1973 if (ndlp && ndlp->nlp_active) { 1974 /* Open the node again */ 1975 emlxs_node_open(port, ndlp, FC_FCP_RING); 1976 } 1977 1978 break; 1979 } 1980 1981 emlxs_pkt_complete(sbp, iocb->ulpStatus, 1982 iocb->un.grsp.perr.statLocalError, 1); 1983 1984 return; 1985 1986 } /* emlxs_handle_reject() */ 1987 1988 1989 /* ARGSUSED */ 1990 extern int32_t 1991 emlxs_els_reply(emlxs_port_t *port, IOCBQ *iocbq, uint32_t type, 1992 uint32_t type2, uint32_t reason, uint32_t explain) 1993 { 1994 emlxs_hba_t *hba = HBA; 1995 emlxs_config_t *cfg = &CFG; 1996 fc_packet_t *pkt; 1997 ELS_PKT *els; 1998 uint32_t rval; 1999 IOCB *iocb; 2000 2001 iocb = &iocbq->iocb; 2002 2003 switch (type) { 2004 case ELS_CMD_ACC: /* Accept Response */ 2005 2006 /* Allocate the pkt */ 2007 switch (type2) { 2008 case ELS_CMD_FLOGI: 2009 if (!(pkt = emlxs_pkt_alloc(port, 2010 sizeof (uint32_t) + sizeof (SERV_PARM), 0, 2011 0, KM_NOSLEEP))) { 2012 return (1); 2013 } 2014 break; 2015 2016 case ELS_CMD_ADISC: 2017 if (!(pkt = emlxs_pkt_alloc(port, 2018 sizeof (uint32_t) + sizeof (ADISC), 0, 0, 2019 KM_NOSLEEP))) { 2020 return (1); 2021 } 2022 break; 2023 2024 case ELS_CMD_PRLI: 2025 if (!(pkt = emlxs_pkt_alloc(port, 2026 sizeof (uint32_t) + sizeof (PRLI), 0, 0, 2027 KM_NOSLEEP))) { 2028 return (1); 2029 } 2030 break; 2031 2032 case ELS_CMD_PRLO: 2033 if (!(pkt = emlxs_pkt_alloc(port, 2034 sizeof (uint32_t) + sizeof (PRLO), 0, 0, 2035 KM_NOSLEEP))) { 2036 return (1); 2037 } 2038 break; 2039 2040 case ELS_CMD_AUTH: 2041 default: 2042 2043 if (!(pkt = emlxs_pkt_alloc(port, sizeof (uint32_t), 2044 0, 0, KM_NOSLEEP))) { 2045 return (1); 2046 } 2047 } 2048 2049 /* Common initialization */ 2050 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 2051 pkt->pkt_timeout = (2 * hba->fc_ratov); 2052 2053 if ((uint32_t)iocb->ulpClass == CLASS2) { 2054 pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3; 2055 pkt->pkt_tran_flags |= FC_TRAN_CLASS2; 2056 } 2057 2058 /* Build the fc header */ 2059 pkt->pkt_cmd_fhdr.d_id = 2060 SWAP_DATA24_LO(iocb->un.elsreq.remoteID); 2061 pkt->pkt_cmd_fhdr.r_ctl = 2062 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL; 2063 pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(iocb->un.elsreq.myID); 2064 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 2065 pkt->pkt_cmd_fhdr.f_ctl = 2066 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ; 2067 pkt->pkt_cmd_fhdr.seq_id = 0; 2068 pkt->pkt_cmd_fhdr.df_ctl = 0; 2069 pkt->pkt_cmd_fhdr.seq_cnt = 0; 2070 pkt->pkt_cmd_fhdr.ox_id = (type2 >> ELS_CMD_SHIFT) & 0xff; 2071 pkt->pkt_cmd_fhdr.rx_id = iocb->ulpContext; 2072 pkt->pkt_cmd_fhdr.ro = 0; 2073 2074 /* 2075 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 2076 * "%s ACC send. oxid=%x", emlxs_elscmd_xlate(type2), 2077 * pkt->pkt_cmd_fhdr.ox_id); 2078 */ 2079 2080 /* Build the command */ 2081 els = (ELS_PKT *)pkt->pkt_cmd; 2082 els->elsCode = 0x02; 2083 2084 /* Build the payload */ 2085 switch (type2) { 2086 case ELS_CMD_ADISC: 2087 2088 els->un.adisc.hardAL_PA = 2089 (uint8_t)cfg[CFG_ASSIGN_ALPA].current; 2090 bcopy(&port->wwnn, &els->un.adisc.nodeName, 2091 sizeof (NAME_TYPE)); 2092 bcopy(&port->wwpn, &els->un.adisc.portName, 2093 sizeof (NAME_TYPE)); 2094 els->un.adisc.DID = SWAP_DATA24_LO(port->did); 2095 2096 break; 2097 2098 case ELS_CMD_PRLI: 2099 2100 els->elsByte1 = 0x10; 2101 els->elsByte2 = 0; 2102 els->elsByte3 = 0x14; 2103 2104 els->un.prli.prliType = PRLI_FCP_TYPE; 2105 els->un.prli.estabImagePair = 1; 2106 els->un.prli.acceptRspCode = PRLI_REQ_EXECUTED; 2107 2108 if (port->ini_mode) { 2109 els->un.prli.initiatorFunc = 1; 2110 } 2111 2112 if (port->tgt_mode) { 2113 els->un.prli.targetFunc = 1; 2114 } 2115 2116 els->un.prli.readXferRdyDis = 1; 2117 2118 if (hba->vpd.feaLevelHigh >= 0x02) { 2119 els->un.prli.ConfmComplAllowed = 1; 2120 els->un.prli.Retry = 1; 2121 els->un.prli.TaskRetryIdReq = 1; 2122 } else { 2123 els->un.prli.ConfmComplAllowed = 0; 2124 els->un.prli.Retry = 0; 2125 els->un.prli.TaskRetryIdReq = 0; 2126 } 2127 2128 break; 2129 2130 case ELS_CMD_PRLO: 2131 2132 els->elsByte1 = 0x10; 2133 els->elsByte2 = 0; 2134 els->elsByte3 = 0x14; 2135 2136 els->un.prlo.prloType = PRLO_FCP_TYPE; 2137 els->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED; 2138 2139 break; 2140 2141 2142 } /* switch(type2) */ 2143 break; 2144 2145 case ELS_CMD_LS_RJT: /* reject response */ 2146 2147 if (!(pkt = emlxs_pkt_alloc(port, 2148 sizeof (uint32_t) + sizeof (LS_RJT), 0, 0, KM_NOSLEEP))) { 2149 return (1); 2150 } 2151 2152 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 2153 pkt->pkt_timeout = (2 * hba->fc_ratov); 2154 2155 if ((uint32_t)iocb->ulpClass == CLASS2) { 2156 pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3; 2157 pkt->pkt_tran_flags |= FC_TRAN_CLASS2; 2158 } 2159 2160 /* Build the fc header */ 2161 pkt->pkt_cmd_fhdr.d_id = 2162 SWAP_DATA24_LO(iocb->un.elsreq.remoteID); 2163 pkt->pkt_cmd_fhdr.r_ctl = 2164 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL; 2165 pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(iocb->un.elsreq.myID); 2166 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 2167 pkt->pkt_cmd_fhdr.f_ctl = 2168 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ; 2169 pkt->pkt_cmd_fhdr.seq_id = 0; 2170 pkt->pkt_cmd_fhdr.df_ctl = 0; 2171 pkt->pkt_cmd_fhdr.seq_cnt = 0; 2172 pkt->pkt_cmd_fhdr.ox_id = (type2 >> ELS_CMD_SHIFT) & 0xff; 2173 pkt->pkt_cmd_fhdr.rx_id = iocb->ulpContext; 2174 pkt->pkt_cmd_fhdr.ro = 0; 2175 2176 /* 2177 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 2178 * "%s LS_RJT send. oxid=%x", emlxs_elscmd_xlate(type2), 2179 * pkt->pkt_cmd_fhdr.ox_id); 2180 */ 2181 2182 /* Build the command */ 2183 els = (ELS_PKT *)pkt->pkt_cmd; 2184 els->elsCode = 0x01; 2185 els->un.lsRjt.un.b.lsRjtRsvd0 = 0; 2186 els->un.lsRjt.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; 2187 els->un.lsRjt.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; 2188 els->un.lsRjt.un.b.vendorUnique = 0x01; 2189 2190 break; 2191 } 2192 2193 if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) { 2194 /* Free the pkt */ 2195 emlxs_pkt_free(pkt); 2196 } 2197 2198 return (rval); 2199 2200 } /* emlxs_els_reply() */ 2201 2202 2203 #ifdef ULP_PATCH6 2204 2205 extern uint32_t 2206 emlxs_generate_rscn(emlxs_port_t *port, uint32_t d_id) 2207 { 2208 fc_unsol_buf_t *ubp; 2209 fc_rscn_t *rscn; 2210 emlxs_ub_priv_t *ub_priv; 2211 uint32_t *page; 2212 2213 ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, 8, FC_ELS_DATA, 1); 2214 2215 if (ubp == NULL) { 2216 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg, 2217 "RSCN create: sid=0xfffffd 1 page(s): %08X, 00000000. " 2218 "Creation failed.", d_id); 2219 2220 return ((uint32_t)FC_FAILURE); 2221 } 2222 2223 /* Simulate an RSCN payload */ 2224 rscn = (fc_rscn_t *)ubp->ub_buffer; 2225 rscn->rscn_code = 0x61; 2226 rscn->rscn_len = 0x04; 2227 rscn->rscn_payload_len = 0x0008; 2228 page = ((uint32_t *)rscn); 2229 page++; 2230 *page = d_id; 2231 2232 #ifdef EMLXS_I386 2233 /* Put payload in BE format */ 2234 rscn->rscn_payload_len = SWAP_DATA16(rscn->rscn_payload_len); 2235 *page = SWAP_DATA32(d_id); 2236 #endif /* EMLXS_I386 */ 2237 2238 ub_priv = ubp->ub_fca_private; 2239 ub_priv->cmd = ELS_CMD_RSCN; 2240 ub_priv->flags |= EMLXS_UB_INTERCEPT; 2241 2242 ubp->ub_frame.r_ctl = FC_ELS_REQ; 2243 ubp->ub_frame.type = FC_ELS_DATA; 2244 ubp->ub_frame.s_id = 0xfffffd; 2245 ubp->ub_frame.d_id = SWAP_DATA24_LO(port->did); 2246 ubp->ub_frame.ox_id = ub_priv->token; 2247 ubp->ub_frame.rx_id = 0xffff; 2248 ubp->ub_class = FC_TRAN_CLASS3; 2249 2250 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 2251 "RSCN: sid=fffffd 1 page(s): %08X, 00000000 buffer=%p " 2252 "token=%x. Created.", d_id, ubp, ub_priv->token); 2253 2254 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 2255 emlxs_swap_els_ub(ubp); 2256 #endif /* EMLXS_MODREV2X */ 2257 2258 emlxs_ub_callback(port, ubp); 2259 2260 return (FC_SUCCESS); 2261 2262 } /* emlxs_generate_rscn() */ 2263 2264 #endif /* ULP_PATCH6 */ 2265 2266 2267 #ifdef MENLO_SUPPORT 2268 extern int 2269 emlxs_menlo_handle_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 2270 { 2271 emlxs_port_t *port = &PPORT; 2272 IOCB *iocb; 2273 emlxs_buf_t *sbp; 2274 fc_packet_t *pkt; 2275 uint32_t cmd_code = 0; 2276 uint32_t rsp_code = 0; 2277 menlo_cmd_t *cmd; 2278 uint32_t *rsp; 2279 2280 iocb = &iocbq->iocb; 2281 2282 HBASTATS.CtEvent++; 2283 2284 sbp = (emlxs_buf_t *)iocbq->sbp; 2285 2286 if (!sbp) { 2287 /* 2288 * completion with missing xmit command 2289 */ 2290 HBASTATS.CtStray++; 2291 2292 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ct_completion_msg, 2293 "iocbq=%p cmd=0x%x iotag=0x%x status=0x%x perr=0x%x", 2294 iocbq, (uint32_t)iocb->ulpCommand, 2295 (uint32_t)iocb->ulpIoTag, iocb->ulpStatus, 2296 iocb->un.ulpWord[4]); 2297 2298 return (1); 2299 } 2300 2301 if (rp->ringno != FC_CT_RING) { 2302 HBASTATS.CtStray++; 2303 2304 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ct_completion_msg, 2305 "Invalid ring: ring=%d iocbq=%p", rp->ringno, iocbq); 2306 2307 return (1); 2308 } 2309 2310 port = sbp->iocbq.port; 2311 pkt = PRIV2PKT(sbp); 2312 2313 cmd = (menlo_cmd_t *)pkt->pkt_cmd; 2314 cmd_code = SWAP_LONG(cmd->code); 2315 2316 /* Check if a response buffer was provided */ 2317 if (pkt->pkt_rsplen) { 2318 emlxs_mpdata_sync(pkt->pkt_resp_dma, 0, pkt->pkt_rsplen, 2319 DDI_DMA_SYNC_FORKERNEL); 2320 } 2321 2322 switch (iocb->ulpCommand) { 2323 /* 2324 * MENLO Command completion 2325 */ 2326 case CMD_GEN_REQUEST64_CR: 2327 case CMD_GEN_REQUEST64_CX: 2328 2329 HBASTATS.CtCmdCompleted++; 2330 2331 sbp->pkt_flags |= PACKET_CT_RSP_VALID; 2332 2333 rsp = (uint32_t *)pkt->pkt_resp; 2334 rsp_code = *rsp; 2335 rsp_code = SWAP_LONG(rsp_code); 2336 2337 #ifdef SLI3_SUPPORT 2338 if (hba->sli_mode >= 3) { 2339 pkt->pkt_resp_resid = 2340 pkt->pkt_rsplen - iocb->unsli3.ext_iocb.rsplen; 2341 } else 2342 #endif /* SLI3_SUPPORT */ 2343 { 2344 pkt->pkt_resp_resid = 2345 pkt->pkt_rsplen - iocb->un.genreq64.bdl.bdeSize; 2346 } 2347 2348 pkt->pkt_data_resid = pkt->pkt_datalen; 2349 pkt->pkt_cmd_fhdr.rx_id = iocb->ulpContext; 2350 2351 if ((iocb->ulpStatus == 0) && (rsp_code == MENLO_RSP_SUCCESS)) { 2352 HBASTATS.CtCmdGood++; 2353 2354 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg, 2355 "%s: %s rxid=0x%x", 2356 emlxs_menlo_cmd_xlate(cmd_code), 2357 emlxs_menlo_rsp_xlate(rsp_code), 2358 iocb->ulpContext); 2359 2360 } else { 2361 HBASTATS.CtCmdError++; 2362 2363 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg, 2364 "%s: %s %s %s rxid=0x%x", 2365 emlxs_menlo_cmd_xlate(cmd_code), 2366 emlxs_menlo_rsp_xlate(rsp_code), 2367 emlxs_state_xlate(iocb->ulpStatus), 2368 emlxs_error_xlate(iocb->un.grsp.perr. 2369 statLocalError), iocb->ulpContext); 2370 } 2371 2372 emlxs_pkt_complete(sbp, iocb->ulpStatus, 2373 iocb->un.grsp.perr.statLocalError, 1); 2374 2375 break; 2376 2377 default: 2378 2379 HBASTATS.CtStray++; 2380 2381 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_invalid_ct_msg, 2382 "Invalid iocb: cmd=0x%x", iocb->ulpCommand); 2383 2384 emlxs_pkt_complete(sbp, iocb->ulpStatus, 2385 iocb->un.grsp.perr.statLocalError, 1); 2386 2387 break; 2388 2389 } /* switch(iocb->ulpCommand) */ 2390 2391 return (0); 2392 2393 } /* emlxs_menlo_handle_event() */ 2394 2395 #endif /* MENLO_SUPPORT */ 2396 2397 2398 extern int 2399 emlxs_ct_handle_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 2400 { 2401 emlxs_port_t *port = &PPORT; 2402 IOCB *iocb; 2403 emlxs_buf_t *sbp; 2404 fc_packet_t *pkt; 2405 uint32_t *rsp; 2406 SLI_CT_REQUEST *CtRsp; 2407 SLI_CT_REQUEST *CtCmd; 2408 uint32_t cmd_code = 0; 2409 uint32_t rsp_code = 0; 2410 2411 iocb = &iocbq->iocb; 2412 2413 HBASTATS.CtEvent++; 2414 2415 sbp = (emlxs_buf_t *)iocbq->sbp; 2416 2417 if (!sbp) { 2418 /* 2419 * completion with missing xmit command 2420 */ 2421 HBASTATS.CtStray++; 2422 2423 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ct_completion_msg, 2424 "iocbq=%p cmd=0x%x iotag=0x%x status=0x%x perr=0x%x", 2425 iocbq, (uint32_t)iocb->ulpCommand, 2426 (uint32_t)iocb->ulpIoTag, iocb->ulpStatus, 2427 iocb->un.ulpWord[4]); 2428 2429 return (1); 2430 } 2431 2432 if (rp->ringno != FC_CT_RING) { 2433 HBASTATS.CtStray++; 2434 2435 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ct_completion_msg, 2436 "Invalid ring: ring=%d iocbq=%p", rp->ringno, iocbq); 2437 2438 return (1); 2439 } 2440 2441 pkt = PRIV2PKT(sbp); 2442 port = sbp->iocbq.port; 2443 CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd; 2444 cmd_code = SWAP_DATA16(CtCmd->CommandResponse.bits.CmdRsp); 2445 2446 #ifdef DFC_SUPPORT 2447 if (cmd_code == SLI_CT_LOOPBACK) { 2448 HBASTATS.CtEvent--; 2449 return (emlxs_dfc_handle_event(hba, rp, iocbq)); 2450 } 2451 #endif /* DFC_SUPPORT */ 2452 2453 /* Check if a response buffer was provided */ 2454 if (pkt->pkt_rsplen) { 2455 emlxs_mpdata_sync(pkt->pkt_resp_dma, 0, pkt->pkt_rsplen, 2456 DDI_DMA_SYNC_FORKERNEL); 2457 } 2458 2459 switch (iocb->ulpCommand) { 2460 /* 2461 * CT Reply completion 2462 */ 2463 case CMD_XMIT_SEQUENCE_CX: 2464 case CMD_XMIT_SEQUENCE64_CX: 2465 2466 HBASTATS.CtRspCompleted++; 2467 2468 switch (CtCmd->FsType) { 2469 case 0xFC: /* Name server */ 2470 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg, 2471 "%s: %s %s", emlxs_ctcmd_xlate(cmd_code), 2472 emlxs_state_xlate(iocb->ulpStatus), 2473 emlxs_error_xlate(iocb->un.grsp.perr. 2474 statLocalError)); 2475 break; 2476 2477 case 0xFA: /* Managment server */ 2478 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg, 2479 "%s: %s %s", emlxs_mscmd_xlate(cmd_code), 2480 emlxs_state_xlate(iocb->ulpStatus), 2481 emlxs_error_xlate(iocb->un.grsp.perr. 2482 statLocalError)); 2483 break; 2484 2485 case 0x0A: /* Emulex Remote server */ 2486 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg, 2487 "%s: %s %s", emlxs_rmcmd_xlate(cmd_code), 2488 emlxs_state_xlate(iocb->ulpStatus), 2489 emlxs_error_xlate(iocb->un.grsp.perr. 2490 statLocalError)); 2491 break; 2492 2493 default: 2494 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg, 2495 "%s: %s %s", emlxs_ctcmd_xlate(cmd_code), 2496 emlxs_state_xlate(iocb->ulpStatus), 2497 emlxs_error_xlate(iocb->un.grsp.perr. 2498 statLocalError)); 2499 } 2500 2501 emlxs_pkt_complete(sbp, iocb->ulpStatus, 2502 iocb->un.grsp.perr.statLocalError, 1); 2503 2504 break; 2505 2506 /* 2507 * CT Command completion 2508 */ 2509 case CMD_GEN_REQUEST64_CR: 2510 case CMD_GEN_REQUEST64_CX: 2511 2512 HBASTATS.CtCmdCompleted++; 2513 2514 sbp->pkt_flags |= PACKET_CT_RSP_VALID; 2515 2516 rsp = (uint32_t *)pkt->pkt_resp; 2517 CtRsp = (SLI_CT_REQUEST *)pkt->pkt_resp; 2518 rsp_code = SWAP_DATA16(CtRsp->CommandResponse.bits.CmdRsp); 2519 2520 #ifdef SLI3_SUPPORT 2521 if (hba->sli_mode >= 3) { 2522 pkt->pkt_resp_resid = 2523 pkt->pkt_rsplen - iocb->unsli3.ext_iocb.rsplen; 2524 } else 2525 #endif /* SLI3_SUPPORT */ 2526 { 2527 pkt->pkt_resp_resid = 2528 pkt->pkt_rsplen - iocb->un.genreq64.bdl.bdeSize; 2529 } 2530 2531 pkt->pkt_data_resid = pkt->pkt_datalen; 2532 2533 /* 2534 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg, 2535 * "INFO: pkt_resid=%d %d %d %x", pkt->pkt_resp_resid, 2536 * pkt->pkt_rsplen, iocb->un.genreq64.bdl.bdeSize, 2537 * iocb->un.genreq64.bdl.bdeFlags); 2538 */ 2539 2540 if ((iocb->ulpStatus == 0) && 2541 (rsp_code == SLI_CT_RESPONSE_FS_ACC)) { 2542 HBASTATS.CtCmdGood++; 2543 2544 if (!(sbp->pkt_flags & PACKET_ALLOCATED)) { 2545 /* ULP patch - ULP expects */ 2546 /* resp_resid = 0 on success */ 2547 pkt->pkt_resp_resid = 0; 2548 } 2549 2550 switch (CtCmd->FsType) { 2551 case 0xFC: /* Name server */ 2552 EMLXS_MSGF(EMLXS_CONTEXT, 2553 &emlxs_ct_completion_msg, 2554 "%s: %s: Rsn=%x Exp=%x [%08x,%08x]", 2555 emlxs_ctcmd_xlate(cmd_code), 2556 emlxs_ctcmd_xlate(rsp_code), 2557 CtRsp->ReasonCode, CtRsp->Explanation, 2558 SWAP_DATA32(rsp[4]), SWAP_DATA32(rsp[5])); 2559 2560 #if (EMLXS_MODREV < EMLXS_MODREV4) 2561 if (cmd_code == SLI_CTNS_RNN_ID) { 2562 emlxs_send_rsnn(port); 2563 } 2564 #endif /* < EMLXS_MODREV4 */ 2565 2566 break; 2567 2568 case 0xFA: /* Managment server */ 2569 EMLXS_MSGF(EMLXS_CONTEXT, 2570 &emlxs_ct_completion_msg, 2571 "%s: %s: Rsn=%x Exp=%x [%08x,%08x]", 2572 emlxs_mscmd_xlate(cmd_code), 2573 emlxs_mscmd_xlate(rsp_code), 2574 CtRsp->ReasonCode, CtRsp->Explanation, 2575 SWAP_DATA32(rsp[4]), SWAP_DATA32(rsp[5])); 2576 break; 2577 2578 case 0x0A: /* Emulex Remote server */ 2579 EMLXS_MSGF(EMLXS_CONTEXT, 2580 &emlxs_ct_completion_msg, 2581 "%s: %s: Rsn=%x Exp=%x [%08x,%08x]", 2582 emlxs_rmcmd_xlate(cmd_code), 2583 emlxs_rmcmd_xlate(rsp_code), 2584 CtRsp->ReasonCode, CtRsp->Explanation, 2585 SWAP_DATA32(rsp[4]), SWAP_DATA32(rsp[5])); 2586 break; 2587 2588 default: 2589 EMLXS_MSGF(EMLXS_CONTEXT, 2590 &emlxs_ct_completion_msg, 2591 "%s: %s: Rsn=%x Exp=%x [%08x,%08x]", 2592 emlxs_ctcmd_xlate(cmd_code), 2593 emlxs_ctcmd_xlate(rsp_code), 2594 CtRsp->ReasonCode, CtRsp->Explanation, 2595 SWAP_DATA32(rsp[4]), SWAP_DATA32(rsp[5])); 2596 } 2597 } else { 2598 HBASTATS.CtCmdError++; 2599 2600 if (rsp_code == SLI_CT_RESPONSE_FS_RJT) { 2601 pkt->pkt_state = FC_PKT_FS_RJT; 2602 pkt->pkt_action = FC_ACTION_RETRYABLE; 2603 pkt->pkt_reason = CtRsp->ReasonCode; 2604 pkt->pkt_expln = CtRsp->Explanation; 2605 sbp->pkt_flags |= PACKET_STATE_VALID; 2606 2607 EMLXS_MSGF(EMLXS_CONTEXT, 2608 &emlxs_ct_completion_msg, 2609 "%s: Rejected. rsn=%x exp=%x", 2610 emlxs_ctcmd_xlate(cmd_code), 2611 pkt->pkt_reason, pkt->pkt_expln); 2612 } else if (iocb->ulpStatus == IOSTAT_LOCAL_REJECT) { 2613 switch (CtCmd->FsType) { 2614 case 0xFC: /* Name server */ 2615 EMLXS_MSGF(EMLXS_CONTEXT, 2616 &emlxs_ct_completion_msg, 2617 "%s: %s %s", 2618 emlxs_ctcmd_xlate(cmd_code), 2619 emlxs_state_xlate(iocb-> 2620 ulpStatus), 2621 emlxs_error_xlate(iocb->un.grsp. 2622 perr.statLocalError)); 2623 break; 2624 2625 case 0xFA: /* Managment server */ 2626 EMLXS_MSGF(EMLXS_CONTEXT, 2627 &emlxs_ct_completion_msg, 2628 "%s: %s %s", 2629 emlxs_mscmd_xlate(cmd_code), 2630 emlxs_state_xlate(iocb-> 2631 ulpStatus), 2632 emlxs_error_xlate(iocb->un.grsp. 2633 perr.statLocalError)); 2634 break; 2635 2636 case 0x0A: /* Emulex Remote server */ 2637 EMLXS_MSGF(EMLXS_CONTEXT, 2638 &emlxs_ct_completion_msg, 2639 "%s: %s %s", 2640 emlxs_rmcmd_xlate(cmd_code), 2641 emlxs_state_xlate(iocb-> 2642 ulpStatus), 2643 emlxs_error_xlate(iocb->un.grsp. 2644 perr.statLocalError)); 2645 break; 2646 2647 default: 2648 EMLXS_MSGF(EMLXS_CONTEXT, 2649 &emlxs_ct_completion_msg, 2650 "%s: %s %s", 2651 emlxs_ctcmd_xlate(cmd_code), 2652 emlxs_state_xlate(iocb-> 2653 ulpStatus), 2654 emlxs_error_xlate(iocb->un.grsp. 2655 perr.statLocalError)); 2656 } 2657 } else { 2658 switch (CtCmd->FsType) { 2659 case 0xFC: /* Name server */ 2660 EMLXS_MSGF(EMLXS_CONTEXT, 2661 &emlxs_ct_completion_msg, 2662 "%s: %s (%02x%02x%02x%02x)", 2663 emlxs_ctcmd_xlate(cmd_code), 2664 emlxs_state_xlate(iocb-> 2665 ulpStatus), 2666 iocb->un.grsp.perr.statAction, 2667 iocb->un.grsp.perr.statRsn, 2668 iocb->un.grsp.perr.statBaExp, 2669 iocb->un.grsp.perr. 2670 statLocalError); 2671 break; 2672 2673 case 0xFA: /* Managment server */ 2674 EMLXS_MSGF(EMLXS_CONTEXT, 2675 &emlxs_ct_completion_msg, 2676 "%s: %s (%02x%02x%02x%02x)", 2677 emlxs_mscmd_xlate(cmd_code), 2678 emlxs_state_xlate(iocb-> 2679 ulpStatus), 2680 iocb->un.grsp.perr.statAction, 2681 iocb->un.grsp.perr.statRsn, 2682 iocb->un.grsp.perr.statBaExp, 2683 iocb->un.grsp.perr. 2684 statLocalError); 2685 break; 2686 2687 case 0x0A: /* Emulex Remote server */ 2688 EMLXS_MSGF(EMLXS_CONTEXT, 2689 &emlxs_ct_completion_msg, 2690 "%s: %s (%02x%02x%02x%02x)", 2691 emlxs_rmcmd_xlate(cmd_code), 2692 emlxs_state_xlate(iocb-> 2693 ulpStatus), 2694 iocb->un.grsp.perr.statAction, 2695 iocb->un.grsp.perr.statRsn, 2696 iocb->un.grsp.perr.statBaExp, 2697 iocb->un.grsp.perr. 2698 statLocalError); 2699 break; 2700 2701 default: 2702 EMLXS_MSGF(EMLXS_CONTEXT, 2703 &emlxs_ct_completion_msg, 2704 "%s: %s (%02x%02x%02x%02x)", 2705 emlxs_ctcmd_xlate(cmd_code), 2706 emlxs_state_xlate(iocb-> 2707 ulpStatus), 2708 iocb->un.grsp.perr.statAction, 2709 iocb->un.grsp.perr.statRsn, 2710 iocb->un.grsp.perr.statBaExp, 2711 iocb->un.grsp.perr. 2712 statLocalError); 2713 } 2714 } 2715 } 2716 2717 emlxs_pkt_complete(sbp, iocb->ulpStatus, 2718 iocb->un.grsp.perr.statLocalError, 1); 2719 2720 break; 2721 2722 default: 2723 2724 HBASTATS.CtStray++; 2725 2726 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_invalid_ct_msg, 2727 "Invalid iocb: cmd=0x%x", iocb->ulpCommand); 2728 2729 emlxs_pkt_complete(sbp, iocb->ulpStatus, 2730 iocb->un.grsp.perr.statLocalError, 1); 2731 2732 break; 2733 } /* switch(iocb->ulpCommand) */ 2734 2735 return (0); 2736 2737 } /* emlxs_ct_handle_event() */ 2738 2739 2740 extern int 2741 emlxs_ct_handle_unsol_req(emlxs_port_t *port, RING *rp, IOCBQ *iocbq, 2742 MATCHMAP *mp, uint32_t size) 2743 { 2744 emlxs_hba_t *hba = HBA; 2745 IOCB *iocb; 2746 SLI_CT_REQUEST *CtCmd; 2747 uint32_t cmd_code; 2748 2749 iocb = &iocbq->iocb; 2750 2751 CtCmd = (SLI_CT_REQUEST *)mp->virt; 2752 cmd_code = SWAP_DATA16(CtCmd->CommandResponse.bits.CmdRsp); 2753 2754 #ifdef DFC_SUPPORT 2755 if (cmd_code == SLI_CT_LOOPBACK) { 2756 int rval; 2757 2758 rval = emlxs_dfc_handle_unsol_req(port, rp, iocbq, mp, size); 2759 2760 return (rval); 2761 } 2762 #endif /* DFC_SUPPORT */ 2763 2764 HBASTATS.CtCmdReceived++; 2765 2766 switch (CtCmd->FsType) { 2767 case 0xFC: /* Name server */ 2768 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg, 2769 "%s: pl=%p size=%d rxid=%x", emlxs_ctcmd_xlate(cmd_code), 2770 CtCmd, size, iocb->ulpContext); 2771 break; 2772 2773 case 0xFA: /* Managment server */ 2774 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg, 2775 "%s: pl=%p size=%d rxid=%x", emlxs_mscmd_xlate(cmd_code), 2776 CtCmd, size, iocb->ulpContext); 2777 break; 2778 2779 case 0x0A: /* Emulex Remote server */ 2780 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg, 2781 "%s: pl=%p size=%d rxid=%x", emlxs_rmcmd_xlate(cmd_code), 2782 CtCmd, size, iocb->ulpContext); 2783 break; 2784 2785 default: 2786 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg, 2787 "%s: pl=%p size=%d rxid=%x", emlxs_ctcmd_xlate(cmd_code), 2788 CtCmd, size, iocb->ulpContext); 2789 } 2790 2791 if (emlxs_log_ct_event(port, (uint8_t *)mp->virt, size, 2792 iocb->ulpContext)) { 2793 /* Abort the exchange */ 2794 emlxs_abort_ct_exchange(hba, port, iocb->ulpContext); 2795 } 2796 2797 return (0); 2798 2799 } /* emlxs_ct_handle_unsol_req() */ 2800 2801 2802 static void 2803 emlxs_send_rsnn(emlxs_port_t *port) 2804 { 2805 emlxs_hba_t *hba = HBA; 2806 fc_packet_t *pkt; 2807 SLI_CT_REQUEST *ct; 2808 2809 if (!(pkt = emlxs_pkt_alloc(port, sizeof (SLI_CT_REQUEST), 2810 sizeof (SLI_CT_REQUEST), 0, KM_NOSLEEP))) { 2811 return; 2812 } 2813 2814 pkt->pkt_tran_type = FC_PKT_EXCHANGE; 2815 pkt->pkt_timeout = (2 * hba->fc_ratov); 2816 2817 /* Build the fc header */ 2818 pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(NameServer_DID); 2819 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL; 2820 pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did); 2821 pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES; 2822 pkt->pkt_cmd_fhdr.f_ctl = 2823 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 2824 pkt->pkt_cmd_fhdr.seq_id = 0; 2825 pkt->pkt_cmd_fhdr.df_ctl = 0; 2826 pkt->pkt_cmd_fhdr.seq_cnt = 0; 2827 pkt->pkt_cmd_fhdr.ox_id = 0xffff; 2828 pkt->pkt_cmd_fhdr.rx_id = 0xffff; 2829 pkt->pkt_cmd_fhdr.ro = 0; 2830 2831 /* Build the command */ 2832 ct = (SLI_CT_REQUEST *)pkt->pkt_cmd; 2833 2834 ct->RevisionId.bits.Revision = SLI_CT_REVISION; 2835 ct->RevisionId.bits.InId = 0; 2836 2837 ct->FsType = SLI_CT_DIRECTORY_SERVICE; 2838 ct->FsSubType = SLI_CT_DIRECTORY_NAME_SERVER; 2839 2840 ct->CommandResponse.bits.Size = 0; 2841 ct->CommandResponse.bits.CmdRsp = SWAP_DATA16(SLI_CTNS_RSNN_NN); 2842 2843 bcopy((uint8_t *)&hba->wwnn, (char *)ct->un.rsnn.wwnn, 8); 2844 2845 ct->un.rsnn.snn_len = strlen(port->snn); 2846 bcopy(port->snn, (char *)ct->un.rsnn.snn, ct->un.rsnn.snn_len); 2847 2848 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg, "Sending RSNN_NN. [%s]", 2849 port->snn); 2850 2851 /* Send the pkt later in another thread */ 2852 if (emlxs_pkt_send(pkt, 0) != FC_SUCCESS) { 2853 /* Free the pkt */ 2854 emlxs_pkt_free(pkt); 2855 } 2856 2857 return; 2858 2859 } /* emlxs_send_rsnn() */ 2860 2861 2862 extern uint32_t 2863 emlxs_ub_send_login_acc(emlxs_port_t *port, fc_unsol_buf_t *ubp) 2864 { 2865 emlxs_hba_t *hba = HBA; 2866 fc_packet_t *pkt; 2867 ELS_PKT *els; 2868 uint32_t rval; 2869 emlxs_ub_priv_t *ub_priv; 2870 2871 ub_priv = ubp->ub_fca_private; 2872 2873 if (!(pkt = emlxs_pkt_alloc(port, 2874 sizeof (uint32_t) + sizeof (SERV_PARM), 0, 0, KM_NOSLEEP))) { 2875 return (1); 2876 } 2877 2878 /* Common initialization */ 2879 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 2880 pkt->pkt_timeout = (2 * hba->fc_ratov); 2881 2882 if ((uint32_t)ubp->ub_class == FC_TRAN_CLASS2) { 2883 pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3; 2884 pkt->pkt_tran_flags |= FC_TRAN_CLASS2; 2885 } 2886 2887 /* Build the fc header */ 2888 pkt->pkt_cmd_fhdr.d_id = ubp->ub_frame.s_id; 2889 pkt->pkt_cmd_fhdr.r_ctl = 2890 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL; 2891 pkt->pkt_cmd_fhdr.s_id = ubp->ub_frame.d_id; 2892 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 2893 pkt->pkt_cmd_fhdr.f_ctl = 2894 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ; 2895 pkt->pkt_cmd_fhdr.seq_id = 0; 2896 pkt->pkt_cmd_fhdr.df_ctl = 0; 2897 pkt->pkt_cmd_fhdr.seq_cnt = 0; 2898 pkt->pkt_cmd_fhdr.ox_id = (ub_priv->cmd >> ELS_CMD_SHIFT) & 0xff; 2899 pkt->pkt_cmd_fhdr.rx_id = ubp->ub_frame.rx_id; 2900 pkt->pkt_cmd_fhdr.ro = 0; 2901 2902 /* Build the command */ 2903 els = (ELS_PKT *)pkt->pkt_cmd; 2904 els->elsCode = 0x02; 2905 bcopy((void *)&port->sparam, (void *)&els->un.logi, 2906 sizeof (SERV_PARM)); 2907 2908 if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) { 2909 /* Free the pkt */ 2910 emlxs_pkt_free(pkt); 2911 } else { 2912 ub_priv->flags |= EMLXS_UB_INTERCEPT; 2913 } 2914 2915 return (rval); 2916 2917 } /* emlxs_ub_send_login_acc */ 2918 2919 2920 extern void 2921 emlxs_send_logo(emlxs_port_t *port, uint32_t d_id) 2922 { 2923 emlxs_hba_t *hba = HBA; 2924 fc_packet_t *pkt; 2925 ELS_PKT *els; 2926 2927 if (hba->state <= FC_LINK_DOWN) { 2928 return; 2929 } 2930 2931 if (!(pkt = emlxs_pkt_alloc(port, 2932 sizeof (uint32_t) + sizeof (LOGO), 2933 sizeof (uint32_t) + sizeof (LOGO), 0, KM_NOSLEEP))) { 2934 return; 2935 } 2936 2937 pkt->pkt_tran_type = FC_PKT_EXCHANGE; 2938 pkt->pkt_timeout = (2 * hba->fc_ratov); 2939 2940 /* Build the fc header */ 2941 pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(d_id); 2942 pkt->pkt_cmd_fhdr.r_ctl = 2943 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL; 2944 pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did); 2945 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 2946 pkt->pkt_cmd_fhdr.f_ctl = 2947 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 2948 pkt->pkt_cmd_fhdr.seq_id = 0; 2949 pkt->pkt_cmd_fhdr.df_ctl = 0; 2950 pkt->pkt_cmd_fhdr.seq_cnt = 0; 2951 pkt->pkt_cmd_fhdr.ox_id = 0xffff; 2952 pkt->pkt_cmd_fhdr.rx_id = 0xffff; 2953 pkt->pkt_cmd_fhdr.ro = 0; 2954 2955 /* Build the command */ 2956 els = (ELS_PKT *)pkt->pkt_cmd; 2957 els->elsCode = 0x05; 2958 els->un.logo.un.nPortId32 = pkt->pkt_cmd_fhdr.s_id; 2959 bcopy((uint8_t *)&port->wwpn, (uint8_t *)&els->un.logo.portName, 2960 8); 2961 2962 /* Send the pkt now */ 2963 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 2964 /* Free the pkt */ 2965 emlxs_pkt_free(pkt); 2966 } 2967 2968 return; 2969 2970 } /* emlxs_send_logo() */ 2971