xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_intr.c (revision 67dbe2be0c0f1e2eb428b89088bb5667e8f0b9f6)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  *
21  *
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * This file contains functions that are called via interrupts.
28  */
29 
30 #include <sys/scsi/adapters/pmcs/pmcs.h>
31 
32 #ifdef	DEBUG
33 #define	VALID_IOMB_CHECK(p, w, m, b, c)					\
34 	if (!(w & PMCS_IOMB_VALID)) {					\
35 		char l[64];						\
36 		(void) snprintf(l, sizeof (l),				\
37 		    "%s: INVALID IOMB (oq_ci=%u oq_pi=%u)", __func__, b, c); \
38 		pmcs_print_entry(pwp, PMCS_PRT_DEBUG, l, m);		\
39 		STEP_OQ_ENTRY(pwp, PMCS_OQ_EVENTS, b, 1);		\
40 		continue;						\
41 	}
42 #define	WRONG_OBID_CHECK(pwp, w, q)	\
43 	if (((w & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT) != q) {	\
44 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,		\
45 		    "%s: COMPLETION WITH WRONG OBID (0x%x)", __func__,	\
46 		    (w & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT);	\
47 	}
48 #else
49 #define	VALID_IOMB_CHECK(a, b, c, d, e)
50 #define	WRONG_OBID_CHECK(a, b, c)
51 #endif
52 
53 #define	OQLIM_CHECK(p, l)				\
54 	if (++l == (p)->ioq_depth) {			\
55 		pmcs_prt(p, PMCS_PRT_DEBUG, NULL, NULL,	\
56 		    "%s: possible ob queue overflow",	\
57 		    __func__);				\
58 		break;					\
59 	}
60 
61 #define	COPY_OUTBOUND(p, w, l, n, a, x, q, c)				\
62 	n = ((w & PMCS_IOMB_BC_MASK) >> PMCS_IOMB_BC_SHIFT);		\
63 	a = PMCS_QENTRY_SIZE;						\
64 	(void) memcpy(l, x, PMCS_QENTRY_SIZE);				\
65 	if (n > 1) {							\
66 		a <<= 1;						\
67 		(void) memcpy(&l[PMCS_QENTRY_SIZE],			\
68 		    GET_OQ_ENTRY(p, q, c, 1), PMCS_QENTRY_SIZE);	\
69 	}								\
70 	pmcs_prt(p, PMCS_PRT_DEBUG3, NULL, NULL,			\
71 	    "%s: ptr %p ci %d w0 %x nbuf %d",				\
72 	    __func__, (void *)x, ci, w0, n)
73 
74 #define	EVT_PRT(hwp, msg, phy)	\
75 	pmcs_prt(hwp, PMCS_PRT_INFO, NULL, NULL, "Phy 0x%x: %s", phy, # msg)
76 
77 
78 /*
79  * Map the link rate reported in the event to the SAS link rate value
80  */
81 static uint8_t
82 pmcs_link_rate(uint32_t event_link_rate)
83 {
84 	uint8_t sas_link_rate = 0;
85 
86 	switch (event_link_rate) {
87 	case 1:
88 		sas_link_rate = SAS_LINK_RATE_1_5GBIT;
89 		break;
90 	case 2:
91 		sas_link_rate = SAS_LINK_RATE_3GBIT;
92 		break;
93 	case 4:
94 		sas_link_rate = SAS_LINK_RATE_6GBIT;
95 		break;
96 	}
97 
98 	return (sas_link_rate);
99 }
100 
101 /*
102  * Called with pwrk lock
103  */
104 static void
105 pmcs_complete_work(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *iomb, size_t amt)
106 {
107 #ifdef	DEBUG
108 	pwp->ltime[pwp->lti] = gethrtime();
109 	pwp->ltags[pwp->lti++] = pwrk->htag;
110 #endif
111 	pwrk->htag |= PMCS_TAG_DONE;
112 
113 	/*
114 	 * If the command has timed out, leave it in that state.
115 	 */
116 	if (pwrk->state != PMCS_WORK_STATE_TIMED_OUT) {
117 		pwrk->state = PMCS_WORK_STATE_INTR;
118 	}
119 
120 	pmcs_complete_work_impl(pwp, pwrk, iomb, amt);
121 }
122 
123 static void
124 pmcs_work_not_found(pmcs_hw_t *pwp, uint32_t htag, uint32_t *iomb)
125 {
126 #ifdef	DEBUG
127 	int i;
128 	hrtime_t now;
129 	char buf[64];
130 
131 	(void) snprintf(buf, sizeof (buf),
132 	    "unable to find work structure for tag 0x%x", htag);
133 
134 	pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, iomb);
135 	if (htag == 0) {
136 		return;
137 	}
138 	now = gethrtime();
139 	for (i = 0; i < 256; i++) {
140 		mutex_enter(&pwp->dbglock);
141 		if (pwp->ltags[i] == htag) {
142 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
143 			    "same tag already completed (%llu us ago)",
144 			    (unsigned long long) (now - pwp->ltime[i]));
145 		}
146 		if (pwp->ftags[i] == htag) {
147 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
148 			    "same tag started (line %d) (%llu ns ago)",
149 			    pwp->ftag_lines[i], (unsigned long long)
150 			    (now - pwp->ftime[i]));
151 		}
152 		mutex_exit(&pwp->dbglock);
153 	}
154 #else
155 	char buf[64];
156 	(void) snprintf(buf, sizeof (buf),
157 	    "unable to find work structure for tag 0x%x", htag);
158 	pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, iomb);
159 #endif
160 }
161 
162 
163 static void
164 pmcs_process_io_completion(pmcs_hw_t *pwp, pmcs_iocomp_cb_t *ioccb, size_t amt)
165 {
166 	pmcwork_t *pwrk;
167 	uint32_t tag_type;
168 	uint32_t htag = LE_32(((uint32_t *)((void *)ioccb->iomb))[1]);
169 
170 	pwrk = pmcs_tag2wp(pwp, htag);
171 	if (pwrk == NULL) {
172 		pmcs_work_not_found(pwp, htag, (void *)&ioccb->iomb);
173 		kmem_cache_free(pwp->iocomp_cb_cache, ioccb);
174 		return;
175 	}
176 
177 	pwrk->htag |= PMCS_TAG_DONE;
178 
179 	/*
180 	 * If the command has timed out, leave it in that state.
181 	 */
182 	if (pwrk->state != PMCS_WORK_STATE_TIMED_OUT) {
183 		pwrk->state = PMCS_WORK_STATE_INTR;
184 	}
185 
186 	/*
187 	 * Some SATA and SAS commands are run in "WAIT" mode.
188 	 * We can tell this from the tag type. In this case,
189 	 * we just do a wakeup (not a callback).
190 	 */
191 	tag_type = PMCS_TAG_TYPE(pwrk->htag);
192 	if (tag_type == PMCS_TAG_TYPE_WAIT) {
193 		ASSERT(PMCS_TAG_TYPE(pwrk->htag) == PMCS_TAG_TYPE_WAIT);
194 		if (pwrk->arg && amt) {
195 			(void) memcpy(pwrk->arg, ioccb->iomb, amt);
196 		}
197 		cv_signal(&pwrk->sleep_cv);
198 		mutex_exit(&pwrk->lock);
199 		kmem_cache_free(pwp->iocomp_cb_cache, ioccb);
200 		return;
201 	}
202 	ASSERT(tag_type == PMCS_TAG_TYPE_CBACK);
203 
204 #ifdef	DEBUG
205 	pwp->ltime[pwp->lti] = gethrtime();
206 	pwp->ltags[pwp->lti++] = pwrk->htag;
207 #endif
208 
209 	ioccb->pwrk = pwrk;
210 
211 	/*
212 	 * Only update state to IOCOMPQ if we were in the INTR state.
213 	 * Any other state (e.g. TIMED_OUT, ABORTED) needs to remain.
214 	 */
215 	if (pwrk->state == PMCS_WORK_STATE_INTR) {
216 		pwrk->state = PMCS_WORK_STATE_IOCOMPQ;
217 	}
218 
219 	mutex_enter(&pwp->cq_lock);
220 	if (pwp->iocomp_cb_tail) {
221 		pwp->iocomp_cb_tail->next = ioccb;
222 		pwp->iocomp_cb_tail = ioccb;
223 	} else {
224 		pwp->iocomp_cb_head = ioccb;
225 		pwp->iocomp_cb_tail = ioccb;
226 	}
227 	ioccb->next = NULL;
228 	mutex_exit(&pwp->cq_lock);
229 
230 	mutex_exit(&pwrk->lock);
231 	/* Completion queue will be run at end of pmcs_iodone_intr */
232 }
233 
234 
235 static void
236 pmcs_process_completion(pmcs_hw_t *pwp, void *iomb, size_t amt)
237 {
238 	pmcwork_t *pwrk;
239 	uint32_t htag = LE_32(((uint32_t *)iomb)[1]);
240 
241 	pwrk = pmcs_tag2wp(pwp, htag);
242 	if (pwrk == NULL) {
243 		pmcs_work_not_found(pwp, htag, iomb);
244 		return;
245 	}
246 
247 	pmcs_complete_work(pwp, pwrk, iomb, amt);
248 	/*
249 	 * The pwrk lock is now released
250 	 */
251 }
252 
253 static void
254 pmcs_kill_port(pmcs_hw_t *pwp, int portid)
255 {
256 	pmcs_phy_t *pptr = pwp->ports[portid];
257 
258 	if (pptr == NULL) {
259 		return;
260 	}
261 
262 	/*
263 	 * Clear any subsidiary phys
264 	 */
265 	mutex_enter(&pwp->lock);
266 
267 	for (pptr = pwp->root_phys; pptr; pptr = pptr->sibling) {
268 		pmcs_lock_phy(pptr);
269 		if (pptr->link_rate && pptr->portid == portid &&
270 		    pptr->subsidiary) {
271 			pmcs_clear_phy(pwp, pptr);
272 		}
273 		pmcs_unlock_phy(pptr);
274 	}
275 
276 	pptr = pwp->ports[portid];
277 	pwp->ports[portid] = NULL;
278 	mutex_exit(&pwp->lock);
279 
280 	pmcs_lock_phy(pptr);
281 	pmcs_kill_changed(pwp, pptr, 0);
282 	pmcs_unlock_phy(pptr);
283 
284 	RESTART_DISCOVERY(pwp);
285 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "PortID 0x%x Cleared", portid);
286 }
287 
288 void
289 pmcs_process_sas_hw_event(pmcs_hw_t *pwp, void *iomb, size_t amt)
290 {
291 	uint32_t w1 = LE_32(((uint32_t *)iomb)[1]);
292 	uint32_t w3 = LE_32(((uint32_t *)iomb)[3]);
293 	char buf[32];
294 	uint8_t phynum = IOP_EVENT_PHYNUM(w1);
295 	uint8_t portid = IOP_EVENT_PORTID(w1);
296 	pmcs_iport_t *iport;
297 	pmcs_phy_t *pptr, *subphy, *tphyp;
298 	int need_ack = 0;
299 	int primary;
300 
301 	switch (IOP_EVENT_EVENT(w1)) {
302 	case IOP_EVENT_PHY_STOP_STATUS:
303 		if (IOP_EVENT_STATUS(w1)) {
304 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
305 			    "PORT %d failed to stop (0x%x)",
306 			    phynum, IOP_EVENT_STATUS(w1));
307 		} else {
308 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
309 			    "PHY 0x%x Stopped", phynum);
310 			mutex_enter(&pwp->lock);
311 			pptr = pwp->root_phys + phynum;
312 			pmcs_lock_phy(pptr);
313 			mutex_exit(&pwp->lock);
314 			if (pptr->configured) {
315 				pmcs_kill_changed(pwp, pptr, 0);
316 			} else {
317 				pmcs_set_changed(pwp, pptr, B_TRUE, 0);
318 			}
319 			pmcs_unlock_phy(pptr);
320 			RESTART_DISCOVERY(pwp);
321 		}
322 		/* Reposition htag to the 'expected' position. */
323 		((uint32_t *)iomb)[1] = ((uint32_t *)iomb)[2];
324 		pmcs_process_completion(pwp, iomb, amt);
325 		break;
326 	case IOP_EVENT_SAS_PHY_UP:
327 	{
328 		static const uint8_t sas_identify_af_endian_xfvec[] = {
329 			0x5c, 0x5a, 0x56, 0x00
330 		};
331 		pmcs_phy_t *rp;
332 		sas_identify_af_t af;
333 
334 		/*
335 		 * If we're not at running state, don't do anything
336 		 */
337 		mutex_enter(&pwp->lock);
338 		if (pwp->state != STATE_RUNNING) {
339 			mutex_exit(&pwp->lock);
340 			break;
341 		}
342 		pptr = pwp->root_phys + phynum;
343 		pmcs_lock_phy(pptr);
344 
345 		/*
346 		 * No need to lock the primary root PHY.  It can never go
347 		 * away, and we're only concerned with the port width and
348 		 * the portid, both of which only ever change in this function.
349 		 */
350 		rp = pwp->ports[portid];
351 
352 		mutex_exit(&pwp->lock);
353 
354 		pmcs_endian_transform(pwp, &af, &((uint32_t *)iomb)[4],
355 		    sas_identify_af_endian_xfvec);
356 
357 		/* Copy the remote address into our phy handle */
358 		(void) memcpy(pptr->sas_address, af.sas_address, 8);
359 
360 		/*
361 		 * Check to see if there is a PortID already active.
362 		 */
363 		if (rp) {
364 			if (rp->portid != portid) {
365 				pmcs_unlock_phy(pptr);
366 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
367 				    "PortID 0x%x: PHY 0x%x SAS LINK UP IS FOR "
368 				    "A DIFFERENT PORTID 0x%x", rp->portid,
369 				    phynum, portid);
370 				break;
371 			}
372 
373 			/*
374 			 * If the dtype isn't NOTHING, then this is actually
375 			 * the primary PHY for this port.  It probably went
376 			 * down and came back up, so be sure not to mark it
377 			 * as a subsidiary.
378 			 */
379 			if (pptr->dtype == NOTHING) {
380 				pptr->subsidiary = 1;
381 			}
382 			pptr->link_rate =
383 			    pmcs_link_rate(IOP_EVENT_LINK_RATE(w1));
384 			pptr->portid = portid;
385 			pptr->dead = 0;
386 			pmcs_unlock_phy(pptr);
387 
388 			rp->width = IOP_EVENT_NPIP(w3);
389 
390 			/* Add this PHY to the phymap */
391 			if (sas_phymap_phy_add(pwp->hss_phymap, phynum,
392 			    pwp->sas_wwns[0],
393 			    pmcs_barray2wwn(pptr->sas_address)) !=
394 			    DDI_SUCCESS) {
395 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
396 				    "Unable to add phy %u for 0x%" PRIx64 ".0x%"
397 				    PRIx64, phynum, pwp->sas_wwns[rp->phynum],
398 				    pmcs_barray2wwn(pptr->sas_address));
399 			}
400 
401 			/* Get our iport, if attached, and set it up */
402 			pmcs_lock_phy(pptr);
403 			iport = pmcs_get_iport_by_phy(pwp, pptr);
404 			pmcs_unlock_phy(pptr);
405 			if (iport) {
406 				pptr->iport = iport;
407 				primary = !pptr->subsidiary;
408 
409 				mutex_enter(&iport->lock);
410 				if (primary) {
411 					iport->pptr = pptr;
412 				}
413 				if (iport->ua_state == UA_ACTIVE) {
414 					pmcs_add_phy_to_iport(iport, pptr);
415 				}
416 				mutex_exit(&iport->lock);
417 				pmcs_rele_iport(iport);
418 			}
419 
420 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
421 			    "PortID 0x%x: PHY 0x%x SAS LINK UP WIDENS PORT "
422 			    "TO %d PHYS", portid, phynum, rp->width);
423 
424 			break;
425 		}
426 
427 		/*
428 		 * Check to see if anything is here already
429 		 */
430 		if (pptr->dtype != NOTHING && pptr->configured) {
431 			pmcs_unlock_phy(pptr);
432 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
433 			    "PortID 0x%x: SAS PHY 0x%x UP HITS EXISTING "
434 			    "CONFIGURED TREE", portid, phynum);
435 			break;
436 		}
437 
438 		if (af.address_frame_type != SAS_AF_IDENTIFY) {
439 			pmcs_unlock_phy(pptr);
440 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
441 			    "SAS link up on phy 0x%x, "
442 			    "but unexpected frame type 0x%x found", phynum,
443 			    af.address_frame_type);
444 			break;
445 		}
446 		pptr->width = IOP_EVENT_NPIP(w3);
447 		pptr->portid = portid;
448 		pptr->dead = 0;
449 		pptr->link_rate = pmcs_link_rate(IOP_EVENT_LINK_RATE(w1));
450 
451 		/*
452 		 * Check to see whether this is an expander or an endpoint
453 		 */
454 		switch (af.device_type) {
455 		case SAS_IF_DTYPE_ENDPOINT:
456 			pptr->pend_dtype = SAS;
457 			pptr->dtype = SAS;
458 			break;
459 		case SAS_IF_DTYPE_EDGE:
460 		case SAS_IF_DTYPE_FANOUT:
461 			pptr->pend_dtype = EXPANDER;
462 			pptr->dtype = EXPANDER;
463 			break;
464 		default:
465 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
466 			    "unknown device type 0x%x", af.device_type);
467 			pptr->pend_dtype = NOTHING;
468 			pptr->dtype = NOTHING;
469 			break;
470 		}
471 
472 		/*
473 		 * If this is a direct-attached SAS drive, do the spinup
474 		 * release now.
475 		 */
476 		if (pptr->dtype == SAS) {
477 			pptr->spinup_hold = 1;
478 			pmcs_spinup_release(pwp, pptr);
479 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
480 			    "Release spinup hold on PHY 0x%x", phynum);
481 		}
482 
483 		pmcs_set_changed(pwp, pptr, B_TRUE, 0);
484 		if (pptr->width > 1) {
485 			pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL,
486 			    "PortID 0x%x: PHY 0x%x SAS"
487 			    " LINK UP @ %s Gb with %d phys/s", portid, phynum,
488 			    pmcs_get_rate(pptr->link_rate), pptr->width);
489 		} else {
490 			pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL,
491 			    "PortID 0x%x: PHY 0x%x SAS"
492 			    " LINK UP @ %s Gb/s", portid, phynum,
493 			    pmcs_get_rate(pptr->link_rate));
494 		}
495 		pmcs_unlock_phy(pptr);
496 
497 		/* Add this PHY to the phymap */
498 		if (sas_phymap_phy_add(pwp->hss_phymap, phynum,
499 		    pwp->sas_wwns[0],
500 		    pmcs_barray2wwn(pptr->sas_address)) != DDI_SUCCESS) {
501 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
502 			    "Unable to add phy %u for 0x%" PRIx64 ".0x%"
503 			    PRIx64, phynum, pwp->sas_wwns[pptr->phynum],
504 			    pmcs_barray2wwn(pptr->sas_address));
505 		}
506 
507 		/* Get a pointer to our iport and set it up if attached */
508 		pmcs_lock_phy(pptr);
509 		iport = pmcs_get_iport_by_phy(pwp, pptr);
510 		pmcs_unlock_phy(pptr);
511 		if (iport) {
512 			pptr->iport = iport;
513 			primary = !pptr->subsidiary;
514 
515 			mutex_enter(&iport->lock);
516 			if (primary) {
517 				iport->pptr = pptr;
518 			}
519 			if (iport->ua_state == UA_ACTIVE) {
520 				pmcs_add_phy_to_iport(iport, pptr);
521 			}
522 			mutex_exit(&iport->lock);
523 			pmcs_rele_iport(iport);
524 		}
525 
526 		pmcs_lock_phy(pptr);
527 		pmcs_smhba_log_sysevent(pwp, ESC_SAS_PHY_EVENT,
528 		    SAS_PHY_ONLINE, pptr);
529 		pmcs_unlock_phy(pptr);
530 
531 		mutex_enter(&pwp->lock);
532 		pwp->ports[portid] = pptr;
533 		mutex_exit(&pwp->lock);
534 		RESTART_DISCOVERY(pwp);
535 
536 		break;
537 	}
538 	case IOP_EVENT_SATA_PHY_UP:
539 		/*
540 		 * If we're not at running state, don't do anything
541 		 */
542 		mutex_enter(&pwp->lock);
543 		if (pwp->state != STATE_RUNNING) {
544 			mutex_exit(&pwp->lock);
545 			break;
546 		}
547 
548 		/*
549 		 * Check to see if anything is here already
550 		 */
551 		pmcs_lock_phy(pwp->root_phys + phynum);
552 		pptr = pwp->root_phys + phynum;
553 		mutex_exit(&pwp->lock);
554 
555 		if (pptr->dtype != NOTHING && pptr->configured) {
556 			pmcs_unlock_phy(pptr);
557 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
558 			    "PortID 0x%x: SATA PHY 0x%x"
559 			    " UP HITS EXISTING CONFIGURED TREE",
560 			    portid, phynum);
561 			break;
562 		}
563 
564 		pptr->width = 1;
565 		pptr->dead = 0;
566 
567 		/*
568 		 * Install the PHY number in the least significant byte
569 		 * with a NAA=3 (locally assigned address) in the most
570 		 * significant nubble.
571 		 *
572 		 * Later, we'll either use that or dig a
573 		 * WWN out of words 108..111.
574 		 */
575 		pptr->sas_address[0] = 0x30;
576 		pptr->sas_address[1] = 0;
577 		pptr->sas_address[2] = 0;
578 		pptr->sas_address[3] = 0;
579 		pptr->sas_address[4] = 0;
580 		pptr->sas_address[5] = 0;
581 		pptr->sas_address[6] = 0;
582 		pptr->sas_address[7] = phynum;
583 		pptr->portid = portid;
584 		pptr->link_rate = pmcs_link_rate(IOP_EVENT_LINK_RATE(w1));
585 		pptr->dtype = SATA;
586 		pmcs_set_changed(pwp, pptr, B_TRUE, 0);
587 		pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL,
588 		    "PortID 0x%x: PHY 0x%x SATA LINK UP @ %s Gb/s",
589 		    pptr->portid, phynum, pmcs_get_rate(pptr->link_rate));
590 		pmcs_unlock_phy(pptr);
591 
592 		/* Add this PHY to the phymap */
593 		if (sas_phymap_phy_add(pwp->hss_phymap, phynum,
594 		    pwp->sas_wwns[0],
595 		    pmcs_barray2wwn(pptr->sas_address)) != DDI_SUCCESS) {
596 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
597 			    "Unable to add phy %u for 0x%" PRIx64 ".0x%"
598 			    PRIx64, phynum, pwp->sas_wwns[pptr->phynum],
599 			    pmcs_barray2wwn(pptr->sas_address));
600 		}
601 
602 		/* Get our iport, if attached, and set it up */
603 		pmcs_lock_phy(pptr);
604 		iport = pmcs_get_iport_by_phy(pwp, pptr);
605 		pmcs_unlock_phy(pptr);
606 		if (iport) {
607 			pptr->iport = iport;
608 
609 			mutex_enter(&iport->lock);
610 			iport->pptr = pptr;
611 			if (iport->ua_state == UA_ACTIVE) {
612 				pmcs_add_phy_to_iport(iport, pptr);
613 				ASSERT(iport->nphy == 1);
614 				iport->nphy = 1;
615 			}
616 			mutex_exit(&iport->lock);
617 			pmcs_rele_iport(iport);
618 		}
619 
620 		pmcs_lock_phy(pptr);
621 		pmcs_smhba_log_sysevent(pwp, ESC_SAS_PHY_EVENT,
622 		    SAS_PHY_ONLINE, pptr);
623 		pmcs_unlock_phy(pptr);
624 
625 		mutex_enter(&pwp->lock);
626 		pwp->ports[pptr->portid] = pptr;
627 		mutex_exit(&pwp->lock);
628 		RESTART_DISCOVERY(pwp);
629 		break;
630 
631 	case IOP_EVENT_SATA_SPINUP_HOLD:
632 		tphyp = (pmcs_phy_t *)(pwp->root_phys + phynum);
633 		/*
634 		 * No need to lock the entire tree for this
635 		 */
636 		mutex_enter(&tphyp->phy_lock);
637 		tphyp->spinup_hold = 1;
638 		pmcs_spinup_release(pwp, tphyp);
639 		mutex_exit(&tphyp->phy_lock);
640 		break;
641 	case IOP_EVENT_PHY_DOWN:
642 		/*
643 		 * If we're not at running state, don't do anything
644 		 */
645 		mutex_enter(&pwp->lock);
646 		if (pwp->state != STATE_RUNNING) {
647 			mutex_exit(&pwp->lock);
648 			break;
649 		}
650 		pptr = pwp->ports[portid];
651 
652 		subphy = pwp->root_phys + phynum;
653 		/*
654 		 * subphy is a pointer to the PHY corresponding to the incoming
655 		 * event. pptr points to the primary PHY for the corresponding
656 		 * port.  So, subphy and pptr may or may not be the same PHY,
657 		 * but that doesn't change what we need to do with each.
658 		 */
659 		ASSERT(subphy);
660 		mutex_exit(&pwp->lock);
661 
662 		if (pptr == NULL) {
663 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
664 			    "PortID 0x%x: PHY 0x%x LINK DOWN- no portid ptr",
665 			    portid, phynum);
666 			break;
667 		}
668 		if (IOP_EVENT_PORT_STATE(w3) == IOP_EVENT_PS_NIL) {
669 			pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
670 			    "PortID 0x%x: PHY 0x%x NOT VALID YET",
671 			    portid, phynum);
672 			need_ack = 1;
673 			break;
674 		}
675 		if (IOP_EVENT_PORT_STATE(w3) == IOP_EVENT_PS_IN_RESET) {
676 			pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
677 			    "PortID 0x%x: PHY 0x%x IN RESET",
678 			    portid, phynum);
679 			/* Entire port is down due to a host-initiated reset */
680 			mutex_enter(&pptr->phy_lock);
681 			iport = pptr->iport;
682 			mutex_exit(&pptr->phy_lock);
683 			if (iport) {
684 				mutex_enter(&iport->lock);
685 				pmcs_iport_teardown_phys(iport);
686 				mutex_exit(&iport->lock);
687 			}
688 
689 			break;
690 		}
691 		if (IOP_EVENT_PORT_STATE(w3) == IOP_EVENT_PS_LOSTCOMM) {
692 			pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
693 			    "PortID 0x%x: PHY 0x%x TEMPORARILY DOWN",
694 			    portid, phynum);
695 			need_ack = 1;
696 			break;
697 		}
698 
699 		if (IOP_EVENT_PORT_STATE(w3) == IOP_EVENT_PS_VALID) {
700 			/*
701 			 * This is not the last phy in the port, so if this
702 			 * is the primary PHY, promote another PHY to primary.
703 			 */
704 			if (pptr == subphy) {
705 				primary = !subphy->subsidiary;
706 				ASSERT(primary);
707 
708 				tphyp = pptr;
709 				pptr = pmcs_promote_next_phy(tphyp);
710 
711 				if (pptr) {
712 					/* Update primary pptr in ports */
713 					pwp->ports[portid] = pptr;
714 					pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr,
715 					    NULL, "PortID 0x%x: PHY 0x%x "
716 					    "promoted to primary", portid,
717 					    pptr->phynum);
718 				} else {
719 					/* This should not happen */
720 					pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr,
721 					    NULL, "PortID 0x%x: PHY 0x%x: "
722 					    "unable to promote phy", portid,
723 					    phynum);
724 				}
725 			}
726 
727 			/*
728 			 * Drop port width on the primary phy handle
729 			 * No need to lock the entire tree for this
730 			 */
731 			mutex_enter(&pptr->phy_lock);
732 			pptr->width = IOP_EVENT_NPIP(w3);
733 			mutex_exit(&pptr->phy_lock);
734 
735 			/* Clear the iport reference on the subphy */
736 			mutex_enter(&subphy->phy_lock);
737 			iport = subphy->iport;
738 			subphy->iport = NULL;
739 			mutex_exit(&subphy->phy_lock);
740 
741 			/*
742 			 * If the iport was set on this phy, decrement its
743 			 * nphy count and remove this phy from the phys list.
744 			 */
745 			if (iport) {
746 				mutex_enter(&iport->lock);
747 				pmcs_remove_phy_from_iport(iport, subphy);
748 				mutex_exit(&iport->lock);
749 			}
750 
751 			pmcs_lock_phy(subphy);
752 			if (subphy->subsidiary)
753 				pmcs_clear_phy(pwp, subphy);
754 			pmcs_unlock_phy(subphy);
755 
756 			/* Remove this PHY from the phymap */
757 			if (sas_phymap_phy_rem(pwp->hss_phymap, phynum) !=
758 			    DDI_SUCCESS) {
759 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
760 				    "Unable to remove phy %u for 0x%" PRIx64
761 				    ".0x%" PRIx64, phynum,
762 				    pwp->sas_wwns[pptr->phynum],
763 				    pmcs_barray2wwn((pwp->root_phys +
764 				    pptr->phynum)-> sas_address));
765 			}
766 
767 			pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL,
768 			    "PortID 0x%x: PHY 0x%x LINK DOWN NARROWS PORT "
769 			    "TO %d PHYS", portid, phynum, pptr->width);
770 			break;
771 		}
772 		if (IOP_EVENT_PORT_STATE(w3) != IOP_EVENT_PS_INVALID) {
773 			pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
774 			    "PortID 0x%x: PHY 0x%x LINK DOWN NOT HANDLED "
775 			    "(state 0x%x)", portid, phynum,
776 			    IOP_EVENT_PORT_STATE(w3));
777 			need_ack = 1;
778 			break;
779 		}
780 		/* Remove this PHY from the phymap */
781 		if (sas_phymap_phy_rem(pwp->hss_phymap, phynum) !=
782 		    DDI_SUCCESS) {
783 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
784 			    "Unable to remove phy %u for 0x%" PRIx64
785 			    ".0x%" PRIx64, phynum,
786 			    pwp->sas_wwns[pptr->phynum],
787 			    pmcs_barray2wwn(
788 			    (pwp->root_phys + pptr->phynum)->sas_address));
789 		}
790 
791 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
792 		    "PortID 0x%x: PHY 0x%x LINK DOWN (port invalid)",
793 		    portid, phynum);
794 
795 		/*
796 		 * Last PHY on the port.
797 		 * Assumption: pptr and subphy are both "valid"
798 		 *
799 		 * Drop port width on the primary phy handle
800 		 * Report the event while we've got the lock
801 		 */
802 		mutex_enter(&pptr->phy_lock);
803 		pptr->width = 0;
804 		pmcs_smhba_log_sysevent(pwp, ESC_SAS_PHY_EVENT,
805 		    SAS_PHY_OFFLINE, pptr);
806 		mutex_exit(&pptr->phy_lock);
807 
808 		/* Clear the iport reference on the subphy */
809 		mutex_enter(&subphy->phy_lock);
810 		iport = subphy->iport;
811 		subphy->iport = NULL;
812 		mutex_exit(&subphy->phy_lock);
813 
814 		/*
815 		 * If the iport was set on this phy, decrement its
816 		 * nphy count and remove this phy from the phys list.
817 		 * Also, clear the iport's pptr as this port is now
818 		 * down.
819 		 */
820 		if (iport) {
821 			mutex_enter(&iport->lock);
822 			pmcs_remove_phy_from_iport(iport, subphy);
823 			iport->pptr = NULL;
824 			iport->ua_state = UA_PEND_DEACTIVATE;
825 			mutex_exit(&iport->lock);
826 		}
827 
828 		pmcs_lock_phy(subphy);
829 		if (subphy->subsidiary)
830 			pmcs_clear_phy(pwp, subphy);
831 		pmcs_unlock_phy(subphy);
832 
833 		/*
834 		 * Since we're now really dead, it's time to clean up.
835 		 */
836 		pmcs_kill_port(pwp, portid);
837 		need_ack = 1;
838 
839 		break;
840 	case IOP_EVENT_BROADCAST_CHANGE:
841 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
842 		    "PortID 0x%x: PHY 0x%x Broadcast Change", portid, phynum);
843 		need_ack = 1;
844 		mutex_enter(&pwp->lock);
845 		pptr = pwp->ports[portid];
846 		if (pptr) {
847 			pmcs_lock_phy(pptr);
848 			if (pptr->phynum == phynum) {
849 				pmcs_set_changed(pwp, pptr, B_TRUE, 0);
850 			}
851 			pmcs_smhba_log_sysevent(pwp, ESC_SAS_HBA_PORT_BROADCAST,
852 			    SAS_PORT_BROADCAST_CHANGE, pptr);
853 			pmcs_unlock_phy(pptr);
854 		}
855 		mutex_exit(&pwp->lock);
856 		RESTART_DISCOVERY(pwp);
857 		break;
858 	case IOP_EVENT_BROADCAST_SES:
859 		EVT_PRT(pwp, IOP_EVENT_BROADCAST_SES, phynum);
860 		mutex_enter(&pwp->lock);
861 		pptr = pwp->ports[portid];
862 		mutex_exit(&pwp->lock);
863 		if (pptr) {
864 			pmcs_lock_phy(pptr);
865 			pmcs_smhba_log_sysevent(pwp, ESC_SAS_HBA_PORT_BROADCAST,
866 			    SAS_PORT_BROADCAST_SES, pptr);
867 			pmcs_unlock_phy(pptr);
868 		}
869 		break;
870 	case IOP_EVENT_PHY_ERR_INBOUND_CRC:
871 	{
872 		char buf[32];
873 		(void) snprintf(buf, sizeof (buf), "Inbound PHY CRC error");
874 		need_ack = 1;
875 		break;
876 	}
877 	case IOP_EVENT_HARD_RESET_RECEIVED:
878 		EVT_PRT(pwp, IOP_EVENT_HARD_RESET_RECEIVED, phynum);
879 		break;
880 	case IOP_EVENT_EVENT_ID_FRAME_TIMO:
881 		EVT_PRT(pwp, IOP_EVENT_EVENT_ID_FRAME_TIMO, phynum);
882 		break;
883 	case IOP_EVENT_BROADCAST_EXP:
884 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
885 		    "PortID 0x%x: PHY 0x%x Broadcast Exp Change",
886 		    portid, phynum);
887 		/*
888 		 * Comparing Section 6.8.1.4 of SMHBA (rev 7) spec and Section
889 		 * 7.2.3 of SAS2 (Rev 15) spec,
890 		 * _BROADCAST_EXPANDER event corresponds to _D01_4 primitive
891 		 */
892 		mutex_enter(&pwp->lock);
893 		pptr = pwp->ports[portid];
894 		mutex_exit(&pwp->lock);
895 		if (pptr) {
896 			pmcs_lock_phy(pptr);
897 			pmcs_smhba_log_sysevent(pwp, ESC_SAS_HBA_PORT_BROADCAST,
898 			    SAS_PORT_BROADCAST_D01_4, pptr);
899 			pmcs_unlock_phy(pptr);
900 		}
901 		break;
902 	case IOP_EVENT_PHY_START_STATUS:
903 		switch (IOP_EVENT_STATUS(w1)) {
904 		case IOP_PHY_START_OK:
905 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
906 			    "PHY 0x%x Started", phynum);
907 			break;
908 		case IOP_PHY_START_ALREADY:
909 			pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
910 			    "PHY 0x%x Started (Already)", phynum);
911 			break;
912 		case IOP_PHY_START_INVALID:
913 			pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
914 			    "PHY 0x%x failed to start (invalid phy)", phynum);
915 			break;
916 		case IOP_PHY_START_ERROR:
917 			pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
918 			    "PHY 0x%x Start Error", phynum);
919 			break;
920 		default:
921 			pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
922 			    "PHY 0x%x failed to start (0x%x)", phynum,
923 			    IOP_EVENT_STATUS(w1));
924 			break;
925 		}
926 		/* Reposition htag to the 'expected' position. */
927 		((uint32_t *)iomb)[1] = ((uint32_t *)iomb)[2];
928 		pmcs_process_completion(pwp, iomb, amt);
929 		break;
930 	case IOP_EVENT_PHY_ERR_INVALID_DWORD:
931 		need_ack = 1;
932 		EVT_PRT(pwp, IOP_EVENT_PHY_ERR_INVALID_DWORD, phynum);
933 		break;
934 	case IOP_EVENT_PHY_ERR_DISPARITY_ERROR:
935 		need_ack = 1;
936 		EVT_PRT(pwp, IOP_EVENT_PHY_ERR_DISPARITY_ERROR, phynum);
937 		break;
938 	case IOP_EVENT_PHY_ERR_CODE_VIOLATION:
939 		need_ack = 1;
940 		EVT_PRT(pwp, IOP_EVENT_PHY_ERR_CODE_VIOLATION, phynum);
941 		break;
942 	case IOP_EVENT_PHY_ERR_LOSS_OF_DWORD_SYN:
943 		need_ack = 1;
944 		EVT_PRT(pwp, IOP_EVENT_PHY_ERR_LOSS_OF_DWORD_SYN, phynum);
945 		break;
946 	case IOP_EVENT_PHY_ERR_PHY_RESET_FAILD:
947 		need_ack = 1;
948 		EVT_PRT(pwp, IOP_EVENT_PHY_ERR_PHY_RESET_FAILD, phynum);
949 		break;
950 	case IOP_EVENT_PORT_RECOVERY_TIMER_TMO:
951 		EVT_PRT(pwp, IOP_EVENT_PORT_RECOVERY_TIMER_TMO, phynum);
952 		break;
953 	case IOP_EVENT_PORT_RECOVER:
954 		EVT_PRT(pwp, IOP_EVENT_PORT_RECOVER, phynum);
955 		break;
956 	case IOP_EVENT_PORT_INVALID:
957 		mutex_enter(&pwp->lock);
958 		if (pwp->state != STATE_RUNNING) {
959 			mutex_exit(&pwp->lock);
960 			break;
961 		}
962 		mutex_exit(&pwp->lock);
963 		pmcs_kill_port(pwp, portid);
964 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
965 		    "PortID 0x%x: PORT Now Invalid", portid);
966 		break;
967 	case IOP_EVENT_PORT_RESET_TIMER_TMO:
968 		EVT_PRT(pwp, IOP_EVENT_PORT_RESET_TIMER_TMO, phynum);
969 		break;
970 	case IOP_EVENT_PORT_RESET_COMPLETE:
971 		EVT_PRT(pwp, IOP_EVENT_PORT_RESET_COMPLETE, phynum);
972 		break;
973 	case IOP_EVENT_BROADCAST_ASYNC_EVENT:
974 		EVT_PRT(pwp, IOP_EVENT_BROADCAST_ASYNC_EVENT, phynum);
975 		/*
976 		 * Comparing Section 6.8.1.4 of SMHBA (rev 7) spec and Section
977 		 * 7.2.3 of SAS2 (Rev 15) spec,
978 		 * _BROADCAST_ASYNC event corresponds to _D04_7 primitive
979 		 */
980 		mutex_enter(&pwp->lock);
981 		pptr = pwp->ports[portid];
982 		mutex_exit(&pwp->lock);
983 		if (pptr) {
984 			pmcs_lock_phy(pptr);
985 			pmcs_smhba_log_sysevent(pwp, ESC_SAS_HBA_PORT_BROADCAST,
986 			    SAS_PORT_BROADCAST_D04_7, pptr);
987 			pmcs_unlock_phy(pptr);
988 		}
989 		break;
990 	default:
991 		(void) snprintf(buf, sizeof (buf),
992 		    "unknown SAS H/W Event PHY 0x%x", phynum);
993 		pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, iomb);
994 		break;
995 	}
996 	if (need_ack) {
997 		mutex_enter(&pwp->lock);
998 		/*
999 		 * Don't lock the entire tree for this.  Just grab the mutex
1000 		 * on the root PHY.
1001 		 */
1002 		tphyp = pwp->root_phys + phynum;
1003 		mutex_enter(&tphyp->phy_lock);
1004 		tphyp->hw_event_ack = w1;
1005 		mutex_exit(&tphyp->phy_lock);
1006 		mutex_exit(&pwp->lock);
1007 		pmcs_ack_events(pwp);
1008 	}
1009 }
1010 
1011 static void
1012 pmcs_process_echo_completion(pmcs_hw_t *pwp, void *iomb, size_t amt)
1013 {
1014 	echo_test_t fred;
1015 	pmcwork_t *pwrk;
1016 	uint32_t *msg = iomb, htag = LE_32(msg[1]);
1017 	pwrk = pmcs_tag2wp(pwp, htag);
1018 	if (pwrk) {
1019 		(void) memcpy(&fred, &((uint32_t *)iomb)[2], sizeof (fred));
1020 		fred.ptr[0]++;
1021 		msg[2] = LE_32(PMCOUT_STATUS_OK);
1022 		pmcs_complete_work(pwp, pwrk, msg, amt);
1023 	} else {
1024 		pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
1025 		    "ECHO completion with no work structure", iomb);
1026 	}
1027 }
1028 
1029 static void
1030 pmcs_process_ssp_event(pmcs_hw_t *pwp, void *iomb, size_t amt)
1031 {
1032 	_NOTE(ARGUNUSED(amt));
1033 	uint32_t status, htag, *w;
1034 	pmcwork_t *pwrk;
1035 	pmcs_phy_t *phyp = NULL;
1036 	char *path;
1037 
1038 	w = iomb;
1039 	htag = LE_32(w[1]);
1040 	status = LE_32(w[2]);
1041 
1042 
1043 	pwrk = pmcs_tag2wp(pwp, htag);
1044 	if (pwrk == NULL) {
1045 		path = "????";
1046 	} else {
1047 		phyp = pwrk->phy;
1048 		path = pwrk->phy->path;
1049 	}
1050 
1051 	if (status != PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED) {
1052 		char buf[20];
1053 		const char *emsg = pmcs_status_str(status);
1054 
1055 		if (emsg == NULL) {
1056 			(void) snprintf(buf, sizeof (buf), "Status 0x%x",
1057 			    status);
1058 			emsg = buf;
1059 		}
1060 		pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, NULL, "%s: Bad SAS Status "
1061 		    "(tag 0x%x) %s on %s", __func__, htag, emsg, path);
1062 		if (pwrk != NULL) {
1063 			/*
1064 			 * There may be pending command on a target device.
1065 			 * Or, it may be a double fault.
1066 			 */
1067 			pmcs_start_ssp_event_recovery(pwp, pwrk, iomb, amt);
1068 		}
1069 	} else {
1070 		pmcs_prt(pwp, PMCS_PRT_DEBUG2, phyp, NULL,
1071 		    "%s: tag %x put onto the wire for %s",
1072 		    __func__, htag, path);
1073 		if (pwrk) {
1074 			pwrk->onwire = 1;
1075 			mutex_exit(&pwrk->lock);
1076 		}
1077 	}
1078 }
1079 
1080 static void
1081 pmcs_process_sata_event(pmcs_hw_t *pwp, void *iomb, size_t amt)
1082 {
1083 	_NOTE(ARGUNUSED(amt));
1084 	pmcwork_t *pwrk = NULL;
1085 	pmcs_phy_t *pptr;
1086 	uint32_t status, htag, *w;
1087 	char *path;
1088 
1089 	w = iomb;
1090 	htag = LE_32(w[1]);
1091 	status = LE_32(w[2]);
1092 
1093 	/*
1094 	 * If the status is PMCOUT_STATUS_XFER_ERROR_ABORTED_NCQ_MODE,
1095 	 * we have to issue a READ LOG EXT ATA (page 0x10) command
1096 	 * to the device. In this case, htag is not valid.
1097 	 *
1098 	 * If the status is PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED, we're
1099 	 * just noting that an I/O got put onto the wire.
1100 	 *
1101 	 * Othewise, other errors are indicative that things need to
1102 	 * be aborted.
1103 	 */
1104 	path = NULL;
1105 	if (htag) {
1106 		pwrk = pmcs_tag2wp(pwp, htag);
1107 		if (pwrk) {
1108 			pmcs_lock_phy(pwrk->phy);
1109 			pptr = pwrk->phy;
1110 			path = pptr->path;
1111 		}
1112 	}
1113 	if (path == NULL) {
1114 		mutex_enter(&pwp->lock);
1115 		pptr = pmcs_find_phy_by_devid(pwp, LE_32(w[4]));
1116 		/* This PHY is now locked */
1117 		mutex_exit(&pwp->lock);
1118 		if (pptr) {
1119 			path = pptr->path;
1120 		} else {
1121 			path = "????";
1122 		}
1123 	}
1124 
1125 	if (status != PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED) {
1126 		char buf[20];
1127 		const char *emsg = pmcs_status_str(status);
1128 
1129 		ASSERT(pptr != NULL);
1130 		if (emsg == NULL) {
1131 			(void) snprintf(buf, sizeof (buf), "Status 0x%x",
1132 			    status);
1133 			emsg = buf;
1134 		}
1135 		if (status == PMCOUT_STATUS_XFER_ERROR_ABORTED_NCQ_MODE) {
1136 			ASSERT(pptr != NULL);
1137 			pptr->need_rl_ext = 1;
1138 			htag = 0;
1139 		} else {
1140 			pptr->abort_pending = 1;
1141 		}
1142 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
1143 		    "%s: Bad SATA Status (tag 0x%x) %s on %s",
1144 		    __func__, htag, emsg, path);
1145 		SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
1146 		/*
1147 		 * Unlike SSP devices, we let the abort we
1148 		 * schedule above force the completion of
1149 		 * problem commands.
1150 		 */
1151 		if (pwrk) {
1152 			mutex_exit(&pwrk->lock);
1153 		}
1154 	} else if (status == PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED) {
1155 		pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, NULL,
1156 		    "%s: tag %x put onto the wire for %s",
1157 		    __func__, htag, path);
1158 		if (pwrk) {
1159 			pwrk->onwire = 1;
1160 			mutex_exit(&pwrk->lock);
1161 		}
1162 	}
1163 
1164 	if (pptr) {
1165 		pmcs_unlock_phy(pptr);
1166 	}
1167 }
1168 
1169 static void
1170 pmcs_process_abort_completion(pmcs_hw_t *pwp, void *iomb, size_t amt)
1171 {
1172 	pmcs_phy_t *pptr;
1173 	struct pmcwork *pwrk;
1174 	uint32_t htag = LE_32(((uint32_t *)iomb)[1]);
1175 	uint32_t status = LE_32(((uint32_t *)iomb)[2]);
1176 	uint32_t scp = LE_32(((uint32_t *)iomb)[3]) & 0x1;
1177 	char *path;
1178 
1179 	pwrk = pmcs_tag2wp(pwp, htag);
1180 	if (pwrk == NULL) {
1181 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1182 		    "%s: cannot find work structure for ABORT", __func__);
1183 		return;
1184 	}
1185 
1186 	pptr = pwrk->phy;
1187 	if (pptr) {
1188 		pmcs_lock_phy(pptr);
1189 		pptr->abort_pending = 0;
1190 		pptr->abort_sent = 0;
1191 
1192 		/*
1193 		 * Don't do this if the status was ABORT_IN_PROGRESS and
1194 		 * the scope bit was set
1195 		 */
1196 		if ((status != PMCOUT_STATUS_IO_ABORT_IN_PROGRESS) || !scp) {
1197 			pptr->abort_all_start = 0;
1198 			cv_signal(&pptr->abort_all_cv);
1199 		}
1200 		path = pptr->path;
1201 		pmcs_unlock_phy(pptr);
1202 	} else {
1203 		path = "(no phy)";
1204 	}
1205 
1206 	switch (status) {
1207 	case PMCOUT_STATUS_OK:
1208 		if (scp) {
1209 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
1210 			    "%s: abort all succeeded for %s. (htag=0x%x)",
1211 			    __func__, path, htag);
1212 		} else {
1213 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
1214 			    "%s: abort tag 0x%x succeeded for %s. (htag=0x%x)",
1215 			    __func__, pwrk->abt_htag, path, htag);
1216 		}
1217 		break;
1218 
1219 	case PMCOUT_STATUS_IO_NOT_VALID:
1220 		if (scp) {
1221 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
1222 			    "%s: ABORT %s failed (DEV NOT VALID) for %s. "
1223 			    "(htag=0x%x)", __func__, scp ? "all" : "tag",
1224 			    path, htag);
1225 		} else {
1226 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
1227 			    "%s: ABORT %s failed (I/O NOT VALID) for %s. "
1228 			    "(htag=0x%x)", __func__, scp ? "all" : "tag",
1229 			    path, htag);
1230 		}
1231 		break;
1232 
1233 	case PMCOUT_STATUS_IO_ABORT_IN_PROGRESS:
1234 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, "%s: ABORT %s failed "
1235 		    "for %s, htag 0x%x (ABORT IN PROGRESS)", __func__,
1236 		    scp ? "all" : "tag", path, htag);
1237 		break;
1238 
1239 	default:
1240 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, "%s: Unknown status "
1241 		    "%d for ABORT %s, htag 0x%x, PHY %s", __func__, status,
1242 		    scp ? "all" : "tag", htag, path);
1243 		break;
1244 	}
1245 
1246 	pmcs_complete_work(pwp, pwrk, iomb, amt);
1247 }
1248 
1249 static void
1250 pmcs_process_general_event(pmcs_hw_t *pwp, uint32_t *iomb)
1251 {
1252 	uint32_t htag;
1253 	char local[60];
1254 	struct pmcwork *pwrk;
1255 	int i;
1256 
1257 	if (LE_32(iomb[1]) == INBOUND_IOMB_V_BIT_NOT_SET) {
1258 		(void) snprintf(local, sizeof (local),
1259 		    "VALID bit not set on INBOUND IOMB");
1260 	} else if (LE_32(iomb[1]) ==
1261 	    INBOUND_IOMB_OPC_NOT_SUPPORTED) {
1262 		(void) snprintf(local, sizeof (local),
1263 		    "opcode not set on inbound IOMB");
1264 	} else {
1265 		(void) snprintf(local, sizeof (local),
1266 		    "unknown GENERAL EVENT status (0x%x)",
1267 		    LE_32(iomb[1]));
1268 	}
1269 	/* Pull up bad IOMB into usual position */
1270 	for (i = 0; i < PMCS_MSG_SIZE - 2; i++) {
1271 		iomb[i] = iomb[i+2];
1272 	}
1273 	/* overwrite status with an error */
1274 	iomb[2] = LE_32(PMCOUT_STATUS_PROG_ERROR);
1275 	iomb[PMCS_MSG_SIZE - 2] = 0;
1276 	iomb[PMCS_MSG_SIZE - 1] = 0;
1277 	htag = LE_32(iomb[1]);
1278 	pmcs_print_entry(pwp, PMCS_PRT_DEBUG, local, iomb);
1279 	pwrk = pmcs_tag2wp(pwp, htag);
1280 	if (pwrk) {
1281 		pmcs_complete_work(pwp, pwrk, iomb, PMCS_QENTRY_SIZE);
1282 	}
1283 }
1284 
1285 void
1286 pmcs_general_intr(pmcs_hw_t *pwp)
1287 {
1288 	char local[PMCS_QENTRY_SIZE << 1];
1289 	uint32_t w0, pi, ci;
1290 	uint32_t *ptr, nbuf, lim = 0;
1291 	size_t amt;
1292 
1293 	ci = pmcs_rd_oqci(pwp, PMCS_OQ_GENERAL);
1294 	pi = pmcs_rd_oqpi(pwp, PMCS_OQ_GENERAL);
1295 
1296 	while (ci != pi) {
1297 		OQLIM_CHECK(pwp, lim);
1298 		ptr = GET_OQ_ENTRY(pwp, PMCS_OQ_GENERAL, ci, 0);
1299 		w0 = LE_32(ptr[0]);
1300 		VALID_IOMB_CHECK(pwp, w0, ptr, ci, pi);
1301 		WRONG_OBID_CHECK(pwp, w0, PMCS_OQ_GENERAL);
1302 		COPY_OUTBOUND(pwp, w0, local, nbuf, amt, ptr,
1303 		    PMCS_OQ_GENERAL, ci);
1304 
1305 		switch (w0 & PMCS_IOMB_OPCODE_MASK) {
1306 		case PMCOUT_SSP_COMPLETION:
1307 			/*
1308 			 * We only get SSP completion here for Task Management
1309 			 * completions.
1310 			 */
1311 		case PMCOUT_SMP_COMPLETION:
1312 		case PMCOUT_LOCAL_PHY_CONTROL:
1313 		case PMCOUT_DEVICE_REGISTRATION:
1314 		case PMCOUT_DEREGISTER_DEVICE_HANDLE:
1315 		case PMCOUT_GET_NVMD_DATA:
1316 		case PMCOUT_SET_NVMD_DATA:
1317 		case PMCOUT_GET_DEVICE_STATE:
1318 		case PMCOUT_SET_DEVICE_STATE:
1319 			pmcs_process_completion(pwp, local, amt);
1320 			break;
1321 		case PMCOUT_SSP_ABORT:
1322 		case PMCOUT_SATA_ABORT:
1323 		case PMCOUT_SMP_ABORT:
1324 			pmcs_process_abort_completion(pwp, local, amt);
1325 			break;
1326 		case PMCOUT_SSP_EVENT:
1327 			pmcs_process_ssp_event(pwp, local, amt);
1328 			break;
1329 		case PMCOUT_ECHO:
1330 			pmcs_process_echo_completion(pwp, local, amt);
1331 			break;
1332 		case PMCOUT_SAS_HW_EVENT_ACK_ACK:
1333 			if (LE_32(ptr[2]) != SAS_HW_EVENT_ACK_OK) {
1334 				pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1335 				    "SAS H/W EVENT ACK/ACK Status=0x%b",
1336 				    LE_32(ptr[2]), "\020\4InvParm\3"
1337 				    "InvPort\2InvPhy\1InvSEA");
1338 			}
1339 			pmcs_process_completion(pwp, local, amt);
1340 			break;
1341 		case PMCOUT_SKIP_ENTRIES:
1342 			pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, NULL,
1343 			    "%s: skip %d entries", __func__, nbuf);
1344 			break;
1345 		default:
1346 			(void) snprintf(local, sizeof (local),
1347 			    "%s: unhandled message", __func__);
1348 			pmcs_print_entry(pwp, PMCS_PRT_DEBUG, local, ptr);
1349 			break;
1350 		}
1351 		STEP_OQ_ENTRY(pwp, PMCS_OQ_GENERAL, ci, nbuf);
1352 	}
1353 	if (lim) {
1354 		SYNC_OQ_ENTRY(pwp, PMCS_OQ_GENERAL, ci, pi);
1355 	}
1356 }
1357 
1358 /*
1359  * pmcs_check_intr_coal
1360  *
1361  * This function makes a determination on the dynamic value of the
1362  * interrupt coalescing timer register.  We only use this for I/O
1363  * completions.
1364  *
1365  * The basic algorithm is as follows:
1366  *
1367  * PMCS_MAX_IO_COMPS_PER_INTR: The maximum number of I/O completions per
1368  * I/O completion interrupt.  We won't increase the interrupt coalescing
1369  * timer if we're already processing this many completions per interrupt
1370  * beyond the threshold.
1371  *
1372  * Values in io_intr_coal structure:
1373  *
1374  * intr_latency: The average number of nsecs between interrupts during
1375  * the echo test.  Used to help determine whether to increase the coalescing
1376  * timer.
1377  *
1378  * intr_threshold: Calculated number of interrupts beyond which we may
1379  * increase the timer.  This value is calculated based on the calculated
1380  * interrupt latency during the ECHO test and the current value of the
1381  * coalescing timer.
1382  *
1383  * nsecs_between_intrs: Total number of nsecs between all the interrupts
1384  * in the current timeslice.
1385  *
1386  * last_io_comp: Time of the last I/O interrupt.
1387  *
1388  * num_io_completions: Number of I/O completions during the slice
1389  *
1390  * num_intrs: Number of I/O completion interrupts during the slice
1391  *
1392  * max_io_completions: Number of times we hit >= PMCS_MAX_IO_COMPS_PER_INTR
1393  * during interrupt processing.
1394  *
1395  * PMCS_MAX_IO_COMPS_LOWAT_SHIFT/HIWAT_SHIFT
1396  * Low and high marks used to determine whether we processed enough interrupts
1397  * that contained the maximum number of I/O completions to warrant increasing
1398  * the timer
1399  *
1400  * intr_coal_timer: The current value of the register (in usecs)
1401  *
1402  * timer_on: B_TRUE means we are using the timer
1403  *
1404  * The timer is increased if we processed more than intr_threshold interrupts
1405  * during the quantum and the number of interrupts containing the maximum
1406  * number of I/O completions is between PMCS_MAX_IO_COMPS_LOWAT_SHIFT and
1407  * _HIWAT_SHIFT
1408  *
1409  * If the average time between completions is greater than twice
1410  * the current timer value, the timer value is decreased.
1411  *
1412  * If we did not take any interrupts during a quantum, we turn the timer off.
1413  */
1414 void
1415 pmcs_check_intr_coal(void *arg)
1416 {
1417 	pmcs_hw_t	*pwp = (pmcs_hw_t *)arg;
1418 	uint32_t	avg_nsecs;
1419 	pmcs_io_intr_coal_t *ici;
1420 
1421 	ici = &pwp->io_intr_coal;
1422 	mutex_enter(&pwp->ict_lock);
1423 
1424 	while (ici->stop_thread == B_FALSE) {
1425 		/*
1426 		 * Wait for next time quantum... collect stats
1427 		 */
1428 		(void) cv_timedwait(&pwp->ict_cv, &pwp->ict_lock,
1429 		    ddi_get_lbolt() + ici->quantum);
1430 
1431 		if (ici->stop_thread == B_TRUE) {
1432 			continue;
1433 		}
1434 
1435 		DTRACE_PROBE1(pmcs__check__intr__coal, pmcs_io_intr_coal_t *,
1436 		    &pwp->io_intr_coal);
1437 
1438 		/*
1439 		 * Determine whether to adjust timer
1440 		 */
1441 		if (ici->num_intrs == 0) {
1442 			/*
1443 			 * If timer is off, nothing more to do.
1444 			 */
1445 			if (!pwp->io_intr_coal.timer_on) {
1446 				continue;
1447 			}
1448 
1449 			/*
1450 			 * No interrupts.  Turn off the timer.
1451 			 */
1452 			pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_CONTROL, 0);
1453 
1454 			if (pwp->odb_auto_clear & (1 << PMCS_MSIX_IODONE)) {
1455 				pmcs_wr_topunit(pwp, PMCS_OBDB_AUTO_CLR,
1456 				    pwp->odb_auto_clear);
1457 			}
1458 
1459 			ici->timer_on = B_FALSE;
1460 			ici->max_io_completions = 0;
1461 			ici->num_intrs = 0;
1462 			ici->int_cleared = B_FALSE;
1463 			ici->num_io_completions = 0;
1464 			DTRACE_PROBE1(pmcs__intr__coalesce__timer__off,
1465 			    pmcs_io_intr_coal_t *, ici);
1466 			continue;
1467 		}
1468 
1469 		avg_nsecs = ici->nsecs_between_intrs / ici->num_intrs;
1470 
1471 		if ((ici->num_intrs > ici->intr_threshold) &&
1472 		    (ici->max_io_completions > (ici->num_intrs >>
1473 		    PMCS_MAX_IO_COMPS_LOWAT_SHIFT)) &&
1474 		    (ici->max_io_completions < (ici->num_intrs >>
1475 		    PMCS_MAX_IO_COMPS_HIWAT_SHIFT))) {
1476 			pmcs_set_intr_coal_timer(pwp, INCREASE_TIMER);
1477 		} else if (avg_nsecs >
1478 		    (ici->intr_coal_timer * 1000 * 2)) {
1479 			pmcs_set_intr_coal_timer(pwp, DECREASE_TIMER);
1480 		}
1481 
1482 		/*
1483 		 * Reset values for new sampling period.
1484 		 */
1485 		ici->max_io_completions = 0;
1486 		ici->nsecs_between_intrs = 0;
1487 		ici->num_intrs = 0;
1488 		ici->num_io_completions = 0;
1489 	}
1490 
1491 	mutex_exit(&pwp->ict_lock);
1492 	thread_exit();
1493 }
1494 
1495 void
1496 pmcs_iodone_intr(pmcs_hw_t *pwp)
1497 {
1498 	char local[PMCS_QENTRY_SIZE << 1];
1499 	pmcs_iocomp_cb_t *ioccb;
1500 	uint32_t w0, ci, pi, nbuf, lim = 0, niodone = 0, iomb_opcode;
1501 	size_t amt;
1502 	uint32_t *ptr;
1503 	hrtime_t curtime = gethrtime();
1504 
1505 	ci = pmcs_rd_oqci(pwp, PMCS_OQ_IODONE);
1506 	pi = pmcs_rd_oqpi(pwp, PMCS_OQ_IODONE);
1507 
1508 	while (ci != pi) {
1509 		OQLIM_CHECK(pwp, lim);
1510 		ptr = GET_OQ_ENTRY(pwp, PMCS_OQ_IODONE, ci, 0);
1511 		w0 = LE_32(ptr[0]);
1512 		VALID_IOMB_CHECK(pwp, w0, ptr, ci, pi);
1513 		WRONG_OBID_CHECK(pwp, w0, PMCS_OQ_IODONE);
1514 		iomb_opcode = (w0 & PMCS_IOMB_OPCODE_MASK);
1515 
1516 		if ((iomb_opcode == PMCOUT_SSP_COMPLETION) ||
1517 		    (iomb_opcode == PMCOUT_SATA_COMPLETION)) {
1518 			ioccb =
1519 			    kmem_cache_alloc(pwp->iocomp_cb_cache, KM_NOSLEEP);
1520 			if (ioccb == NULL) {
1521 				pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
1522 				    "%s: kmem_cache_alloc failed", __func__);
1523 				break;
1524 			}
1525 
1526 			COPY_OUTBOUND(pwp, w0, ioccb->iomb, nbuf, amt, ptr,
1527 			    PMCS_OQ_IODONE, ci);
1528 
1529 			niodone++;
1530 			pmcs_process_io_completion(pwp, ioccb, amt);
1531 		} else {
1532 			COPY_OUTBOUND(pwp, w0, local, nbuf, amt, ptr,
1533 			    PMCS_OQ_IODONE, ci);
1534 
1535 			switch (iomb_opcode) {
1536 			case PMCOUT_ECHO:
1537 				pmcs_process_echo_completion(pwp, local, amt);
1538 				break;
1539 			case PMCOUT_SATA_EVENT:
1540 				pmcs_process_sata_event(pwp, local, amt);
1541 				break;
1542 			case PMCOUT_SSP_EVENT:
1543 				pmcs_process_ssp_event(pwp, local, amt);
1544 				break;
1545 			case PMCOUT_SKIP_ENTRIES:
1546 				pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, NULL,
1547 				    "%s: skip %d entries", __func__, nbuf);
1548 				break;
1549 			default:
1550 				(void) snprintf(local, sizeof (local),
1551 				    "%s: unhandled message", __func__);
1552 				pmcs_print_entry(pwp, PMCS_PRT_DEBUG, local,
1553 				    ptr);
1554 				break;
1555 			}
1556 		}
1557 
1558 		STEP_OQ_ENTRY(pwp, PMCS_OQ_IODONE, ci, nbuf);
1559 	}
1560 
1561 	if (lim != 0) {
1562 		SYNC_OQ_ENTRY(pwp, PMCS_OQ_IODONE, ci, pi);
1563 	}
1564 
1565 	/*
1566 	 * Update the interrupt coalescing timer check stats and run
1567 	 * completions for queued up commands.
1568 	 */
1569 
1570 	if (niodone > 0) {
1571 		/*
1572 		 * If we can't get the lock, then completions are either
1573 		 * already running or will be scheduled to do so shortly.
1574 		 */
1575 		if (mutex_tryenter(&pwp->cq_lock) != 0) {
1576 			PMCS_CQ_RUN_LOCKED(pwp);
1577 			mutex_exit(&pwp->cq_lock);
1578 		}
1579 
1580 		mutex_enter(&pwp->ict_lock);
1581 		pwp->io_intr_coal.nsecs_between_intrs +=
1582 		    curtime - pwp->io_intr_coal.last_io_comp;
1583 		pwp->io_intr_coal.num_intrs++;
1584 		pwp->io_intr_coal.num_io_completions += niodone;
1585 		if (niodone >= PMCS_MAX_IO_COMPS_PER_INTR) {
1586 			pwp->io_intr_coal.max_io_completions++;
1587 		}
1588 		pwp->io_intr_coal.last_io_comp = gethrtime();
1589 		mutex_exit(&pwp->ict_lock);
1590 	}
1591 }
1592 
1593 void
1594 pmcs_event_intr(pmcs_hw_t *pwp)
1595 {
1596 	char local[PMCS_QENTRY_SIZE << 1];
1597 	uint32_t w0, ci, pi, nbuf, lim =  0;
1598 	size_t amt;
1599 	uint32_t *ptr;
1600 
1601 	ci = pmcs_rd_oqci(pwp, PMCS_OQ_EVENTS);
1602 	pi = pmcs_rd_oqpi(pwp, PMCS_OQ_EVENTS);
1603 
1604 	while (ci != pi) {
1605 		OQLIM_CHECK(pwp, lim);
1606 		ptr = GET_OQ_ENTRY(pwp, PMCS_OQ_EVENTS, ci, 0);
1607 		w0 = LE_32(ptr[0]);
1608 		VALID_IOMB_CHECK(pwp, w0, ptr, ci, pi);
1609 		WRONG_OBID_CHECK(pwp, w0, PMCS_OQ_EVENTS);
1610 		COPY_OUTBOUND(pwp, w0, local, nbuf, amt, ptr,
1611 		    PMCS_OQ_EVENTS, ci);
1612 
1613 		switch (w0 & PMCS_IOMB_OPCODE_MASK) {
1614 		case PMCOUT_ECHO:
1615 			pmcs_process_echo_completion(pwp, local, amt);
1616 			break;
1617 		case PMCOUT_SATA_EVENT:
1618 			pmcs_process_sata_event(pwp, local, amt);
1619 			break;
1620 		case PMCOUT_SSP_EVENT:
1621 			pmcs_process_ssp_event(pwp, local, amt);
1622 			break;
1623 		case PMCOUT_GENERAL_EVENT:
1624 			pmcs_process_general_event(pwp, ptr);
1625 			break;
1626 		case PMCOUT_DEVICE_HANDLE_REMOVED:
1627 		{
1628 			uint32_t port = IOP_EVENT_PORTID(LE_32(ptr[1]));
1629 			uint32_t did = LE_32(ptr[2]);
1630 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1631 			    "PortID 0x%x device_id 0x%x removed", port, did);
1632 			break;
1633 		}
1634 		case PMCOUT_SAS_HW_EVENT:
1635 			if (nbuf > 1) {
1636 				pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
1637 				    "multiple SAS HW_EVENT (%d) responses "
1638 				    "in EVENT OQ", nbuf);
1639 			}
1640 			pmcs_process_sas_hw_event(pwp, local, PMCS_QENTRY_SIZE);
1641 			break;
1642 		case PMCOUT_FW_FLASH_UPDATE:
1643 		case PMCOUT_GET_TIME_STAMP:
1644 		case PMCOUT_GET_DEVICE_STATE:
1645 		case PMCOUT_SET_DEVICE_STATE:
1646 		case PMCOUT_SAS_DIAG_EXECUTE:
1647 			pmcs_process_completion(pwp, local, amt);
1648 			break;
1649 		case PMCOUT_SKIP_ENTRIES:
1650 			pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, NULL,
1651 			    "%s: skip %d entries", __func__, nbuf);
1652 			break;
1653 		default:
1654 			(void) snprintf(local, sizeof (local),
1655 			    "%s: unhandled message", __func__);
1656 			pmcs_print_entry(pwp, PMCS_PRT_DEBUG, local, ptr);
1657 			break;
1658 		}
1659 		STEP_OQ_ENTRY(pwp, PMCS_OQ_EVENTS, ci, nbuf);
1660 	}
1661 	if (lim) {
1662 		SYNC_OQ_ENTRY(pwp, PMCS_OQ_EVENTS, ci, pi);
1663 	}
1664 }
1665 
1666 void
1667 pmcs_timed_out(pmcs_hw_t *pwp, uint32_t htag, const char *func)
1668 {
1669 #ifdef	DEBUG
1670 	hrtime_t now = gethrtime();
1671 	int i;
1672 
1673 	for (i = 0; i < 256; i++) {
1674 		if (pwp->ftags[i] == htag) {
1675 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1676 			    "Inbound msg (tag 0x%8x) timed out - "
1677 			    "was started %llu ns ago in %s:%d",
1678 			    htag, (unsigned long long) (now - pwp->ftime[i]),
1679 			    func, pwp->ftag_lines[i]);
1680 			return;
1681 		}
1682 	}
1683 #endif
1684 	pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1685 	    "Inbound Message (tag 0x%08x) timed out- was started in %s",
1686 	    htag, func);
1687 }
1688