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