xref: /illumos-gate/usr/src/uts/common/io/scsi/impl/scsi_watch.c (revision 948f2876ce2a3010558f4f6937e16086ebcd36f2)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
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 /*
30  * generic scsi device watch
31  */
32 
33 #if DEBUG || lint
34 #define	SWDEBUG
35 #endif
36 
37 /*
38  * debug goodies
39  */
40 #ifdef SWDEBUG
41 static int swdebug = 0;
42 #define	DEBUGGING	((scsi_options & SCSI_DEBUG_TGT) && sddebug > 1)
43 #define	SW_DEBUG	if (swdebug == 1) scsi_log
44 #define	SW_DEBUG2	if (swdebug > 1) scsi_log
45 #else	/* SWDEBUG */
46 #define	swdebug		(0)
47 #define	DEBUGGING	(0)
48 #define	SW_DEBUG	if (0) scsi_log
49 #define	SW_DEBUG2	if (0) scsi_log
50 #endif
51 
52 
53 
54 /*
55  * Includes, Declarations and Local Data
56  */
57 
58 #include <sys/note.h>
59 #include <sys/scsi/scsi.h>
60 #include <sys/var.h>
61 #include <sys/proc.h>
62 #include <sys/thread.h>
63 #include <sys/callb.h>
64 
65 /*
66  * macro for filling in lun value for scsi-1 support
67  */
68 #define	FILL_SCSI1_LUN(devp, pkt) \
69 	if ((devp->sd_address.a_lun > 0) && \
70 	    (devp->sd_inq->inq_ansi == 0x1)) { \
71 		((union scsi_cdb *)(pkt)->pkt_cdbp)->scc_lun = \
72 		    devp->sd_address.a_lun; \
73 	}
74 
75 char *sw_label = "scsi-watch";
76 
77 static int scsi_watch_io_time = SCSI_WATCH_IO_TIME;
78 
79 /*
80  * all info resides in the scsi watch structure
81  *
82  * the monitoring is performed by one separate thread which works
83  * from a linked list of scsi_watch_request packets
84  */
85 static struct scsi_watch {
86 	kthread_t		*sw_thread;	/* the watch thread	*/
87 	kmutex_t		sw_mutex;	/* mutex protecting list */
88 						/* and this structure */
89 	kcondvar_t		sw_cv;		/* cv for waking up thread */
90 	struct scsi_watch_request *sw_head;	/* head of linked list	*/
91 						/* of request structures */
92 	uchar_t			sw_state;	/* for suspend-resume */
93 	uchar_t			sw_flags;	/* to start at head of list */
94 						/* for watch thread */
95 } sw;
96 
97 #if !defined(lint)
98 _NOTE(MUTEX_PROTECTS_DATA(scsi_watch::sw_mutex, scsi_watch))
99 #endif
100 
101 /*
102  * Values for sw_state
103  */
104 #define	SW_RUNNING		0
105 #define	SW_SUSPEND_REQUESTED	1
106 #define	SW_SUSPENDED		2
107 
108 /*
109  * values for sw_flags
110  */
111 #define	SW_START_HEAD		0x1
112 
113 struct scsi_watch_request {
114 	struct scsi_watch_request *swr_next;	/* linked request list	*/
115 	struct scsi_watch_request *swr_prev;
116 	clock_t			swr_interval;	/* interval between TURs */
117 	clock_t			swr_timeout;	/* count down		*/
118 	uchar_t			swr_busy;	/* TUR in progress	*/
119 	uchar_t			swr_what;	/* watch or stop	*/
120 	uchar_t			swr_sense_length; /* required sense length */
121 	struct scsi_pkt		*swr_pkt;	/* TUR pkt itself	*/
122 	struct scsi_pkt		*swr_rqpkt;	/* request sense pkt	*/
123 	struct buf		*swr_rqbp;	/* bp for request sense data */
124 	int			(*swr_callback)(); /* callback to driver */
125 	caddr_t			swr_callback_arg;
126 	kcondvar_t		swr_terminate_cv; /* cv to wait on to cleanup */
127 						/* request synchronously */
128 };
129 
130 #if !defined(lint)
131 _NOTE(SCHEME_PROTECTS_DATA("unshared data", scsi_watch_request))
132 #endif
133 
134 /*
135  * values for sw_what
136  */
137 #define	SWR_WATCH		0	/* device watch */
138 #define	SWR_STOP		1	/* stop monitoring and destroy swr */
139 #define	SWR_SUSPEND_REQUESTED	2	/* req. pending suspend */
140 #define	SWR_SUSPENDED		3	/* req. is suspended */
141 
142 static void scsi_watch_request_destroy(struct scsi_watch_request *swr);
143 static void scsi_watch_thread(void);
144 static void scsi_watch_request_intr(struct scsi_pkt *pkt);
145 
146 /*
147  * setup, called from _init(), the thread is created when we need it
148  * and exits when there is nothing to do anymore and everything has been
149  * cleaned up (ie. resources deallocated)
150  */
151 void
152 scsi_watch_init()
153 {
154 /* NO OTHER THREADS ARE RUNNING */
155 	mutex_init(&sw.sw_mutex, NULL, MUTEX_DRIVER, NULL);
156 	cv_init(&sw.sw_cv, NULL, CV_DRIVER, NULL);
157 	sw.sw_state = SW_RUNNING;
158 	sw.sw_flags = 0;
159 }
160 
161 /*
162  * cleaning up, called from _fini()
163  */
164 void
165 scsi_watch_fini()
166 {
167 /* NO OTHER THREADS ARE RUNNING */
168 	/*
169 	 * hope and pray that the thread has exited
170 	 */
171 	ASSERT(sw.sw_thread == 0);
172 	mutex_destroy(&sw.sw_mutex);
173 	cv_destroy(&sw.sw_cv);
174 }
175 
176 /*
177  * allocate an swr (scsi watch request structure) and initialize pkts
178  */
179 #define	ROUTE		&devp->sd_address
180 
181 opaque_t
182 scsi_watch_request_submit(
183 	struct scsi_device	*devp,
184 	int			interval,
185 	int			sense_length,
186 	int			(*callback)(),	/* callback function */
187 	caddr_t			cb_arg)		/* device number */
188 {
189 	register struct scsi_watch_request	*swr = NULL;
190 	register struct scsi_watch_request	*sswr, *p;
191 	struct buf				*bp = NULL;
192 	struct scsi_pkt				*rqpkt = NULL;
193 	struct scsi_pkt				*pkt = NULL;
194 	uchar_t					dtype;
195 
196 	SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
197 		"scsi_watch_request_submit: Entering ...\n");
198 
199 	mutex_enter(&sw.sw_mutex);
200 	if (sw.sw_thread == 0) {
201 		register kthread_t	*t;
202 
203 		t = thread_create((caddr_t)NULL, 0, scsi_watch_thread,
204 			NULL, 0, &p0, TS_RUN, v.v_maxsyspri - 2);
205 		sw.sw_thread = t;
206 	}
207 
208 	for (p = sw.sw_head; p != NULL; p = p->swr_next) {
209 		if ((p->swr_callback_arg == cb_arg) &&
210 			(p->swr_callback == callback))
211 			break;
212 	}
213 
214 	/* update time interval for an existing request */
215 	if (p) {
216 		p->swr_timeout = p->swr_interval = drv_usectohz(interval);
217 		p->swr_what = SWR_WATCH;
218 		cv_signal(&sw.sw_cv);
219 		mutex_exit(&sw.sw_mutex);
220 		return ((opaque_t)p);
221 	}
222 	mutex_exit(&sw.sw_mutex);
223 
224 	/*
225 	 * allocate space for scsi_watch_request
226 	 */
227 	swr = kmem_zalloc(sizeof (struct scsi_watch_request), KM_SLEEP);
228 
229 	/*
230 	 * allocate request sense bp and pkt and make cmd
231 	 * we shouldn't really need it if ARQ is enabled but it is useful
232 	 * if the ARQ failed.
233 	 */
234 	bp = scsi_alloc_consistent_buf(ROUTE, NULL,
235 		sense_length, B_READ, SLEEP_FUNC, NULL);
236 
237 	rqpkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL,
238 		bp, CDB_GROUP0, 1, 0, PKT_CONSISTENT, SLEEP_FUNC, NULL);
239 
240 	(void) scsi_setup_cdb((union scsi_cdb *)rqpkt->pkt_cdbp,
241 	    SCMD_REQUEST_SENSE, 0, SENSE_LENGTH, 0);
242 	FILL_SCSI1_LUN(devp, rqpkt);
243 	rqpkt->pkt_private = (opaque_t)swr;
244 	rqpkt->pkt_time = scsi_watch_io_time;
245 	rqpkt->pkt_comp = scsi_watch_request_intr;
246 	rqpkt->pkt_flags |= FLAG_HEAD;
247 
248 	/*
249 	 * Create TUR pkt or a zero byte WRITE(10) based on the
250 	 * disk-type for reservation state.
251 	 * For inq_dtype of SBC (DIRECT, dtype == 0)
252 	 * OR for RBC devices (dtype is 0xE) AND for
253 	 * ANSI version of SPC/SPC-2/SPC-3 (inq_ansi == 3-5).
254 	 */
255 
256 	dtype = devp->sd_inq->inq_dtype & DTYPE_MASK;
257 	if (((dtype == 0) || (dtype == 0xE)) &&
258 		(devp->sd_inq->inq_ansi > 2)) {
259 		pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL, NULL,
260 			CDB_GROUP1, sizeof (struct scsi_arq_status),
261 			0, 0, SLEEP_FUNC, NULL);
262 
263 		(void) scsi_setup_cdb((union scsi_cdb *)pkt->pkt_cdbp,
264 			SCMD_WRITE_G1, 0, 0, 0);
265 	} else {
266 		pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL, NULL,
267 			CDB_GROUP0, sizeof (struct scsi_arq_status),
268 			0, 0, SLEEP_FUNC, NULL);
269 
270 		(void) scsi_setup_cdb((union scsi_cdb *)pkt->pkt_cdbp,
271 			SCMD_TEST_UNIT_READY, 0, 0, 0);
272 		FILL_SCSI1_LUN(devp, pkt);
273 	}
274 
275 	pkt->pkt_private = (opaque_t)swr;
276 	pkt->pkt_time = scsi_watch_io_time;
277 	pkt->pkt_comp = scsi_watch_request_intr;
278 	if (scsi_ifgetcap(&pkt->pkt_address, "tagged-qing", 1) == 1) {
279 		pkt->pkt_flags |= FLAG_STAG;
280 	}
281 
282 	/*
283 	 * set the allocated resources in swr
284 	 */
285 	swr->swr_rqbp = bp;
286 	swr->swr_rqpkt = rqpkt;
287 	swr->swr_pkt = pkt;
288 	swr->swr_timeout = swr->swr_interval = drv_usectohz(interval);
289 	swr->swr_callback = callback;
290 	swr->swr_callback_arg = cb_arg;
291 	swr->swr_what = SWR_WATCH;
292 	swr->swr_sense_length = (uchar_t)sense_length;
293 	cv_init(&swr->swr_terminate_cv, NULL, CV_DRIVER, NULL);
294 
295 	/*
296 	 * add to the list and wake up the thread
297 	 */
298 	mutex_enter(&sw.sw_mutex);
299 	swr->swr_next = sw.sw_head;
300 	swr->swr_prev = NULL;
301 	if (sw.sw_head) {
302 		sw.sw_head->swr_prev = swr;
303 	}
304 	sw.sw_head = swr;
305 
306 	/*
307 	 * reset all timeouts, so all requests are in sync again
308 	 * XXX there is a small window where the watch thread releases
309 	 * the mutex so that could upset the resyncing
310 	 */
311 	sswr = swr;
312 	while (sswr) {
313 		sswr->swr_timeout = swr->swr_interval;
314 		sswr = sswr->swr_next;
315 	}
316 	cv_signal(&sw.sw_cv);
317 	mutex_exit(&sw.sw_mutex);
318 	return ((opaque_t)swr);
319 }
320 
321 
322 /*
323  * called by (eg. pwr management) to resume the scsi_watch_thread
324  */
325 void
326 scsi_watch_resume(opaque_t token)
327 {
328 	struct scsi_watch_request *swr = (struct scsi_watch_request *)NULL;
329 	/*
330 	 * Change the state to SW_RUNNING and wake up the scsi_watch_thread
331 	 */
332 	SW_DEBUG(0, sw_label, SCSI_DEBUG, "scsi_watch_resume:\n");
333 	mutex_enter(&sw.sw_mutex);
334 
335 	if (!sw.sw_head)
336 		goto exit;
337 
338 	/* search for token */
339 	for (swr = sw.sw_head; swr; swr = swr->swr_next) {
340 		if (swr == (struct scsi_watch_request *)token)
341 			break;
342 	}
343 
344 	/* if we can't find this value, then we just do nothing */
345 	if (swr == (struct scsi_watch_request *)NULL)
346 		goto exit;
347 
348 	swr->swr_what = SWR_WATCH;
349 
350 
351 	/* see if all swr's are awake, then start the thread again */
352 	for (swr = sw.sw_head; swr; swr = swr->swr_next) {
353 		if (swr->swr_what != SWR_WATCH)
354 			goto exit;
355 	}
356 
357 	sw.sw_state = SW_RUNNING;
358 	cv_signal(&sw.sw_cv);
359 
360 exit:
361 	mutex_exit(&sw.sw_mutex);
362 }
363 
364 
365 /*
366  * called by clients (eg. pwr management) to suspend the scsi_watch_thread
367  */
368 void
369 scsi_watch_suspend(opaque_t token)
370 {
371 	struct scsi_watch_request *swr = (struct scsi_watch_request *)NULL;
372 	clock_t	now;
373 	clock_t halfsec_delay = drv_usectohz(500000);
374 
375 	SW_DEBUG(0, sw_label, SCSI_DEBUG, "scsi_watch_suspend:\n");
376 
377 	mutex_enter(&sw.sw_mutex);
378 
379 	if (!sw.sw_head)
380 		goto exit;
381 
382 	/* search for token */
383 	for (swr = sw.sw_head; swr; swr = swr->swr_next) {
384 		if (swr == (struct scsi_watch_request *)token)
385 			break;
386 	}
387 
388 	/* if we can't find this value, then we just do nothing */
389 	if (swr == (struct scsi_watch_request *)NULL)
390 		goto exit;
391 
392 
393 	for (;;) {
394 		if (swr->swr_busy) {
395 			/*
396 			 * XXX: Assumes that this thread can rerun
397 			 * till all outstanding cmds are complete
398 			 */
399 			swr->swr_what = SWR_SUSPEND_REQUESTED;
400 			now = ddi_get_lbolt();
401 			(void) cv_timedwait(&sw.sw_cv, &sw.sw_mutex,
402 			    now + halfsec_delay);
403 		} else {
404 			swr->swr_what = SWR_SUSPENDED;
405 			break;
406 		}
407 	}
408 
409 	/* see if all swr's are suspended, then suspend the thread */
410 	for (swr = sw.sw_head; swr; swr = swr->swr_next) {
411 		if (swr->swr_what != SWR_SUSPENDED)
412 			goto exit;
413 	}
414 
415 	sw.sw_state = SW_SUSPENDED;
416 
417 exit:
418 	mutex_exit(&sw.sw_mutex);
419 }
420 
421 /*
422  * destroy swr, called for watch thread
423  */
424 static void
425 scsi_watch_request_destroy(struct scsi_watch_request *swr)
426 {
427 	ASSERT(MUTEX_HELD(&sw.sw_mutex));
428 	ASSERT(swr->swr_busy == 0);
429 
430 	SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
431 		"scsi_watch_request_destroy: Entering ...\n");
432 
433 	/*
434 	 * remove swr from linked list and destroy pkts
435 	 */
436 	if (swr->swr_prev) {
437 		swr->swr_prev->swr_next = swr->swr_next;
438 	}
439 	if (swr->swr_next) {
440 		swr->swr_next->swr_prev = swr->swr_prev;
441 	}
442 	if (sw.sw_head == swr) {
443 		sw.sw_head = swr->swr_next;
444 	}
445 
446 	scsi_destroy_pkt(swr->swr_rqpkt);
447 	scsi_free_consistent_buf(swr->swr_rqbp);
448 	scsi_destroy_pkt(swr->swr_pkt);
449 	cv_signal(&swr->swr_terminate_cv);
450 }
451 
452 /*
453  * scsi_watch_request_terminate()
454  * called by requestor to terminate any pending watch request.
455  * if the request is currently "busy", and the caller cannot wait, failure
456  * is returned. O/w the request is cleaned up immediately.
457  */
458 int
459 scsi_watch_request_terminate(opaque_t token, int flags)
460 {
461 	struct scsi_watch_request *swr =
462 		(struct scsi_watch_request *)token;
463 	struct scsi_watch_request *sswr;
464 
465 	/*
466 	 * We try to clean up this request if we can. We also inform
467 	 * the watch thread that we mucked around the list so it has
468 	 * to start reading from head of list again.
469 	 */
470 	SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
471 		"scsi_watch_request_terminate: Entering(0x%p) ...\n",
472 		(void *)swr);
473 	mutex_enter(&sw.sw_mutex);
474 
475 	/*
476 	 * check if it is still in the list
477 	 */
478 	sswr = sw.sw_head;
479 	while (sswr) {
480 		if (sswr == swr) {
481 			if (swr->swr_busy) {
482 				if (flags == SCSI_WATCH_TERMINATE_NOWAIT) {
483 					mutex_exit(&sw.sw_mutex);
484 					return (SCSI_WATCH_TERMINATE_FAIL);
485 				} else {
486 					swr->swr_what = SWR_STOP;
487 					cv_wait(&swr->swr_terminate_cv,
488 						&sw.sw_mutex);
489 					goto done;
490 				}
491 			} else {
492 				scsi_watch_request_destroy(swr);
493 				sw.sw_flags |= SW_START_HEAD;
494 				goto done;
495 			}
496 		}
497 		sswr = sswr->swr_next;
498 	}
499 done:
500 	mutex_exit(&sw.sw_mutex);
501 	if (sswr) {
502 		cv_destroy(&swr->swr_terminate_cv);
503 		kmem_free((caddr_t)swr, sizeof (struct scsi_watch_request));
504 		return (SCSI_WATCH_TERMINATE_SUCCESS);
505 	} else {
506 		return (SCSI_WATCH_TERMINATE_FAIL);
507 	}
508 }
509 
510 
511 /*
512  * The routines scsi_watch_thread & scsi_watch_request_intr are
513  * on different threads.
514  * If there is no work to be done by the lower level driver
515  * then swr->swr_busy will not be set.
516  * In this case we will call CALLB_CPR_SAFE_BEGIN before
517  * calling cv_timedwait.
518  * In the other case where there is work to be done by
519  * the lower level driver then the flag swr->swr_busy will
520  * be set.
521  * We cannot call CALLB_CPR_SAFE_BEGIN at this point the reason
522  * is the intr thread can interfere with our operations. So
523  * we do a cv_timedwait here. Now at the completion of the
524  * lower level driver's work we will call CALLB_CPR_SAFE_BEGIN
525  * in scsi_watch_request_intr.
526  * In all the cases we will call CALLB_CPR_SAFE_END only if
527  * we already called a CALLB_CPR_SAFE_BEGIN and this is flagged
528  * by sw_cpr_flag.
529  * Warlock has a problem when we use different locks
530  * on the same type of structure in different contexts.
531  * We use callb_cpr_t in both scsi_watch and esp_callback threads.
532  * we use different mutexe's in different threads. And
533  * this is not acceptable to warlock. To avoid this
534  * problem we use the same name for the mutex in
535  * both scsi_watch & esp_callback. when __lock_lint is not defined
536  * esp_callback uses the mutex on the stack and in scsi_watch
537  * a static variable. But when __lock_lint is defined
538  * we make a mutex which is global in esp_callback and
539  * a external mutex for scsi_watch.
540  */
541 static int sw_cmd_count = 0;
542 static int sw_cpr_flag = 0;
543 static callb_cpr_t cpr_info;
544 #ifndef __lock_lint
545 static kmutex_t cpr_mutex;
546 #else
547 extern kmutex_t cpr_mutex;
548 #endif
549 
550 #if !defined(lint)
551 _NOTE(MUTEX_PROTECTS_DATA(cpr_mutex, cpr_info))
552 _NOTE(MUTEX_PROTECTS_DATA(cpr_mutex, sw_cmd_count))
553 #endif
554 /*
555  * the scsi watch thread:
556  * it either wakes up if there is work to do or if the cv_timeait
557  * timed out
558  * normally, it wakes up every <delay> seconds and checks the list.
559  * the interval is not very accurate if the cv was signalled but that
560  * really doesn't matter much
561  * it is more important that we fire off all TURs simulataneously so
562  * we don't have to wake up frequently
563  */
564 static void
565 scsi_watch_thread()
566 {
567 	struct scsi_watch_request	*swr, *next;
568 	clock_t				now;
569 	clock_t				last_delay = 0;
570 	clock_t				next_delay = 0;
571 	clock_t				onesec = drv_usectohz(1000000);
572 	clock_t				exit_delay = 60 * onesec;
573 
574 	SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
575 		"scsi_watch_thread: Entering ...\n");
576 
577 #if !defined(lint)
578 	_NOTE(NO_COMPETING_THREADS_NOW);
579 #endif
580 	mutex_init(&cpr_mutex, NULL, MUTEX_DRIVER, NULL);
581 	CALLB_CPR_INIT(&cpr_info,
582 		&cpr_mutex, callb_generic_cpr, "scsi_watch");
583 	sw_cpr_flag = 0;
584 #if !defined(lint)
585 	/*LINTED*/
586 	_NOTE(COMPETING_THREADS_NOW);
587 #endif
588 	/*
589 	 * grab the mutex and wait for work
590 	 */
591 	mutex_enter(&sw.sw_mutex);
592 	if (sw.sw_head == NULL) {
593 		cv_wait(&sw.sw_cv, &sw.sw_mutex);
594 	}
595 
596 	/*
597 	 * now loop forever for work; if queue is empty exit
598 	 */
599 	for (;;) {
600 head:
601 		swr = sw.sw_head;
602 		while (swr) {
603 
604 			/*
605 			 * If state is not running, wait for scsi_watch_resume
606 			 * to signal restart, but before going into cv_wait
607 			 * need to let the PM framework know that it is safe
608 			 * to stop this thread for CPR
609 			 */
610 			if (sw.sw_state != SW_RUNNING) {
611 				SW_DEBUG(0, sw_label, SCSI_DEBUG,
612 					"scsi_watch_thread suspended\n");
613 				mutex_enter(&cpr_mutex);
614 				if (!sw_cmd_count) {
615 					CALLB_CPR_SAFE_BEGIN(&cpr_info);
616 					sw_cpr_flag = 1;
617 				}
618 				mutex_exit(&cpr_mutex);
619 				cv_wait(&sw.sw_cv, &sw.sw_mutex);
620 				/*
621 				 * Need to let the PM framework know that it
622 				 * is no longer safe to stop the thread for
623 				 * CPR.
624 				 */
625 				mutex_exit(&sw.sw_mutex);
626 				mutex_enter(&cpr_mutex);
627 				if (sw_cpr_flag == 1) {
628 					CALLB_CPR_SAFE_END(
629 						&cpr_info, &cpr_mutex);
630 					sw_cpr_flag = 0;
631 				}
632 				mutex_exit(&cpr_mutex);
633 				mutex_enter(&sw.sw_mutex);
634 			}
635 
636 			if (next_delay == 0) {
637 				next_delay = swr->swr_timeout;
638 			} else {
639 				next_delay = min(swr->swr_timeout, next_delay);
640 			}
641 
642 			swr->swr_timeout -= last_delay;
643 			next = swr->swr_next;
644 
645 			SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
646 				"scsi_watch_thread: "
647 				"swr(0x%p),what=%x,timeout=%lx,"
648 				"interval=%lx,delay=%lx\n",
649 				(void *)swr, swr->swr_what, swr->swr_timeout,
650 				swr->swr_interval, last_delay);
651 
652 			switch (swr->swr_what) {
653 			case SWR_SUSPENDED:
654 			case SWR_SUSPEND_REQUESTED:
655 				/* if we are suspended, don't do anything */
656 				break;
657 
658 			case SWR_STOP:
659 				if (swr->swr_busy == 0) {
660 					scsi_watch_request_destroy(swr);
661 				}
662 				break;
663 
664 			default:
665 				if (swr->swr_timeout <= 0 && !swr->swr_busy) {
666 					swr->swr_busy = 1;
667 
668 					/*
669 					 * submit the cmd and let the completion
670 					 * function handle the result
671 					 * release the mutex (good practice)
672 					 * this should be safe even if the list
673 					 * is changing
674 					 */
675 					mutex_exit(&sw.sw_mutex);
676 					mutex_enter(&cpr_mutex);
677 					sw_cmd_count++;
678 					mutex_exit(&cpr_mutex);
679 					SW_DEBUG((dev_info_t *)NULL,
680 						sw_label, SCSI_DEBUG,
681 						"scsi_watch_thread: "
682 						"Starting TUR\n");
683 					if (scsi_transport(swr->swr_pkt) !=
684 						TRAN_ACCEPT) {
685 
686 						/*
687 						 * try again later
688 						 */
689 						swr->swr_busy = 0;
690 						SW_DEBUG((dev_info_t *)NULL,
691 							sw_label, SCSI_DEBUG,
692 							"scsi_watch_thread: "
693 							"Transport Failed\n");
694 						mutex_enter(&cpr_mutex);
695 						sw_cmd_count--;
696 						mutex_exit(&cpr_mutex);
697 					}
698 					mutex_enter(&sw.sw_mutex);
699 					swr->swr_timeout = swr->swr_interval;
700 				}
701 				break;
702 			}
703 			swr = next;
704 			if (sw.sw_flags & SW_START_HEAD) {
705 				sw.sw_flags &= ~SW_START_HEAD;
706 				goto head;
707 			}
708 		}
709 
710 		/*
711 		 * delay using cv_timedwait; we return when
712 		 * signalled or timed out
713 		 */
714 		if (sw.sw_head != NULL) {
715 			if (next_delay <= 0) {
716 				next_delay = onesec;
717 			}
718 		} else {
719 			next_delay = exit_delay;
720 		}
721 		now = ddi_get_lbolt();
722 
723 		mutex_enter(&cpr_mutex);
724 		if (!sw_cmd_count) {
725 			CALLB_CPR_SAFE_BEGIN(&cpr_info);
726 			sw_cpr_flag = 1;
727 		}
728 		mutex_exit(&cpr_mutex);
729 		/*
730 		 * if we return from cv_timedwait because we were
731 		 * signalled, the delay is not accurate but that doesn't
732 		 * really matter
733 		 */
734 		(void) cv_timedwait(&sw.sw_cv, &sw.sw_mutex, now + next_delay);
735 		mutex_exit(&sw.sw_mutex);
736 		mutex_enter(&cpr_mutex);
737 		if (sw_cpr_flag == 1) {
738 			CALLB_CPR_SAFE_END(&cpr_info, &cpr_mutex);
739 			sw_cpr_flag = 0;
740 		}
741 		mutex_exit(&cpr_mutex);
742 		mutex_enter(&sw.sw_mutex);
743 		last_delay = next_delay;
744 		next_delay = 0;
745 
746 		/*
747 		 * is there still work to do?
748 		 */
749 		if (sw.sw_head == NULL) {
750 			break;
751 		}
752 	}
753 
754 	/*
755 	 * no more work to do, reset sw_thread and exit
756 	 */
757 	sw.sw_thread = 0;
758 	mutex_exit(&sw.sw_mutex);
759 #ifndef __lock_lint
760 	mutex_enter(&cpr_mutex);
761 	CALLB_CPR_EXIT(&cpr_info);
762 #endif
763 	mutex_destroy(&cpr_mutex);
764 	SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
765 		"scsi_watch_thread: Exiting ...\n");
766 }
767 
768 /*
769  * callback completion function for scsi watch pkt
770  */
771 #define	SCBP(pkt)	((struct scsi_status *)(pkt)->pkt_scbp)
772 #define	SCBP_C(pkt)	((*(pkt)->pkt_scbp) & STATUS_MASK)
773 
774 static void
775 scsi_watch_request_intr(struct scsi_pkt *pkt)
776 {
777 	struct scsi_watch_result	result;
778 	struct scsi_watch_request	*swr =
779 		(struct scsi_watch_request *)pkt->pkt_private;
780 	struct scsi_status		*rqstatusp;
781 	struct scsi_extended_sense	*rqsensep = NULL;
782 	int				amt = 0;
783 
784 	SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
785 		"scsi_watch_intr: Entering ...\n");
786 
787 	/*
788 	 * first check if it is the TUR or RQS pkt
789 	 */
790 	if (pkt == swr->swr_pkt) {
791 		if (SCBP_C(pkt) != STATUS_GOOD &&
792 			SCBP_C(pkt) != STATUS_RESERVATION_CONFLICT) {
793 			if (SCBP(pkt)->sts_chk &&
794 			    ((pkt->pkt_state & STATE_ARQ_DONE) == 0)) {
795 
796 				/*
797 				 * submit the request sense pkt
798 				 */
799 				SW_DEBUG((dev_info_t *)NULL,
800 					sw_label, SCSI_DEBUG,
801 					"scsi_watch_intr: "
802 					"Submitting a Request Sense "
803 					"Packet\n");
804 				if (scsi_transport(swr->swr_rqpkt) !=
805 					TRAN_ACCEPT) {
806 
807 					/*
808 					 * just give up and try again later
809 					 */
810 					SW_DEBUG((dev_info_t *)NULL,
811 						sw_label, SCSI_DEBUG,
812 						"scsi_watch_intr: "
813 						"Request Sense "
814 						"Transport Failed\n");
815 					goto done;
816 				}
817 
818 				/*
819 				 * wait for rqsense to complete
820 				 */
821 				return;
822 
823 			} else	if (SCBP(pkt)->sts_chk) {
824 
825 				/*
826 				 * check the autorequest sense data
827 				 */
828 				struct scsi_arq_status	*arqstat =
829 				    (struct scsi_arq_status *)pkt->pkt_scbp;
830 
831 				rqstatusp = &arqstat->sts_rqpkt_status;
832 				rqsensep = &arqstat->sts_sensedata;
833 				amt = swr->swr_sense_length -
834 					arqstat->sts_rqpkt_resid;
835 				SW_DEBUG((dev_info_t *)NULL,
836 					sw_label, SCSI_DEBUG,
837 					"scsi_watch_intr: "
838 					"Auto Request Sense, amt=%x\n", amt);
839 			}
840 		}
841 
842 	} else if (pkt == swr->swr_rqpkt) {
843 
844 		/*
845 		 * check the request sense data
846 		 */
847 		rqstatusp = (struct scsi_status *)pkt->pkt_scbp;
848 		rqsensep = (struct scsi_extended_sense *)
849 			swr->swr_rqbp->b_un.b_addr;
850 		amt = swr->swr_sense_length - pkt->pkt_resid;
851 		SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
852 		"scsi_watch_intr: "
853 		"Request Sense Completed, amt=%x\n", amt);
854 	} else {
855 
856 		/*
857 		 * should not reach here!!!
858 		 */
859 		scsi_log((dev_info_t *)NULL, sw_label, CE_PANIC,
860 			"scsi_watch_intr: Bad Packet(0x%p)", (void *)pkt);
861 	}
862 
863 	if (rqsensep) {
864 
865 		/*
866 		 * check rqsense status and data
867 		 */
868 		if (rqstatusp->sts_busy || rqstatusp->sts_chk) {
869 
870 			/*
871 			 * try again later
872 			 */
873 			SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
874 				"scsi_watch_intr: "
875 				"Auto Request Sense Failed - "
876 				"Busy or Check Condition\n");
877 			goto done;
878 		}
879 
880 		SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
881 			"scsi_watch_intr: "
882 			"es_key=%x, adq=%x, amt=%x\n",
883 			rqsensep->es_key, rqsensep->es_add_code, amt);
884 	}
885 
886 	/*
887 	 * callback to target driver to do the real work
888 	 */
889 	result.statusp = SCBP(swr->swr_pkt);
890 	result.sensep = rqsensep;
891 	result.actual_sense_length = (uchar_t)amt;
892 	result.pkt = swr->swr_pkt;
893 
894 	if ((*swr->swr_callback)(swr->swr_callback_arg, &result)) {
895 		swr->swr_what = SWR_STOP;
896 	}
897 
898 done:
899 	swr->swr_busy = 0;
900 	mutex_enter(&cpr_mutex);
901 	sw_cmd_count --;
902 	if (!sw_cmd_count) {
903 		CALLB_CPR_SAFE_BEGIN(&cpr_info);
904 		sw_cpr_flag = 1;
905 	}
906 	mutex_exit(&cpr_mutex);
907 }
908