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