1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at 9 * http://www.opensource.org/licenses/cddl1.txt. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2004-2012 Emulex. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #define DEF_EVENT_STRUCT /* Needed for emlxs_events.h in emlxs_event.h */ 28 #include <emlxs.h> 29 30 31 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 32 EMLXS_MSG_DEF(EMLXS_EVENT_C); 33 34 35 static uint32_t emlxs_event_check(emlxs_port_t *port, emlxs_event_t *evt); 36 static void emlxs_event_destroy(emlxs_hba_t *hba, emlxs_event_entry_t *entry); 37 38 extern void 39 emlxs_null_func() {} 40 41 42 static uint32_t 43 emlxs_event_check(emlxs_port_t *port, emlxs_event_t *evt) 44 { 45 emlxs_hba_t *hba = HBA; 46 47 /* Check if the event is being requested */ 48 if ((hba->event_mask & evt->mask)) { 49 return (1); 50 } 51 52 #ifdef SAN_DIAG_SUPPORT 53 if ((port->sd_event_mask & evt->mask)) { 54 return (1); 55 } 56 #endif /* SAN_DIAG_SUPPORT */ 57 58 return (0); 59 60 } /* emlxs_event_check() */ 61 62 63 extern uint32_t 64 emlxs_event_queue_create(emlxs_hba_t *hba) 65 { 66 emlxs_event_queue_t *eventq = &EVENTQ; 67 ddi_iblock_cookie_t iblock; 68 69 /* Clear the queue */ 70 bzero(eventq, sizeof (emlxs_event_queue_t)); 71 72 cv_init(&eventq->lock_cv, NULL, CV_DRIVER, NULL); 73 74 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 75 /* Get the current interrupt block cookie */ 76 (void) ddi_get_iblock_cookie(hba->dip, (uint_t)EMLXS_INUMBER, 77 &iblock); 78 79 /* Create the mutex lock */ 80 mutex_init(&eventq->lock, NULL, MUTEX_DRIVER, (void *)iblock); 81 } 82 #ifdef MSI_SUPPORT 83 else { 84 /* Create event mutex lock */ 85 mutex_init(&eventq->lock, NULL, MUTEX_DRIVER, 86 DDI_INTR_PRI(hba->intr_arg)); 87 } 88 #endif 89 90 return (1); 91 92 } /* emlxs_event_queue_create() */ 93 94 95 extern void 96 emlxs_event_queue_destroy(emlxs_hba_t *hba) 97 { 98 emlxs_port_t *vport; 99 emlxs_event_queue_t *eventq = &EVENTQ; 100 uint32_t i; 101 uint32_t wakeup = 0; 102 103 mutex_enter(&eventq->lock); 104 105 /* Clear all event masks and broadcast a wakeup */ 106 /* to clear any sleeping threads */ 107 if (hba->event_mask) { 108 hba->event_mask = 0; 109 hba->event_timer = 0; 110 wakeup = 1; 111 } 112 113 for (i = 0; i < MAX_VPORTS; i++) { 114 vport = &VPORT(i); 115 116 if (vport->sd_event_mask) { 117 vport->sd_event_mask = 0; 118 wakeup = 1; 119 } 120 } 121 122 if (wakeup) { 123 cv_broadcast(&eventq->lock_cv); 124 125 mutex_exit(&eventq->lock); 126 BUSYWAIT_MS(10); 127 mutex_enter(&eventq->lock); 128 } 129 130 /* Destroy the remaining events */ 131 while (eventq->first) { 132 emlxs_event_destroy(hba, eventq->first); 133 } 134 135 mutex_exit(&eventq->lock); 136 137 /* Destroy the queue lock */ 138 mutex_destroy(&eventq->lock); 139 cv_destroy(&eventq->lock_cv); 140 141 /* Clear the queue */ 142 bzero(eventq, sizeof (emlxs_event_queue_t)); 143 144 return; 145 146 } /* emlxs_event_queue_destroy() */ 147 148 149 /* Event queue lock must be held */ 150 static void 151 emlxs_event_destroy(emlxs_hba_t *hba, emlxs_event_entry_t *entry) 152 { 153 emlxs_event_queue_t *eventq = &EVENTQ; 154 emlxs_port_t *port; 155 uint32_t missed = 0; 156 157 port = (emlxs_port_t *)entry->port; 158 159 eventq->count--; 160 if (eventq->count == 0) { 161 eventq->first = NULL; 162 eventq->last = NULL; 163 } else { 164 if (entry->prev) { 165 entry->prev->next = entry->next; 166 } 167 if (entry->next) { 168 entry->next->prev = entry->prev; 169 } 170 if (eventq->first == entry) { 171 eventq->first = entry->next; 172 } 173 if (eventq->last == entry) { 174 eventq->last = entry->prev; 175 } 176 } 177 178 entry->prev = NULL; 179 entry->next = NULL; 180 181 if ((entry->evt->mask == EVT_LINK) || 182 (entry->evt->mask == EVT_RSCN)) { 183 if (!(entry->flag & EMLXS_DFC_EVENT_DONE)) { 184 hba->hba_event.missed++; 185 missed = 1; 186 } 187 } 188 189 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_dequeued_msg, 190 "%s[%d]: flag=%x missed=%d cnt=%d", 191 entry->evt->label, entry->id, entry->flag, missed, eventq->count); 192 193 /* Call notification handler */ 194 if (entry->evt->destroy != emlxs_null_func) { 195 entry->evt->destroy(entry); 196 } 197 198 /* Free context buffer */ 199 if (entry->bp && entry->size) { 200 kmem_free(entry->bp, entry->size); 201 } 202 203 /* Free entry buffer */ 204 kmem_free(entry, sizeof (emlxs_event_entry_t)); 205 206 return; 207 208 } /* emlxs_event_destroy() */ 209 210 211 extern void 212 emlxs_event(emlxs_port_t *port, emlxs_event_t *evt, void *bp, uint32_t size) 213 { 214 emlxs_hba_t *hba = HBA; 215 emlxs_event_queue_t *eventq = &EVENTQ; 216 emlxs_event_entry_t *entry; 217 uint32_t i; 218 uint32_t mask; 219 220 if (emlxs_event_check(port, evt) == 0) { 221 goto failed; 222 } 223 224 /* Create event entry */ 225 if (!(entry = (emlxs_event_entry_t *)kmem_alloc( 226 sizeof (emlxs_event_entry_t), KM_NOSLEEP))) { 227 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 228 "%s: Unable to allocate event entry.", evt->label); 229 230 goto failed; 231 } 232 233 /* Initialize */ 234 bzero(entry, sizeof (emlxs_event_entry_t)); 235 236 entry->evt = evt; 237 entry->port = (void *)port; 238 entry->bp = bp; 239 entry->size = size; 240 241 mutex_enter(&eventq->lock); 242 243 /* Set the event timer */ 244 entry->timestamp = hba->timer_tics; 245 if (evt->timeout) { 246 entry->timer = entry->timestamp + evt->timeout; 247 } 248 249 /* Eventq id starts with 1 */ 250 if (eventq->next_id == 0) { 251 eventq->next_id = 1; 252 } 253 254 /* Set the event id */ 255 entry->id = eventq->next_id++; 256 257 /* Set last event table */ 258 mask = evt->mask; 259 for (i = 0; i < 32; i++) { 260 if (mask & 0x01) { 261 eventq->last_id[i] = entry->id; 262 } 263 mask >>= 1; 264 } 265 266 /* Put event on bottom of queue */ 267 entry->next = NULL; 268 if (eventq->count == 0) { 269 entry->prev = NULL; 270 eventq->first = entry; 271 eventq->last = entry; 272 } else { 273 entry->prev = eventq->last; 274 entry->prev->next = entry; 275 eventq->last = entry; 276 } 277 eventq->count++; 278 279 if ((entry->evt->mask == EVT_LINK) || 280 (entry->evt->mask == EVT_RSCN)) { 281 hba->hba_event.new++; 282 } 283 284 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_queued_msg, 285 "%s[%d]: bp=%p size=%d cnt=%d", entry->evt->label, 286 entry->id, bp, size, eventq->count); 287 288 /* Broadcast the event */ 289 cv_broadcast(&eventq->lock_cv); 290 291 mutex_exit(&eventq->lock); 292 293 return; 294 295 failed: 296 297 if (bp && size) { 298 kmem_free(bp, size); 299 } 300 301 return; 302 303 } /* emlxs_event() */ 304 305 306 extern void 307 emlxs_timer_check_events(emlxs_hba_t *hba) 308 { 309 emlxs_config_t *cfg = &CFG; 310 emlxs_event_queue_t *eventq = &EVENTQ; 311 emlxs_event_entry_t *entry; 312 emlxs_event_entry_t *next; 313 314 if (!cfg[CFG_TIMEOUT_ENABLE].current) { 315 return; 316 } 317 318 if ((hba->event_timer > hba->timer_tics)) { 319 return; 320 } 321 322 if (eventq->count) { 323 mutex_enter(&eventq->lock); 324 325 entry = eventq->first; 326 while (entry) { 327 if ((!entry->timer) || 328 (entry->timer > hba->timer_tics)) { 329 entry = entry->next; 330 continue; 331 } 332 333 /* Event timed out, destroy it */ 334 next = entry->next; 335 emlxs_event_destroy(hba, entry); 336 entry = next; 337 } 338 339 mutex_exit(&eventq->lock); 340 } 341 342 /* Set next event timer check */ 343 hba->event_timer = hba->timer_tics + EMLXS_EVENT_PERIOD; 344 345 return; 346 347 } /* emlxs_timer_check_events() */ 348 349 350 extern void 351 emlxs_log_rscn_event(emlxs_port_t *port, uint8_t *payload, uint32_t size) 352 { 353 uint8_t *bp; 354 uint32_t *ptr; 355 356 /* Check if the event is being requested */ 357 if (emlxs_event_check(port, &emlxs_rscn_event) == 0) { 358 return; 359 } 360 361 if (size > MAX_RSCN_PAYLOAD) { 362 size = MAX_RSCN_PAYLOAD; 363 } 364 365 size += sizeof (uint32_t); 366 367 /* Save a copy of the payload for the event log */ 368 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 369 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 370 "%s: Unable to allocate buffer.", emlxs_rscn_event.label); 371 372 return; 373 } 374 375 /* 376 * Buffer Format: 377 * word[0] = DID of the RSCN 378 * word[1] = RSCN Payload 379 */ 380 ptr = (uint32_t *)bp; 381 *ptr++ = port->did; 382 bcopy(payload, (char *)ptr, (size - sizeof (uint32_t))); 383 384 emlxs_event(port, &emlxs_rscn_event, bp, size); 385 386 return; 387 388 } /* emlxs_log_rscn_event() */ 389 390 391 extern void 392 emlxs_log_vportrscn_event(emlxs_port_t *port, uint8_t *payload, uint32_t size) 393 { 394 uint8_t *bp; 395 uint8_t *ptr; 396 397 /* Check if the event is being requested */ 398 if (emlxs_event_check(port, &emlxs_vportrscn_event) == 0) { 399 return; 400 } 401 402 if (size > MAX_RSCN_PAYLOAD) { 403 size = MAX_RSCN_PAYLOAD; 404 } 405 406 size += sizeof (NAME_TYPE); 407 408 /* Save a copy of the payload for the event log */ 409 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 410 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 411 "%s: Unable to allocate buffer.", 412 emlxs_vportrscn_event.label); 413 414 return; 415 } 416 417 /* 418 * Buffer Format: 419 * word[0 - 4] = WWPN of the RSCN 420 * word[5] = RSCN Payload 421 */ 422 ptr = bp; 423 bcopy(&port->wwpn, ptr, sizeof (NAME_TYPE)); 424 ptr += sizeof (NAME_TYPE); 425 bcopy(payload, ptr, (size - sizeof (NAME_TYPE))); 426 427 emlxs_event(port, &emlxs_vportrscn_event, bp, size); 428 429 return; 430 431 } /* emlxs_log_vportrscn_event() */ 432 433 434 extern uint32_t 435 emlxs_flush_ct_event(emlxs_port_t *port, uint32_t rxid) 436 { 437 emlxs_hba_t *hba = HBA; 438 emlxs_event_queue_t *eventq = &EVENTQ; 439 emlxs_event_entry_t *entry; 440 uint32_t *ptr; 441 uint32_t found = 0; 442 443 mutex_enter(&eventq->lock); 444 445 for (entry = eventq->first; entry != NULL; entry = entry->next) { 446 if ((entry->port != port) || 447 (entry->evt != &emlxs_ct_event)) { 448 continue; 449 } 450 451 ptr = (uint32_t *)entry->bp; 452 if (rxid == *ptr) { 453 /* This will prevent a CT exchange abort */ 454 /* in emlxs_ct_event_destroy() */ 455 entry->flag |= EMLXS_DFC_EVENT_DONE; 456 457 emlxs_event_destroy(hba, entry); 458 found = 1; 459 break; 460 } 461 } 462 463 mutex_exit(&eventq->lock); 464 465 return (found); 466 467 } /* emlxs_flush_ct_event() */ 468 469 470 extern uint32_t 471 emlxs_log_ct_event(emlxs_port_t *port, uint8_t *payload, uint32_t size, 472 uint32_t rxid) 473 { 474 uint8_t *bp; 475 uint32_t *ptr; 476 477 /* Check if the event is being requested */ 478 if (emlxs_event_check(port, &emlxs_ct_event) == 0) { 479 return (1); 480 } 481 482 if (size > MAX_CT_PAYLOAD) { 483 size = MAX_CT_PAYLOAD; 484 } 485 486 size += sizeof (uint32_t); 487 488 /* Save a copy of the payload for the event log */ 489 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 490 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 491 "%s: Unable to allocate buffer.", emlxs_ct_event.label); 492 493 return (1); 494 } 495 496 /* 497 * Buffer Format: 498 * word[0] = RXID tag for outgoing reply to this CT request 499 * word[1] = CT Payload 500 */ 501 ptr = (uint32_t *)bp; 502 *ptr++ = rxid; 503 bcopy(payload, (char *)ptr, (size - sizeof (uint32_t))); 504 505 emlxs_event(port, &emlxs_ct_event, bp, size); 506 507 return (0); 508 509 } /* emlxs_log_ct_event() */ 510 511 512 extern void 513 emlxs_ct_event_destroy(emlxs_event_entry_t *entry) 514 { 515 emlxs_port_t *port = (emlxs_port_t *)entry->port; 516 emlxs_hba_t *hba = HBA; 517 uint32_t rxid; 518 519 if (!(entry->flag & EMLXS_DFC_EVENT_DONE)) { 520 521 rxid = *(uint32_t *)entry->bp; 522 523 /* Abort exchange */ 524 emlxs_thread_spawn(hba, emlxs_abort_ct_exchange, 525 entry->port, (void *)(unsigned long)rxid); 526 } 527 528 return; 529 530 } /* emlxs_ct_event_destroy() */ 531 532 533 extern void 534 emlxs_log_link_event(emlxs_port_t *port) 535 { 536 emlxs_hba_t *hba = HBA; 537 uint8_t *bp; 538 dfc_linkinfo_t *linkinfo; 539 uint8_t *byte; 540 uint8_t *linkspeed; 541 uint8_t *liptype; 542 uint8_t *resv1; 543 uint8_t *resv2; 544 uint32_t size; 545 546 /* Check if the event is being requested */ 547 if (emlxs_event_check(port, &emlxs_link_event) == 0) { 548 return; 549 } 550 551 size = sizeof (dfc_linkinfo_t) + sizeof (uint32_t); 552 553 /* Save a copy of the buffer for the event log */ 554 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 555 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 556 "%s: Unable to allocate buffer.", emlxs_link_event.label); 557 558 return; 559 } 560 561 /* 562 * Buffer Format: 563 * word[0] = Linkspeed:8 564 * word[0] = LIP_type:8 565 * word[0] = resv1:8 566 * word[0] = resv2:8 567 * word[1] = dfc_linkinfo_t data 568 */ 569 byte = (uint8_t *)bp; 570 linkspeed = &byte[0]; 571 liptype = &byte[1]; 572 resv1 = &byte[2]; 573 resv2 = &byte[3]; 574 linkinfo = (dfc_linkinfo_t *)&byte[4]; 575 576 *resv1 = 0; 577 *resv2 = 0; 578 579 if (hba->state <= FC_LINK_DOWN) { 580 *linkspeed = 0; 581 *liptype = 0; 582 } else { 583 /* Set linkspeed */ 584 if (hba->linkspeed == LA_2GHZ_LINK) { 585 *linkspeed = HBA_PORTSPEED_2GBIT; 586 } else if (hba->linkspeed == LA_4GHZ_LINK) { 587 *linkspeed = HBA_PORTSPEED_4GBIT; 588 } else if (hba->linkspeed == LA_8GHZ_LINK) { 589 *linkspeed = HBA_PORTSPEED_8GBIT; 590 } else if (hba->linkspeed == LA_10GHZ_LINK) { 591 *linkspeed = HBA_PORTSPEED_10GBIT; 592 } else if (hba->linkspeed == LA_16GHZ_LINK) { 593 *linkspeed = HBA_PORTSPEED_16GBIT; 594 } else { 595 *linkspeed = HBA_PORTSPEED_1GBIT; 596 } 597 598 /* Set LIP type */ 599 *liptype = port->lip_type; 600 } 601 602 bzero(linkinfo, sizeof (dfc_linkinfo_t)); 603 604 linkinfo->a_linkEventTag = hba->link_event_tag; 605 linkinfo->a_linkUp = HBASTATS.LinkUp; 606 linkinfo->a_linkDown = HBASTATS.LinkDown; 607 linkinfo->a_linkMulti = HBASTATS.LinkMultiEvent; 608 609 if (hba->state <= FC_LINK_DOWN) { 610 linkinfo->a_linkState = LNK_DOWN; 611 linkinfo->a_DID = port->prev_did; 612 } else if (hba->state < FC_READY) { 613 linkinfo->a_linkState = LNK_DISCOVERY; 614 } else { 615 linkinfo->a_linkState = LNK_READY; 616 } 617 618 if (linkinfo->a_linkState != LNK_DOWN) { 619 if (hba->topology == TOPOLOGY_LOOP) { 620 if (hba->flag & FC_FABRIC_ATTACHED) { 621 linkinfo->a_topology = LNK_PUBLIC_LOOP; 622 } else { 623 linkinfo->a_topology = LNK_LOOP; 624 } 625 626 linkinfo->a_alpa = port->did & 0xff; 627 linkinfo->a_DID = linkinfo->a_alpa; 628 linkinfo->a_alpaCnt = port->alpa_map[0]; 629 630 if (linkinfo->a_alpaCnt > 127) { 631 linkinfo->a_alpaCnt = 127; 632 } 633 634 bcopy((void *)&port->alpa_map[1], linkinfo->a_alpaMap, 635 linkinfo->a_alpaCnt); 636 } else { 637 if (port->node_count == 1) { 638 linkinfo->a_topology = LNK_PT2PT; 639 } else { 640 linkinfo->a_topology = LNK_FABRIC; 641 } 642 643 linkinfo->a_DID = port->did; 644 } 645 } 646 647 bcopy(&hba->wwpn, linkinfo->a_wwpName, 8); 648 bcopy(&hba->wwnn, linkinfo->a_wwnName, 8); 649 650 emlxs_event(port, &emlxs_link_event, bp, size); 651 652 return; 653 654 } /* emlxs_log_link_event() */ 655 656 657 extern void 658 emlxs_log_dump_event(emlxs_port_t *port, uint8_t *buffer, uint32_t size) 659 { 660 emlxs_hba_t *hba = HBA; 661 uint8_t *bp; 662 663 /* Check if the event is being requested */ 664 if (emlxs_event_check(port, &emlxs_dump_event) == 0) { 665 #ifdef DUMP_SUPPORT 666 /* Schedule a dump thread */ 667 emlxs_dump(hba, EMLXS_DRV_DUMP, 0, 0); 668 #endif /* DUMP_SUPPORT */ 669 return; 670 } 671 672 if (buffer && size) { 673 /* Save a copy of the buffer for the event log */ 674 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 675 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 676 "%s: Unable to allocate buffer.", 677 emlxs_dump_event.label); 678 679 return; 680 } 681 682 bcopy(buffer, bp, size); 683 } else { 684 bp = NULL; 685 size = 0; 686 } 687 688 emlxs_event(port, &emlxs_dump_event, bp, size); 689 690 return; 691 692 } /* emlxs_log_dump_event() */ 693 694 695 extern void 696 emlxs_log_temp_event(emlxs_port_t *port, uint32_t type, uint32_t temp) 697 { 698 emlxs_hba_t *hba = HBA; 699 uint32_t *bp; 700 uint32_t size; 701 702 /* Check if the event is being requested */ 703 if (emlxs_event_check(port, &emlxs_temp_event) == 0) { 704 #ifdef DUMP_SUPPORT 705 /* Schedule a dump thread */ 706 emlxs_dump(hba, EMLXS_TEMP_DUMP, type, temp); 707 #endif /* DUMP_SUPPORT */ 708 return; 709 } 710 711 size = 2 * sizeof (uint32_t); 712 713 if (!(bp = (uint32_t *)kmem_alloc(size, KM_NOSLEEP))) { 714 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 715 "%s: Unable to allocate buffer.", emlxs_temp_event.label); 716 717 return; 718 } 719 720 bp[0] = type; 721 bp[1] = temp; 722 723 emlxs_event(port, &emlxs_temp_event, bp, size); 724 725 return; 726 727 } /* emlxs_log_temp_event() */ 728 729 730 731 extern void 732 emlxs_log_fcoe_event(emlxs_port_t *port, menlo_init_rsp_t *init_rsp) 733 { 734 emlxs_hba_t *hba = HBA; 735 uint8_t *bp; 736 uint32_t size; 737 738 /* Check if the event is being requested */ 739 if (emlxs_event_check(port, &emlxs_fcoe_event) == 0) { 740 return; 741 } 742 743 /* Check if this is a FCOE adapter */ 744 if (hba->model_info.device_id != PCI_DEVICE_ID_HORNET) { 745 return; 746 } 747 748 size = sizeof (menlo_init_rsp_t); 749 750 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 751 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 752 "%s: Unable to allocate buffer.", emlxs_fcoe_event.label); 753 754 return; 755 } 756 757 bcopy((uint8_t *)init_rsp, bp, size); 758 759 emlxs_event(port, &emlxs_fcoe_event, bp, size); 760 761 return; 762 763 } /* emlxs_log_fcoe_event() */ 764 765 766 extern void 767 emlxs_log_async_event(emlxs_port_t *port, IOCB *iocb) 768 { 769 uint8_t *bp; 770 uint32_t size; 771 772 if (emlxs_event_check(port, &emlxs_async_event) == 0) { 773 return; 774 } 775 776 /* ASYNC_STATUS_CN response size */ 777 size = 64; 778 779 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) { 780 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 781 "%s: Unable to allocate buffer.", emlxs_async_event.label); 782 783 return; 784 } 785 786 bcopy((uint8_t *)iocb, bp, size); 787 788 emlxs_event(port, &emlxs_async_event, bp, size); 789 790 return; 791 792 } /* emlxs_log_async_event() */ 793 794 795 extern uint32_t 796 emlxs_get_dfc_eventinfo(emlxs_port_t *port, HBA_EVENTINFO *eventinfo, 797 uint32_t *eventcount, uint32_t *missed) 798 { 799 emlxs_hba_t *hba = HBA; 800 emlxs_event_queue_t *eventq = &EVENTQ; 801 emlxs_event_entry_t *entry; 802 uint32_t max_events; 803 dfc_linkinfo_t *linkinfo; 804 uint32_t *word; 805 uint8_t *byte; 806 uint8_t linkspeed; 807 uint8_t liptype; 808 fc_affected_id_t *aid; 809 uint32_t events; 810 uint8_t format; 811 812 if (!eventinfo || !eventcount || !missed) { 813 return (DFC_ARG_NULL); 814 } 815 816 max_events = *eventcount; 817 *eventcount = 0; 818 *missed = 0; 819 820 mutex_enter(&eventq->lock); 821 822 /* Account for missed events */ 823 if (hba->hba_event.new > hba->hba_event.missed) { 824 hba->hba_event.new -= hba->hba_event.missed; 825 } else { 826 hba->hba_event.new = 0; 827 } 828 829 *missed = hba->hba_event.missed; 830 hba->hba_event.missed = 0; 831 832 if (!hba->hba_event.new) { 833 hba->hba_event.last_id = eventq->next_id - 1; 834 mutex_exit(&eventq->lock); 835 return (0); 836 } 837 838 /* A new event has occurred since last acquisition */ 839 840 events = 0; 841 entry = eventq->first; 842 while (entry && (events < max_events)) { 843 844 /* Skip old events */ 845 if (entry->id <= hba->hba_event.last_id) { 846 entry = entry->next; 847 continue; 848 } 849 850 /* Process this entry */ 851 switch (entry->evt->mask) { 852 case EVT_LINK: 853 byte = (uint8_t *)entry->bp; 854 linkspeed = byte[0]; 855 liptype = byte[1]; 856 linkinfo = (dfc_linkinfo_t *)&byte[4]; 857 858 if (linkinfo->a_linkState == LNK_DOWN) { 859 eventinfo->EventCode = 860 HBA_EVENT_LINK_DOWN; 861 eventinfo->Event.Link_EventInfo. 862 PortFcId = linkinfo->a_DID; 863 eventinfo->Event.Link_EventInfo. 864 Reserved[0] = 0; 865 eventinfo->Event.Link_EventInfo. 866 Reserved[1] = 0; 867 eventinfo->Event.Link_EventInfo. 868 Reserved[2] = 0; 869 } else { 870 eventinfo->EventCode = 871 HBA_EVENT_LINK_UP; 872 eventinfo->Event.Link_EventInfo. 873 PortFcId = linkinfo->a_DID; 874 875 if ((linkinfo->a_topology == 876 LNK_PUBLIC_LOOP) || 877 (linkinfo->a_topology == 878 LNK_LOOP)) { 879 eventinfo->Event. 880 Link_EventInfo. 881 Reserved[0] = 2; 882 } else { 883 eventinfo->Event. 884 Link_EventInfo. 885 Reserved[0] = 1; 886 } 887 888 eventinfo->Event.Link_EventInfo. 889 Reserved[1] = liptype; 890 eventinfo->Event.Link_EventInfo. 891 Reserved[2] = linkspeed; 892 } 893 894 eventinfo++; 895 events++; 896 hba->hba_event.new--; 897 break; 898 899 case EVT_RSCN: 900 word = (uint32_t *)entry->bp; 901 eventinfo->EventCode = HBA_EVENT_RSCN; 902 eventinfo->Event.RSCN_EventInfo.PortFcId = 903 word[0] & 0xFFFFFF; 904 /* word[1] is the RSCN payload command */ 905 906 aid = (fc_affected_id_t *)&word[2]; 907 format = aid->aff_format; 908 909 switch (format) { 910 case 0: /* Port */ 911 eventinfo->Event.RSCN_EventInfo. 912 NPortPage = 913 aid->aff_d_id & 0x00ffffff; 914 break; 915 916 case 1: /* Area */ 917 eventinfo->Event.RSCN_EventInfo. 918 NPortPage = 919 aid->aff_d_id & 0x00ffff00; 920 break; 921 922 case 2: /* Domain */ 923 eventinfo->Event.RSCN_EventInfo. 924 NPortPage = 925 aid->aff_d_id & 0x00ff0000; 926 break; 927 928 case 3: /* Network */ 929 eventinfo->Event.RSCN_EventInfo. 930 NPortPage = 0; 931 break; 932 } 933 934 eventinfo->Event.RSCN_EventInfo.Reserved[0] = 935 0; 936 eventinfo->Event.RSCN_EventInfo.Reserved[1] = 937 0; 938 939 eventinfo++; 940 events++; 941 hba->hba_event.new--; 942 break; 943 } 944 945 hba->hba_event.last_id = entry->id; 946 entry = entry->next; 947 } 948 949 /* Return number of events acquired */ 950 *eventcount = events; 951 952 mutex_exit(&eventq->lock); 953 954 return (0); 955 956 } /* emlxs_get_dfc_eventinfo() */ 957 958 959 void 960 emlxs_get_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event, 961 uint32_t sleep) 962 { 963 emlxs_hba_t *hba = HBA; 964 emlxs_event_queue_t *eventq = &EVENTQ; 965 emlxs_event_entry_t *entry; 966 uint32_t found; 967 uint32_t mask; 968 uint32_t i; 969 uint32_t size = 0; 970 uint32_t rc; 971 972 if (dfc_event->dataout && dfc_event->size) { 973 size = dfc_event->size; 974 } 975 dfc_event->size = 0; 976 977 /* Calculate the event index */ 978 mask = dfc_event->event; 979 for (i = 0; i < 32; i++) { 980 if (mask & 0x01) { 981 break; 982 } 983 984 mask >>= 1; 985 } 986 987 if (i == 32) { 988 return; 989 } 990 991 mutex_enter(&eventq->lock); 992 993 wait_for_event: 994 995 /* Check if no new event has occurred */ 996 if (dfc_event->last_id == eventq->last_id[i]) { 997 if (!sleep) { 998 mutex_exit(&eventq->lock); 999 return; 1000 } 1001 1002 /* While event is still active and */ 1003 /* no new event has been logged */ 1004 while ((dfc_event->event & hba->event_mask) && 1005 (dfc_event->last_id == eventq->last_id[i])) { 1006 1007 rc = cv_wait_sig(&eventq->lock_cv, &eventq->lock); 1008 1009 /* Check if thread was killed by kernel */ 1010 if (rc == 0) { 1011 dfc_event->pid = 0; 1012 dfc_event->event = 0; 1013 mutex_exit(&eventq->lock); 1014 return; 1015 } 1016 } 1017 1018 /* If the event is no longer registered then */ 1019 /* return immediately */ 1020 if (!(dfc_event->event & hba->event_mask)) { 1021 mutex_exit(&eventq->lock); 1022 return; 1023 } 1024 } 1025 1026 /* !!! An event has occurred since last_id !!! */ 1027 1028 /* Check if event data is not being requested */ 1029 if (!size) { 1030 /* If so, then just return the last event id */ 1031 dfc_event->last_id = eventq->last_id[i]; 1032 1033 mutex_exit(&eventq->lock); 1034 return; 1035 } 1036 1037 /* !!! The requester wants the next event buffer !!! */ 1038 1039 found = 0; 1040 entry = eventq->first; 1041 while (entry) { 1042 if ((entry->id > dfc_event->last_id) && 1043 (entry->evt->mask == dfc_event->event)) { 1044 found = 1; 1045 break; 1046 } 1047 1048 entry = entry->next; 1049 } 1050 1051 if (!found) { 1052 /* Update last_id to the last known event */ 1053 dfc_event->last_id = eventq->last_id[i]; 1054 1055 /* Try waiting again if we can */ 1056 goto wait_for_event; 1057 } 1058 1059 /* !!! Next event found !!! */ 1060 1061 /* Copy the context buffer to the buffer provided */ 1062 if (entry->bp && entry->size) { 1063 if (entry->size < size) { 1064 size = entry->size; 1065 } 1066 1067 bcopy((void *)entry->bp, dfc_event->dataout, size); 1068 1069 /* Event has been retrieved by DFCLIB */ 1070 entry->flag |= EMLXS_DFC_EVENT_DONE; 1071 1072 dfc_event->size = size; 1073 } 1074 1075 dfc_event->last_id = entry->id; 1076 1077 mutex_exit(&eventq->lock); 1078 1079 return; 1080 1081 } /* emlxs_get_dfc_event() */ 1082 1083 1084 uint32_t 1085 emlxs_kill_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event) 1086 { 1087 emlxs_hba_t *hba = HBA; 1088 emlxs_event_queue_t *eventq = &EVENTQ; 1089 1090 mutex_enter(&eventq->lock); 1091 dfc_event->pid = 0; 1092 dfc_event->event = 0; 1093 cv_broadcast(&eventq->lock_cv); 1094 mutex_exit(&eventq->lock); 1095 1096 return (0); 1097 1098 } /* emlxs_kill_dfc_event() */ 1099 1100 1101 #ifdef SAN_DIAG_SUPPORT 1102 extern void 1103 emlxs_log_sd_basic_els_event(emlxs_port_t *port, uint32_t subcat, 1104 HBA_WWN *portname, HBA_WWN *nodename) 1105 { 1106 struct sd_plogi_rcv_v0 *bp; 1107 uint32_t size; 1108 1109 /* Check if the event is being requested */ 1110 if (emlxs_event_check(port, &emlxs_sd_els_event) == 0) { 1111 return; 1112 } 1113 1114 size = sizeof (struct sd_plogi_rcv_v0); 1115 1116 if (!(bp = (struct sd_plogi_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP))) { 1117 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 1118 "%s: Unable to allocate buffer.", emlxs_sd_els_event.label); 1119 1120 return; 1121 } 1122 1123 /* 1124 * we are using version field to store subtype, libdfc 1125 * will fix this up before returning data to app. 1126 */ 1127 bp->sd_plogir_version = subcat; 1128 bcopy((uint8_t *)portname, (uint8_t *)&bp->sd_plogir_portname, 1129 sizeof (HBA_WWN)); 1130 bcopy((uint8_t *)nodename, (uint8_t *)&bp->sd_plogir_nodename, 1131 sizeof (HBA_WWN)); 1132 1133 emlxs_event(port, &emlxs_sd_els_event, bp, size); 1134 1135 return; 1136 1137 } /* emlxs_log_sd_basic_els_event() */ 1138 1139 1140 extern void 1141 emlxs_log_sd_prlo_event(emlxs_port_t *port, HBA_WWN *remoteport) 1142 { 1143 struct sd_prlo_rcv_v0 *bp; 1144 uint32_t size; 1145 1146 /* Check if the event is being requested */ 1147 if (emlxs_event_check(port, &emlxs_sd_els_event) == 0) { 1148 return; 1149 } 1150 1151 size = sizeof (struct sd_prlo_rcv_v0); 1152 1153 if (!(bp = (struct sd_prlo_rcv_v0 *)kmem_alloc(size, 1154 KM_NOSLEEP))) { 1155 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 1156 "%s PRLO: Unable to allocate buffer.", 1157 emlxs_sd_els_event.label); 1158 1159 return; 1160 } 1161 1162 /* 1163 * we are using version field to store subtype, libdfc 1164 * will fix this up before returning data to app. 1165 */ 1166 bp->sd_prlor_version = SD_ELS_SUBCATEGORY_PRLO_RCV; 1167 bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_prlor_remoteport, 1168 sizeof (HBA_WWN)); 1169 1170 emlxs_event(port, &emlxs_sd_els_event, bp, size); 1171 1172 return; 1173 1174 } /* emlxs_log_sd_prlo_event() */ 1175 1176 1177 extern void 1178 emlxs_log_sd_lsrjt_event(emlxs_port_t *port, HBA_WWN *remoteport, 1179 uint32_t orig_cmd, uint32_t reason, uint32_t reason_expl) 1180 { 1181 struct sd_lsrjt_rcv_v0 *bp; 1182 uint32_t size; 1183 1184 /* Check if the event is being requested */ 1185 if (emlxs_event_check(port, &emlxs_sd_els_event) == 0) { 1186 return; 1187 } 1188 1189 size = sizeof (struct sd_lsrjt_rcv_v0); 1190 1191 if (!(bp = (struct sd_lsrjt_rcv_v0 *)kmem_alloc(size, 1192 KM_NOSLEEP))) { 1193 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 1194 "%s LSRJT: Unable to allocate buffer.", 1195 emlxs_sd_els_event.label); 1196 1197 return; 1198 } 1199 1200 /* 1201 * we are using version field to store subtype, libdfc 1202 * will fix this up before returning data to app. 1203 */ 1204 bp->sd_lsrjtr_version = SD_ELS_SUBCATEGORY_LSRJT_RCV; 1205 bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_lsrjtr_remoteport, 1206 sizeof (HBA_WWN)); 1207 bp->sd_lsrjtr_original_cmd = orig_cmd; 1208 bp->sd_lsrjtr_reasoncode = reason; 1209 bp->sd_lsrjtr_reasoncodeexpl = reason_expl; 1210 1211 emlxs_event(port, &emlxs_sd_els_event, bp, size); 1212 1213 return; 1214 1215 } /* emlxs_log_sd_lsrjt_event() */ 1216 1217 1218 extern void 1219 emlxs_log_sd_fc_bsy_event(emlxs_port_t *port, HBA_WWN *remoteport) 1220 { 1221 struct sd_pbsy_rcv_v0 *bp; 1222 uint32_t size; 1223 1224 /* Check if the event is being requested */ 1225 if (emlxs_event_check(port, &emlxs_sd_fabric_event) == 0) { 1226 return; 1227 } 1228 1229 size = sizeof (struct sd_pbsy_rcv_v0); 1230 1231 if (!(bp = (struct sd_pbsy_rcv_v0 *)kmem_alloc(size, 1232 KM_NOSLEEP))) { 1233 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 1234 "%s BSY: Unable to allocate buffer.", 1235 emlxs_sd_fabric_event.label); 1236 1237 return; 1238 } 1239 1240 /* 1241 * we are using version field to store subtype, libdfc 1242 * will fix this up before returning data to app. 1243 */ 1244 if (remoteport == NULL) 1245 bp->sd_pbsyr_evt_version = SD_FABRIC_SUBCATEGORY_FABRIC_BUSY; 1246 else 1247 { 1248 bp->sd_pbsyr_evt_version = SD_FABRIC_SUBCATEGORY_PORT_BUSY; 1249 bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_pbsyr_rport, 1250 sizeof (HBA_WWN)); 1251 } 1252 1253 emlxs_event(port, &emlxs_sd_fabric_event, bp, size); 1254 1255 return; 1256 1257 } /* emlxs_log_sd_fc_bsy_event() */ 1258 1259 1260 extern void 1261 emlxs_log_sd_fc_rdchk_event(emlxs_port_t *port, HBA_WWN *remoteport, 1262 uint32_t lun, uint32_t opcode, uint32_t fcp_param) 1263 { 1264 struct sd_fcprdchkerr_v0 *bp; 1265 uint32_t size; 1266 1267 /* Check if the event is being requested */ 1268 if (emlxs_event_check(port, &emlxs_sd_fabric_event) == 0) { 1269 return; 1270 } 1271 1272 size = sizeof (struct sd_fcprdchkerr_v0); 1273 1274 if (!(bp = (struct sd_fcprdchkerr_v0 *)kmem_alloc(size, 1275 KM_NOSLEEP))) { 1276 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 1277 "%s RDCHK: Unable to allocate buffer.", 1278 emlxs_sd_fabric_event.label); 1279 1280 return; 1281 } 1282 1283 /* 1284 * we are using version field to store subtype, libdfc 1285 * will fix this up before returning data to app. 1286 */ 1287 bp->sd_fcprdchkerr_version = SD_FABRIC_SUBCATEGORY_FCPRDCHKERR; 1288 bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_fcprdchkerr_rport, 1289 sizeof (HBA_WWN)); 1290 bp->sd_fcprdchkerr_lun = lun; 1291 bp->sd_fcprdchkerr_opcode = opcode; 1292 bp->sd_fcprdchkerr_fcpiparam = fcp_param; 1293 1294 emlxs_event(port, &emlxs_sd_fabric_event, bp, size); 1295 1296 return; 1297 1298 } /* emlxs_log_sd_rdchk_event() */ 1299 1300 1301 extern void 1302 emlxs_log_sd_scsi_event(emlxs_port_t *port, uint32_t type, 1303 HBA_WWN *remoteport, int32_t lun) 1304 { 1305 struct sd_scsi_generic_v0 *bp; 1306 uint32_t size; 1307 1308 /* Check if the event is being requested */ 1309 if (emlxs_event_check(port, &emlxs_sd_scsi_event) == 0) { 1310 return; 1311 } 1312 1313 size = sizeof (struct sd_scsi_generic_v0); 1314 1315 if (!(bp = (struct sd_scsi_generic_v0 *)kmem_alloc(size, 1316 KM_NOSLEEP))) { 1317 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 1318 "%s: Unable to allocate buffer.", 1319 emlxs_sd_scsi_event.label); 1320 1321 return; 1322 } 1323 1324 /* 1325 * we are using version field to store subtype, libdfc 1326 * will fix this up before returning data to app. 1327 */ 1328 bp->sd_scsi_generic_version = type; 1329 bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_scsi_generic_rport, 1330 sizeof (HBA_WWN)); 1331 bp->sd_scsi_generic_lun = lun; 1332 1333 emlxs_event(port, &emlxs_sd_scsi_event, bp, size); 1334 1335 return; 1336 1337 } /* emlxs_log_sd_scsi_event() */ 1338 1339 1340 extern void 1341 emlxs_log_sd_scsi_check_event(emlxs_port_t *port, HBA_WWN *remoteport, 1342 uint32_t lun, uint32_t cmdcode, uint32_t sensekey, 1343 uint32_t asc, uint32_t ascq) 1344 { 1345 struct sd_scsi_checkcond_v0 *bp; 1346 uint32_t size; 1347 1348 /* Check if the event is being requested */ 1349 if (emlxs_event_check(port, &emlxs_sd_scsi_event) == 0) { 1350 return; 1351 } 1352 1353 size = sizeof (struct sd_scsi_checkcond_v0); 1354 1355 if (!(bp = (struct sd_scsi_checkcond_v0 *)kmem_alloc(size, 1356 KM_NOSLEEP))) { 1357 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg, 1358 "%s CHECK: Unable to allocate buffer.", 1359 emlxs_sd_scsi_event.label); 1360 1361 return; 1362 } 1363 1364 /* 1365 * we are using version field to store subtype, libdfc 1366 * will fix this up before returning data to app. 1367 */ 1368 bp->sd_scsi_checkcond_version = SD_SCSI_SUBCATEGORY_CHECKCONDITION; 1369 bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_scsi_checkcond_rport, 1370 sizeof (HBA_WWN)); 1371 bp->sd_scsi_checkcond_lun = lun; 1372 bp->sd_scsi_checkcond_cmdcode = cmdcode; 1373 bp->sd_scsi_checkcond_sensekey = sensekey; 1374 bp->sd_scsi_checkcond_asc = asc; 1375 bp->sd_scsi_checkcond_ascq = ascq; 1376 1377 emlxs_event(port, &emlxs_sd_scsi_event, bp, size); 1378 1379 return; 1380 1381 } /* emlxs_log_sd_scsi_check_event() */ 1382 1383 1384 void 1385 emlxs_get_sd_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event, 1386 uint32_t sleep) 1387 { 1388 emlxs_hba_t *hba = HBA; 1389 emlxs_event_queue_t *eventq = &EVENTQ; 1390 emlxs_event_entry_t *entry; 1391 uint32_t found; 1392 uint32_t mask; 1393 uint32_t i; 1394 uint32_t size = 0; 1395 uint32_t rc; 1396 1397 if (dfc_event->dataout && dfc_event->size) { 1398 size = dfc_event->size; 1399 } 1400 dfc_event->size = 0; 1401 1402 /* Calculate the event index */ 1403 mask = dfc_event->event; 1404 for (i = 0; i < 32; i++) { 1405 if (mask & 0x01) { 1406 break; 1407 } 1408 1409 mask >>= 1; 1410 } 1411 1412 if (i == 32) { 1413 return; 1414 } 1415 1416 mutex_enter(&eventq->lock); 1417 1418 wait_for_event: 1419 1420 /* Check if no new event has ocurred */ 1421 if (dfc_event->last_id == eventq->last_id[i]) { 1422 if (!sleep) { 1423 mutex_exit(&eventq->lock); 1424 return; 1425 } 1426 1427 /* While event is active and no new event has been logged */ 1428 while ((dfc_event->event & port->sd_event_mask) && 1429 (dfc_event->last_id == eventq->last_id[i])) { 1430 rc = cv_wait_sig(&eventq->lock_cv, &eventq->lock); 1431 1432 /* Check if thread was killed by kernel */ 1433 if (rc == 0) { 1434 dfc_event->pid = 0; 1435 dfc_event->event = 0; 1436 mutex_exit(&eventq->lock); 1437 return; 1438 } 1439 } 1440 1441 /* If the event is no longer registered then return */ 1442 if (!(dfc_event->event & port->sd_event_mask)) { 1443 mutex_exit(&eventq->lock); 1444 return; 1445 } 1446 } 1447 1448 /* !!! An event has occurred since last_id !!! */ 1449 1450 /* Check if event data is not being requested */ 1451 if (!size) { 1452 /* If so, then just return the last event id */ 1453 dfc_event->last_id = eventq->last_id[i]; 1454 1455 mutex_exit(&eventq->lock); 1456 return; 1457 } 1458 1459 /* !!! The requester wants the next event buffer !!! */ 1460 1461 found = 0; 1462 entry = eventq->first; 1463 while (entry) { 1464 if ((entry->id > dfc_event->last_id) && 1465 (entry->port == (void *)port) && 1466 (entry->evt->mask == dfc_event->event)) { 1467 found = 1; 1468 break; 1469 } 1470 1471 entry = entry->next; 1472 } 1473 1474 if (!found) { 1475 /* Update last_id to the last known event */ 1476 dfc_event->last_id = eventq->last_id[i]; 1477 1478 /* Try waiting again if we can */ 1479 goto wait_for_event; 1480 } 1481 1482 /* !!! Next event found !!! */ 1483 1484 /* Copy the context buffer to the buffer provided */ 1485 if (entry->bp && entry->size) { 1486 if (entry->size < size) { 1487 size = entry->size; 1488 } 1489 1490 bcopy((void *)entry->bp, dfc_event->dataout, size); 1491 1492 /* Event has been retrieved by SANDIAG */ 1493 entry->flag |= EMLXS_SD_EVENT_DONE; 1494 1495 dfc_event->size = size; 1496 } 1497 1498 dfc_event->last_id = entry->id; 1499 1500 mutex_exit(&eventq->lock); 1501 1502 return; 1503 1504 } /* emlxs_get_sd_event */ 1505 #endif /* SAN_DIAG_SUPPORT */ 1506