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