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 2008 Emulex. All rights reserved. 24 * Use is subject to License terms. 25 */ 26 27 28 #define DEF_MSG_STRUCT /* Needed for emlxs_messages.h in emlxs_msg.h */ 29 #include "emlxs.h" 30 31 32 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 33 EMLXS_MSG_DEF(EMLXS_MSG_C); 34 35 uint32_t emlxs_log_size = 1024; 36 /* uint32_t emlxs_log_debugs = 0x000FFFFF; */ 37 uint32_t emlxs_log_debugs = 0x7FFFFFFF; 38 uint32_t emlxs_log_notices = 0xFFFFFFFF; 39 uint32_t emlxs_log_warnings = 0xFFFFFFFF; 40 uint32_t emlxs_log_errors = 0xFFFFFFFF; 41 42 static uint32_t emlxs_msg_log_check(emlxs_port_t *port, emlxs_msg_t *msg); 43 static uint32_t emlxs_msg_print_check(emlxs_port_t *port, emlxs_msg_t *msg); 44 static void emlxs_msg_sprintf(char *buffer, emlxs_msg_entry_t *entry); 45 46 47 uint32_t 48 emlxs_msg_log_create(emlxs_hba_t *hba) 49 { 50 emlxs_msg_log_t *log = &LOG; 51 uint32_t size = sizeof (emlxs_msg_entry_t) * emlxs_log_size; 52 char buf[40]; 53 #ifdef MSI_SUPPORT 54 ddi_intr_handle_t handle; 55 uint32_t intr_pri; 56 int32_t actual; 57 uint32_t ret; 58 #endif /* MSI_SUPPORT */ 59 ddi_iblock_cookie_t iblock; 60 61 /* Check if log is already created */ 62 if (log->entry) { 63 cmn_err(CE_WARN, "?%s%d: message log already created. log=%p", 64 DRIVER_NAME, hba->ddiinst, (void *) log); 65 return (0); 66 } 67 /* Clear the log */ 68 bzero(log, sizeof (emlxs_msg_log_t)); 69 70 /* Allocate the memory needed for the log file */ 71 if (!(log->entry = (emlxs_msg_entry_t *)kmem_zalloc(size, KM_SLEEP))) { 72 cmn_err(CE_WARN, "?%s%d: Unable to allocate log memory. log=%p", 73 DRIVER_NAME, hba->ddiinst, (void *) log); 74 return (0); 75 } 76 /* Initialize */ 77 log->size = emlxs_log_size; 78 log->instance = hba->ddiinst; 79 log->start_time = emlxs_device.log_timestamp; 80 81 (void) sprintf(buf, "?%s%d_log_lock control variable", DRIVER_NAME, 82 hba->ddiinst); 83 cv_init(&log->lock_cv, buf, CV_DRIVER, NULL); 84 85 (void) sprintf(buf, "?%s%d_log_lock mutex", DRIVER_NAME, hba->ddiinst); 86 87 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 88 /* Get the current interrupt block cookie */ 89 (void) ddi_get_iblock_cookie(hba->dip, (uint_t)EMLXS_INUMBER, 90 &iblock); 91 92 /* Create the log mutex lock */ 93 mutex_init(&log->lock, buf, MUTEX_DRIVER, (void *) iblock); 94 } 95 #ifdef MSI_SUPPORT 96 else { 97 98 /* Allocate a temporary interrupt handle */ 99 actual = 0; 100 ret = ddi_intr_alloc(hba->dip, &handle, DDI_INTR_TYPE_FIXED, 101 EMLXS_MSI_INUMBER, 1, &actual, DDI_INTR_ALLOC_NORMAL); 102 103 if (ret != DDI_SUCCESS || actual == 0) { 104 cmn_err(CE_WARN, "?%s%d: Unable to allocate " 105 "temporary interrupt handle. ret=%d actual=%d", 106 DRIVER_NAME, hba->ddiinst, ret, actual); 107 108 /* Free the log buffer */ 109 kmem_free(log->entry, size); 110 bzero(log, sizeof (emlxs_msg_log_t)); 111 112 return (0); 113 } 114 /* Get the current interrupt priority */ 115 ret = ddi_intr_get_pri(handle, &intr_pri); 116 117 if (ret != DDI_SUCCESS) { 118 cmn_err(CE_WARN, "?%s%d: Unable to get interrupt " 119 "priority. ret=%d", DRIVER_NAME, hba->ddiinst, ret); 120 121 /* Free the log buffer */ 122 kmem_free(log->entry, size); 123 bzero(log, sizeof (emlxs_msg_log_t)); 124 125 return (0); 126 } 127 /* Create the log mutex lock */ 128 mutex_init(&log->lock, buf, MUTEX_DRIVER, 129 (void *)(unsigned long) intr_pri); 130 131 /* Free the temporary handle */ 132 (void) ddi_intr_free(handle); 133 } 134 #endif 135 136 return (1); 137 138 } /* emlxs_msg_log_create() */ 139 140 141 uint32_t 142 emlxs_msg_log_destroy(emlxs_hba_t *hba) 143 { 144 emlxs_msg_log_t *log = &LOG; 145 uint32_t size; 146 emlxs_msg_entry_t *entry; 147 uint32_t i; 148 149 /* Check if log is already destroyed */ 150 if (!log->entry) { 151 cmn_err(CE_WARN, "?%s%d: message log already destroyed. log=%p", 152 DRIVER_NAME, hba->ddiinst, (void *) log); 153 154 return (1); 155 } 156 /* 157 * If events are being logged there might be threads waiting so 158 * release them 159 */ 160 if (hba->log_events) { 161 mutex_enter(&log->lock); 162 hba->log_events = 0; 163 cv_broadcast(&log->lock_cv); 164 mutex_exit(&log->lock); 165 166 DELAYMS(1); 167 } 168 /* Destroy the lock */ 169 mutex_destroy(&log->lock); 170 cv_destroy(&log->lock_cv); 171 172 /* Free the context buffers */ 173 for (i = 0; i < log->size; i++) { 174 entry = &log->entry[i]; 175 176 if (entry->bp && entry->size) { 177 kmem_free(entry->bp, entry->size); 178 } 179 } 180 181 /* Free the log buffer */ 182 size = sizeof (emlxs_msg_entry_t) * log->size; 183 kmem_free(log->entry, size); 184 185 /* Clear the log */ 186 bzero(log, sizeof (emlxs_msg_log_t)); 187 188 return (1); 189 190 } /* emlxs_msg_log_destroy() */ 191 192 193 194 uint32_t 195 emlxs_msg_log(emlxs_port_t *port, const uint32_t fileno, const uint32_t line, 196 void *bp, uint32_t size, emlxs_msg_t *msg, char *buffer) 197 { 198 emlxs_hba_t *hba = HBA; 199 emlxs_msg_entry_t *entry; 200 emlxs_msg_entry_t *entry2; 201 clock_t time; 202 emlxs_msg_log_t *log; 203 uint32_t last; 204 uint32_t mask; 205 emlxs_msg_t *msg2; 206 uint32_t i; 207 208 /* Get the log file for this instance */ 209 log = &LOG; 210 211 /* Check if log is initialized */ 212 if (log->entry == NULL) { 213 214 if (port->vpi == 0) { 215 cmn_err(CE_WARN, "?%s%d: message log not created. " 216 "log=%p", DRIVER_NAME, hba->ddiinst, (void *) log); 217 } else { 218 cmn_err(CE_WARN, "?%s%d.%d: message log not created. " 219 "log=%p", DRIVER_NAME, hba->ddiinst, port->vpi, 220 (void *) log); 221 } 222 223 if (bp && size) { 224 kmem_free(bp, size); 225 } 226 return (1); 227 } 228 mutex_enter(&log->lock); 229 230 /* Get the pointer to the last log entry */ 231 if (log->next == 0) { 232 last = log->size - 1; 233 } else { 234 last = log->next - 1; 235 } 236 entry = &log->entry[last]; 237 238 /* Check if this matches the last message */ 239 if ((entry->instance == log->instance) && 240 (entry->vpi == port->vpi) && 241 (entry->fileno == fileno) && 242 (entry->line == line) && 243 (entry->bp == bp) && 244 (entry->size == size) && 245 (entry->msg == msg) && 246 (strcmp(entry->buffer, buffer) == 0)) { 247 /* If the same message is being logged then increment */ 248 log->repeat++; 249 250 mutex_exit(&log->lock); 251 252 return (0); 253 } else if (log->repeat) { 254 /* Get the pointer to the next log entry */ 255 entry2 = &log->entry[log->next]; 256 257 /* Increment and check the next entry index */ 258 if (++(log->next) >= log->size) { 259 log->next = 0; 260 } 261 switch (entry->msg->level) { 262 case EMLXS_DEBUG: 263 msg2 = &emlxs_debug_msg; 264 break; 265 266 case EMLXS_NOTICE: 267 msg2 = &emlxs_notice_msg; 268 break; 269 270 case EMLXS_WARNING: 271 msg2 = &emlxs_warning_msg; 272 break; 273 274 case EMLXS_ERROR: 275 msg2 = &emlxs_error_msg; 276 break; 277 278 case EMLXS_PANIC: 279 msg2 = &emlxs_panic_msg; 280 break; 281 282 case EMLXS_EVENT: 283 msg2 = &emlxs_event_msg; 284 break; 285 } 286 287 /* Check if we are about to overwrite an event entry */ 288 if (entry2->msg && (entry2->msg->level == EMLXS_EVENT)) { 289 /* Check if this event has not been acquired */ 290 if (log->count > (hba->hba_event.last_id + log->size)) { 291 hba->hba_event.missed++; 292 } 293 } 294 /* Free the old context buffer since we are about to erase it */ 295 if (entry2->bp && entry2->size) { 296 kmem_free(entry2->bp, entry2->size); 297 } 298 /* Initialize */ 299 entry2->id = log->count++; 300 entry2->fileno = entry->fileno; 301 entry2->line = entry->line; 302 entry2->bp = 0; 303 entry2->size = 0; 304 entry2->msg = msg2; 305 entry2->instance = log->instance; 306 entry2->vpi = port->vpi; 307 308 /* Save the additional info buffer */ 309 (void) sprintf(entry2->buffer, 310 "Last message repeated %d time(s).", 311 log->repeat); 312 313 /* Set the entry time stamp */ 314 (void) drv_getparm(LBOLT, &time); 315 entry2->time = time - log->start_time; 316 317 log->repeat = 0; 318 } 319 /* Get the pointer to the next log entry */ 320 entry = &log->entry[log->next]; 321 322 /* Increment and check the next entry index */ 323 if (++(log->next) >= log->size) { 324 log->next = 0; 325 } 326 /* Check if we are about to overwrite an event entry */ 327 if (entry->msg && (entry->msg->level == EMLXS_EVENT)) { 328 /* Check if this event has not been acquired */ 329 if (log->count > (hba->hba_event.last_id + log->size)) { 330 hba->hba_event.missed++; 331 } 332 } 333 /* Free the old context buffer since we are about to erase it */ 334 if (entry->bp && entry->size) { 335 kmem_free(entry->bp, entry->size); 336 } 337 /* Initialize */ 338 entry->id = log->count++; 339 entry->fileno = fileno; 340 entry->line = line; 341 entry->bp = bp; 342 entry->size = size; 343 entry->msg = msg; 344 entry->instance = log->instance; 345 entry->vpi = port->vpi; 346 347 /* Save the additional info buffer */ 348 (void) strncpy(entry->buffer, buffer, (MAX_LOG_INFO_LENGTH - 1)); 349 entry->buffer[MAX_LOG_INFO_LENGTH - 1] = 0; 350 351 /* Set the entry time stamp */ 352 (void) drv_getparm(LBOLT, &time); 353 entry->time = time - log->start_time; 354 355 /* Check for a new event */ 356 if (msg->level == EMLXS_EVENT) { 357 /* Update the event id */ 358 mask = msg->mask; 359 for (i = 0; i < 32; i++) { 360 if (mask & 0x01) { 361 hba->hba_event.new++; 362 log->event_id[i] = entry->id; 363 cv_broadcast(&log->lock_cv); 364 break; 365 } 366 mask >>= 1; 367 } 368 } 369 mutex_exit(&log->lock); 370 371 return (0); 372 373 } /* emlxs_msg_log() */ 374 375 376 static uint32_t 377 emlxs_msg_log_check(emlxs_port_t *port, emlxs_msg_t *msg) 378 { 379 emlxs_hba_t *hba = HBA; 380 381 switch (msg->level) { 382 case EMLXS_DEBUG: 383 if (msg->mask & emlxs_log_debugs) { 384 return (1); 385 } 386 break; 387 388 case EMLXS_NOTICE: 389 if (msg->mask & emlxs_log_notices) { 390 return (1); 391 } 392 break; 393 394 case EMLXS_WARNING: 395 if (msg->mask & emlxs_log_warnings) { 396 return (1); 397 } 398 break; 399 400 case EMLXS_ERROR: 401 if (msg->mask & emlxs_log_errors) { 402 return (1); 403 } 404 break; 405 406 case EMLXS_EVENT: 407 if (msg->mask & hba->log_events) { 408 return (1); 409 } 410 break; 411 412 case EMLXS_PANIC: 413 return (1); 414 } 415 416 return (0); 417 418 } /* emlxs_msg_log_check() */ 419 420 421 static uint32_t 422 emlxs_msg_print_check(emlxs_port_t *port, emlxs_msg_t *msg) 423 { 424 emlxs_hba_t *hba = HBA; 425 emlxs_config_t *cfg; 426 uint32_t rval = 0; 427 428 cfg = &CFG; 429 430 switch (msg->level) { 431 case EMLXS_DEBUG: 432 if (msg->mask & cfg[CFG_CONSOLE_DEBUGS].current) { 433 rval |= 2; 434 } 435 if (msg->mask & cfg[CFG_LOG_DEBUGS].current) { 436 rval |= 1; 437 } 438 break; 439 440 case EMLXS_NOTICE: 441 if (msg->mask & cfg[CFG_CONSOLE_NOTICES].current) { 442 rval |= 2; 443 } 444 if (msg->mask & cfg[CFG_LOG_NOTICES].current) { 445 rval |= 1; 446 } 447 break; 448 449 case EMLXS_WARNING: 450 if (msg->mask & cfg[CFG_CONSOLE_WARNINGS].current) { 451 rval |= 2; 452 } 453 if (msg->mask & cfg[CFG_LOG_WARNINGS].current) { 454 rval |= 1; 455 } 456 break; 457 458 case EMLXS_ERROR: 459 if (msg->mask & cfg[CFG_CONSOLE_ERRORS].current) { 460 rval |= 2; 461 } 462 if (msg->mask & cfg[CFG_LOG_ERRORS].current) { 463 rval |= 1; 464 } 465 break; 466 467 case EMLXS_EVENT: 468 /* Only print an event if it is being logged internally */ 469 if (msg->mask & hba->log_events) { 470 if (msg->mask & cfg[CFG_CONSOLE_EVENTS].current) { 471 rval |= 2; 472 } 473 if (msg->mask & cfg[CFG_LOG_EVENTS].current) { 474 rval |= 1; 475 } 476 } 477 break; 478 479 case EMLXS_PANIC: 480 default: 481 rval |= 1; 482 483 } 484 485 return (rval); 486 487 } /* emlxs_msg_print_check() */ 488 489 490 void 491 emlxs_msg_printf(emlxs_port_t *port, const uint32_t fileno, const uint32_t line, 492 void *bp, uint32_t size, emlxs_msg_t *msg, const char *fmt, ...) 493 { 494 emlxs_hba_t *hba = HBA; 495 va_list valist; 496 char va_str[256]; 497 char msg_str[512]; 498 char *level; 499 int32_t cmn_level; 500 uint32_t rval; 501 uint32_t logged; 502 char driver[32]; 503 504 va_str[0] = 0; 505 506 if (fmt) { 507 va_start(valist, fmt); 508 (void) vsprintf(va_str, fmt, valist); 509 va_end(valist); 510 } 511 /* Check if msg should be logged */ 512 if ((logged = emlxs_msg_log_check(port, msg))) { 513 /* Log the message */ 514 if (emlxs_msg_log(port, fileno, line, bp, size, msg, va_str)) { 515 return; 516 } 517 } 518 /* Check if msg should be printed */ 519 if (rval = emlxs_msg_print_check(port, msg)) { 520 cmn_level = CE_CONT; 521 522 switch (msg->level) { 523 case EMLXS_DEBUG: 524 level = " DEBUG"; 525 break; 526 527 case EMLXS_NOTICE: 528 level = " NOTICE"; 529 break; 530 531 case EMLXS_WARNING: 532 level = "WARNING"; 533 break; 534 535 case EMLXS_ERROR: 536 level = " ERROR"; 537 break; 538 539 case EMLXS_PANIC: 540 cmn_level = CE_PANIC; 541 level = " PANIC"; 542 break; 543 544 case EMLXS_EVENT: 545 level = " EVENT"; 546 break; 547 548 default: 549 level = "UNKNOWN"; 550 break; 551 } 552 553 if (port->vpi == 0) { 554 (void) sprintf(driver, "%s%d", DRIVER_NAME, 555 hba->ddiinst); 556 } else { 557 (void) sprintf(driver, "%s%d.%d", DRIVER_NAME, 558 hba->ddiinst, port->vpi); 559 } 560 561 /* Generate the message string */ 562 if (msg->buffer[0] != 0) { 563 if (va_str[0] != 0) { 564 (void) sprintf(msg_str, 565 "[%2X.%04X]%s:%7s:%4d: %s (%s)\n", 566 fileno, line, driver, level, msg->id, 567 msg->buffer, va_str); 568 } else { 569 (void) sprintf(msg_str, 570 "[%2X.%04X]%s:%7s:%4d: %s\n", 571 fileno, line, driver, level, msg->id, 572 msg->buffer); 573 } 574 } else { 575 if (va_str[0] != 0) { 576 (void) sprintf(msg_str, 577 "[%2X.%04X]%s:%7s:%4d: (%s)\n", 578 fileno, line, driver, level, msg->id, 579 va_str); 580 } else { 581 (void) sprintf(msg_str, 582 "[%2X.%04X]%s:%7s:%4d\n", 583 fileno, line, driver, level, msg->id); 584 } 585 } 586 587 switch (rval) { 588 case 1: /* MESSAGE LOG ONLY */ 589 /* cmn_err(cmn_level, "!%s", msg_str); */ 590 /* 591 * Message log & console, if system booted in verbose 592 * mode (CE_CONT only) 593 */ 594 cmn_err(cmn_level, "?%s", msg_str); 595 break; 596 597 case 2: /* CONSOLE ONLY */ 598 cmn_err(cmn_level, "^%s", msg_str); 599 break; 600 601 case 3: /* CONSOLE AND MESSAGE LOG */ 602 cmn_err(cmn_level, "%s", msg_str); 603 break; 604 605 } 606 607 } 608 /* If message was not logged, then free any context buffer provided */ 609 if (!logged && bp && size) { 610 kmem_free(bp, size); 611 } 612 return; 613 614 } /* emlxs_msg_printf() */ 615 616 617 uint32_t 618 emlxs_msg_log_get(emlxs_hba_t *hba, emlxs_log_req_t *req, 619 emlxs_log_resp_t *resp) 620 { 621 emlxs_msg_log_t *log; 622 uint32_t first; 623 uint32_t last; 624 uint32_t count; 625 uint32_t index; 626 uint32_t i; 627 char *resp_buf; 628 629 log = &LOG; 630 631 mutex_enter(&log->lock); 632 633 /* Check if buffer is empty */ 634 if (log->count == 0) { 635 /* If so, exit now */ 636 resp->first = 0; 637 resp->last = 0; 638 resp->count = 0; 639 mutex_exit(&log->lock); 640 641 return (1); 642 } 643 /* Get current log entry ranges */ 644 645 /* Get last entry id saved */ 646 last = log->count - 1; 647 648 /* Check if request is out of current range */ 649 if (req->first > last) { 650 /* if so, exit now */ 651 resp->first = last; 652 resp->last = last; 653 resp->count = 0; 654 mutex_exit(&log->lock); 655 656 return (0); 657 } 658 /* Get oldest entry id and its index */ 659 660 /* Check if buffer has already been filled once */ 661 if (log->count >= log->size) { 662 first = log->count - log->size; 663 index = log->next; 664 } else { /* Buffer not yet filled */ 665 first = 0; 666 index = 0; 667 } 668 669 /* 670 * Check if requested first message is greater than actual. If so, 671 * adjust for it. 672 */ 673 if (req->first > first) { 674 /* Adjust entry index to first requested message */ 675 index += (req->first - first); 676 if (index >= log->size) { 677 index -= log->size; 678 } 679 first = req->first; 680 } 681 /* Get the total number of messages available for return */ 682 count = last - first + 1; 683 684 /* Check if requested count is less than actual. If so, adjust it. */ 685 if (req->count < count) { 686 count = req->count; 687 } 688 /* Fill in the response header */ 689 resp->count = count; 690 resp->first = first; 691 resp->last = last; 692 693 /* Fill the response buffer */ 694 resp_buf = (char *)resp + sizeof (emlxs_log_resp_t); 695 for (i = 0; i < count; i++) { 696 emlxs_msg_sprintf(resp_buf, &log->entry[index]); 697 698 /* Increment the response buffer */ 699 resp_buf += MAX_LOG_MSG_LENGTH; 700 701 /* Increment index */ 702 if (++index >= log->size) { 703 index = 0; 704 } 705 } 706 707 mutex_exit(&log->lock); 708 709 return (1); 710 711 } /* emlxs_msg_log_get() */ 712 713 714 715 static void 716 emlxs_msg_sprintf(char *buffer, emlxs_msg_entry_t *entry) 717 { 718 char *level; 719 emlxs_msg_t *msg; 720 uint32_t secs; 721 uint32_t hsecs; 722 char buf[256]; 723 uint32_t buflen; 724 char driver[32]; 725 726 msg = entry->msg; 727 hsecs = (entry->time % 100); 728 secs = entry->time / 100; 729 730 switch (msg->level) { 731 case EMLXS_DEBUG: 732 level = " DEBUG"; 733 break; 734 735 case EMLXS_NOTICE: 736 level = " NOTICE"; 737 break; 738 739 case EMLXS_WARNING: 740 level = "WARNING"; 741 break; 742 743 case EMLXS_ERROR: 744 level = " ERROR"; 745 break; 746 747 case EMLXS_PANIC: 748 level = " PANIC"; 749 break; 750 751 case EMLXS_EVENT: 752 level = " EVENT"; 753 break; 754 755 default: 756 level = "UNKNOWN"; 757 break; 758 } 759 760 if (entry->vpi == 0) { 761 (void) sprintf(driver, "%s%d", DRIVER_NAME, entry->instance); 762 } else { 763 (void) sprintf(driver, "%s%d.%d", DRIVER_NAME, entry->instance, 764 entry->vpi); 765 } 766 767 /* Generate the message string */ 768 if (msg->buffer[0] != 0) { 769 if (entry->buffer[0] != 0) { 770 (void) sprintf(buf, 771 "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: %s (%s)\n", 772 secs, hsecs, entry->id, entry->fileno, entry->line, 773 driver, level, msg->id, msg->buffer, entry->buffer); 774 775 } else { 776 (void) sprintf(buf, 777 "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: %s\n", 778 secs, hsecs, entry->id, entry->fileno, entry->line, 779 driver, level, msg->id, msg->buffer); 780 } 781 } else { 782 if (entry->buffer[0] != 0) { 783 (void) sprintf(buf, 784 "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: (%s)\n", 785 secs, hsecs, entry->id, entry->fileno, entry->line, 786 driver, level, msg->id, entry->buffer); 787 } else { 788 (void) sprintf(buf, 789 "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d\n", 790 secs, hsecs, entry->id, entry->fileno, entry->line, 791 driver, level, msg->id); 792 } 793 } 794 795 bzero(buffer, MAX_LOG_MSG_LENGTH); 796 buflen = strlen(buf); 797 798 if (buflen > (MAX_LOG_MSG_LENGTH - 1)) { 799 (void) strncpy(buffer, buf, (MAX_LOG_MSG_LENGTH - 2)); 800 buffer[MAX_LOG_MSG_LENGTH - 2] = '\n'; 801 } else { 802 (void) strncpy(buffer, buf, buflen); 803 } 804 805 return; 806 807 } /* emlxs_msg_sprintf() */ 808 809 810 811 812 void 813 emlxs_log_rscn_event(emlxs_port_t *port, uint8_t *payload, uint32_t size) 814 { 815 #ifdef DFC_SUPPORT 816 uint8_t *bp; 817 uint32_t *ptr; 818 819 /* Check if the event is being requested */ 820 /* 821 * if(!(hba->log_events & EVT_RSCN)) { return; } 822 */ 823 824 if (size > MAX_RSCN_PAYLOAD) { 825 size = MAX_RSCN_PAYLOAD; 826 } 827 size += sizeof (uint32_t); 828 829 /* Save a copy of the payload for the event log */ 830 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 831 return; 832 } 833 /* 834 * Buffer Format: word[0] = DID of the RSCN word[1] = RSCN Payload 835 */ 836 ptr = (uint32_t *)bp; 837 *ptr++ = port->did; 838 bcopy(payload, (char *)ptr, (size - sizeof (uint32_t))); 839 840 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_rscn_event, 841 "bp=%p size=%d", bp, size); 842 843 #endif /* DFC_SUPPORT */ 844 return; 845 846 } /* emlxs_log_rscn_event() */ 847 848 849 void 850 emlxs_log_ct_event(emlxs_port_t *port, uint8_t *payload, uint32_t size, 851 uint32_t rxid) 852 { 853 #ifdef DFC_SUPPORT 854 emlxs_hba_t *hba = HBA; 855 uint8_t *bp; 856 uint32_t *ptr; 857 858 /* Check if the event is being requested */ 859 if (!(hba->log_events & EVT_CT)) { 860 return; 861 } 862 if (size > MAX_CT_PAYLOAD) { 863 size = MAX_CT_PAYLOAD; 864 } 865 size += sizeof (uint32_t); 866 867 /* Save a copy of the payload for the event log */ 868 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 869 return; 870 } 871 /* 872 * Buffer Format: word[0] = RXID tag for outgoing reply to this CT 873 * request word[1] = CT Payload 874 */ 875 ptr = (uint32_t *)bp; 876 *ptr++ = rxid; 877 878 bcopy(payload, (char *)ptr, (size - sizeof (uint32_t))); 879 880 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_ct_event, 881 "bp=%p size=%d rxid=%x", bp, size, rxid); 882 883 #endif /* DFC_SUPPORT */ 884 885 return; 886 887 } /* emlxs_log_ct_event() */ 888 889 890 void 891 emlxs_log_link_event(emlxs_port_t *port) 892 { 893 #ifdef DFC_SUPPORT 894 emlxs_hba_t *hba = HBA; 895 uint8_t *bp; 896 dfc_linkinfo_t *linkinfo; 897 uint8_t *byte; 898 uint8_t *linkspeed; 899 uint8_t *liptype; 900 uint8_t *resv1; 901 uint8_t *resv2; 902 uint32_t size; 903 904 /* Check if the event is being requested */ 905 /* 906 * if(!(hba->log_events & EVT_LINK)) { return; } 907 */ 908 size = sizeof (dfc_linkinfo_t) + sizeof (uint32_t); 909 910 /* Save a copy of the buffer for the event log */ 911 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 912 return; 913 } 914 /* 915 * Buffer Format: word[0] = Linkspeed:8 word[0] = LIP_type:8 word[0] 916 * = resv1:8 word[0] = resv2:8 word[1] = dfc_linkinfo_t data 917 */ 918 byte = (uint8_t *)bp; 919 linkspeed = &byte[0]; 920 liptype = &byte[1]; 921 resv1 = &byte[2]; 922 resv2 = &byte[3]; 923 linkinfo = (dfc_linkinfo_t *)& byte[4]; 924 925 *resv1 = 0; 926 *resv2 = 0; 927 928 if (hba->state <= FC_LINK_DOWN) { 929 *linkspeed = 0; 930 *liptype = 0; 931 } else { 932 /* Set linkspeed */ 933 if (hba->linkspeed == LA_2GHZ_LINK) { 934 *linkspeed = HBA_PORTSPEED_2GBIT; 935 } else if (hba->linkspeed == LA_4GHZ_LINK) { 936 *linkspeed = HBA_PORTSPEED_4GBIT; 937 } else if (hba->linkspeed == LA_8GHZ_LINK) { 938 *linkspeed = HBA_PORTSPEED_8GBIT; 939 } else if (hba->linkspeed == LA_10GHZ_LINK) { 940 *linkspeed = HBA_PORTSPEED_10GBIT; 941 } else { 942 *linkspeed = HBA_PORTSPEED_1GBIT; 943 } 944 945 /* Set LIP type */ 946 *liptype = port->lip_type; 947 } 948 949 bzero(linkinfo, sizeof (dfc_linkinfo_t)); 950 951 linkinfo->a_linkEventTag = hba->link_event_tag; 952 linkinfo->a_linkUp = HBASTATS.LinkUp; 953 linkinfo->a_linkDown = HBASTATS.LinkDown; 954 linkinfo->a_linkMulti = HBASTATS.LinkMultiEvent; 955 956 if (hba->state <= FC_LINK_DOWN) { 957 linkinfo->a_linkState = LNK_DOWN; 958 linkinfo->a_DID = port->prev_did; 959 } else if (hba->state < FC_READY) { 960 linkinfo->a_linkState = LNK_DISCOVERY; 961 } else { 962 linkinfo->a_linkState = LNK_READY; 963 } 964 965 if (linkinfo->a_linkState != LNK_DOWN) { 966 if (hba->topology == TOPOLOGY_LOOP) { 967 if (hba->flag & FC_FABRIC_ATTACHED) { 968 linkinfo->a_topology = LNK_PUBLIC_LOOP; 969 } else { 970 linkinfo->a_topology = LNK_LOOP; 971 } 972 973 linkinfo->a_alpa = port->did & 0xff; 974 linkinfo->a_DID = linkinfo->a_alpa; 975 linkinfo->a_alpaCnt = port->alpa_map[0]; 976 977 if (linkinfo->a_alpaCnt > 127) { 978 linkinfo->a_alpaCnt = 127; 979 } 980 bcopy((void *) &port->alpa_map[1], linkinfo->a_alpaMap, 981 linkinfo->a_alpaCnt); 982 } else { 983 if (port->node_count == 1) { 984 linkinfo->a_topology = LNK_PT2PT; 985 } else { 986 linkinfo->a_topology = LNK_FABRIC; 987 } 988 989 linkinfo->a_DID = port->did; 990 } 991 } 992 bcopy(&hba->wwpn, linkinfo->a_wwpName, 8); 993 bcopy(&hba->wwnn, linkinfo->a_wwnName, 8); 994 995 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_link_event, 996 "bp=%p size=%d tag=%x", bp, size, hba->link_event_tag); 997 998 #endif /* DFC_SUPPORT */ 999 1000 return; 1001 1002 } /* emlxs_log_link_event() */ 1003 1004 1005 void 1006 emlxs_log_dump_event(emlxs_port_t *port, uint8_t *buffer, uint32_t size) 1007 { 1008 #ifdef DFC_SUPPORT 1009 emlxs_hba_t *hba = HBA; 1010 uint8_t *bp; 1011 1012 /* Check if the event is being requested */ 1013 if (!(hba->log_events & EVT_DUMP)) { 1014 return; 1015 } 1016 if (buffer && size) { 1017 /* Save a copy of the buffer for the event log */ 1018 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 1019 return; 1020 } 1021 bcopy(buffer, bp, size); 1022 } else { 1023 bp = NULL; 1024 size = 0; 1025 } 1026 1027 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_dump_event, 1028 "bp=%p size=%d", bp, size); 1029 1030 #endif /* DFC_SUPPORT */ 1031 1032 return; 1033 1034 } /* emlxs_log_dump_event() */ 1035 1036 1037 extern void 1038 emlxs_log_temp_event(emlxs_port_t *port, uint32_t type, uint32_t temp) 1039 { 1040 #ifdef DFC_SUPPORT 1041 emlxs_hba_t *hba = HBA; 1042 uint32_t *bp; 1043 uint32_t size; 1044 1045 /* Check if the event is being requested */ 1046 if (!(hba->log_events & EVT_TEMP)) { 1047 return; 1048 } 1049 size = 2 * sizeof (uint32_t); 1050 1051 if (!(bp = (uint32_t *)kmem_alloc(size, KM_NOSLEEP))) { 1052 return; 1053 } 1054 bp[0] = type; 1055 bp[1] = temp; 1056 1057 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_temp_event, 1058 "type=%x temp=%d bp=%p size=%d", type, temp, bp, size); 1059 1060 #endif /* DFC_SUPPORT */ 1061 1062 return; 1063 1064 } /* emlxs_log_temp_event() */ 1065 1066 1067 1068 extern void 1069 emlxs_log_fcoe_event(emlxs_port_t *port, menlo_init_rsp_t *init_rsp) 1070 { 1071 #ifdef DFC_SUPPORT 1072 emlxs_hba_t *hba = HBA; 1073 uint8_t *bp; 1074 uint32_t size; 1075 1076 /* Check if the event is being requested */ 1077 if (!(hba->log_events & EVT_FCOE)) { 1078 return; 1079 } 1080 /* Check if this is a FCOE adapter */ 1081 if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) { 1082 return; 1083 } 1084 size = sizeof (menlo_init_rsp_t); 1085 1086 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 1087 return; 1088 } 1089 bcopy((uint8_t *)init_rsp, bp, size); 1090 1091 EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_fcoe_event, 1092 "bp=%p size=%d", bp, size); 1093 1094 #endif /* DFC_SUPPORT */ 1095 1096 return; 1097 1098 } /* emlxs_log_fcoe_event() */ 1099 1100 1101 1102 #ifdef DFC_SUPPORT 1103 1104 extern uint32_t 1105 emlxs_get_dfc_eventinfo(emlxs_port_t *port, HBA_EVENTINFO *eventinfo, 1106 uint32_t *eventcount, uint32_t *missed) 1107 { 1108 emlxs_hba_t *hba = HBA; 1109 emlxs_msg_log_t *log; 1110 uint32_t first; 1111 uint32_t last; 1112 uint32_t count; 1113 uint32_t index; 1114 emlxs_msg_entry_t *entry; 1115 dfc_linkinfo_t *linkinfo; 1116 uint32_t *word; 1117 uint8_t *byte; 1118 uint8_t linkspeed; 1119 uint8_t liptype; 1120 fc_affected_id_t *aid; 1121 uint32_t max_events; 1122 uint32_t events; 1123 emlxs_hba_event_t *hba_event; 1124 1125 if (!eventinfo || !eventcount || !missed) { 1126 return (DFC_ARG_NULL); 1127 } 1128 hba_event = &hba->hba_event; 1129 max_events = *eventcount; 1130 *eventcount = 0; 1131 1132 log = &LOG; 1133 1134 mutex_enter(&log->lock); 1135 1136 /* Check if log is empty */ 1137 if (log->count == 0) { 1138 /* Make sure everything is initialized */ 1139 hba_event->new = 0; 1140 hba_event->missed = 0; 1141 hba_event->last_id = 0; 1142 1143 mutex_exit(&log->lock); 1144 return (0); 1145 } 1146 /* Safety check */ 1147 if (hba_event->last_id > (log->count - 1)) { 1148 hba_event->last_id = log->count - 1; 1149 } 1150 /* Account for missed events */ 1151 if (hba_event->new > hba_event->missed) { 1152 hba_event->new -= hba_event->missed; 1153 } else { 1154 hba_event->new = 0; 1155 } 1156 1157 *missed = hba_event->missed; 1158 hba_event->missed = 0; 1159 1160 if (!hba_event->new) { 1161 hba_event->last_id = log->count; 1162 mutex_exit(&log->lock); 1163 return (0); 1164 } 1165 /* A new event has occurred since last acquisition */ 1166 /* Calculate the current buffer boundaries */ 1167 1168 /* Get last entry id saved */ 1169 last = log->count - 1; 1170 1171 /* Get oldest entry id and its index */ 1172 /* Check if buffer has already been filled once */ 1173 if (log->count >= log->size) { 1174 first = log->count - log->size; 1175 index = log->next; 1176 } else { /* Buffer not yet filled */ 1177 first = 0; 1178 index = 0; 1179 } 1180 1181 /* 1182 * Check if requested first event is greater than actual. If so, 1183 * adjust for it. 1184 */ 1185 if (hba_event->last_id > first) { 1186 /* Adjust entry index to first requested message */ 1187 index += (hba_event->last_id - first); 1188 if (index >= log->size) { 1189 index -= log->size; 1190 } 1191 first = hba_event->last_id; 1192 } 1193 /* Get the total number of new messages */ 1194 count = last - first; 1195 1196 /* Scan log for next event */ 1197 events = 0; 1198 while (count-- && (events < max_events)) { 1199 if (++index >= log->size) { 1200 index = 0; 1201 } 1202 entry = &log->entry[index]; 1203 1204 if (!entry->msg) { 1205 break; 1206 } 1207 if ((entry->msg->level == EMLXS_EVENT) && 1208 (entry->msg->mask & (EVT_LINK | EVT_RSCN))) { 1209 /* Process this event */ 1210 switch (entry->msg->mask) { 1211 case EVT_LINK: 1212 byte = (uint8_t *)entry->bp; 1213 linkspeed = byte[0]; 1214 liptype = byte[1]; 1215 linkinfo = (dfc_linkinfo_t *)& byte[4]; 1216 1217 if (linkinfo->a_linkState == LNK_DOWN) { 1218 eventinfo->EventCode = 1219 HBA_EVENT_LINK_DOWN; 1220 eventinfo->Event.Link_EventInfo. 1221 PortFcId = linkinfo->a_DID; 1222 eventinfo->Event.Link_EventInfo. 1223 Reserved[0] = 0; 1224 eventinfo->Event.Link_EventInfo. 1225 Reserved[1] = 0; 1226 eventinfo->Event.Link_EventInfo. 1227 Reserved[2] = 0; 1228 } else { 1229 eventinfo->EventCode = 1230 HBA_EVENT_LINK_UP; 1231 eventinfo->Event.Link_EventInfo. 1232 PortFcId = linkinfo->a_DID; 1233 1234 if ((linkinfo->a_topology == 1235 LNK_PUBLIC_LOOP) || 1236 (linkinfo->a_topology == 1237 LNK_LOOP)) { 1238 eventinfo->Event.Link_EventInfo. 1239 Reserved[0] = 2; 1240 } else { 1241 eventinfo->Event.Link_EventInfo. 1242 Reserved[0] = 1; 1243 } 1244 1245 eventinfo->Event.Link_EventInfo. 1246 Reserved[1] = liptype; 1247 eventinfo->Event.Link_EventInfo. 1248 Reserved[2] = linkspeed; 1249 } 1250 1251 break; 1252 1253 case EVT_RSCN: 1254 word = (uint32_t *)entry->bp; 1255 eventinfo->EventCode = HBA_EVENT_RSCN; 1256 eventinfo->Event.RSCN_EventInfo.PortFcId = 1257 word[0] & 0xFFFFFF; 1258 /* word[1] is the RSCN payload command */ 1259 1260 aid = (fc_affected_id_t *)& word[2]; 1261 1262 switch (aid->aff_format) { 1263 case 0: /* Port */ 1264 eventinfo->Event.RSCN_EventInfo. 1265 NPortPage = 1266 aid->aff_d_id & 0x00ffffff; 1267 break; 1268 1269 case 1: /* Area */ 1270 eventinfo->Event.RSCN_EventInfo. 1271 NPortPage = 1272 aid->aff_d_id & 0x00ffff00; 1273 break; 1274 1275 case 2: /* Domain */ 1276 eventinfo->Event.RSCN_EventInfo. 1277 NPortPage = 1278 aid->aff_d_id & 0x00ff0000; 1279 break; 1280 1281 case 3: /* Network */ 1282 eventinfo->Event.RSCN_EventInfo. 1283 NPortPage = 0; 1284 break; 1285 } 1286 1287 eventinfo->Event.RSCN_EventInfo.Reserved[0] = 0; 1288 eventinfo->Event.RSCN_EventInfo.Reserved[1] = 0; 1289 1290 break; 1291 } 1292 1293 eventinfo++; 1294 events++; 1295 } 1296 hba_event->last_id = entry->id; 1297 } 1298 1299 /* Adjust new count */ 1300 if (!count || (events >= hba_event->new)) { 1301 hba_event->new = 0; 1302 } else { 1303 hba_event->new -= events; 1304 } 1305 1306 /* Return number of events acquired */ 1307 *eventcount = events; 1308 1309 mutex_exit(&log->lock); 1310 1311 return (0); 1312 1313 } /* emlxs_get_dfc_eventinfo() */ 1314 1315 1316 uint32_t 1317 emlxs_get_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event, 1318 uint32_t sleep) 1319 { 1320 emlxs_hba_t *hba = HBA; 1321 emlxs_msg_log_t *log; 1322 uint32_t first; 1323 uint32_t last; 1324 uint32_t count; 1325 uint32_t index; 1326 uint32_t mask; 1327 uint32_t i; 1328 emlxs_msg_entry_t *entry; 1329 uint32_t size; 1330 uint32_t rc; 1331 1332 size = 0; 1333 1334 if (dfc_event->dataout && dfc_event->size) { 1335 size = dfc_event->size; 1336 } 1337 dfc_event->size = 0; 1338 1339 /* Get the log file pointer */ 1340 log = &LOG; 1341 1342 /* Calculate the event index */ 1343 mask = dfc_event->event; 1344 for (i = 0; i < 32; i++) { 1345 if (mask & 0x01) { 1346 break; 1347 } 1348 mask >>= 1; 1349 } 1350 if (i == 32) { 1351 return (DFC_ARG_INVALID); 1352 } 1353 mutex_enter(&log->lock); 1354 1355 /* Check if log is empty */ 1356 if (log->count == 0) { 1357 /* Make sure everything is initialized */ 1358 log->event_id[i] = 0; 1359 dfc_event->last_id = 0; 1360 } else { 1361 /* Check ranges for safety */ 1362 if (log->event_id[i] > (log->count - 1)) { 1363 log->event_id[i] = log->count - 1; 1364 } 1365 if (dfc_event->last_id > log->event_id[i]) { 1366 dfc_event->last_id = log->event_id[i]; 1367 } 1368 } 1369 1370 wait_for_event: 1371 1372 /* Check if no new event has ocurred */ 1373 if (dfc_event->last_id == log->event_id[i]) { 1374 if (!sleep) { 1375 mutex_exit(&log->lock); 1376 return (0); 1377 } 1378 /* 1379 * While event is still active and no new event has been 1380 * logged 1381 */ 1382 while ((dfc_event->event & hba->log_events) && 1383 (dfc_event->last_id == log->event_id[i])) { 1384 rc = cv_wait_sig(&log->lock_cv, &log->lock); 1385 1386 /* Check if thread was killed by kernel */ 1387 if (rc == 0) { 1388 dfc_event->pid = 0; 1389 dfc_event->event = 0; 1390 mutex_exit(&log->lock); 1391 return (0); 1392 } 1393 } 1394 1395 /* 1396 * If the event is no longer registered then return 1397 * immediately 1398 */ 1399 if (!(dfc_event->event & hba->log_events)) { 1400 mutex_exit(&log->lock); 1401 return (0); 1402 } 1403 } 1404 /* !!! An event has occurred since last_id !!! */ 1405 1406 /* Check if event data is not being requested */ 1407 if (!size) { 1408 /* If so, then just return the last event id */ 1409 dfc_event->last_id = log->event_id[i]; 1410 1411 mutex_exit(&log->lock); 1412 return (0); 1413 } 1414 /* !!! The requester wants the next event buffer !!! */ 1415 1416 /* Calculate the current buffer boundaries */ 1417 1418 /* Get last entry id saved */ 1419 last = log->count - 1; 1420 1421 /* Get oldest entry id and its index */ 1422 /* Check if buffer has already been filled once */ 1423 if (log->count >= log->size) { 1424 first = log->count - log->size; 1425 index = log->next; 1426 } else { /* Buffer not yet filled */ 1427 first = 0; 1428 index = 0; 1429 } 1430 1431 /* Check to see if the buffer has wrapped since the last event */ 1432 if (first > log->event_id[i]) { 1433 /* Update last_id to the last known event */ 1434 dfc_event->last_id = log->event_id[i]; 1435 1436 /* Try waiting again if we can */ 1437 goto wait_for_event; 1438 } 1439 /* 1440 * Check if requested first event is greater than actual. If so, 1441 * adjust for it. 1442 */ 1443 if (dfc_event->last_id > first) { 1444 /* Adjust entry index to first requested message */ 1445 index += (dfc_event->last_id - first); 1446 if (index >= log->size) { 1447 index -= log->size; 1448 } 1449 first = dfc_event->last_id; 1450 } 1451 /* Get the total number of new messages */ 1452 count = last - first + 1; 1453 1454 /* Scan log for next event */ 1455 while (count--) { 1456 if (++index >= log->size) { 1457 index = 0; 1458 } 1459 entry = &log->entry[index]; 1460 1461 if ((entry->msg->level == EMLXS_EVENT) && 1462 (entry->msg->mask == dfc_event->event)) { 1463 break; 1464 } 1465 } 1466 1467 /* 1468 * Check if no new event was found in the current log buffer. 1469 * This would indicate that the buffer wrapped since that last event 1470 */ 1471 if (!count) { 1472 /* Update last_id to the last known event */ 1473 dfc_event->last_id = log->event_id[i]; 1474 1475 /* Try waiting again if we can */ 1476 goto wait_for_event; 1477 } 1478 /* !!! Next event found !!! */ 1479 1480 /* Copy the context buffer to the buffer provided */ 1481 if (entry->bp && entry->size) { 1482 if (entry->size < size) { 1483 size = entry->size; 1484 } 1485 if (ddi_copyout((void *) entry->bp, dfc_event->dataout, size, 1486 dfc_event->mode) != 0) { 1487 mutex_exit(&log->lock); 1488 1489 return (DFC_COPYOUT_ERROR); 1490 } 1491 dfc_event->size = size; 1492 } 1493 dfc_event->last_id = entry->id; 1494 1495 mutex_exit(&log->lock); 1496 return (0); 1497 1498 } /* emlxs_get_dfc_event() */ 1499 1500 1501 uint32_t 1502 emlxs_kill_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event) 1503 { 1504 emlxs_hba_t *hba = HBA; 1505 emlxs_msg_log_t *log; 1506 1507 /* Get the log file pointer */ 1508 log = &LOG; 1509 1510 mutex_enter(&log->lock); 1511 dfc_event->pid = 0; 1512 dfc_event->event = 0; 1513 cv_broadcast(&log->lock_cv); 1514 mutex_exit(&log->lock); 1515 1516 return (0); 1517 1518 } /* emlxs_kill_dfc_event() */ 1519 1520 1521 1522 #endif /* DFC_SUPPORT */ 1523