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 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 #include <sys/types.h>
29 #include <sys/conf.h>
30 #include <sys/ddi.h>
31 #include <sys/sunddi.h>
32 #include <sys/ksynch.h>
33 #include <sys/scsi/conf/autoconf.h>
34 #include <sys/reboot.h>
35 
36 #include "ghd.h"
37 
38 /*
39  * Local functions
40  */
41 
42 static	gcmd_t	*ghd_timeout_get(ccc_t *cccp);
43 static	int	 ghd_timeout_loop(ccc_t *cccp);
44 static	uint_t	 ghd_timeout_softintr(caddr_t arg);
45 static	void	 ghd_timeout(void *arg);
46 static	void	 ghd_timeout_disable(tmr_t *tmrp);
47 static	void	 ghd_timeout_enable(tmr_t *tmrp);
48 
49 /*
50  * Local data
51  */
52 long	ghd_HZ;
53 static	kmutex_t tglobal_mutex;
54 
55 /* table of timeouts for abort processing steps */
56 cmdstate_t ghd_timeout_table[GCMD_NSTATES];
57 
58 /* This table indirectly initializes the ghd_timeout_table */
59 struct {
60 	int		valid;
61 	cmdstate_t	state;
62 	long		value;
63 } ghd_time_inits[] = {
64 	{ TRUE, GCMD_STATE_ABORTING_CMD, 3 },
65 	{ TRUE, GCMD_STATE_ABORTING_DEV, 3 },
66 	{ TRUE, GCMD_STATE_RESETTING_DEV, 5 },
67 	{ TRUE, GCMD_STATE_RESETTING_BUS, 10 },
68 	{ TRUE, GCMD_STATE_HUNG, 60},
69 	{ FALSE, 0, 0 },	/* spare entry */
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 };
75 int	ghd_ntime_inits = sizeof (ghd_time_inits)
76 				/ sizeof (ghd_time_inits[0]);
77 
78 /*
79  * Locally-used macros
80  */
81 
82 /*
83  * Compare two gcmd_t's to see if they're for the same device (same gdev_t)
84  */
85 #define	GCMD_SAME_DEV(gcmdp1, gcmdp2)		\
86 	(GCMDP2GDEVP(gcmdp1) == GCMDP2GDEVP(gcmdp2))
87 
88 /*
89  * Compare two gcmd_t's to see if they're for the same bus (same HBA inst)
90  */
91 #define	GCMD_SAME_BUS(gcmdp1, gcmdp2)		\
92 	(GCMDP2CCCP(gcmdp1) == GCMDP2CCCP(gcmdp2))
93 
94 
95 /*
96  * Update state of gcmdp (in one direction, increasing state number, only)
97  */
98 #define	GCMD_UPDATE_STATE(gcmdp, newstate)		\
99 {							\
100 	if ((gcmdp)->cmd_state < (newstate)) {		\
101 		((gcmdp)->cmd_state = (newstate));	\
102 	}						\
103 }
104 
105 #ifdef ___notyet___
106 
107 #include <sys/modctl.h>
108 extern struct mod_ops mod_miscops;
109 static struct modlmisc modlmisc = {
110 	&mod_miscops,	/* Type of module */
111 	"CCB Timeout Utility Routines"
112 };
113 static struct modlinkage modlinkage = {
114 	MODREV_1, (void *)&modlmisc, NULL
115 };
116 
117 /*
118  * If this is a loadable module then there's a single CCB timer configure
119  * structure for all HBA drivers (rather than one per HBA driver).
120  */
121 static	tmr_t	tmr_conf;
122 
123 int
_init()124 _init()
125 {
126 	int	err;
127 
128 	ghd_timer_init(&tmr_conf, 0);
129 	return ((err = mod_install(&modlinkage)) != 0)
130 	    ghd_timer_fini(&tmr_conf);
131 	return (err);
132 }
133 
134 int
_fini()135 _fini()
136 {
137 	int	err;
138 
139 	if ((err = mod_remove(&modlinkage)) == 0)
140 		ghd_timer_fini(&tmr_conf);
141 	return (err);
142 }
143 
144 int
_info(struct modinfo * modinfop)145 _info(struct modinfo *modinfop)
146 {
147 	return (mod_info(&modlinkage, modinfop));
148 }
149 
150 #endif /* ___notyet___ */
151 
152 
153 
154 /*
155  *
156  * ghd_timeout_loop()
157  *
158  *	Check the CCB timer value for every active CCB for this
159  * HBA driver instance.
160  *
161  *	This function is called both by the ghd_timeout() interrupt
162  * handler when called via the timer callout, and by ghd_timer_poll()
163  * while procesing "polled" (FLAG_NOINTR) requests.
164  *
165  *	The ccc_activel_mutex is held while a CCB list is being scanned.
166  * This prevents the HBA driver's transport or interrupt functions
167  * from changing the active CCB list. But we wake up very infrequently
168  * and do as little as possible so it shouldn't affect performance.
169  *
170  */
171 
172 static int
ghd_timeout_loop(ccc_t * cccp)173 ghd_timeout_loop(ccc_t *cccp)
174 {
175 	int	 got_any = FALSE;
176 	gcmd_t	*gcmdp;
177 	ulong_t	 lbolt;
178 
179 	mutex_enter(&cccp->ccc_activel_mutex);
180 	lbolt = ddi_get_lbolt();
181 	gcmdp = (gcmd_t *)L2_next(&cccp->ccc_activel);
182 	while (gcmdp) {
183 		/*
184 		 * check to see if this one has timed out
185 		 */
186 		if ((gcmdp->cmd_timeout > 0) &&
187 		    (lbolt - gcmdp->cmd_start_time >= gcmdp->cmd_timeout)) {
188 			got_any = TRUE;
189 		}
190 		gcmdp = (gcmd_t *)L2_next(&gcmdp->cmd_timer_link);
191 	}
192 	mutex_exit(&cccp->ccc_activel_mutex);
193 	return (got_any);
194 }
195 
196 /*
197  *
198  * ghd_timeout()
199  *
200  *	Called every t_ticks ticks to scan the CCB timer lists
201  *
202  *	The t_mutex mutex is held the entire time this routine is active.
203  *	It protects the list of ccc_t's.
204  *
205  *	The list of cmd_t's is protected by the ccc_activel_mutex mutex
206  *	in the ghd_timeout_loop() routine.
207  *
208  *	We also check to see if the waitq is frozen, and if so,
209  *	adjust our timeout to call back sooner if necessary (to
210  *	unfreeze the waitq as soon as possible).
211  *
212  *
213  *	+------------+
214  *	|   tmr_t    |----+
215  *	+------------+    |
216  *			  |
217  *			  V
218  *			  +---------+
219  *			  |  ccc_t  |----+
220  *			  +---------+    |
221  *			  |		 V
222  *			  |		 +--------+   +--------+
223  *			  |		 | gcmd_t |-->| gcmd_t |--> ...
224  *			  |		 +--------+   +--------+
225  *			  V
226  *			  +---------+
227  *			  |  ccc_t  |----+
228  *			  +---------+    |
229  *			  |		 V
230  *			  |		 +--------+
231  *			  |		 | gcmd_t |
232  *			  V		 +--------+
233  *			  ...
234  *
235  *
236  *
237  */
238 
239 static void
ghd_timeout(void * arg)240 ghd_timeout(void *arg)
241 {
242 	tmr_t	*tmrp = (tmr_t *)arg;
243 	ccc_t	*cccp;
244 	clock_t	ufdelay_curr;
245 	clock_t	lbolt, delay_in_hz;
246 	clock_t	resched = (clock_t)0x7FFFFFFF;
247 
248 	/*
249 	 * Each HBA driver instance has a separate CCB timer list.  Skip
250 	 * timeout processing if there are no more active timeout lists
251 	 * to process.  (There are no lists only if there are no attached
252 	 * HBA instances; the list still exists if there are no outstanding
253 	 * active commands.)
254 	 */
255 	mutex_enter(&tmrp->t_mutex);
256 	if ((cccp = tmrp->t_ccc_listp) == NULL) {
257 		mutex_exit(&tmrp->t_mutex);
258 		return;
259 	}
260 
261 	lbolt = ddi_get_lbolt();
262 
263 	do {
264 		/*
265 		 * If any active CCBs on this HBA have timed out
266 		 * then kick off the HBA driver's softintr
267 		 * handler to do the timeout processing
268 		 */
269 		if (ghd_timeout_loop(cccp)) {
270 			cccp->ccc_timeout_pending = 1;
271 			ddi_trigger_softintr(cccp->ccc_soft_id);
272 		}
273 
274 		/* Record closest unfreeze time for use in next timeout */
275 
276 		mutex_enter(&cccp->ccc_waitq_mutex);
277 		if (cccp->ccc_waitq_frozen) {
278 
279 			delay_in_hz =
280 			    drv_usectohz(cccp->ccc_waitq_freezedelay * 1000);
281 			ufdelay_curr = delay_in_hz -
282 			    (lbolt - cccp->ccc_waitq_freezetime);
283 
284 			if (ufdelay_curr < resched)
285 				resched = ufdelay_curr;
286 
287 			/* frozen; trigger softintr to maybe unfreeze */
288 			ddi_trigger_softintr(cccp->ccc_soft_id);
289 		}
290 		mutex_exit(&cccp->ccc_waitq_mutex);
291 
292 	} while ((cccp = cccp->ccc_nextp) != NULL);
293 
294 	/* don't allow any unfreeze delays to increase the timeout delay */
295 	if (resched > tmrp->t_ticks)
296 		resched = tmrp->t_ticks;
297 
298 	/* re-establish the timeout callback */
299 	tmrp->t_timeout_id = timeout(ghd_timeout, (void *)tmrp, resched);
300 
301 	mutex_exit(&tmrp->t_mutex);
302 }
303 
304 
305 /*
306  *
307  * ghd_timer_newstate()
308  *
309  *	The HBA mutex is held by my caller.
310  *
311  */
312 
313 void
ghd_timer_newstate(ccc_t * cccp,gcmd_t * gcmdp,gtgt_t * gtgtp,gact_t action,int calltype)314 ghd_timer_newstate(ccc_t *cccp, gcmd_t *gcmdp, gtgt_t *gtgtp,
315     gact_t action, int calltype)
316 {
317 	gact_t	next_action;
318 	cmdstate_t next_state;
319 	char	*msgp;
320 	long	new_timeout = 0;
321 	int	(*func)(void *, gcmd_t *, gtgt_t *, gact_t, int);
322 	void	*hba_handle;
323 	gcmd_t	gsav;
324 	int	gsav_used = 0;
325 	gcmd_t	*gcmdp_scan;
326 
327 	ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
328 
329 #ifdef	DEBUG
330 	/* it shouldn't be on the timer active list */
331 	if (gcmdp != NULL) {
332 		L2el_t	*lp = &gcmdp->cmd_timer_link;
333 		ASSERT(lp->l2_nextp == lp);
334 		ASSERT(lp->l2_prevp == lp);
335 	}
336 #endif
337 
338 	bzero(&gsav, sizeof (gsav));
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
ghd_timeout_softintr(caddr_t arg)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
ghd_timer_poll(ccc_t * cccp,gtimer_poll_t calltype)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 		    (void *)cccp, (void *)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 *
ghd_timeout_get(ccc_t * cccp)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
ghd_timeout_enable(tmr_t * tmrp)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
ghd_timeout_disable(tmr_t * tmrp)718 ghd_timeout_disable(tmr_t *tmrp)
719 {
720 	ASSERT(tmrp != NULL);
721 
722 	mutex_enter(&tglobal_mutex);
723 	if (tmrp->t_refs-- <= 1) {
724 		(void) untimeout(tmrp->t_timeout_id);
725 	}
726 	mutex_exit(&tglobal_mutex);
727 }
728 
729 /* ************************************************************************ */
730 
731 	/* these are the externally callable routines */
732 
733 
734 void
ghd_timer_init(tmr_t * tmrp,long ticks)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] = (cmdstate_t)value;
765 	}
766 }
767 
768 void
ghd_timer_fini(tmr_t * tmrp)769 ghd_timer_fini(tmr_t *tmrp)
770 {
771 	mutex_destroy(&tmrp->t_mutex);
772 	mutex_destroy(&tglobal_mutex);
773 }
774 
775 int
ghd_timer_attach(ccc_t * cccp,tmr_t * tmrp,int (* timeout_func)(void *,gcmd_t *,gtgt_t *,gact_t,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
ghd_timer_detach(ccc_t * cccp)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
ghd_timer_start(ccc_t * cccp,gcmd_t * gcmdp,long cmd_timeout)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
ghd_timer_stop(ccc_t * cccp,gcmd_t * gcmdp)895 ghd_timer_stop(ccc_t *cccp, gcmd_t *gcmdp)
896 {
897 	GHD_TIMER_STOP_INLINE(cccp, gcmdp);
898 }
899