1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Emulex. All rights reserved. 24 * Use is subject to License terms. 25 */ 26 27 #define DEF_MSG_STRUCT /* Needed for emlxs_messages.h in emlxs_msg.h */ 28 #include <emlxs.h> 29 30 31 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 32 EMLXS_MSG_DEF(EMLXS_MSG_C); 33 34 uint32_t emlxs_log_size = 2048; 35 uint32_t emlxs_log_debugs = 0x7FFFFFFF; 36 uint32_t emlxs_log_notices = 0xFFFFFFFF; 37 uint32_t emlxs_log_warnings = 0xFFFFFFFF; 38 uint32_t emlxs_log_errors = 0xFFFFFFFF; 39 40 static uint32_t emlxs_msg_log_check(emlxs_port_t *port, emlxs_msg_t *msg); 41 static uint32_t emlxs_msg_print_check(emlxs_port_t *port, emlxs_msg_t *msg); 42 static void emlxs_msg_sprintf(char *buffer, emlxs_msg_entry_t *entry); 43 44 45 uint32_t 46 emlxs_msg_log_create(emlxs_hba_t *hba) 47 { 48 emlxs_msg_log_t *log = &LOG; 49 uint32_t size = sizeof (emlxs_msg_entry_t) * emlxs_log_size; 50 char buf[40]; 51 #ifdef MSI_SUPPORT 52 ddi_intr_handle_t handle; 53 uint32_t intr_pri; 54 int32_t actual; 55 uint32_t ret; 56 #endif /* MSI_SUPPORT */ 57 ddi_iblock_cookie_t iblock; 58 59 /* Check if log is already created */ 60 if (log->entry) { 61 cmn_err(CE_WARN, "?%s%d: message log already created. log=%p", 62 DRIVER_NAME, hba->ddiinst, (void *)log); 63 return (0); 64 } 65 66 /* Clear the log */ 67 bzero(log, sizeof (emlxs_msg_log_t)); 68 69 /* Allocate the memory needed for the log file */ 70 if (!(log->entry = (emlxs_msg_entry_t *)kmem_zalloc(size, KM_SLEEP))) { 71 cmn_err(CE_WARN, 72 "?%s%d: Unable to allocate log memory. log=%p", 73 DRIVER_NAME, hba->ddiinst, (void *)log); 74 return (0); 75 } 76 77 /* Initialize */ 78 log->size = emlxs_log_size; 79 log->instance = hba->ddiinst; 80 log->start_time = emlxs_device.log_timestamp; 81 82 (void) sprintf(buf, "?%s%d_log_lock control variable", DRIVER_NAME, 83 hba->ddiinst); 84 cv_init(&log->lock_cv, buf, CV_DRIVER, NULL); 85 86 (void) sprintf(buf, "?%s%d_log_lock mutex", DRIVER_NAME, hba->ddiinst); 87 88 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 89 /* Get the current interrupt block cookie */ 90 (void) ddi_get_iblock_cookie(hba->dip, (uint_t)EMLXS_INUMBER, 91 &iblock); 92 93 /* Create the log mutex lock */ 94 mutex_init(&log->lock, buf, MUTEX_DRIVER, (void *)iblock); 95 } 96 #ifdef MSI_SUPPORT 97 else { 98 /* Allocate a temporary interrupt handle */ 99 actual = 0; 100 ret = 101 ddi_intr_alloc(hba->dip, &handle, DDI_INTR_TYPE_FIXED, 102 EMLXS_MSI_INUMBER, 1, &actual, DDI_INTR_ALLOC_NORMAL); 103 104 if (ret != DDI_SUCCESS || actual == 0) { 105 cmn_err(CE_WARN, 106 "?%s%d: Unable to allocate temporary interrupt " 107 "handle. ret=%d actual=%d", DRIVER_NAME, 108 hba->ddiinst, ret, actual); 109 110 /* Free the log buffer */ 111 kmem_free(log->entry, size); 112 bzero(log, sizeof (emlxs_msg_log_t)); 113 114 return (0); 115 } 116 117 /* Get the current interrupt priority */ 118 ret = ddi_intr_get_pri(handle, &intr_pri); 119 120 if (ret != DDI_SUCCESS) { 121 cmn_err(CE_WARN, 122 "?%s%d: Unable to get interrupt priority. ret=%d", 123 DRIVER_NAME, hba->ddiinst, ret); 124 125 /* Free the log buffer */ 126 kmem_free(log->entry, size); 127 bzero(log, sizeof (emlxs_msg_log_t)); 128 129 return (0); 130 } 131 132 /* Create the log mutex lock */ 133 mutex_init(&log->lock, buf, MUTEX_DRIVER, 134 (void *)((unsigned long)intr_pri)); 135 136 /* Free the temporary handle */ 137 (void) ddi_intr_free(handle); 138 } 139 #endif 140 141 return (1); 142 143 } /* emlxs_msg_log_create() */ 144 145 146 uint32_t 147 emlxs_msg_log_destroy(emlxs_hba_t *hba) 148 { 149 emlxs_msg_log_t *log = &LOG; 150 uint32_t size; 151 emlxs_msg_entry_t *entry; 152 uint32_t i; 153 154 /* Check if log is already destroyed */ 155 if (!log->entry) { 156 cmn_err(CE_WARN, 157 "?%s%d: message log already destroyed. log=%p", 158 DRIVER_NAME, hba->ddiinst, (void *)log); 159 160 return (1); 161 } 162 163 /* If events are being logged there might be */ 164 /* threads waiting so release them */ 165 if (hba->log_events) { 166 mutex_enter(&log->lock); 167 hba->log_events = 0; 168 cv_broadcast(&log->lock_cv); 169 mutex_exit(&log->lock); 170 171 DELAYMS(1); 172 } 173 174 /* Destroy the lock */ 175 mutex_destroy(&log->lock); 176 cv_destroy(&log->lock_cv); 177 178 /* Free the context buffers */ 179 for (i = 0; i < log->size; i++) { 180 entry = &log->entry[i]; 181 182 if (entry->bp && entry->size) { 183 kmem_free(entry->bp, entry->size); 184 } 185 } 186 187 /* Free the log buffer */ 188 size = sizeof (emlxs_msg_entry_t) * log->size; 189 kmem_free(log->entry, size); 190 191 /* Clear the log */ 192 bzero(log, sizeof (emlxs_msg_log_t)); 193 194 return (1); 195 196 } /* emlxs_msg_log_destroy() */ 197 198 199 uint32_t 200 emlxs_msg_log(emlxs_port_t *port, const uint32_t fileno, const uint32_t line, 201 void *bp, uint32_t size, emlxs_msg_t *msg, char *buffer) 202 { 203 emlxs_hba_t *hba = HBA; 204 emlxs_msg_entry_t *entry; 205 emlxs_msg_entry_t *entry2; 206 clock_t time; 207 emlxs_msg_log_t *log; 208 uint32_t last; 209 uint32_t mask; 210 emlxs_msg_t *msg2; 211 uint32_t rxid = 0; 212 uint32_t i; 213 214 /* Get the log file for this instance */ 215 log = &LOG; 216 217 /* Check if log is initialized */ 218 if (log->entry == NULL) { 219 220 if (port->vpi == 0) { 221 cmn_err(CE_WARN, 222 "?%s%d: message log not created. log=%p", 223 DRIVER_NAME, hba->ddiinst, (void *)log); 224 } else { 225 cmn_err(CE_WARN, 226 "?%s%d.%d: message log not created. log=%p", 227 DRIVER_NAME, hba->ddiinst, port->vpi, 228 (void *)log); 229 } 230 231 if (bp && size) { 232 kmem_free(bp, size); 233 } 234 235 return (1); 236 } 237 238 mutex_enter(&log->lock); 239 240 /* Get the pointer to the last log entry */ 241 if (log->next == 0) { 242 last = log->size - 1; 243 } else { 244 last = log->next - 1; 245 } 246 entry = &log->entry[last]; 247 248 /* Check if this matches the last message */ 249 if ((entry->instance == log->instance) && 250 (entry->vpi == port->vpi) && 251 (entry->fileno == fileno) && 252 (entry->line == line) && 253 (entry->bp == bp) && 254 (entry->size == size) && 255 (entry->msg == msg) && 256 (strcmp(entry->buffer, buffer) == 0)) { 257 /* If the same message is being logged then increment */ 258 log->repeat++; 259 260 mutex_exit(&log->lock); 261 262 return (0); 263 } else if (log->repeat) { 264 /* Get the pointer to the next log entry */ 265 entry2 = &log->entry[log->next]; 266 267 /* Increment and check the next entry index */ 268 if (++(log->next) >= log->size) { 269 log->next = 0; 270 } 271 272 switch (entry->msg->level) { 273 case EMLXS_DEBUG: 274 msg2 = &emlxs_debug_msg; 275 break; 276 277 case EMLXS_NOTICE: 278 msg2 = &emlxs_notice_msg; 279 break; 280 281 case EMLXS_WARNING: 282 msg2 = &emlxs_warning_msg; 283 break; 284 285 case EMLXS_ERROR: 286 msg2 = &emlxs_error_msg; 287 break; 288 289 case EMLXS_PANIC: 290 msg2 = &emlxs_panic_msg; 291 break; 292 293 case EMLXS_EVENT: 294 msg2 = &emlxs_event_msg; 295 break; 296 } 297 298 /* Check if we are about to overwrite an event entry */ 299 if (entry2->msg && (entry2->msg->level == EMLXS_EVENT)) { 300 /* Check if this event has not been acquired */ 301 if (log->count > (hba->hba_event.last_id + log->size)) { 302 hba->hba_event.missed++; 303 304 if ((entry2->msg->mask == EVT_CT) && 305 !(entry2->flag & EMLX_EVENT_DONE)) { 306 /* Abort exchange */ 307 rxid = *((uint32_t *)entry2->bp); 308 } 309 } 310 } 311 312 /* Free the old context buffer since we are about to erase it */ 313 if (entry2->bp && entry2->size) { 314 kmem_free(entry2->bp, entry2->size); 315 } 316 317 /* Initialize */ 318 entry2->id = log->count++; 319 entry2->fileno = entry->fileno; 320 entry2->line = entry->line; 321 entry2->bp = 0; 322 entry2->size = 0; 323 entry2->msg = msg2; 324 entry2->instance = log->instance; 325 entry2->vpi = port->vpi; 326 entry2->flag = 0; 327 328 /* Save the additional info buffer */ 329 (void) sprintf(entry2->buffer, 330 "Last message repeated %d time(s).", 331 log->repeat); 332 333 /* Set the entry time stamp */ 334 (void) drv_getparm(LBOLT, &time); 335 entry2->time = time - log->start_time; 336 337 log->repeat = 0; 338 } 339 340 /* Get the pointer to the next log entry */ 341 entry = &log->entry[log->next]; 342 343 /* Increment and check the next entry index */ 344 if (++(log->next) >= log->size) { 345 log->next = 0; 346 } 347 348 /* Check if we are about to overwrite an event entry */ 349 if (entry->msg && (entry->msg->level == EMLXS_EVENT)) { 350 /* Check if this event has not been acquired */ 351 if (log->count > (hba->hba_event.last_id + log->size)) { 352 hba->hba_event.missed++; 353 354 if ((entry->msg->mask == EVT_CT) && 355 !(entry->flag & EMLX_EVENT_DONE)) { 356 357 /* Abort exchange */ 358 rxid = *((uint32_t *)entry->bp); 359 } 360 } 361 } 362 363 /* Free the old context buffer since we are about to erase it */ 364 if (entry->bp && entry->size) { 365 kmem_free(entry->bp, entry->size); 366 } 367 368 /* Initialize */ 369 entry->id = log->count++; 370 entry->fileno = fileno; 371 entry->line = line; 372 entry->bp = bp; 373 entry->size = size; 374 entry->msg = msg; 375 entry->instance = log->instance; 376 entry->vpi = port->vpi; 377 entry->flag = 0; 378 379 /* Save the additional info buffer */ 380 (void) strncpy(entry->buffer, buffer, (MAX_LOG_INFO_LENGTH - 1)); 381 entry->buffer[MAX_LOG_INFO_LENGTH - 1] = 0; 382 383 /* Set the entry time stamp */ 384 (void) drv_getparm(LBOLT, &time); 385 entry->time = time - log->start_time; 386 387 /* Check for a new event */ 388 if (msg->level == EMLXS_EVENT) { 389 /* Update the event id */ 390 mask = msg->mask; 391 for (i = 0; i < 32; i++) { 392 if (mask & 0x01) { 393 hba->hba_event.new++; 394 log->event_id[i] = entry->id; 395 cv_broadcast(&log->lock_cv); 396 break; 397 } 398 399 mask >>= 1; 400 } 401 } 402 403 mutex_exit(&log->lock); 404 405 if (rxid) { 406 emlxs_thread_spawn(hba, emlxs_abort_ct_exchange, 407 (void *)port, (void *)((unsigned long)rxid)); 408 } 409 410 return (0); 411 412 } /* emlxs_msg_log() */ 413 414 415 static uint32_t 416 emlxs_msg_log_check(emlxs_port_t *port, emlxs_msg_t *msg) 417 { 418 emlxs_hba_t *hba = HBA; 419 420 switch (msg->level) { 421 case EMLXS_DEBUG: 422 if (msg->mask & emlxs_log_debugs) { 423 return (1); 424 } 425 break; 426 427 case EMLXS_NOTICE: 428 if (msg->mask & emlxs_log_notices) { 429 return (1); 430 } 431 break; 432 433 case EMLXS_WARNING: 434 if (msg->mask & emlxs_log_warnings) { 435 return (1); 436 } 437 break; 438 439 case EMLXS_ERROR: 440 if (msg->mask & emlxs_log_errors) { 441 return (1); 442 } 443 break; 444 445 case EMLXS_EVENT: 446 if (msg->mask & hba->log_events) { 447 return (1); 448 } 449 #ifdef SAN_DIAG_SUPPORT 450 if (msg->mask & port->sd_reg_events) { 451 return (1); 452 } 453 #endif /* SAN_DIAG_SUPPORT */ 454 break; 455 456 case EMLXS_PANIC: 457 return (1); 458 } 459 460 return (0); 461 462 } /* emlxs_msg_log_check() */ 463 464 465 static uint32_t 466 emlxs_msg_print_check(emlxs_port_t *port, emlxs_msg_t *msg) 467 { 468 emlxs_hba_t *hba = HBA; 469 emlxs_config_t *cfg; 470 uint32_t rval = 0; 471 472 cfg = &CFG; 473 474 switch (msg->level) { 475 case EMLXS_DEBUG: 476 if (msg->mask & cfg[CFG_CONSOLE_DEBUGS].current) { 477 rval |= 2; 478 } 479 480 if (msg->mask & cfg[CFG_LOG_DEBUGS].current) { 481 rval |= 1; 482 } 483 484 break; 485 486 case EMLXS_NOTICE: 487 if (msg->mask & cfg[CFG_CONSOLE_NOTICES].current) { 488 rval |= 2; 489 } 490 491 if (msg->mask & cfg[CFG_LOG_NOTICES].current) { 492 rval |= 1; 493 } 494 495 break; 496 497 case EMLXS_WARNING: 498 if (msg->mask & cfg[CFG_CONSOLE_WARNINGS].current) { 499 rval |= 2; 500 } 501 502 if (msg->mask & cfg[CFG_LOG_WARNINGS].current) { 503 rval |= 1; 504 } 505 506 break; 507 508 case EMLXS_ERROR: 509 if (msg->mask & cfg[CFG_CONSOLE_ERRORS].current) { 510 rval |= 2; 511 } 512 513 if (msg->mask & cfg[CFG_LOG_ERRORS].current) { 514 rval |= 1; 515 } 516 break; 517 518 case EMLXS_EVENT: 519 /* Only print an event if it is being logged internally */ 520 if (msg->mask & hba->log_events) { 521 if (msg->mask & cfg[CFG_CONSOLE_EVENTS].current) { 522 rval |= 2; 523 } 524 525 if (msg->mask & cfg[CFG_LOG_EVENTS].current) { 526 rval |= 1; 527 } 528 } 529 break; 530 531 case EMLXS_PANIC: 532 default: 533 rval |= 1; 534 535 } 536 537 return (rval); 538 539 } /* emlxs_msg_print_check() */ 540 541 542 void 543 emlxs_msg_printf(emlxs_port_t *port, const uint32_t fileno, 544 const uint32_t line, void *bp, uint32_t size, emlxs_msg_t *msg, 545 const char *fmt, ...) 546 { 547 emlxs_hba_t *hba = HBA; 548 va_list valist; 549 char va_str[256]; 550 char msg_str[512]; 551 char *level; 552 int32_t cmn_level; 553 uint32_t rval; 554 uint32_t logged; 555 char driver[32]; 556 557 va_str[0] = 0; 558 559 if (fmt) { 560 va_start(valist, fmt); 561 (void) vsprintf(va_str, fmt, valist); 562 va_end(valist); 563 } 564 565 #ifdef FMA_SUPPORT 566 /* 567 * Don't post fault event or/and error event to fmd 568 * if physical port was not bounded yet. 569 */ 570 if (msg->fm_ereport_code) { 571 emlxs_fm_ereport(hba, msg->fm_ereport_code); 572 } 573 574 if (msg->fm_impact_code) { 575 emlxs_fm_service_impact(hba, msg->fm_impact_code); 576 } 577 #endif /* FMA_SUPPORT */ 578 579 /* Check if msg should be logged */ 580 if ((logged = emlxs_msg_log_check(port, msg))) { 581 /* Log the message */ 582 if (emlxs_msg_log(port, fileno, line, bp, size, msg, va_str)) { 583 return; 584 } 585 } 586 587 /* Check if msg should be printed */ 588 if (rval = emlxs_msg_print_check(port, msg)) { 589 cmn_level = CE_CONT; 590 591 switch (msg->level) { 592 case EMLXS_DEBUG: 593 level = " DEBUG"; 594 break; 595 596 case EMLXS_NOTICE: 597 level = " NOTICE"; 598 break; 599 600 case EMLXS_WARNING: 601 level = "WARNING"; 602 break; 603 604 case EMLXS_ERROR: 605 level = " ERROR"; 606 break; 607 608 case EMLXS_PANIC: 609 cmn_level = CE_PANIC; 610 level = " PANIC"; 611 break; 612 613 case EMLXS_EVENT: 614 level = " EVENT"; 615 break; 616 617 default: 618 level = "UNKNOWN"; 619 break; 620 } 621 622 if (port->vpi == 0) { 623 (void) sprintf(driver, "%s%d", DRIVER_NAME, 624 hba->ddiinst); 625 } else { 626 (void) sprintf(driver, "%s%d.%d", DRIVER_NAME, 627 hba->ddiinst, port->vpi); 628 } 629 630 /* Generate the message string */ 631 if (msg->buffer[0] != 0) { 632 if (va_str[0] != 0) { 633 (void) sprintf(msg_str, 634 "[%2X.%04X]%s:%7s:%4d: %s (%s)\n", fileno, 635 line, driver, level, msg->id, msg->buffer, 636 va_str); 637 } else { 638 (void) sprintf(msg_str, 639 "[%2X.%04X]%s:%7s:%4d: %s\n", 640 fileno, line, driver, level, msg->id, 641 msg->buffer); 642 } 643 } else { 644 if (va_str[0] != 0) { 645 (void) sprintf(msg_str, 646 "[%2X.%04X]%s:%7s:%4d: (%s)\n", fileno, 647 line, driver, level, msg->id, va_str); 648 } else { 649 (void) sprintf(msg_str, 650 "[%2X.%04X]%s:%7s:%4d\n", 651 fileno, line, driver, level, msg->id); 652 } 653 } 654 655 switch (rval) { 656 case 1: /* MESSAGE LOG ONLY */ 657 /* Message log & console, if system booted in */ 658 /* verbose mode (CE_CONT only) */ 659 cmn_err(cmn_level, "?%s", msg_str); 660 break; 661 662 case 2: /* CONSOLE ONLY */ 663 cmn_err(cmn_level, "^%s", msg_str); 664 break; 665 666 case 3: /* CONSOLE AND MESSAGE LOG */ 667 cmn_err(cmn_level, "%s", msg_str); 668 break; 669 670 } 671 672 } 673 674 /* If message was not logged, then free any context buffer provided */ 675 if (!logged && bp && size) { 676 kmem_free(bp, size); 677 } 678 679 return; 680 681 } /* emlxs_msg_printf() */ 682 683 684 uint32_t 685 emlxs_msg_log_get(emlxs_hba_t *hba, emlxs_log_req_t *req, 686 emlxs_log_resp_t *resp) 687 { 688 emlxs_msg_log_t *log; 689 uint32_t first; 690 uint32_t last; 691 uint32_t count; 692 uint32_t index; 693 uint32_t i; 694 char *resp_buf; 695 696 log = &LOG; 697 698 mutex_enter(&log->lock); 699 700 /* Check if buffer is empty */ 701 if (log->count == 0) { 702 /* If so, exit now */ 703 resp->first = 0; 704 resp->last = 0; 705 resp->count = 0; 706 mutex_exit(&log->lock); 707 708 return (1); 709 } 710 711 /* Get current log entry ranges */ 712 713 /* Get last entry id saved */ 714 last = log->count - 1; 715 716 /* Check if request is out of current range */ 717 if (req->first > last) { 718 /* if so, exit now */ 719 resp->first = last; 720 resp->last = last; 721 resp->count = 0; 722 mutex_exit(&log->lock); 723 724 return (0); 725 } 726 727 /* Get oldest entry id and its index */ 728 729 /* Check if buffer has already been filled once */ 730 if (log->count >= log->size) { 731 first = log->count - log->size; 732 index = log->next; 733 } else { /* Buffer not yet filled */ 734 735 first = 0; 736 index = 0; 737 } 738 739 /* Check if requested first message is greater than actual. */ 740 /* If so, adjust for it. */ 741 if (req->first > first) { 742 /* Adjust entry index to first requested message */ 743 index += (req->first - first); 744 if (index >= log->size) { 745 index -= log->size; 746 } 747 748 first = req->first; 749 } 750 751 /* Get the total number of messages available for return */ 752 count = last - first + 1; 753 754 /* Check if requested count is less than actual. If so, adjust it. */ 755 if (req->count < count) { 756 count = req->count; 757 } 758 759 /* Fill in the response header */ 760 resp->count = count; 761 resp->first = first; 762 resp->last = last; 763 764 /* Fill the response buffer */ 765 resp_buf = (char *)resp + sizeof (emlxs_log_resp_t); 766 for (i = 0; i < count; i++) { 767 emlxs_msg_sprintf(resp_buf, &log->entry[index]); 768 769 /* Increment the response buffer */ 770 resp_buf += MAX_LOG_MSG_LENGTH; 771 772 /* Increment index */ 773 if (++index >= log->size) { 774 index = 0; 775 } 776 } 777 778 mutex_exit(&log->lock); 779 780 return (1); 781 782 } /* emlxs_msg_log_get() */ 783 784 785 786 static void 787 emlxs_msg_sprintf(char *buffer, emlxs_msg_entry_t *entry) 788 { 789 char *level; 790 emlxs_msg_t *msg; 791 uint32_t secs; 792 uint32_t hsecs; 793 char buf[256]; 794 uint32_t buflen; 795 char driver[32]; 796 797 msg = entry->msg; 798 hsecs = (entry->time % 100); 799 secs = entry->time / 100; 800 801 switch (msg->level) { 802 case EMLXS_DEBUG: 803 level = " DEBUG"; 804 break; 805 806 case EMLXS_NOTICE: 807 level = " NOTICE"; 808 break; 809 810 case EMLXS_WARNING: 811 level = "WARNING"; 812 break; 813 814 case EMLXS_ERROR: 815 level = " ERROR"; 816 break; 817 818 case EMLXS_PANIC: 819 level = " PANIC"; 820 break; 821 822 case EMLXS_EVENT: 823 level = " EVENT"; 824 break; 825 826 default: 827 level = "UNKNOWN"; 828 break; 829 } 830 831 if (entry->vpi == 0) { 832 (void) sprintf(driver, "%s%d", DRIVER_NAME, entry->instance); 833 } else { 834 (void) sprintf(driver, "%s%d.%d", DRIVER_NAME, entry->instance, 835 entry->vpi); 836 } 837 838 /* Generate the message string */ 839 if (msg->buffer[0] != 0) { 840 if (entry->buffer[0] != 0) { 841 (void) sprintf(buf, 842 "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: %s (%s)\n", 843 secs, hsecs, entry->id, entry->fileno, 844 entry->line, driver, level, msg->id, msg->buffer, 845 entry->buffer); 846 847 } else { 848 (void) sprintf(buf, 849 "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: %s\n", secs, 850 hsecs, entry->id, entry->fileno, entry->line, 851 driver, level, msg->id, msg->buffer); 852 } 853 } else { 854 if (entry->buffer[0] != 0) { 855 (void) sprintf(buf, 856 "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: (%s)\n", 857 secs, hsecs, entry->id, entry->fileno, 858 entry->line, driver, level, msg->id, 859 entry->buffer); 860 } else { 861 (void) sprintf(buf, 862 "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d\n", 863 secs, hsecs, entry->id, entry->fileno, 864 entry->line, driver, level, msg->id); 865 } 866 } 867 868 bzero(buffer, MAX_LOG_MSG_LENGTH); 869 buflen = strlen(buf); 870 871 if (buflen > (MAX_LOG_MSG_LENGTH - 1)) { 872 (void) strncpy(buffer, buf, (MAX_LOG_MSG_LENGTH - 2)); 873 buffer[MAX_LOG_MSG_LENGTH - 2] = '\n'; 874 } else { 875 (void) strncpy(buffer, buf, buflen); 876 } 877 878 return; 879 880 } /* emlxs_msg_sprintf() */ 881 882 883 884 885 void 886 emlxs_log_rscn_event(emlxs_port_t *port, uint8_t *payload, uint32_t size) 887 { 888 #ifdef DFC_SUPPORT 889 emlxs_hba_t *hba = HBA; 890 uint8_t *bp; 891 uint32_t *ptr; 892 893 /* Check if the event is being requested */ 894 if (!(hba->log_events & EVT_RSCN)) { 895 return; 896 } 897 898 if (size > MAX_RSCN_PAYLOAD) { 899 size = MAX_RSCN_PAYLOAD; 900 } 901 902 size += sizeof (uint32_t); 903 904 /* Save a copy of the payload for the event log */ 905 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 906 return; 907 } 908 909 910 /* 911 * Buffer Format: 912 * word[0] = DID of the RSCN 913 * word[1] = RSCN Payload 914 */ 915 ptr = (uint32_t *)bp; 916 *ptr++ = port->did; 917 bcopy(payload, (char *)ptr, (size - sizeof (uint32_t))); 918 919 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_rscn_event, 920 "bp=%p size=%d", bp, size); 921 922 #endif /* DFC_SUPPORT */ 923 return; 924 925 } /* emlxs_log_rscn_event() */ 926 927 928 void 929 emlxs_log_vportrscn_event(emlxs_port_t *port, uint8_t *payload, uint32_t size) 930 { 931 #ifdef DFC_SUPPORT 932 emlxs_hba_t *hba = HBA; 933 uint8_t *bp; 934 uint8_t *ptr; 935 936 /* Check if the event is being requested */ 937 if (!(hba->log_events & EVT_VPORTRSCN)) { 938 return; 939 } 940 941 if (size > MAX_RSCN_PAYLOAD) { 942 size = MAX_RSCN_PAYLOAD; 943 } 944 945 /* Save a copy of the payload for the event log */ 946 if (!(bp = 947 (uint8_t *)kmem_alloc(size + sizeof (NAME_TYPE), KM_NOSLEEP))) { 948 return; 949 } 950 951 952 /* 953 * Buffer Format: 954 * word[0 - 4] = WWPN of the RSCN 955 * word[5] = RSCN Payload 956 */ 957 ptr = bp; 958 bcopy(&port->wwpn, ptr, sizeof (NAME_TYPE)); 959 ptr += sizeof (NAME_TYPE); 960 bcopy(payload, ptr, size); 961 962 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size + sizeof (NAME_TYPE), 963 &emlxs_vportrscn_event, "bp=%p size=%d", bp, size); 964 965 #endif /* DFC_SUPPORT */ 966 return; 967 968 } /* emlxs_log_vportrscn_event() */ 969 970 971 uint32_t 972 emlxs_log_ct_event(emlxs_port_t *port, uint8_t *payload, uint32_t size, 973 uint32_t rxid) 974 { 975 #ifdef DFC_SUPPORT 976 emlxs_hba_t *hba = HBA; 977 uint8_t *bp; 978 uint32_t *ptr; 979 980 /* Check if the event is being requested */ 981 if (!(hba->log_events & EVT_CT)) { 982 return (1); 983 } 984 985 if (size > MAX_CT_PAYLOAD) { 986 size = MAX_CT_PAYLOAD; 987 } 988 989 size += sizeof (uint32_t); 990 991 /* Save a copy of the payload for the event log */ 992 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 993 return (1); 994 } 995 996 /* 997 * Buffer Format: 998 * word[0] = RXID tag for outgoing reply to this CT request 999 * word[1] = CT Payload 1000 */ 1001 ptr = (uint32_t *)bp; 1002 *ptr++ = rxid; 1003 1004 bcopy(payload, (char *)ptr, (size - sizeof (uint32_t))); 1005 1006 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_ct_event, 1007 "bp=%p size=%d rxid=%x", bp, size, rxid); 1008 1009 1010 return (0); 1011 #else 1012 1013 return (1); 1014 1015 #endif /* DFC_SUPPORT */ 1016 1017 } /* emlxs_log_ct_event() */ 1018 1019 1020 void 1021 emlxs_log_link_event(emlxs_port_t *port) 1022 { 1023 #ifdef DFC_SUPPORT 1024 emlxs_hba_t *hba = HBA; 1025 uint8_t *bp; 1026 dfc_linkinfo_t *linkinfo; 1027 uint8_t *byte; 1028 uint8_t *linkspeed; 1029 uint8_t *liptype; 1030 uint8_t *resv1; 1031 uint8_t *resv2; 1032 uint32_t size; 1033 1034 /* Check if the event is being requested */ 1035 /* 1036 * if(!(hba->log_events & EVT_LINK)) { return; } 1037 */ 1038 size = sizeof (dfc_linkinfo_t) + sizeof (uint32_t); 1039 1040 /* Save a copy of the buffer for the event log */ 1041 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 1042 return; 1043 } 1044 1045 /* 1046 * Buffer Format: 1047 * word[0] = Linkspeed:8 1048 * word[0] = LIP_type:8 1049 * word[0] = resv1:8 1050 * word[0] = resv2:8 1051 * word[1] = dfc_linkinfo_t data 1052 */ 1053 byte = (uint8_t *)bp; 1054 linkspeed = &byte[0]; 1055 liptype = &byte[1]; 1056 resv1 = &byte[2]; 1057 resv2 = &byte[3]; 1058 linkinfo = (dfc_linkinfo_t *)&byte[4]; 1059 1060 *resv1 = 0; 1061 *resv2 = 0; 1062 1063 if (hba->state <= FC_LINK_DOWN) { 1064 *linkspeed = 0; 1065 *liptype = 0; 1066 } else { 1067 /* Set linkspeed */ 1068 if (hba->linkspeed == LA_2GHZ_LINK) { 1069 *linkspeed = HBA_PORTSPEED_2GBIT; 1070 } else if (hba->linkspeed == LA_4GHZ_LINK) { 1071 *linkspeed = HBA_PORTSPEED_4GBIT; 1072 } else if (hba->linkspeed == LA_8GHZ_LINK) { 1073 *linkspeed = HBA_PORTSPEED_8GBIT; 1074 } else if (hba->linkspeed == LA_10GHZ_LINK) { 1075 *linkspeed = HBA_PORTSPEED_10GBIT; 1076 } else { 1077 *linkspeed = HBA_PORTSPEED_1GBIT; 1078 } 1079 1080 /* Set LIP type */ 1081 *liptype = port->lip_type; 1082 } 1083 1084 bzero(linkinfo, sizeof (dfc_linkinfo_t)); 1085 1086 linkinfo->a_linkEventTag = hba->link_event_tag; 1087 linkinfo->a_linkUp = HBASTATS.LinkUp; 1088 linkinfo->a_linkDown = HBASTATS.LinkDown; 1089 linkinfo->a_linkMulti = HBASTATS.LinkMultiEvent; 1090 1091 if (hba->state <= FC_LINK_DOWN) { 1092 linkinfo->a_linkState = LNK_DOWN; 1093 linkinfo->a_DID = port->prev_did; 1094 } else if (hba->state < FC_READY) { 1095 linkinfo->a_linkState = LNK_DISCOVERY; 1096 } else { 1097 linkinfo->a_linkState = LNK_READY; 1098 } 1099 1100 if (linkinfo->a_linkState != LNK_DOWN) { 1101 if (hba->topology == TOPOLOGY_LOOP) { 1102 if (hba->flag & FC_FABRIC_ATTACHED) { 1103 linkinfo->a_topology = LNK_PUBLIC_LOOP; 1104 } else { 1105 linkinfo->a_topology = LNK_LOOP; 1106 } 1107 1108 linkinfo->a_alpa = port->did & 0xff; 1109 linkinfo->a_DID = linkinfo->a_alpa; 1110 linkinfo->a_alpaCnt = port->alpa_map[0]; 1111 1112 if (linkinfo->a_alpaCnt > 127) { 1113 linkinfo->a_alpaCnt = 127; 1114 } 1115 1116 bcopy((void *)&port->alpa_map[1], linkinfo->a_alpaMap, 1117 linkinfo->a_alpaCnt); 1118 } else { 1119 if (port->node_count == 1) { 1120 linkinfo->a_topology = LNK_PT2PT; 1121 } else { 1122 linkinfo->a_topology = LNK_FABRIC; 1123 } 1124 1125 linkinfo->a_DID = port->did; 1126 } 1127 } 1128 1129 bcopy(&hba->wwpn, linkinfo->a_wwpName, 8); 1130 bcopy(&hba->wwnn, linkinfo->a_wwnName, 8); 1131 1132 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_link_event, 1133 "bp=%p size=%d tag=%x", bp, size, hba->link_event_tag); 1134 1135 #endif /* DFC_SUPPORT */ 1136 1137 return; 1138 1139 } /* emlxs_log_link_event() */ 1140 1141 1142 void 1143 emlxs_log_dump_event(emlxs_port_t *port, uint8_t *buffer, uint32_t size) 1144 { 1145 #ifdef DFC_SUPPORT 1146 emlxs_hba_t *hba = HBA; 1147 uint8_t *bp; 1148 1149 /* Check if the event is being requested */ 1150 if (!(hba->log_events & EVT_DUMP)) { 1151 #ifdef DUMP_SUPPORT 1152 /* Schedule a dump thread */ 1153 emlxs_dump(hba, EMLXS_DRV_DUMP, 0, 0); 1154 #endif /* DUMP_SUPPORT */ 1155 return; 1156 } 1157 1158 if (buffer && size) { 1159 /* Save a copy of the buffer for the event log */ 1160 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 1161 return; 1162 } 1163 1164 bcopy(buffer, bp, size); 1165 } else { 1166 bp = NULL; 1167 size = 0; 1168 } 1169 1170 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_dump_event, 1171 "bp=%p size=%d", bp, size); 1172 #else 1173 1174 #ifdef DUMP_SUPPORT 1175 /* Schedule a dump thread */ 1176 emlxs_dump(hba, EMLXS_DRV_DUMP, 0, 0); 1177 #endif /* DUMP_SUPPORT */ 1178 1179 #endif /* DFC_SUPPORT */ 1180 1181 return; 1182 1183 } /* emlxs_log_dump_event() */ 1184 1185 1186 extern void 1187 emlxs_log_temp_event(emlxs_port_t *port, uint32_t type, uint32_t temp) 1188 { 1189 emlxs_hba_t *hba = HBA; 1190 1191 #ifdef DFC_SUPPORT 1192 uint32_t *bp; 1193 uint32_t size; 1194 1195 /* Check if the event is being requested */ 1196 if (!(hba->log_events & EVT_TEMP)) { 1197 #ifdef DUMP_SUPPORT 1198 /* Schedule a dump thread */ 1199 emlxs_dump(hba, EMLXS_TEMP_DUMP, type, temp); 1200 #endif /* DUMP_SUPPORT */ 1201 return; 1202 } 1203 1204 size = 2 * sizeof (uint32_t); 1205 1206 if (!(bp = (uint32_t *)kmem_alloc(size, KM_NOSLEEP))) { 1207 return; 1208 } 1209 1210 bp[0] = type; 1211 bp[1] = temp; 1212 1213 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_temp_event, 1214 "type=%x temp=%d bp=%p size=%d", type, temp, bp, size); 1215 1216 #else /* !DFC_SUPPORT */ 1217 1218 #ifdef DUMP_SUPPORT 1219 /* Schedule a dump thread */ 1220 emlxs_dump(hba, EMLXS_TEMP_DUMP, type, temp); 1221 #endif /* DUMP_SUPPORT */ 1222 1223 #endif /* DFC_SUPPORT */ 1224 1225 return; 1226 1227 } /* emlxs_log_temp_event() */ 1228 1229 1230 1231 extern void 1232 emlxs_log_fcoe_event(emlxs_port_t *port, menlo_init_rsp_t *init_rsp) 1233 { 1234 #ifdef DFC_SUPPORT 1235 emlxs_hba_t *hba = HBA; 1236 uint8_t *bp; 1237 uint32_t size; 1238 1239 /* Check if the event is being requested */ 1240 if (!(hba->log_events & EVT_FCOE)) { 1241 return; 1242 } 1243 1244 /* Check if this is a FCOE adapter */ 1245 if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) { 1246 return; 1247 } 1248 1249 size = sizeof (menlo_init_rsp_t); 1250 1251 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 1252 return; 1253 } 1254 1255 bcopy((uint8_t *)init_rsp, bp, size); 1256 1257 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_fcoe_event, 1258 "bp=%p size=%d", bp, size); 1259 #endif /* DFC_SUPPORT */ 1260 1261 return; 1262 1263 } /* emlxs_log_fcoe_event() */ 1264 1265 1266 #ifdef SAN_DIAG_SUPPORT 1267 extern void 1268 emlxs_log_sd_basic_els_event(emlxs_port_t *port, uint32_t subcat, 1269 HBA_WWN *portname, HBA_WWN *nodename) 1270 { 1271 struct sd_plogi_rcv_v0 *bp; 1272 uint32_t size; 1273 1274 /* Check if the event is being requested */ 1275 if (!(port->sd_reg_events & EVT_SD_ELS)) 1276 return; 1277 1278 size = sizeof (struct sd_plogi_rcv_v0); 1279 1280 if (!(bp = (struct sd_plogi_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP))) 1281 return; 1282 1283 /* 1284 * we are using version field to store subtype, libdfc 1285 * will fix this up before returning data to app. 1286 */ 1287 bp->sd_plogir_version = subcat; 1288 bcopy((uint8_t *)portname, (uint8_t *)&bp->sd_plogir_portname, 1289 sizeof (HBA_WWN)); 1290 bcopy((uint8_t *)nodename, (uint8_t *)&bp->sd_plogir_nodename, 1291 sizeof (HBA_WWN)); 1292 1293 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_els_event, 1294 "bp=%p size=%d", bp, size); 1295 1296 return; 1297 1298 } /* emlxs_log_sd_basic_els_event() */ 1299 1300 1301 extern void 1302 emlxs_log_sd_prlo_event(emlxs_port_t *port, HBA_WWN *remoteport) 1303 { 1304 struct sd_prlo_rcv_v0 *bp; 1305 uint32_t size; 1306 1307 /* Check if the event is being requested */ 1308 if (!(port->sd_reg_events & EVT_SD_ELS)) 1309 return; 1310 1311 size = sizeof (struct sd_prlo_rcv_v0); 1312 1313 if (!(bp = (struct sd_prlo_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP))) 1314 return; 1315 1316 /* 1317 * we are using version field to store subtype, libdfc 1318 * will fix this up before returning data to app. 1319 */ 1320 bp->sd_prlor_version = SD_ELS_SUBCATEGORY_PRLO_RCV; 1321 bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_prlor_remoteport, 1322 sizeof (HBA_WWN)); 1323 1324 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_els_event, 1325 "bp=%p size=%d", bp, size); 1326 1327 return; 1328 1329 } /* emlxs_log_sd_prlo_event() */ 1330 1331 1332 extern void 1333 emlxs_log_sd_lsrjt_event(emlxs_port_t *port, HBA_WWN *remoteport, 1334 uint32_t orig_cmd, uint32_t reason, uint32_t reason_expl) 1335 { 1336 struct sd_lsrjt_rcv_v0 *bp; 1337 uint32_t size; 1338 1339 /* Check if the event is being requested */ 1340 if (!(port->sd_reg_events & EVT_SD_ELS)) 1341 return; 1342 1343 size = sizeof (struct sd_lsrjt_rcv_v0); 1344 1345 if (!(bp = (struct sd_lsrjt_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP))) 1346 return; 1347 1348 /* 1349 * we are using version field to store subtype, libdfc 1350 * will fix this up before returning data to app. 1351 */ 1352 bp->sd_lsrjtr_version = SD_ELS_SUBCATEGORY_LSRJT_RCV; 1353 bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_lsrjtr_remoteport, 1354 sizeof (HBA_WWN)); 1355 bp->sd_lsrjtr_original_cmd = orig_cmd; 1356 bp->sd_lsrjtr_reasoncode = reason; 1357 bp->sd_lsrjtr_reasoncodeexpl = reason_expl; 1358 1359 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_els_event, 1360 "bp=%p size=%d", bp, size); 1361 1362 return; 1363 1364 } /* emlxs_log_sd_lsrjt_event() */ 1365 1366 1367 1368 extern void 1369 emlxs_log_sd_fc_bsy_event(emlxs_port_t *port, HBA_WWN *remoteport) 1370 { 1371 struct sd_pbsy_rcv_v0 *bp; 1372 uint32_t size; 1373 1374 /* Check if the event is being requested */ 1375 if (!(port->sd_reg_events & EVT_SD_FABRIC)) 1376 return; 1377 1378 size = sizeof (struct sd_pbsy_rcv_v0); 1379 1380 if (!(bp = (struct sd_pbsy_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP))) 1381 return; 1382 1383 /* 1384 * we are using version field to store subtype, libdfc 1385 * will fix this up before returning data to app. 1386 */ 1387 if (remoteport == NULL) 1388 bp->sd_pbsyr_evt_version = SD_FABRIC_SUBCATEGORY_FABRIC_BUSY; 1389 else 1390 { 1391 bp->sd_pbsyr_evt_version = SD_FABRIC_SUBCATEGORY_PORT_BUSY; 1392 bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_pbsyr_rport, 1393 sizeof (HBA_WWN)); 1394 } 1395 1396 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_fabric_event, 1397 "bp=%p size=%d", bp, size); 1398 1399 return; 1400 1401 } /* emlxs_log_sd_fc_bsy_event() */ 1402 1403 1404 extern void 1405 emlxs_log_sd_fc_rdchk_event(emlxs_port_t *port, HBA_WWN *remoteport, 1406 uint32_t lun, uint32_t opcode, uint32_t fcp_param) 1407 { 1408 struct sd_fcprdchkerr_v0 *bp; 1409 uint32_t size; 1410 1411 /* Check if the event is being requested */ 1412 if (!(port->sd_reg_events & EVT_SD_FABRIC)) 1413 return; 1414 1415 size = sizeof (struct sd_fcprdchkerr_v0); 1416 1417 if (!(bp = (struct sd_fcprdchkerr_v0 *)kmem_alloc(size, KM_NOSLEEP))) 1418 return; 1419 1420 /* 1421 * we are using version field to store subtype, libdfc 1422 * will fix this up before returning data to app. 1423 */ 1424 bp->sd_fcprdchkerr_version = SD_FABRIC_SUBCATEGORY_FCPRDCHKERR; 1425 bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_fcprdchkerr_rport, 1426 sizeof (HBA_WWN)); 1427 bp->sd_fcprdchkerr_lun = lun; 1428 bp->sd_fcprdchkerr_opcode = opcode; 1429 bp->sd_fcprdchkerr_fcpiparam = fcp_param; 1430 1431 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_fabric_event, 1432 "bp=%p size=%d", bp, size); 1433 1434 return; 1435 1436 } /* emlxs_log_sd_rdchk_event() */ 1437 1438 1439 extern void 1440 emlxs_log_sd_scsi_event(emlxs_port_t *port, uint32_t type, 1441 HBA_WWN *remoteport, int32_t lun) 1442 { 1443 struct sd_scsi_generic_v0 *bp; 1444 uint32_t size; 1445 1446 /* Check if the event is being requested */ 1447 if (!(port->sd_reg_events & EVT_SD_SCSI)) 1448 return; 1449 1450 size = sizeof (struct sd_scsi_generic_v0); 1451 1452 if (!(bp = (struct sd_scsi_generic_v0 *)kmem_alloc(size, KM_NOSLEEP))) 1453 return; 1454 1455 /* 1456 * we are using version field to store subtype, libdfc 1457 * will fix this up before returning data to app. 1458 */ 1459 bp->sd_scsi_generic_version = type; 1460 bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_scsi_generic_rport, 1461 sizeof (HBA_WWN)); 1462 bp->sd_scsi_generic_lun = lun; 1463 1464 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_scsi_event, 1465 "bp=%p size=%d", bp, size); 1466 1467 return; 1468 1469 } /* emlxs_log_sd_scsi_event() */ 1470 1471 1472 extern void 1473 emlxs_log_sd_scsi_check_event(emlxs_port_t *port, HBA_WWN *remoteport, 1474 uint32_t lun, uint32_t cmdcode, uint32_t sensekey, 1475 uint32_t asc, uint32_t ascq) 1476 { 1477 struct sd_scsi_checkcond_v0 *bp; 1478 uint32_t size; 1479 1480 /* Check if the event is being requested */ 1481 if (!(port->sd_reg_events & EVT_SD_SCSI)) 1482 return; 1483 1484 size = sizeof (struct sd_scsi_checkcond_v0); 1485 1486 if (!(bp = (struct sd_scsi_checkcond_v0 *)kmem_alloc(size, KM_NOSLEEP))) 1487 return; 1488 1489 /* 1490 * we are using version field to store subtype, libdfc 1491 * will fix this up before returning data to app. 1492 */ 1493 bp->sd_scsi_checkcond_version = SD_SCSI_SUBCATEGORY_CHECKCONDITION; 1494 bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_scsi_checkcond_rport, 1495 sizeof (HBA_WWN)); 1496 bp->sd_scsi_checkcond_lun = lun; 1497 bp->sd_scsi_checkcond_cmdcode = cmdcode; 1498 bp->sd_scsi_checkcond_sensekey = sensekey; 1499 bp->sd_scsi_checkcond_asc = asc; 1500 bp->sd_scsi_checkcond_ascq = ascq; 1501 1502 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_scsi_event, 1503 "bp=%p size=%d", bp, size); 1504 1505 } 1506 #endif /* SAN_DIAG_SUPPORT */ 1507 1508 1509 extern void 1510 emlxs_log_async_event(emlxs_port_t *port, IOCB *iocb) 1511 { 1512 uint8_t *bp; 1513 uint32_t size; 1514 1515 /* ASYNC_STATUS_CN response size */ 1516 size = 64; 1517 1518 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 1519 return; 1520 } 1521 1522 bcopy((uint8_t *)iocb, bp, size); 1523 1524 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_async_event, 1525 "bp=%p size=%d", bp, size); 1526 1527 } /* emlxs_log_async_event() */ 1528 1529 #ifdef DFC_SUPPORT 1530 1531 extern uint32_t 1532 emlxs_get_dfc_eventinfo(emlxs_port_t *port, HBA_EVENTINFO *eventinfo, 1533 uint32_t *eventcount, uint32_t *missed) 1534 { 1535 emlxs_hba_t *hba = HBA; 1536 emlxs_msg_log_t *log; 1537 uint32_t first; 1538 uint32_t last; 1539 uint32_t count; 1540 uint32_t index; 1541 emlxs_msg_entry_t *entry; 1542 dfc_linkinfo_t *linkinfo; 1543 uint32_t *word; 1544 uint8_t *byte; 1545 uint8_t linkspeed; 1546 uint8_t liptype; 1547 fc_affected_id_t *aid; 1548 uint32_t max_events; 1549 uint32_t events; 1550 uint8_t format; 1551 emlxs_hba_event_t *hba_event; 1552 1553 if (!eventinfo || !eventcount || !missed) { 1554 return (DFC_ARG_NULL); 1555 } 1556 1557 hba_event = &hba->hba_event; 1558 max_events = *eventcount; 1559 *eventcount = 0; 1560 1561 log = &LOG; 1562 1563 mutex_enter(&log->lock); 1564 1565 /* Check if log is empty */ 1566 if (log->count == 0) { 1567 /* Make sure everything is initialized */ 1568 hba_event->new = 0; 1569 hba_event->missed = 0; 1570 hba_event->last_id = 0; 1571 1572 mutex_exit(&log->lock); 1573 return (0); 1574 } 1575 1576 /* Safety check */ 1577 if (hba_event->last_id > (log->count - 1)) { 1578 hba_event->last_id = log->count - 1; 1579 } 1580 1581 /* Account for missed events */ 1582 if (hba_event->new > hba_event->missed) { 1583 hba_event->new -= hba_event->missed; 1584 } else { 1585 hba_event->new = 0; 1586 } 1587 1588 *missed = hba_event->missed; 1589 hba_event->missed = 0; 1590 1591 if (!hba_event->new) { 1592 hba_event->last_id = log->count; 1593 mutex_exit(&log->lock); 1594 return (0); 1595 } 1596 1597 /* A new event has occurred since last acquisition */ 1598 /* Calculate the current buffer boundaries */ 1599 1600 /* Get last entry id saved */ 1601 last = log->count - 1; 1602 1603 /* Get oldest entry id and its index */ 1604 /* Check if buffer has already been filled once */ 1605 if (log->count >= log->size) { 1606 first = log->count - log->size; 1607 index = log->next; 1608 } else { /* Buffer not yet filled */ 1609 1610 first = 0; 1611 index = 0; 1612 } 1613 1614 /* Check if requested first event is greater than actual. */ 1615 /* If so, adjust for it. */ 1616 if (hba_event->last_id > first) { 1617 /* Adjust entry index to first requested message */ 1618 index += (hba_event->last_id - first); 1619 if (index >= log->size) { 1620 index -= log->size; 1621 } 1622 1623 first = hba_event->last_id; 1624 } 1625 1626 /* Get the total number of new messages */ 1627 count = last - first; 1628 1629 /* Scan log for next event */ 1630 events = 0; 1631 while (count-- && (events < max_events)) { 1632 if (++index >= log->size) { 1633 index = 0; 1634 } 1635 1636 entry = &log->entry[index]; 1637 1638 if (!entry->msg) { 1639 break; 1640 } 1641 1642 if ((entry->msg->level == EMLXS_EVENT) && 1643 (entry->msg->mask & (EVT_LINK | EVT_RSCN))) { 1644 /* Process this event */ 1645 switch (entry->msg->mask) { 1646 case EVT_LINK: 1647 byte = (uint8_t *)entry->bp; 1648 linkspeed = byte[0]; 1649 liptype = byte[1]; 1650 linkinfo = (dfc_linkinfo_t *)&byte[4]; 1651 1652 if (linkinfo->a_linkState == LNK_DOWN) { 1653 eventinfo->EventCode = 1654 HBA_EVENT_LINK_DOWN; 1655 eventinfo->Event.Link_EventInfo. 1656 PortFcId = linkinfo->a_DID; 1657 eventinfo->Event.Link_EventInfo. 1658 Reserved[0] = 0; 1659 eventinfo->Event.Link_EventInfo. 1660 Reserved[1] = 0; 1661 eventinfo->Event.Link_EventInfo. 1662 Reserved[2] = 0; 1663 } else { 1664 eventinfo->EventCode = 1665 HBA_EVENT_LINK_UP; 1666 eventinfo->Event.Link_EventInfo. 1667 PortFcId = linkinfo->a_DID; 1668 1669 if ((linkinfo->a_topology == 1670 LNK_PUBLIC_LOOP) || 1671 (linkinfo->a_topology == 1672 LNK_LOOP)) { 1673 eventinfo->Event. 1674 Link_EventInfo. 1675 Reserved[0] = 2; 1676 } else { 1677 eventinfo->Event. 1678 Link_EventInfo. 1679 Reserved[0] = 1; 1680 } 1681 1682 eventinfo->Event.Link_EventInfo. 1683 Reserved[1] = liptype; 1684 eventinfo->Event.Link_EventInfo. 1685 Reserved[2] = linkspeed; 1686 } 1687 1688 break; 1689 1690 case EVT_RSCN: 1691 word = (uint32_t *)entry->bp; 1692 eventinfo->EventCode = HBA_EVENT_RSCN; 1693 eventinfo->Event.RSCN_EventInfo.PortFcId = 1694 word[0] & 0xFFFFFF; 1695 /* word[1] is the RSCN payload command */ 1696 1697 aid = (fc_affected_id_t *)&word[2]; 1698 format = aid->aff_format; 1699 1700 switch (format) { 1701 case 0: /* Port */ 1702 eventinfo->Event.RSCN_EventInfo. 1703 NPortPage = 1704 aid->aff_d_id & 0x00ffffff; 1705 break; 1706 1707 case 1: /* Area */ 1708 eventinfo->Event.RSCN_EventInfo. 1709 NPortPage = 1710 aid->aff_d_id & 0x00ffff00; 1711 break; 1712 1713 case 2: /* Domain */ 1714 eventinfo->Event.RSCN_EventInfo. 1715 NPortPage = 1716 aid->aff_d_id & 0x00ff0000; 1717 break; 1718 1719 case 3: /* Network */ 1720 eventinfo->Event.RSCN_EventInfo. 1721 NPortPage = 0; 1722 break; 1723 } 1724 1725 eventinfo->Event.RSCN_EventInfo.Reserved[0] = 1726 0; 1727 eventinfo->Event.RSCN_EventInfo.Reserved[1] = 1728 0; 1729 1730 break; 1731 } 1732 1733 eventinfo++; 1734 events++; 1735 } 1736 1737 hba_event->last_id = entry->id; 1738 } 1739 1740 /* Adjust new count */ 1741 if (!count || (events >= hba_event->new)) { 1742 hba_event->new = 0; 1743 } else { 1744 hba_event->new -= events; 1745 } 1746 1747 /* Return number of events acquired */ 1748 *eventcount = events; 1749 1750 mutex_exit(&log->lock); 1751 1752 return (0); 1753 1754 } /* emlxs_get_dfc_eventinfo() */ 1755 1756 1757 uint32_t 1758 emlxs_get_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event, 1759 uint32_t sleep) 1760 { 1761 emlxs_hba_t *hba = HBA; 1762 emlxs_msg_log_t *log; 1763 uint32_t first; 1764 uint32_t last; 1765 uint32_t count; 1766 uint32_t index; 1767 uint32_t mask; 1768 uint32_t i; 1769 emlxs_msg_entry_t *entry; 1770 uint32_t size; 1771 uint32_t rc; 1772 1773 size = 0; 1774 1775 if (dfc_event->dataout && dfc_event->size) { 1776 size = dfc_event->size; 1777 } 1778 dfc_event->size = 0; 1779 1780 /* Get the log file pointer */ 1781 log = &LOG; 1782 1783 /* Calculate the event index */ 1784 mask = dfc_event->event; 1785 for (i = 0; i < 32; i++) { 1786 if (mask & 0x01) { 1787 break; 1788 } 1789 1790 mask >>= 1; 1791 } 1792 if (i == 32) { 1793 return (DFC_ARG_INVALID); 1794 } 1795 1796 mutex_enter(&log->lock); 1797 1798 /* Check if log is empty */ 1799 if (log->count == 0) { 1800 /* Make sure everything is initialized */ 1801 log->event_id[i] = 0; 1802 dfc_event->last_id = 0; 1803 } else { 1804 /* Check ranges for safety */ 1805 if (log->event_id[i] > (log->count - 1)) { 1806 log->event_id[i] = log->count - 1; 1807 } 1808 1809 if (dfc_event->last_id > log->event_id[i]) { 1810 dfc_event->last_id = log->event_id[i]; 1811 } 1812 } 1813 1814 wait_for_event: 1815 1816 /* Check if no new event has ocurred */ 1817 if (dfc_event->last_id == log->event_id[i]) { 1818 if (!sleep) { 1819 mutex_exit(&log->lock); 1820 return (0); 1821 } 1822 1823 /* While event is still active and */ 1824 /* no new event has been logged */ 1825 while ((dfc_event->event & hba->log_events) && 1826 (dfc_event->last_id == log->event_id[i])) { 1827 rc = cv_wait_sig(&log->lock_cv, &log->lock); 1828 1829 /* Check if thread was killed by kernel */ 1830 if (rc == 0) { 1831 dfc_event->pid = 0; 1832 dfc_event->event = 0; 1833 mutex_exit(&log->lock); 1834 return (0); 1835 } 1836 } 1837 1838 /* If the event is no longer registered then */ 1839 /* return immediately */ 1840 if (!(dfc_event->event & hba->log_events)) { 1841 mutex_exit(&log->lock); 1842 return (0); 1843 } 1844 } 1845 1846 /* !!! An event has occurred since last_id !!! */ 1847 1848 /* Check if event data is not being requested */ 1849 if (!size) { 1850 /* If so, then just return the last event id */ 1851 dfc_event->last_id = log->event_id[i]; 1852 1853 mutex_exit(&log->lock); 1854 return (0); 1855 } 1856 1857 /* !!! The requester wants the next event buffer !!! */ 1858 1859 /* Calculate the current buffer boundaries */ 1860 1861 /* Get last entry id saved */ 1862 last = log->count - 1; 1863 1864 /* Get oldest entry id and its index */ 1865 /* Check if buffer has already been filled once */ 1866 if (log->count >= log->size) { 1867 first = log->count - log->size; 1868 index = log->next; 1869 } else { /* Buffer not yet filled */ 1870 1871 first = 0; 1872 index = 0; 1873 } 1874 1875 /* Check to see if the buffer has wrapped since the last event */ 1876 if (first > log->event_id[i]) { 1877 /* Update last_id to the last known event */ 1878 dfc_event->last_id = log->event_id[i]; 1879 1880 /* Try waiting again if we can */ 1881 goto wait_for_event; 1882 } 1883 1884 /* Check if requested first event is greater than actual. */ 1885 /* If so, adjust for it. */ 1886 if (dfc_event->last_id > first) { 1887 /* Adjust entry index to first requested message */ 1888 index += (dfc_event->last_id - first); 1889 if (index >= log->size) { 1890 index -= log->size; 1891 } 1892 1893 first = dfc_event->last_id; 1894 } 1895 1896 /* Get the total number of new messages */ 1897 count = last - first + 1; 1898 1899 /* Scan log for next event */ 1900 while (count--) { 1901 if (++index >= log->size) { 1902 index = 0; 1903 } 1904 1905 entry = &log->entry[index]; 1906 1907 if ((entry->msg->level == EMLXS_EVENT) && 1908 (entry->msg->mask == dfc_event->event)) { 1909 break; 1910 } 1911 } 1912 1913 /* Check if no new event was found in the current log buffer */ 1914 /* This would indicate that the buffer wrapped since that last event */ 1915 if (!count) { 1916 /* Update last_id to the last known event */ 1917 dfc_event->last_id = log->event_id[i]; 1918 1919 /* Try waiting again if we can */ 1920 goto wait_for_event; 1921 } 1922 1923 /* !!! Next event found !!! */ 1924 1925 /* Copy the context buffer to the buffer provided */ 1926 if (entry->bp && entry->size) { 1927 if (entry->size < size) { 1928 size = entry->size; 1929 } 1930 1931 if (ddi_copyout((void *)entry->bp, dfc_event->dataout, size, 1932 dfc_event->mode) != 0) { 1933 mutex_exit(&log->lock); 1934 1935 return (DFC_COPYOUT_ERROR); 1936 } 1937 1938 /* Data has been retrieved by the apps */ 1939 entry->flag |= EMLX_EVENT_DONE; 1940 1941 dfc_event->size = size; 1942 } 1943 1944 dfc_event->last_id = entry->id; 1945 1946 mutex_exit(&log->lock); 1947 return (0); 1948 1949 } /* emlxs_get_dfc_event() */ 1950 1951 1952 uint32_t 1953 emlxs_kill_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event) 1954 { 1955 emlxs_hba_t *hba = HBA; 1956 emlxs_msg_log_t *log; 1957 1958 /* Get the log file pointer */ 1959 log = &LOG; 1960 1961 mutex_enter(&log->lock); 1962 dfc_event->pid = 0; 1963 dfc_event->event = 0; 1964 cv_broadcast(&log->lock_cv); 1965 mutex_exit(&log->lock); 1966 1967 return (0); 1968 1969 } /* emlxs_kill_dfc_event() */ 1970 1971 1972 #ifdef SAN_DIAG_SUPPORT 1973 uint32_t 1974 emlxs_get_sd_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event, 1975 uint32_t sleep) 1976 { 1977 emlxs_hba_t *hba = HBA; 1978 emlxs_msg_log_t *log; 1979 emlxs_msg_entry_t *entry; 1980 uint32_t size; 1981 uint32_t rc; 1982 uint32_t first; 1983 uint32_t last; 1984 uint32_t count; 1985 uint32_t index; 1986 uint32_t mask; 1987 uint32_t i; 1988 1989 size = 0; 1990 1991 if (dfc_event->dataout && dfc_event->size) { 1992 size = dfc_event->size; 1993 } 1994 dfc_event->size = 0; 1995 1996 /* Get the log file pointer */ 1997 log = &LOG; 1998 1999 /* Calculate the event index */ 2000 mask = dfc_event->event; 2001 for (i = 0; i < 32; i++) { 2002 if (mask & 0x01) 2003 break; 2004 2005 mask >>= 1; 2006 } 2007 if (i == 32) 2008 return (DFC_ARG_INVALID); 2009 2010 mutex_enter(&log->lock); 2011 2012 /* Check if log is empty */ 2013 if (log->count == 0) { 2014 /* Make sure everything is initialized */ 2015 log->event_id[i] = 0; 2016 dfc_event->last_id = 0; 2017 } else { 2018 /* Check ranges for safety */ 2019 if (log->event_id[i] > (log->count - 1)) 2020 log->event_id[i] = log->count - 1; 2021 2022 if (dfc_event->last_id > log->event_id[i]) 2023 dfc_event->last_id = log->event_id[i]; 2024 } 2025 2026 wait_for_sd_event: 2027 /* Check if no new event has ocurred */ 2028 if (dfc_event->last_id == log->event_id[i]) { 2029 if (!sleep) { 2030 mutex_exit(&log->lock); 2031 return (0); 2032 } 2033 2034 /* While event is active and no new event has been logged */ 2035 while ((dfc_event->event & port->sd_reg_events) && 2036 (dfc_event->last_id == log->event_id[i])) { 2037 rc = cv_wait_sig(&log->lock_cv, &log->lock); 2038 2039 /* Check if thread was killed by kernel */ 2040 if (rc == 0) { 2041 dfc_event->pid = 0; 2042 dfc_event->event = 0; 2043 mutex_exit(&log->lock); 2044 return (0); 2045 } 2046 } 2047 2048 /* If the event is no longer registered then return */ 2049 if (!(dfc_event->event & port->sd_reg_events)) { 2050 mutex_exit(&log->lock); 2051 return (0); 2052 } 2053 } 2054 2055 /* !!! An event has occurred since last_id !!! */ 2056 2057 /* Check if event data is not being requested */ 2058 if (!size) { 2059 /* If so, then just return the last event id */ 2060 dfc_event->last_id = log->event_id[i]; 2061 mutex_exit(&log->lock); 2062 return (0); 2063 } 2064 2065 /* !!! The requester wants the next event buffer !!! */ 2066 2067 /* Calculate the current buffer boundaries */ 2068 2069 /* Get last entry id saved */ 2070 last = log->count - 1; 2071 2072 /* Get oldest entry id and its index */ 2073 /* Check if buffer has already been filled once */ 2074 if (log->count >= log->size) { 2075 first = log->count - log->size; 2076 index = log->next; 2077 } else { /* Buffer not yet filled */ 2078 first = 0; 2079 index = 0; 2080 } 2081 2082 /* Check to see if the buffer has wrapped since the last event */ 2083 if (first > log->event_id[i]) { 2084 /* Update last_id to the last known event */ 2085 dfc_event->last_id = log->event_id[i]; 2086 2087 /* Try waiting again if we can */ 2088 goto wait_for_sd_event; 2089 } 2090 2091 /* if requested first event is greater than actual, adjust for it. */ 2092 if (dfc_event->last_id > first) { 2093 /* Adjust entry index to first requested message */ 2094 index += (dfc_event->last_id - first); 2095 if (index >= log->size) { 2096 index -= log->size; 2097 } 2098 2099 first = dfc_event->last_id; 2100 } 2101 2102 /* Get the total number of new messages */ 2103 count = last - first + 1; 2104 2105 /* Scan log for next event */ 2106 while (count--) { 2107 if (++index >= log->size) 2108 index = 0; 2109 2110 entry = &log->entry[index]; 2111 2112 if ((entry->msg->level == EMLXS_EVENT) && 2113 (entry->vpi == port->vpi) && 2114 (entry->msg->mask == dfc_event->event)) 2115 break; 2116 } 2117 2118 /* Check if no new event was found in the current log buffer */ 2119 /* This would indicate that the buffer wrapped since that last event */ 2120 if (!count) { 2121 /* Update last_id to the last known event */ 2122 dfc_event->last_id = log->event_id[i]; 2123 2124 /* Try waiting again if we can */ 2125 goto wait_for_sd_event; 2126 } 2127 2128 /* !!! Next event found !!! */ 2129 2130 /* Copy the context buffer to the buffer provided */ 2131 if (entry->bp && entry->size) { 2132 if (entry->size < size) 2133 size = entry->size; 2134 2135 if (ddi_copyout((void *) entry->bp, dfc_event->dataout, 2136 size, dfc_event->mode) != 0) { 2137 mutex_exit(&log->lock); 2138 2139 return (DFC_COPYOUT_ERROR); 2140 } 2141 2142 dfc_event->size = size; 2143 } 2144 2145 dfc_event->last_id = entry->id; 2146 mutex_exit(&log->lock); 2147 2148 return (0); 2149 } /* emlxs_get_sd_event */ 2150 #endif /* SAN_DIAG_SUPPORT */ 2151 2152 2153 #endif /* DFC_SUPPORT */ 2154