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