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 9 * http://www.opensource.org/licenses/cddl1.txt. 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 (c) 2004-2011 Emulex. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <emlxs.h> 28 29 30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 31 EMLXS_MSG_DEF(EMLXS_NODE_C); 32 33 static void emlxs_node_add(emlxs_port_t *, NODELIST *); 34 static int emlxs_node_match_did(emlxs_port_t *, NODELIST *, uint32_t); 35 36 /* Timeout == -1 will enable the offline timer */ 37 /* Timeout not -1 will apply the timeout */ 38 extern void 39 emlxs_node_close(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno, 40 int32_t timeout) 41 { 42 emlxs_hba_t *hba = HBA; 43 emlxs_config_t *cfg = &CFG; 44 CHANNEL *cp; 45 NODELIST *prev; 46 uint32_t offline = 0; 47 48 49 /* If node is on a channel service queue, then remove it */ 50 mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 51 52 /* Return if node destroyed */ 53 if (!ndlp || !ndlp->nlp_active) { 54 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 55 56 return; 57 } 58 59 /* Check offline support */ 60 if (timeout == -1) { 61 if (cfg[CFG_OFFLINE_TIMEOUT].current) { 62 timeout = cfg[CFG_OFFLINE_TIMEOUT].current; 63 offline = 1; 64 } else { 65 timeout = 0; 66 } 67 } 68 69 if (channelno == hba->channel_ip) { 70 /* Clear IP XRI */ 71 ndlp->nlp_Xri = 0; 72 } 73 74 /* Check if node is already closed */ 75 if (ndlp->nlp_flag[channelno] & NLP_CLOSED) { 76 if (ndlp->nlp_flag[channelno] & NLP_OFFLINE) { 77 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 78 return; 79 } 80 81 if (offline) { 82 ndlp->nlp_tics[channelno] = hba->timer_tics + timeout; 83 ndlp->nlp_flag[channelno] |= NLP_OFFLINE; 84 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 85 86 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg, 87 "node=%p did=%06x channel=%d. offline=%d update.", 88 ndlp, ndlp->nlp_DID, channelno, timeout); 89 90 } else if (timeout) { 91 ndlp->nlp_tics[channelno] = hba->timer_tics + timeout; 92 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 93 94 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg, 95 "node=%p did=%06x channel=%d. timeout=%d update.", 96 ndlp, ndlp->nlp_DID, channelno, timeout); 97 } else { 98 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 99 } 100 101 return; 102 } 103 104 /* Set the node closed */ 105 ndlp->nlp_flag[channelno] |= NLP_CLOSED; 106 107 if (offline) { 108 ndlp->nlp_tics[channelno] = hba->timer_tics + timeout; 109 ndlp->nlp_flag[channelno] |= NLP_OFFLINE; 110 111 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg, 112 "node=%p did=%06x channel=%d. offline=%d set.", 113 ndlp, ndlp->nlp_DID, channelno, timeout); 114 115 } else if (timeout) { 116 ndlp->nlp_tics[channelno] = hba->timer_tics + timeout; 117 118 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg, 119 "node=%p did=%06x channel=%d. timeout=%d set.", 120 ndlp, ndlp->nlp_DID, channelno, timeout); 121 } else { 122 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg, 123 "node=%p did=%06x channel=%d.", 124 ndlp, ndlp->nlp_DID, channelno); 125 } 126 127 128 /* 129 * ndlp->nlp_next[] and cp->nodeq list have to be updated 130 * simulaneously 131 */ 132 if (ndlp->nlp_next[channelno]) { 133 /* Remove node from channel queue */ 134 cp = &hba->chan[channelno]; 135 136 /* If this is the only node on list */ 137 if (cp->nodeq.q_first == (void *)ndlp && 138 cp->nodeq.q_last == (void *)ndlp) { 139 cp->nodeq.q_last = NULL; 140 cp->nodeq.q_first = NULL; 141 cp->nodeq.q_cnt = 0; 142 } else if (cp->nodeq.q_first == (void *)ndlp) { 143 cp->nodeq.q_first = ndlp->nlp_next[channelno]; 144 ((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] = 145 cp->nodeq.q_first; 146 cp->nodeq.q_cnt--; 147 } else { /* This is a little more difficult */ 148 149 /* Find the previous node in circular channel queue */ 150 prev = ndlp; 151 while (prev->nlp_next[channelno] != ndlp) { 152 prev = prev->nlp_next[channelno]; 153 } 154 155 prev->nlp_next[channelno] = ndlp->nlp_next[channelno]; 156 157 if (cp->nodeq.q_last == (void *)ndlp) { 158 cp->nodeq.q_last = (void *)prev; 159 } 160 cp->nodeq.q_cnt--; 161 162 } 163 164 /* Clear node */ 165 ndlp->nlp_next[channelno] = NULL; 166 } 167 168 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 169 170 return; 171 172 } /* emlxs_node_close() */ 173 174 175 /* Called by emlxs_timer_check_nodes() */ 176 extern void 177 emlxs_node_timeout(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno) 178 { 179 emlxs_hba_t *hba = HBA; 180 181 /* If node needs servicing, then add it to the channel queues */ 182 mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 183 184 /* Return if node destroyed */ 185 if (!ndlp || !ndlp->nlp_active) { 186 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 187 return; 188 } 189 190 /* Open the node if not offline */ 191 if (!(ndlp->nlp_flag[channelno] & NLP_OFFLINE)) { 192 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 193 194 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg, 195 "node=%p did=%06x channel=%d Opening.", ndlp, ndlp->nlp_DID, 196 channelno); 197 198 emlxs_node_open(port, ndlp, channelno); 199 return; 200 } 201 202 /* OFFLINE TIMEOUT OCCURRED! */ 203 204 /* Clear the timer */ 205 ndlp->nlp_tics[channelno] = 0; 206 207 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 208 209 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg, 210 "node=%p did=%06x channel=%d. Flushing.", ndlp, ndlp->nlp_DID, 211 channelno); 212 213 /* Flush tx queue for this channel */ 214 (void) emlxs_tx_node_flush(port, ndlp, &hba->chan[channelno], 0, 0); 215 216 /* Flush chip queue for this channel */ 217 (void) emlxs_chipq_node_flush(port, &hba->chan[channelno], ndlp, 0); 218 219 return; 220 221 } /* emlxs_node_timeout() */ 222 223 224 extern void 225 emlxs_node_open(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno) 226 { 227 emlxs_hba_t *hba = HBA; 228 CHANNEL *cp; 229 uint32_t found; 230 NODELIST *nlp; 231 MAILBOXQ *mbox; 232 uint32_t i; 233 int rc; 234 235 /* If node needs servicing, then add it to the channel queues */ 236 mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 237 238 /* Return if node destroyed */ 239 if (!ndlp || !ndlp->nlp_active) { 240 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 241 242 return; 243 } 244 245 /* Return if node already open */ 246 if (!(ndlp->nlp_flag[channelno] & NLP_CLOSED)) { 247 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 248 249 return; 250 } 251 252 /* Set the node open (not closed) */ 253 ndlp->nlp_flag[channelno] &= ~(NLP_CLOSED|NLP_OFFLINE); 254 255 /* Clear the timer */ 256 ndlp->nlp_tics[channelno] = 0; 257 258 /* 259 * If the ptx or the tx queue needs servicing and 260 * the node is not already on the channel queue 261 */ 262 if ((ndlp->nlp_ptx[channelno].q_first || 263 ndlp->nlp_tx[channelno].q_first) && !ndlp->nlp_next[channelno]) { 264 cp = &hba->chan[channelno]; 265 266 /* If so, then add it to the channel queue */ 267 if (cp->nodeq.q_first) { 268 ((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] = 269 (uint8_t *)ndlp; 270 ndlp->nlp_next[channelno] = cp->nodeq.q_first; 271 272 /* If this is not the base node then */ 273 /* add it to the tail */ 274 if (!ndlp->nlp_base) { 275 cp->nodeq.q_last = (uint8_t *)ndlp; 276 } else { /* Otherwise, add it to the head */ 277 278 /* The command node always gets priority */ 279 cp->nodeq.q_first = (uint8_t *)ndlp; 280 } 281 282 cp->nodeq.q_cnt++; 283 } else { 284 cp->nodeq.q_first = (uint8_t *)ndlp; 285 cp->nodeq.q_last = (uint8_t *)ndlp; 286 ndlp->nlp_next[channelno] = ndlp; 287 cp->nodeq.q_cnt = 1; 288 } 289 } 290 291 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 292 293 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_opened_msg, 294 "node=%p did=%06x rpi=%d channel=%d", ndlp, ndlp->nlp_DID, 295 ndlp->nlp_Rpi, channelno); 296 297 /* If link attention needs to be cleared */ 298 if ((hba->state == FC_LINK_UP) && (channelno == hba->channel_fcp)) { 299 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 300 goto done; 301 } 302 303 /* Scan to see if any FCP2 devices are still closed */ 304 found = 0; 305 rw_enter(&port->node_rwlock, RW_READER); 306 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 307 nlp = port->node_table[i]; 308 while (nlp != NULL) { 309 if ((nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) && 310 (nlp->nlp_flag[hba->channel_fcp] & 311 NLP_CLOSED)) { 312 found = 1; 313 break; 314 315 } 316 nlp = nlp->nlp_list_next; 317 } 318 319 if (found) { 320 break; 321 } 322 } 323 324 rw_exit(&port->node_rwlock); 325 326 if (!found) { 327 /* Clear link attention */ 328 if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba, 329 MEM_MBOX))) { 330 mutex_enter(&EMLXS_PORT_LOCK); 331 332 /* 333 * If state is not FC_LINK_UP, then either the 334 * link has gone down or a FC_CLEAR_LA has 335 * already been issued 336 */ 337 if (hba->state != FC_LINK_UP) { 338 mutex_exit(&EMLXS_PORT_LOCK); 339 emlxs_mem_put(hba, MEM_MBOX, 340 (void *)mbox); 341 goto done; 342 } 343 344 EMLXS_STATE_CHANGE_LOCKED(hba, FC_CLEAR_LA); 345 hba->discovery_timer = 0; 346 mutex_exit(&EMLXS_PORT_LOCK); 347 348 emlxs_mb_clear_la(hba, mbox); 349 350 rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, 351 mbox, MBX_NOWAIT, 0); 352 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 353 emlxs_mem_put(hba, MEM_MBOX, 354 (void *)mbox); 355 } 356 } else { 357 /* Close the node and try again */ 358 /* in a few seconds */ 359 emlxs_node_close(port, ndlp, channelno, 5); 360 return; 361 } 362 } 363 } 364 365 done: 366 367 /* Wake any sleeping threads */ 368 mutex_enter(&EMLXS_PKT_LOCK); 369 cv_broadcast(&EMLXS_PKT_CV); 370 mutex_exit(&EMLXS_PKT_LOCK); 371 372 return; 373 374 } /* emlxs_node_open() */ 375 376 377 static int 378 emlxs_node_match_did(emlxs_port_t *port, NODELIST *ndlp, uint32_t did) 379 { 380 D_ID mydid; 381 D_ID odid; 382 D_ID ndid; 383 384 if (ndlp->nlp_DID == did) 385 return (1); 386 387 /* 388 * Next check for area/domain == 0 match 389 */ 390 mydid.un.word = port->did; 391 if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) { 392 goto out; 393 } 394 395 ndid.un.word = did; 396 odid.un.word = ndlp->nlp_DID; 397 if (ndid.un.b.id == odid.un.b.id) { 398 if ((mydid.un.b.domain == ndid.un.b.domain) && 399 (mydid.un.b.area == ndid.un.b.area)) { 400 ndid.un.word = ndlp->nlp_DID; 401 odid.un.word = did; 402 if ((ndid.un.b.domain == 0) && (ndid.un.b.area == 0)) { 403 return (1); 404 } 405 goto out; 406 } 407 408 ndid.un.word = ndlp->nlp_DID; 409 if ((mydid.un.b.domain == ndid.un.b.domain) && 410 (mydid.un.b.area == ndid.un.b.area)) { 411 odid.un.word = ndlp->nlp_DID; 412 ndid.un.word = did; 413 if ((ndid.un.b.domain == 0) && (ndid.un.b.area == 0)) { 414 return (1); 415 } 416 } 417 } 418 419 out: 420 421 return (0); 422 423 } /* emlxs_node_match_did() */ 424 425 426 427 extern NODELIST * 428 emlxs_node_find_mac(emlxs_port_t *port, uint8_t *mac) 429 { 430 NODELIST *nlp; 431 uint32_t i; 432 433 rw_enter(&port->node_rwlock, RW_READER); 434 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 435 nlp = port->node_table[i]; 436 while (nlp != NULL) { 437 /* 438 * If portname matches mac address, 439 * return NODELIST entry 440 */ 441 if ((nlp->nlp_portname.IEEE[0] == mac[0])) { 442 if ((nlp->nlp_DID != BCAST_DID) && 443 ((nlp->nlp_DID & FABRIC_DID_MASK) == 444 FABRIC_DID_MASK)) { 445 nlp = (NODELIST *)nlp->nlp_list_next; 446 continue; 447 } 448 449 if ((nlp->nlp_portname.IEEE[1] == mac[1]) && 450 (nlp->nlp_portname.IEEE[2] == mac[2]) && 451 (nlp->nlp_portname.IEEE[3] == mac[3]) && 452 (nlp->nlp_portname.IEEE[4] == mac[4]) && 453 (nlp->nlp_portname.IEEE[5] == mac[5])) { 454 rw_exit(&port->node_rwlock); 455 return (nlp); 456 } 457 458 } 459 460 nlp = (NODELIST *)nlp->nlp_list_next; 461 } 462 } 463 rw_exit(&port->node_rwlock); 464 465 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, 466 "find: MAC=%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], 467 mac[3], mac[4], mac[5]); 468 469 return (NULL); 470 471 } /* emlxs_node_find_mac() */ 472 473 474 extern NODELIST * 475 emlxs_node_find_did(emlxs_port_t *port, uint32_t did, uint32_t lock) 476 { 477 emlxs_hba_t *hba = HBA; 478 NODELIST *nlp; 479 uint32_t hash; 480 481 /* Check for invalid node ids */ 482 if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) { 483 return ((NODELIST *)0); 484 } 485 486 if (did & 0xff000000) { 487 return ((NODELIST *)0); 488 } 489 490 /* Check for bcast node */ 491 if (did == BCAST_DID) { 492 /* Use the base node here */ 493 return (&port->node_base); 494 } 495 #ifdef MENLO_SUPPORT 496 /* Check for menlo node */ 497 if (did == EMLXS_MENLO_DID) { 498 /* Use the base node here */ 499 return (&port->node_base); 500 } 501 #endif /* MENLO_SUPPORT */ 502 503 /* Check for host node */ 504 if (did == port->did && !(hba->flag & FC_LOOPBACK_MODE)) { 505 /* Use the base node here */ 506 return (&port->node_base); 507 } 508 509 /* 510 * Convert well known fabric addresses to the FABRIC_DID, 511 * since we don't login to some of them 512 */ 513 if ((did == SCR_DID)) { 514 did = FABRIC_DID; 515 } 516 517 if (lock) { 518 rw_enter(&port->node_rwlock, RW_READER); 519 } 520 hash = EMLXS_DID_HASH(did); 521 nlp = port->node_table[hash]; 522 while (nlp != NULL) { 523 /* Check for obvious match */ 524 if (nlp->nlp_DID == did) { 525 if (lock) { 526 rw_exit(&port->node_rwlock); 527 } 528 return (nlp); 529 } 530 531 /* Check for detailed match */ 532 else if (emlxs_node_match_did(port, nlp, did)) { 533 if (lock) { 534 rw_exit(&port->node_rwlock); 535 } 536 return (nlp); 537 } 538 539 nlp = (NODELIST *)nlp->nlp_list_next; 540 } 541 542 if (lock) { 543 rw_exit(&port->node_rwlock); 544 } 545 546 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: did=%x", 547 did); 548 549 /* no match found */ 550 return ((NODELIST *)0); 551 552 } /* emlxs_node_find_did() */ 553 554 555 extern NODELIST * 556 emlxs_node_find_rpi(emlxs_port_t *port, uint32_t rpi) 557 { 558 NODELIST *nlp; 559 uint32_t i; 560 561 rw_enter(&port->node_rwlock, RW_READER); 562 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 563 nlp = port->node_table[i]; 564 while (nlp != NULL) { 565 if (nlp->nlp_Rpi == rpi) { 566 rw_exit(&port->node_rwlock); 567 return (nlp); 568 } 569 570 nlp = (NODELIST *)nlp->nlp_list_next; 571 } 572 } 573 rw_exit(&port->node_rwlock); 574 575 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: rpi=%d", 576 rpi); 577 578 /* no match found */ 579 return ((NODELIST *)0); 580 581 } /* emlxs_node_find_rpi() */ 582 583 584 extern NODELIST * 585 emlxs_node_find_wwpn(emlxs_port_t *port, uint8_t *wwpn, uint32_t lock) 586 { 587 NODELIST *nlp; 588 uint32_t i; 589 uint32_t j; 590 uint8_t *bptr1; 591 uint8_t *bptr2; 592 593 if (lock) { 594 rw_enter(&port->node_rwlock, RW_READER); 595 } 596 597 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 598 nlp = port->node_table[i]; 599 while (nlp != NULL) { 600 bptr1 = (uint8_t *)&nlp->nlp_portname; 601 bptr1 += 7; 602 bptr2 = (uint8_t *)wwpn; 603 bptr2 += 7; 604 605 for (j = 0; j < 8; j++) { 606 if (*bptr1-- != *bptr2--) { 607 break; 608 } 609 } 610 611 if (j == 8) { 612 if (lock) { 613 rw_exit(&port->node_rwlock); 614 } 615 return (nlp); 616 } 617 618 nlp = (NODELIST *)nlp->nlp_list_next; 619 } 620 } 621 622 if (lock) { 623 rw_exit(&port->node_rwlock); 624 } 625 626 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, 627 "find: wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", wwpn[0], wwpn[1], 628 wwpn[2], wwpn[3], wwpn[4], wwpn[5], wwpn[6], wwpn[7]); 629 630 /* no match found */ 631 return ((NODELIST *)0); 632 633 } /* emlxs_node_find_wwpn() */ 634 635 636 extern NODELIST * 637 emlxs_node_find_index(emlxs_port_t *port, uint32_t index, 638 uint32_t nports_only) 639 { 640 NODELIST *nlp; 641 uint32_t i; 642 uint32_t count; 643 644 rw_enter(&port->node_rwlock, RW_READER); 645 646 if (index > port->node_count - 1) { 647 rw_exit(&port->node_rwlock); 648 return (NULL); 649 } 650 651 count = 0; 652 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 653 nlp = port->node_table[i]; 654 while (nlp != NULL) { 655 /* Skip fabric ports if requested */ 656 if (nports_only && 657 (nlp->nlp_DID & 0xFFF000) == 0xFFF000) { 658 nlp = (NODELIST *)nlp->nlp_list_next; 659 continue; 660 } 661 662 if (count == index) { 663 rw_exit(&port->node_rwlock); 664 return (nlp); 665 } 666 667 nlp = (NODELIST *)nlp->nlp_list_next; 668 count++; 669 } 670 } 671 rw_exit(&port->node_rwlock); 672 673 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: index=%d", 674 index); 675 676 /* no match found */ 677 return ((NODELIST *)0); 678 679 } /* emlxs_node_find_index() */ 680 681 682 extern uint32_t 683 emlxs_nport_count(emlxs_port_t *port) 684 { 685 NODELIST *nlp; 686 uint32_t i; 687 uint32_t nport_count = 0; 688 689 rw_enter(&port->node_rwlock, RW_READER); 690 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 691 nlp = port->node_table[i]; 692 while (nlp != NULL) { 693 if ((nlp->nlp_DID & 0xFFF000) != 0xFFF000) { 694 nport_count++; 695 } 696 697 nlp = (NODELIST *)nlp->nlp_list_next; 698 } 699 } 700 rw_exit(&port->node_rwlock); 701 702 return (nport_count); 703 704 } /* emlxs_nport_count() */ 705 706 707 708 extern void 709 emlxs_node_destroy_all(emlxs_port_t *port) 710 { 711 emlxs_hba_t *hba = HBA; 712 NODELIST *next; 713 NODELIST *ndlp; 714 RPIobj_t *rpip; 715 uint8_t *wwn; 716 uint32_t i; 717 718 /* Flush and free the nodes */ 719 rw_enter(&port->node_rwlock, RW_WRITER); 720 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 721 ndlp = port->node_table[i]; 722 port->node_table[i] = 0; 723 while (ndlp != NULL) { 724 next = ndlp->nlp_list_next; 725 ndlp->nlp_list_next = NULL; 726 ndlp->nlp_list_prev = NULL; 727 ndlp->nlp_active = 0; 728 729 if (port->node_count) { 730 port->node_count--; 731 } 732 733 wwn = (uint8_t *)&ndlp->nlp_portname; 734 EMLXS_MSGF(EMLXS_CONTEXT, 735 &emlxs_node_destroy_msg, "did=%06x " 736 "rpi=%d wwpn=%02x%02x%02x%02x%02x%02x%02x%02x " 737 "count=%d", ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], 738 wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], 739 wwn[7], port->node_count); 740 741 (void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0); 742 743 /* Break Node/RPI binding */ 744 if (ndlp->rpip) { 745 rpip = ndlp->rpip; 746 747 ndlp->rpip = NULL; 748 rpip->node = NULL; 749 750 (void) emlxs_rpi_free_notify(port, rpip); 751 } 752 753 emlxs_mem_put(hba, MEM_NLP, (void *)ndlp); 754 755 ndlp = next; 756 } 757 } 758 port->node_count = 0; 759 rw_exit(&port->node_rwlock); 760 761 /* Clean the base node */ 762 mutex_enter(&EMLXS_PORT_LOCK); 763 port->node_base.nlp_list_next = NULL; 764 port->node_base.nlp_list_prev = NULL; 765 port->node_base.nlp_active = 1; 766 mutex_exit(&EMLXS_PORT_LOCK); 767 768 /* Flush the base node */ 769 (void) emlxs_tx_node_flush(port, &port->node_base, 0, 1, 0); 770 (void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0); 771 772 return; 773 774 } /* emlxs_node_destroy_all() */ 775 776 777 extern NODELIST * 778 emlxs_node_create(emlxs_port_t *port, uint32_t did, uint32_t rpi, SERV_PARM *sp) 779 { 780 emlxs_hba_t *hba = HBA; 781 NODELIST *ndlp, *ndlp_wwn; 782 uint8_t *wwn; 783 emlxs_vvl_fmt_t vvl; 784 RPIobj_t *rpip; 785 786 rw_enter(&port->node_rwlock, RW_WRITER); 787 788 ndlp = emlxs_node_find_did(port, did, 0); 789 ndlp_wwn = emlxs_node_find_wwpn(port, (uint8_t *)&sp->portName, 0); 790 791 /* Zero out the stale node worldwide names */ 792 if (ndlp_wwn && (ndlp != ndlp_wwn)) { 793 bzero((uint8_t *)&ndlp_wwn->nlp_nodename, sizeof (NAME_TYPE)); 794 bzero((uint8_t *)&ndlp_wwn->nlp_portname, sizeof (NAME_TYPE)); 795 } 796 797 /* Update the node */ 798 if (ndlp) { 799 ndlp->nlp_Rpi = (uint16_t)rpi; 800 ndlp->nlp_DID = did; 801 802 bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm, 803 sizeof (SERV_PARM)); 804 805 bcopy((uint8_t *)&sp->nodeName, 806 (uint8_t *)&ndlp->nlp_nodename, 807 sizeof (NAME_TYPE)); 808 809 bcopy((uint8_t *)&sp->portName, 810 (uint8_t *)&ndlp->nlp_portname, 811 sizeof (NAME_TYPE)); 812 813 /* Add Node/RPI binding */ 814 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 815 rpip = emlxs_rpi_find(port, rpi); 816 817 if (rpip) { 818 rpip->node = ndlp; 819 ndlp->rpip = rpip; 820 } else { 821 ndlp->rpip = NULL; 822 823 EMLXS_MSGF(EMLXS_CONTEXT, 824 &emlxs_node_create_msg, 825 "Unable to find RPI. did=%x rpi=%d", 826 did, rpi); 827 } 828 } else { 829 ndlp->rpip = NULL; 830 } 831 832 wwn = (uint8_t *)&ndlp->nlp_portname; 833 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_update_msg, 834 "node=%p did=%06x rpi=%d " 835 "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", 836 ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], 837 wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 838 839 goto done; 840 } 841 842 /* Allocate a new node */ 843 ndlp = (NODELIST *)emlxs_mem_get(hba, MEM_NLP); 844 845 if (ndlp) { 846 ndlp->nlp_Rpi = (uint16_t)rpi; 847 ndlp->nlp_DID = did; 848 849 bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm, 850 sizeof (SERV_PARM)); 851 852 bcopy((uint8_t *)&sp->nodeName, 853 (uint8_t *)&ndlp->nlp_nodename, 854 sizeof (NAME_TYPE)); 855 856 bcopy((uint8_t *)&sp->portName, 857 (uint8_t *)&ndlp->nlp_portname, 858 sizeof (NAME_TYPE)); 859 860 ndlp->nlp_active = 1; 861 ndlp->nlp_flag[hba->channel_ct] |= NLP_CLOSED; 862 ndlp->nlp_flag[hba->channel_els] |= NLP_CLOSED; 863 ndlp->nlp_flag[hba->channel_fcp] |= NLP_CLOSED; 864 ndlp->nlp_flag[hba->channel_ip] |= NLP_CLOSED; 865 866 /* Add Node/RPI binding */ 867 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 868 rpip = emlxs_rpi_find(port, rpi); 869 870 if (rpip) { 871 rpip->node = ndlp; 872 ndlp->rpip = rpip; 873 } else { 874 ndlp->rpip = NULL; 875 876 EMLXS_MSGF(EMLXS_CONTEXT, 877 &emlxs_node_create_msg, 878 "Unable to find RPI. did=%x rpi=%d", 879 did, rpi); 880 } 881 } else { 882 ndlp->rpip = NULL; 883 } 884 885 #ifdef NODE_THROTTLE_SUPPORT 886 emlxs_node_throttle_set(port, ndlp); 887 #endif /* NODE_THROTTLE_SUPPORT */ 888 889 /* Add the node */ 890 emlxs_node_add(port, ndlp); 891 892 goto done; 893 } 894 895 rw_exit(&port->node_rwlock); 896 wwn = (uint8_t *)&sp->portName; 897 EMLXS_MSGF(EMLXS_CONTEXT, 898 &emlxs_node_create_failed_msg, 899 "Unable to allocate node. did=%06x " 900 "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", 901 did, wwn[0], wwn[1], wwn[2], 902 wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 903 904 return (NULL); 905 906 done: 907 rw_exit(&port->node_rwlock); 908 if (sp->VALID_VENDOR_VERSION) { 909 bcopy((caddr_t *)&sp->vendorVersion[0], 910 (caddr_t *)&vvl, sizeof (emlxs_vvl_fmt_t)); 911 912 vvl.un0.word0 = LE_SWAP32(vvl.un0.word0); 913 vvl.un1.word1 = LE_SWAP32(vvl.un1.word1); 914 915 if ((vvl.un0.w0.oui == 0x0000C9) && 916 (vvl.un1.w1.vport)) { 917 ndlp->nlp_fcp_info |= NLP_EMLX_VPORT; 918 } 919 } 920 921 /* Open the node */ 922 emlxs_node_open(port, ndlp, hba->channel_ct); 923 emlxs_node_open(port, ndlp, hba->channel_els); 924 emlxs_node_open(port, ndlp, hba->channel_ip); 925 emlxs_node_open(port, ndlp, hba->channel_fcp); 926 927 EMLXS_SET_DFC_STATE(ndlp, NODE_LOGIN); 928 929 return (ndlp); 930 931 } /* emlxs_node_create() */ 932 933 934 /* node_rwlock must be held when calling this routine */ 935 static void 936 emlxs_node_add(emlxs_port_t *port, NODELIST *ndlp) 937 { 938 NODELIST *np; 939 uint8_t *wwn; 940 uint32_t hash; 941 942 hash = EMLXS_DID_HASH(ndlp->nlp_DID); 943 np = port->node_table[hash]; 944 945 /* 946 * Insert node pointer to the head 947 */ 948 port->node_table[hash] = ndlp; 949 if (!np) { 950 ndlp->nlp_list_next = NULL; 951 } else { 952 ndlp->nlp_list_next = np; 953 } 954 port->node_count++; 955 956 wwn = (uint8_t *)&ndlp->nlp_portname; 957 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_msg, 958 "node=%p did=%06x rpi=%d wwpn=%02x%02x%02x%02x%02x%02x%02x%02x " 959 "count=%d", ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], wwn[1], 960 wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7], port->node_count); 961 962 return; 963 964 } /* emlxs_node_add() */ 965 966 967 extern void 968 emlxs_node_rm(emlxs_port_t *port, NODELIST *ndlp) 969 { 970 emlxs_hba_t *hba = HBA; 971 NODELIST *np; 972 NODELIST *prevp; 973 RPIobj_t *rpip; 974 uint8_t *wwn; 975 uint32_t hash; 976 977 rw_enter(&port->node_rwlock, RW_WRITER); 978 hash = EMLXS_DID_HASH(ndlp->nlp_DID); 979 np = port->node_table[hash]; 980 prevp = NULL; 981 while (np != NULL) { 982 if (np->nlp_DID == ndlp->nlp_DID) { 983 if (prevp == NULL) { 984 port->node_table[hash] = np->nlp_list_next; 985 } else { 986 prevp->nlp_list_next = np->nlp_list_next; 987 } 988 989 if (port->node_count) { 990 port->node_count--; 991 } 992 993 wwn = (uint8_t *)&ndlp->nlp_portname; 994 EMLXS_MSGF(EMLXS_CONTEXT, 995 &emlxs_node_destroy_msg, "did=%06x " 996 "rpi=%d wwpn=%02x%02x%02x%02x%02x%02x%02x%02x " 997 "count=%d", ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], 998 wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], 999 wwn[7], port->node_count); 1000 1001 (void) emlxs_tx_node_flush(port, ndlp, 0, 1, 0); 1002 1003 ndlp->nlp_active = 0; 1004 1005 /* Break Node/RPI binding */ 1006 if (ndlp->rpip) { 1007 rpip = ndlp->rpip; 1008 1009 ndlp->rpip = NULL; 1010 rpip->node = NULL; 1011 1012 (void) emlxs_rpi_free_notify(port, rpip); 1013 } 1014 1015 emlxs_mem_put(hba, MEM_NLP, (void *)ndlp); 1016 1017 break; 1018 } 1019 prevp = np; 1020 np = np->nlp_list_next; 1021 } 1022 rw_exit(&port->node_rwlock); 1023 1024 return; 1025 1026 } /* emlxs_node_rm() */ 1027 1028 1029 extern void 1030 emlxs_node_throttle_set(emlxs_port_t *port, NODELIST *ndlp) 1031 { 1032 emlxs_hba_t *hba = HBA; 1033 emlxs_config_t *cfg = &CFG; 1034 char prop[64]; 1035 char buf1[32]; 1036 uint32_t throttle; 1037 1038 /* Set global default */ 1039 throttle = (ndlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE)? 1040 cfg[CFG_TGT_DEPTH].current:0; 1041 1042 /* Check per wwpn default */ 1043 (void) snprintf(prop, sizeof (prop), "w%s-depth", 1044 emlxs_wwn_xlate(buf1, sizeof (buf1), 1045 (uint8_t *)&ndlp->nlp_portname)); 1046 1047 throttle = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, 1048 (void *)hba->dip, DDI_PROP_DONTPASS, prop, throttle); 1049 1050 /* Check per driver/wwpn default */ 1051 (void) snprintf(prop, sizeof (prop), "%s%d-w%s-depth", DRIVER_NAME, 1052 hba->ddiinst, emlxs_wwn_xlate(buf1, sizeof (buf1), 1053 (uint8_t *)&ndlp->nlp_portname)); 1054 1055 throttle = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, 1056 (void *)hba->dip, DDI_PROP_DONTPASS, prop, throttle); 1057 1058 /* Check limit */ 1059 throttle = MIN(throttle, MAX_NODE_THROTTLE); 1060 1061 ndlp->io_throttle = throttle; 1062 1063 return; 1064 1065 } /* emlxs_node_throttle_set() */ 1066