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