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 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <sys/conf.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 #include <sys/ksynch.h>
34 #include <sys/scsi/conf/autoconf.h>
35 #include <sys/reboot.h>
36 
37 #include "ghd.h"
38 
39 /*
40  * Local functions
41  */
42 
43 static	gcmd_t	*ghd_timeout_get(ccc_t *cccp);
44 static	int	 ghd_timeout_loop(ccc_t *cccp);
45 static	uint_t	 ghd_timeout_softintr(caddr_t arg);
46 static	void	 ghd_timeout(void *arg);
47 static	void	 ghd_timeout_disable(tmr_t *tmrp);
48 static	void	 ghd_timeout_enable(tmr_t *tmrp);
49 
50 /*
51  * Local data
52  */
53 long	ghd_HZ;
54 static	kmutex_t tglobal_mutex;
55 
56 /* table of timeouts for abort processing steps */
57 cmdstate_t ghd_timeout_table[GCMD_NSTATES];
58 
59 /* This table indirectly initializes the ghd_timeout_table */
60 struct {
61 	int		valid;
62 	cmdstate_t	state;
63 	long		value;
64 } ghd_time_inits[] = {
65 	{ TRUE, GCMD_STATE_ABORTING_CMD, 3 },
66 	{ TRUE, GCMD_STATE_ABORTING_DEV, 3 },
67 	{ TRUE, GCMD_STATE_RESETTING_DEV, 5 },
68 	{ TRUE, GCMD_STATE_RESETTING_BUS, 10 },
69 	{ TRUE, GCMD_STATE_HUNG, 60},
70 	{ FALSE, 0, 0 },	/* spare entry */
71 	{ FALSE, 0, 0 },	/* spare entry */
72 	{ FALSE, 0, 0 },	/* spare entry */
73 	{ FALSE, 0, 0 },	/* spare entry */
74 	{ FALSE, 0, 0 }		/* spare entry */
75 };
76 int	ghd_ntime_inits = sizeof (ghd_time_inits)
77 				/ sizeof (ghd_time_inits[0]);
78 
79 /*
80  * Locally-used macros
81  */
82 
83 /*
84  * Compare two gcmd_t's to see if they're for the same device (same gdev_t)
85  */
86 #define	GCMD_SAME_DEV(gcmdp1, gcmdp2)		\
87 	(GCMDP2GDEVP(gcmdp1) == GCMDP2GDEVP(gcmdp2))
88 
89 /*
90  * Compare two gcmd_t's to see if they're for the same bus (same HBA inst)
91  */
92 #define	GCMD_SAME_BUS(gcmdp1, gcmdp2)		\
93 	(GCMDP2CCCP(gcmdp1) == GCMDP2CCCP(gcmdp2))
94 
95 
96 /*
97  * Update state of gcmdp (in one direction, increasing state number, only)
98  */
99 #define	GCMD_UPDATE_STATE(gcmdp, newstate) 		\
100 {							\
101 	if ((gcmdp)->cmd_state < (newstate)) {		\
102 		((gcmdp)->cmd_state = (newstate));	\
103 	}						\
104 }
105 
106 #ifdef ___notyet___
107 
108 #include <sys/modctl.h>
109 extern struct mod_ops mod_miscops;
110 static struct modlmisc modlmisc = {
111 	&mod_miscops,	/* Type of module */
112 	"CCB Timeout Utility Routines"
113 };
114 static struct modlinkage modlinkage = {
115 	MODREV_1, (void *)&modlmisc, NULL
116 };
117 
118 /*
119  * If this is a loadable module then there's a single CCB timer configure
120  * structure for all HBA drivers (rather than one per HBA driver).
121  */
122 static	tmr_t	tmr_conf;
123 
124 int
125 _init()
126 {
127 	int	err;
128 
129 	ghd_timer_init(&tmr_conf, 0);
130 	return ((err = mod_install(&modlinkage)) != 0)
131 		ghd_timer_fini(&tmr_conf);
132 	return (err);
133 }
134 
135 int
136 _fini()
137 {
138 	int	err;
139 
140 	if ((err = mod_remove(&modlinkage)) == 0)
141 		ghd_timer_fini(&tmr_conf);
142 	return (err);
143 }
144 
145 int
146 _info(struct modinfo *modinfop)
147 {
148 	return (mod_info(&modlinkage, modinfop));
149 }
150 
151 #endif /* ___notyet___ */
152 
153 
154 
155 /*
156  *
157  * ghd_timeout_loop()
158  *
159  *	Check the CCB timer value for every active CCB for this
160  * HBA driver instance.
161  *
162  *	This function is called both by the ghd_timeout() interrupt
163  * handler when called via the timer callout, and by ghd_timer_poll()
164  * while procesing "polled" (FLAG_NOINTR) requests.
165  *
166  * 	The ccc_activel_mutex is held while a CCB list is being scanned.
167  * This prevents the HBA driver's transport or interrupt functions
168  * from changing the active CCB list. But we wake up very infrequently
169  * and do as little as possible so it shouldn't affect performance.
170  *
171  */
172 
173 static int
174 ghd_timeout_loop(ccc_t *cccp)
175 {
176 	int	 got_any = FALSE;
177 	gcmd_t	*gcmdp;
178 	ulong_t	 lbolt;
179 
180 	mutex_enter(&cccp->ccc_activel_mutex);
181 	lbolt = ddi_get_lbolt();
182 	gcmdp = (gcmd_t *)L2_next(&cccp->ccc_activel);
183 	while (gcmdp) {
184 		/*
185 		 * check to see if this one has timed out
186 		 */
187 		if ((gcmdp->cmd_timeout > 0) &&
188 		    (lbolt - gcmdp->cmd_start_time >= gcmdp->cmd_timeout)) {
189 			got_any = TRUE;
190 		}
191 		gcmdp = (gcmd_t *)L2_next(&gcmdp->cmd_timer_link);
192 	}
193 	mutex_exit(&cccp->ccc_activel_mutex);
194 	return (got_any);
195 }
196 
197 /*
198  *
199  * ghd_timeout()
200  *
201  *	Called every t_ticks ticks to scan the CCB timer lists
202  *
203  *	The t_mutex mutex is held the entire time this routine is active.
204  *	It protects the list of ccc_t's.
205  *
206  *	The list of cmd_t's is protected by the ccc_activel_mutex mutex
207  *	in the ghd_timeout_loop() routine.
208  *
209  * 	We also check to see if the waitq is frozen, and if so,
210  * 	adjust our timeout to call back sooner if necessary (to
211  * 	unfreeze the waitq as soon as possible).
212  *
213  *
214  *	+------------+
215  *	|   tmr_t    |----+
216  *	+------------+    |
217  *			  |
218  *			  V
219  *			  +---------+
220  *			  |  ccc_t  |----+
221  *			  +---------+    |
222  *			  |		 V
223  *			  |		 +--------+   +--------+
224  *			  |		 | gcmd_t |-->| gcmd_t |--> ...
225  *			  |		 +--------+   +--------+
226  *			  V
227  *			  +---------+
228  *			  |  ccc_t  |----+
229  *			  +---------+    |
230  *			  |		 V
231  *			  |		 +--------+
232  *			  |		 | gcmd_t |
233  *			  V		 +--------+
234  *			  ...
235  *
236  *
237  *
238  */
239 
240 static void
241 ghd_timeout(void *arg)
242 {
243 	tmr_t	*tmrp = (tmr_t *)arg;
244 	ccc_t	*cccp;
245 	clock_t	ufdelay_curr;
246 	clock_t	lbolt, delay_in_hz;
247 	clock_t	resched = (clock_t)0x7FFFFFFF;
248 
249 	/*
250 	 * Each HBA driver instance has a separate CCB timer list.  Skip
251 	 * timeout processing if there are no more active timeout lists
252 	 * to process.  (There are no lists only if there are no attached
253 	 * HBA instances; the list still exists if there are no outstanding
254 	 * active commands.)
255 	 */
256 	mutex_enter(&tmrp->t_mutex);
257 	if ((cccp = tmrp->t_ccc_listp) == NULL) {
258 		mutex_exit(&tmrp->t_mutex);
259 		return;
260 	}
261 
262 	lbolt = ddi_get_lbolt();
263 
264 	do {
265 		/*
266 		 * If any active CCBs on this HBA have timed out
267 		 * then kick off the HBA driver's softintr
268 		 * handler to do the timeout processing
269 		 */
270 		if (ghd_timeout_loop(cccp)) {
271 			cccp->ccc_timeout_pending = 1;
272 			ddi_trigger_softintr(cccp->ccc_soft_id);
273 		}
274 
275 		/* Record closest unfreeze time for use in next timeout */
276 
277 		mutex_enter(&cccp->ccc_waitq_mutex);
278 		if (cccp->ccc_waitq_frozen) {
279 
280 			delay_in_hz =
281 			    drv_usectohz(cccp->ccc_waitq_freezedelay * 1000);
282 			ufdelay_curr = delay_in_hz -
283 			    (lbolt - cccp->ccc_waitq_freezetime);
284 
285 			if (ufdelay_curr < resched)
286 				resched = ufdelay_curr;
287 
288 			/* frozen; trigger softintr to maybe unfreeze */
289 			ddi_trigger_softintr(cccp->ccc_soft_id);
290 		}
291 		mutex_exit(&cccp->ccc_waitq_mutex);
292 
293 	} while ((cccp = cccp->ccc_nextp) != NULL);
294 
295 	/* don't allow any unfreeze delays to increase the timeout delay */
296 	if (resched > tmrp->t_ticks)
297 		resched = tmrp->t_ticks;
298 
299 	/* re-establish the timeout callback */
300 	tmrp->t_timeout_id = timeout(ghd_timeout, (void *)tmrp, resched);
301 
302 	mutex_exit(&tmrp->t_mutex);
303 }
304 
305 
306 /*
307  *
308  * ghd_timer_newstate()
309  *
310  *	The HBA mutex is held by my caller.
311  *
312  */
313 
314 void
315 ghd_timer_newstate(ccc_t *cccp, gcmd_t *gcmdp, gtgt_t *gtgtp,
316     gact_t action, int calltype)
317 {
318 	gact_t	next_action;
319 	cmdstate_t next_state;
320 	char	*msgp;
321 	long	new_timeout;
322 	int	(*func)(void *, gcmd_t *, gtgt_t *, gact_t, int);
323 	void	*hba_handle;
324 	gcmd_t	gsav;
325 	int	gsav_used = 0;
326 	gcmd_t	*gcmdp_scan;
327 
328 	ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
329 
330 #ifdef	DEBUG
331 	/* it shouldn't be on the timer active list */
332 	if (gcmdp != NULL) {
333 		L2el_t	*lp = &gcmdp->cmd_timer_link;
334 		ASSERT(lp->l2_nextp == lp);
335 		ASSERT(lp->l2_prevp == lp);
336 	}
337 #endif
338 
339 	func = cccp->ccc_timeout_func;
340 	hba_handle = cccp->ccc_hba_handle;
341 
342 	for (;;) {
343 		switch (action) {
344 		case GACTION_EARLY_ABORT:
345 			/* done before it started */
346 			ASSERT(gcmdp != NULL);
347 			msgp = "early abort";
348 			next_state = GCMD_STATE_DONEQ;
349 			next_action = GACTION_ABORT_CMD;
350 			break;
351 
352 		case GACTION_EARLY_TIMEOUT:
353 			/* done before it started */
354 			ASSERT(gcmdp != NULL);
355 			msgp = "early timeout";
356 			next_state = GCMD_STATE_DONEQ;
357 			next_action = GACTION_ABORT_CMD;
358 			break;
359 
360 		case GACTION_ABORT_CMD:
361 			msgp = "abort request";
362 			ASSERT(gcmdp != NULL);
363 			next_state = GCMD_STATE_ABORTING_CMD;
364 			next_action = GACTION_ABORT_DEV;
365 			break;
366 
367 		case GACTION_ABORT_DEV:
368 			msgp = "abort device";
369 			next_state = GCMD_STATE_ABORTING_DEV;
370 			next_action = GACTION_RESET_TARGET;
371 			break;
372 
373 		case GACTION_RESET_TARGET:
374 			msgp = "reset target";
375 			next_state = GCMD_STATE_RESETTING_DEV;
376 			next_action = GACTION_RESET_BUS;
377 			break;
378 
379 		case GACTION_RESET_BUS:
380 			msgp = "reset bus";
381 			next_state = GCMD_STATE_RESETTING_BUS;
382 			next_action = GACTION_INCOMPLETE;
383 			break;
384 
385 		case GACTION_INCOMPLETE:
386 		default:
387 			/* be verbose about HBA resets */
388 			GDBG_ERROR(("?ghd_timer_newstate: HBA reset failed "
389 			    "hba 0x%p gcmdp 0x%p gtgtp 0x%p\n",
390 			    (void *)hba_handle, (void *)gcmdp, (void *)gtgtp));
391 			/*
392 			 * When all else fails, punt.
393 			 *
394 			 * We're in big trouble if we get to this point.
395 			 * Maybe we should try to re-initialize the HBA.
396 			 */
397 			msgp = "HBA reset";
398 			next_state = GCMD_STATE_HUNG;
399 			next_action = GACTION_INCOMPLETE;
400 			break;
401 		}
402 
403 		/*
404 		 * I want to see target requests only if verbose, but
405 		 * scsi_log() only prints the device pathname if level
406 		 * is CE_WARN or CE_PANIC...so I guess we can't use
407 		 * scsi_log for TGTREQ messages, or they must come to
408 		 * the console.  How silly.  Looking for "verbose boot"
409 		 * is non-DDI-compliant, but let's do it anyway.
410 		 */
411 
412 		if (calltype == GHD_TGTREQ) {
413 			if ((boothowto & RB_VERBOSE)) {
414 				scsi_log(cccp->ccc_hba_dip, cccp->ccc_label,
415 				    CE_WARN,
416 				    "target request: %s, target=%d lun=%d",
417 				    msgp, gtgtp->gt_target, gtgtp->gt_lun);
418 			}
419 		} else {
420 			scsi_log(cccp->ccc_hba_dip, cccp->ccc_label, CE_WARN,
421 			    "timeout: %s, target=%d lun=%d", msgp,
422 				gtgtp->gt_target, gtgtp->gt_lun);
423 		}
424 
425 		/*
426 		 * Before firing off the HBA action, restart the timer
427 		 * using the timeout value from ghd_timeout_table[].
428 		 *
429 		 * The table entries should never restart the timer
430 		 * for the GHD_STATE_IDLE and GHD_STATE_DONEQ states.
431 		 *
432 		 */
433 		if (gcmdp) {
434 			gcmdp->cmd_state = next_state;
435 			new_timeout = ghd_timeout_table[gcmdp->cmd_state];
436 			if (new_timeout != 0)
437 				ghd_timer_start(cccp, gcmdp, new_timeout);
438 
439 			/* save a copy in case action function frees it */
440 			gsav = *gcmdp;
441 			gsav_used = 1;
442 		}
443 
444 		if (action == GACTION_RESET_BUS && cccp->ccc_waitq_frozen) {
445 			GDBG_WARN(("avoiding bus reset while waitq frozen\n"));
446 			break;
447 		}
448 
449 		/* invoke the HBA's action function */
450 		if ((*func)(hba_handle, gcmdp, gtgtp, action, calltype)) {
451 			/* if it took wait for an interrupt or timeout */
452 			break;
453 		}
454 		/*
455 		 * if the HBA reset fails leave the retry
456 		 * timer running and just exit.
457 		 */
458 		if (action == GACTION_INCOMPLETE)
459 			return;
460 
461 		/* all other failures cause transition to next action */
462 		if (gcmdp != NULL && new_timeout != 0) {
463 			/*
464 			 * But stop the old timer prior to
465 			 * restarting a new timer because each step may
466 			 * have a different timeout value.
467 			 */
468 			GHD_TIMER_STOP(cccp, gcmdp);
469 		}
470 		action = next_action;
471 	}
472 
473 	/*
474 	 * HBA action function is done with gsav (if used)
475 	 * or gtgtp/cccp (if gsav not used).  We need to mark other
476 	 * outstanding requests if they were affected by this action
477 	 * (say, a device reset which also cancels all outstanding
478 	 * requests on this device) to prevent multiple timeouts/HBA
479 	 * actions for the same device or bus condition.  Scan the timer
480 	 * list (all active requests) and update states as necessary.
481 	 * Hold the activel_mutex while scanning the active list.  Check
482 	 * for either same dev/bus as gsav (if used) or for same
483 	 * dev/bus as gtgtp or cccp (if gsav is not used).
484 	 */
485 
486 	mutex_enter(&cccp->ccc_activel_mutex);
487 
488 	for (gcmdp_scan = (gcmd_t *)L2_next(&cccp->ccc_activel);
489 	    gcmdp_scan != NULL;
490 	    gcmdp_scan = (gcmd_t *)L2_next(&gcmdp_scan->cmd_timer_link)) {
491 
492 		/* skip idle or waitq commands */
493 		if (gcmdp_scan->cmd_state <= GCMD_STATE_WAITQ)
494 			continue;
495 
496 		switch (action) {
497 
498 		case GACTION_ABORT_DEV:
499 			if ((gsav_used && GCMD_SAME_DEV(&gsav, gcmdp_scan)) ||
500 			    (GCMDP2GDEVP(gcmdp_scan) == GTGTP2GDEVP(gtgtp))) {
501 				GCMD_UPDATE_STATE(gcmdp_scan,
502 				    GCMD_STATE_ABORTING_DEV);
503 			}
504 			break;
505 
506 		case GACTION_RESET_TARGET:
507 			if ((gsav_used && GCMD_SAME_DEV(&gsav, gcmdp_scan)) ||
508 			    (GCMDP2GDEVP(gcmdp_scan) == GTGTP2GDEVP(gtgtp))) {
509 				GCMD_UPDATE_STATE(gcmdp_scan,
510 				    GCMD_STATE_RESETTING_DEV);
511 			}
512 			break;
513 
514 		case GACTION_RESET_BUS:
515 			if ((gsav_used && GCMD_SAME_BUS(&gsav, gcmdp_scan)) ||
516 			    (GCMDP2CCCP(gcmdp_scan) == cccp)) {
517 				GCMD_UPDATE_STATE(gcmdp_scan,
518 				    GCMD_STATE_RESETTING_BUS);
519 			}
520 			break;
521 		default:
522 			break;
523 		}
524 	}
525 
526 	mutex_exit(&cccp->ccc_activel_mutex);
527 }
528 
529 
530 /*
531  *
532  * ghd_timeout_softintr()
533  *
534  *	This interrupt is scheduled if a particular HBA instance's
535  *	CCB timer list has a timed out CCB, or if the waitq is in a
536  * 	frozen state.
537  *
538  *	Find the timed out CCB and then call the HBA driver's timeout
539  *	function.
540  *
541  *	In order to avoid race conditions all processing must be done
542  *	while holding the HBA instance's mutex. If the mutex wasn't
543  *	held the HBA driver's hardware interrupt routine could be
544  *	triggered and it might try to remove a CCB from the list at
545  *	same time as were trying to abort it.
546  *
547  *	For frozen-waitq processing, just call ghd_waitq_process...
548  *	it takes care of the time calculations.
549  *
550  */
551 
552 static uint_t
553 ghd_timeout_softintr(caddr_t arg)
554 {
555 	ccc_t	*cccp = (ccc_t *)arg;
556 
557 	if (cccp->ccc_timeout_pending) {
558 
559 		/* grab this HBA instance's mutex */
560 		mutex_enter(&cccp->ccc_hba_mutex);
561 
562 		/*
563 		 * The claim is we could reset "pending" outside the mutex, but
564 		 * since we have to acquire the mutex anyway, it doesn't hurt
565 		 */
566 		cccp->ccc_timeout_pending = 0;
567 
568 		/* timeout each expired CCB */
569 		ghd_timer_poll(cccp, GHD_TIMER_POLL_ALL);
570 
571 		mutex_enter(&cccp->ccc_waitq_mutex);
572 		ghd_waitq_process_and_mutex_exit(cccp);
573 
574 	} else if (cccp->ccc_waitq_frozen) {
575 		mutex_enter(&cccp->ccc_hba_mutex);
576 		mutex_enter(&cccp->ccc_waitq_mutex);
577 		ghd_waitq_process_and_mutex_exit(cccp);
578 	}
579 
580 	return (DDI_INTR_UNCLAIMED);
581 }
582 
583 
584 /*
585  * ghd_timer_poll()
586  *
587  * This function steps a packet to the next action in the recovery
588  * procedure.
589  *
590  * The caller must be  already holding the HBA mutex and take care of
591  * running the pkt completion functions.
592  *
593  */
594 
595 void
596 ghd_timer_poll(ccc_t *cccp, gtimer_poll_t calltype)
597 {
598 	gcmd_t	*gcmdp;
599 	gact_t	 action;
600 
601 	ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
602 
603 	/* abort each expired CCB */
604 	while (gcmdp = ghd_timeout_get(cccp)) {
605 
606 		GDBG_INTR(("?ghd_timer_poll: cccp=0x%p gcmdp=0x%p\n",
607 		    cccp, gcmdp));
608 
609 		switch (gcmdp->cmd_state) {
610 		case GCMD_STATE_IDLE:
611 		case GCMD_STATE_DONEQ:
612 		default:
613 			/* not supposed to happen */
614 			GDBG_ERROR(("ghd_timer_poll: invalid state %d\n",
615 			    gcmdp->cmd_state));
616 			return;
617 
618 		case GCMD_STATE_WAITQ:
619 			action = GACTION_EARLY_TIMEOUT;
620 			break;
621 
622 		case GCMD_STATE_ACTIVE:
623 			action = GACTION_ABORT_CMD;
624 			break;
625 
626 		case GCMD_STATE_ABORTING_CMD:
627 			action = GACTION_ABORT_DEV;
628 			break;
629 
630 		case GCMD_STATE_ABORTING_DEV:
631 			action = GACTION_RESET_TARGET;
632 			break;
633 
634 		case GCMD_STATE_RESETTING_DEV:
635 			action = GACTION_RESET_BUS;
636 			break;
637 
638 		case GCMD_STATE_RESETTING_BUS:
639 			action = GACTION_INCOMPLETE;
640 			break;
641 
642 		case GCMD_STATE_HUNG:
643 			action = GACTION_INCOMPLETE;
644 			break;
645 		}
646 
647 		ghd_timer_newstate(cccp, gcmdp, gcmdp->cmd_gtgtp, action,
648 		    GHD_TIMEOUT);
649 
650 		/* return after processing first cmd if requested */
651 
652 		if (calltype == GHD_TIMER_POLL_ONE)
653 			return;
654 	}
655 }
656 
657 
658 
659 
660 /*
661  *
662  * ghd_timeout_get()
663  *
664  *	Remove the first expired CCB from a particular timer list.
665  *
666  */
667 
668 static gcmd_t *
669 ghd_timeout_get(ccc_t *cccp)
670 {
671 	gcmd_t	*gcmdp;
672 	ulong_t	lbolt;
673 
674 	ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
675 
676 	mutex_enter(&cccp->ccc_activel_mutex);
677 	lbolt = ddi_get_lbolt();
678 	gcmdp = (gcmd_t *)L2_next(&cccp->ccc_activel);
679 	while (gcmdp != NULL) {
680 		if ((gcmdp->cmd_timeout > 0) &&
681 		    (lbolt - gcmdp->cmd_start_time >= gcmdp->cmd_timeout))
682 			goto expired;
683 		gcmdp = (gcmd_t *)L2_next(&gcmdp->cmd_timer_link);
684 	}
685 	mutex_exit(&cccp->ccc_activel_mutex);
686 	return (NULL);
687 
688 expired:
689 	/* unlink if from the CCB timer list */
690 	L2_delete(&gcmdp->cmd_timer_link);
691 	mutex_exit(&cccp->ccc_activel_mutex);
692 	return (gcmdp);
693 }
694 
695 
696 /*
697  *
698  * ghd_timeout_enable()
699  *
700  *	Only start a single timeout callback for each HBA driver
701  *	regardless of the number of boards it supports.
702  *
703  */
704 
705 static void
706 ghd_timeout_enable(tmr_t *tmrp)
707 {
708 	mutex_enter(&tglobal_mutex);
709 	if (tmrp->t_refs++ == 0)  {
710 		/* establish the timeout callback */
711 		tmrp->t_timeout_id = timeout(ghd_timeout, (void *)tmrp,
712 			tmrp->t_ticks);
713 	}
714 	mutex_exit(&tglobal_mutex);
715 }
716 
717 static void
718 ghd_timeout_disable(tmr_t *tmrp)
719 {
720 	ASSERT(tmrp != NULL);
721 	ASSERT(tmrp->t_ccc_listp == NULL);
722 
723 	mutex_enter(&tglobal_mutex);
724 	if (tmrp->t_refs-- <= 1)
725 		(void) untimeout(tmrp->t_timeout_id);
726 	mutex_exit(&tglobal_mutex);
727 }
728 
729 /* ************************************************************************ */
730 
731 	/* these are the externally callable routines */
732 
733 
734 void
735 ghd_timer_init(tmr_t *tmrp, long ticks)
736 {
737 	int	indx;
738 
739 	mutex_init(&tglobal_mutex, NULL, MUTEX_DRIVER, NULL);
740 	mutex_init(&tmrp->t_mutex, NULL, MUTEX_DRIVER, NULL);
741 
742 	/*
743 	 * determine default timeout value
744 	 */
745 	ghd_HZ = drv_usectohz(1000000);
746 	if (ticks == 0)
747 		ticks = scsi_watchdog_tick * ghd_HZ;
748 	tmrp->t_ticks = ticks;
749 
750 
751 	/*
752 	 * Initialize the table of abort timer values using an
753 	 * indirect lookup table so that this code isn't dependant
754 	 * on the cmdstate_t enum values or order.
755 	 */
756 	for (indx = 0; indx < ghd_ntime_inits; indx++) {
757 		int	state;
758 		ulong_t	value;
759 
760 		if (!ghd_time_inits[indx].valid)
761 			continue;
762 		state = ghd_time_inits[indx].state;
763 		value = ghd_time_inits[indx].value;
764 		ghd_timeout_table[state] = value;
765 	}
766 }
767 
768 void
769 ghd_timer_fini(tmr_t *tmrp)
770 {
771 	mutex_destroy(&tmrp->t_mutex);
772 	mutex_destroy(&tglobal_mutex);
773 }
774 
775 int
776 ghd_timer_attach(ccc_t *cccp, tmr_t *tmrp,
777     int (*timeout_func)(void *, gcmd_t *, gtgt_t *, gact_t, int))
778 {
779 	ddi_iblock_cookie_t iblock;
780 
781 	if (ddi_add_softintr(cccp->ccc_hba_dip, DDI_SOFTINT_LOW,
782 	    &cccp->ccc_soft_id, &iblock, NULL,
783 	    ghd_timeout_softintr, (caddr_t)cccp) != DDI_SUCCESS) {
784 		GDBG_ERROR((
785 		    "ghd_timer_attach: add softintr failed cccp 0x%p\n",
786 		    (void *)cccp));
787 		return (FALSE);
788 	}
789 
790 	/* init the per HBA-instance control fields */
791 	mutex_init(&cccp->ccc_activel_mutex, NULL, MUTEX_DRIVER, iblock);
792 	L2_INIT(&cccp->ccc_activel);
793 	cccp->ccc_timeout_func = timeout_func;
794 
795 	/* stick this HBA's control structure on the master list */
796 	mutex_enter(&tmrp->t_mutex);
797 
798 	cccp->ccc_nextp = tmrp->t_ccc_listp;
799 	tmrp->t_ccc_listp = cccp;
800 	cccp->ccc_tmrp = tmrp;
801 	mutex_exit(&tmrp->t_mutex);
802 
803 	/*
804 	 * The enable and disable routines use a separate mutex than
805 	 * t_mutex which is used by the timeout callback function.
806 	 * This is to avoid a deadlock when calling untimeout() from
807 	 * the disable routine.
808 	 */
809 	ghd_timeout_enable(tmrp);
810 
811 	return (TRUE);
812 }
813 
814 
815 /*
816  *
817  * ghd_timer_detach()
818  *
819  *	clean up for a detaching HBA instance
820  *
821  */
822 
823 void
824 ghd_timer_detach(ccc_t *cccp)
825 {
826 	tmr_t	*tmrp = cccp->ccc_tmrp;
827 	ccc_t	**prevpp;
828 
829 	/* make certain the CCB list is empty */
830 	ASSERT(cccp->ccc_activel.l2_nextp == &cccp->ccc_activel);
831 	ASSERT(cccp->ccc_activel.l2_nextp == cccp->ccc_activel.l2_prevp);
832 
833 	mutex_enter(&tmrp->t_mutex);
834 
835 	prevpp = &tmrp->t_ccc_listp;
836 	ASSERT(*prevpp != NULL);
837 
838 	/* run down the linked list to find the entry that preceeds this one */
839 	do {
840 		if (*prevpp == cccp)
841 			goto remove_it;
842 		prevpp = &(*prevpp)->ccc_nextp;
843 	} while (*prevpp != NULL);
844 
845 	/* fell off the end of the list */
846 	GDBG_ERROR(("ghd_timer_detach: corrupt list, cccp=0x%p\n",
847 	    (void *)cccp));
848 
849 remove_it:
850 	*prevpp = cccp->ccc_nextp;
851 	mutex_exit(&tmrp->t_mutex);
852 	mutex_destroy(&cccp->ccc_activel_mutex);
853 
854 	ddi_remove_softintr(cccp->ccc_soft_id);
855 
856 	ghd_timeout_disable(tmrp);
857 }
858 
859 /*
860  *
861  * ghd_timer_start()
862  *
863  *	Add a CCB to the CCB timer list.
864  */
865 
866 void
867 ghd_timer_start(ccc_t *cccp, gcmd_t *gcmdp, long cmd_timeout)
868 {
869 	ulong_t	lbolt;
870 
871 	mutex_enter(&cccp->ccc_activel_mutex);
872 	lbolt = ddi_get_lbolt();
873 
874 	/* initialize this CCB's timer */
875 	gcmdp->cmd_start_time = lbolt;
876 	gcmdp->cmd_timeout = (cmd_timeout * ghd_HZ);
877 
878 	/* add it to the list */
879 	L2_add(&cccp->ccc_activel, &gcmdp->cmd_timer_link, gcmdp);
880 	mutex_exit(&cccp->ccc_activel_mutex);
881 }
882 
883 
884 /*
885  *
886  * ghd_timer_stop()
887  *
888  *	Remove a completed CCB from the CCB timer list.
889  *
890  *	See the GHD_TIMER_STOP_INLINE() macro in ghd.h for
891  *	the actual code.
892  */
893 
894 void
895 ghd_timer_stop(ccc_t *cccp, gcmd_t *gcmdp)
896 {
897 	GHD_TIMER_STOP_INLINE(cccp, gcmdp);
898 }
899