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