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