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
emlxs_null_func()39 emlxs_null_func() {}
40
41
42 static uint32_t
emlxs_event_check(emlxs_port_t * port,emlxs_event_t * evt)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
emlxs_event_queue_create(emlxs_hba_t * hba)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
emlxs_event_queue_destroy(emlxs_hba_t * hba)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
emlxs_event_destroy(emlxs_hba_t * hba,emlxs_event_entry_t * entry)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
emlxs_event(emlxs_port_t * port,emlxs_event_t * evt,void * bp,uint32_t size)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
emlxs_timer_check_events(emlxs_hba_t * hba)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
emlxs_log_rscn_event(emlxs_port_t * port,uint8_t * payload,uint32_t size)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
emlxs_log_vportrscn_event(emlxs_port_t * port,uint8_t * payload,uint32_t size)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
emlxs_flush_ct_event(emlxs_port_t * port,uint32_t rxid)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
emlxs_log_ct_event(emlxs_port_t * port,uint8_t * payload,uint32_t size,uint32_t rxid)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
emlxs_ct_event_destroy(emlxs_event_entry_t * entry)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
emlxs_log_link_event(emlxs_port_t * port)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
emlxs_log_dump_event(emlxs_port_t * port,uint8_t * buffer,uint32_t size)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
emlxs_log_temp_event(emlxs_port_t * port,uint32_t type,uint32_t temp)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
emlxs_log_fcoe_event(emlxs_port_t * port,menlo_init_rsp_t * init_rsp)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
emlxs_log_async_event(emlxs_port_t * port,IOCB * iocb)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
emlxs_get_dfc_eventinfo(emlxs_port_t * port,HBA_EVENTINFO * eventinfo,uint32_t * eventcount,uint32_t * missed)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
emlxs_get_dfc_event(emlxs_port_t * port,emlxs_dfc_event_t * dfc_event,uint32_t sleep)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
emlxs_kill_dfc_event(emlxs_port_t * port,emlxs_dfc_event_t * dfc_event)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
emlxs_log_sd_basic_els_event(emlxs_port_t * port,uint32_t subcat,HBA_WWN * portname,HBA_WWN * nodename)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
emlxs_log_sd_prlo_event(emlxs_port_t * port,HBA_WWN * remoteport)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
emlxs_log_sd_lsrjt_event(emlxs_port_t * port,HBA_WWN * remoteport,uint32_t orig_cmd,uint32_t reason,uint32_t reason_expl)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
emlxs_log_sd_fc_bsy_event(emlxs_port_t * port,HBA_WWN * remoteport)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
emlxs_log_sd_fc_rdchk_event(emlxs_port_t * port,HBA_WWN * remoteport,uint32_t lun,uint32_t opcode,uint32_t fcp_param)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
emlxs_log_sd_scsi_event(emlxs_port_t * port,uint32_t type,HBA_WWN * remoteport,int32_t lun)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
emlxs_log_sd_scsi_check_event(emlxs_port_t * port,HBA_WWN * remoteport,uint32_t lun,uint32_t cmdcode,uint32_t sensekey,uint32_t asc,uint32_t ascq)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
emlxs_get_sd_event(emlxs_port_t * port,emlxs_dfc_event_t * dfc_event,uint32_t sleep)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