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 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28#include <sys/types.h>
29#include <sys/kmem.h>
30#include <sys/debug.h>
31#include <sys/scsi/scsi.h>
32
33#include "ghd.h"
34
35/* ghd_poll() function codes: */
36typedef enum {
37	GHD_POLL_REQUEST,	/* wait for a specific request */
38	GHD_POLL_DEVICE,	/* wait for a specific device to idle */
39	GHD_POLL_ALL		/* wait for the whole bus to idle */
40} gpoll_t;
41
42/*
43 * Local functions:
44 */
45static	gcmd_t	*ghd_doneq_get(ccc_t *cccp);
46static	void	 ghd_doneq_pollmode_enter(ccc_t *cccp);
47static	void	 ghd_doneq_pollmode_exit(ccc_t *cccp);
48static	uint_t	 ghd_doneq_process(caddr_t arg);
49static	void	 ghd_do_reset_notify_callbacks(ccc_t *cccp);
50
51static	int	 ghd_poll(ccc_t *cccp, gpoll_t polltype, ulong_t polltime,
52			gcmd_t *poll_gcmdp, gtgt_t *gtgtp, void *intr_status);
53
54
55/*
56 * Local configuration variables
57 */
58#define	DEFAULT_GHD_TIMEOUT    50000	/* Amount of time to poll(50ms) */
59
60ulong_t	ghd_tran_abort_timeout = DEFAULT_GHD_TIMEOUT;
61ulong_t	ghd_tran_abort_lun_timeout = DEFAULT_GHD_TIMEOUT;
62ulong_t	ghd_tran_reset_target_timeout = DEFAULT_GHD_TIMEOUT;
63ulong_t	ghd_tran_reset_bus_timeout = DEFAULT_GHD_TIMEOUT;
64
65static int
66ghd_doneq_init(ccc_t *cccp)
67{
68	ddi_iblock_cookie_t iblock;
69
70	L2_INIT(&cccp->ccc_doneq);
71	cccp->ccc_hba_pollmode = TRUE;
72
73	if (ddi_add_softintr(cccp->ccc_hba_dip, DDI_SOFTINT_LOW,
74	    &cccp->ccc_doneq_softid, &iblock, NULL,
75	    ghd_doneq_process, (caddr_t)cccp) != DDI_SUCCESS) {
76		GDBG_ERROR(("ghd_doneq_init: add softintr failed cccp 0x%p\n",
77		    (void *)cccp));
78		return (FALSE);
79	}
80
81	mutex_init(&cccp->ccc_doneq_mutex, NULL, MUTEX_DRIVER, iblock);
82	ghd_doneq_pollmode_exit(cccp);
83	return (TRUE);
84}
85
86/*
87 * ghd_complete():
88 *
89 *	The HBA driver calls this entry point when it's completely
90 *	done processing a request.
91 *
92 *	See the GHD_COMPLETE_INLINE() macro in ghd.h for the actual code.
93 */
94
95void
96ghd_complete(ccc_t *cccp, gcmd_t *gcmdp)
97{
98	ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
99	GHD_COMPLETE_INLINE(cccp, gcmdp);
100}
101
102
103/*
104 * ghd_doneq_put_head():
105 *
106 *	Mark the request done and prepend it to the doneq.
107 *	See the GHD_DONEQ_PUT_HEAD_INLINE() macros in ghd.h for
108 *	the actual code.
109 */
110void
111ghd_doneq_put_head(ccc_t *cccp, gcmd_t *gcmdp)
112{
113	GHD_DONEQ_PUT_HEAD_INLINE(cccp, gcmdp)
114}
115
116/*
117 * ghd_doneq_put_tail():
118 *
119 *	Mark the request done and append it to the doneq.
120 *	See the GHD_DONEQ_PUT_TAIL_INLINE() macros in ghd.h for
121 *	the actual code.
122 */
123void
124ghd_doneq_put_tail(ccc_t *cccp, gcmd_t *gcmdp)
125{
126	GHD_DONEQ_PUT_TAIL_INLINE(cccp, gcmdp)
127}
128
129static gcmd_t	*
130ghd_doneq_get(ccc_t *cccp)
131{
132	kmutex_t *doneq_mutexp = &cccp->ccc_doneq_mutex;
133	gcmd_t	 *gcmdp;
134
135	mutex_enter(doneq_mutexp);
136	if ((gcmdp = L2_next(&cccp->ccc_doneq)) != NULL)
137		L2_delete(&gcmdp->cmd_q);
138	mutex_exit(doneq_mutexp);
139	return (gcmdp);
140}
141
142
143static void
144ghd_doneq_pollmode_enter(ccc_t *cccp)
145{
146	kmutex_t *doneq_mutexp = &cccp->ccc_doneq_mutex;
147
148	mutex_enter(doneq_mutexp);
149	cccp->ccc_hba_pollmode = TRUE;
150	mutex_exit(doneq_mutexp);
151}
152
153
154static void
155ghd_doneq_pollmode_exit(ccc_t *cccp)
156{
157	kmutex_t *doneq_mutexp = &cccp->ccc_doneq_mutex;
158
159	mutex_enter(doneq_mutexp);
160	cccp->ccc_hba_pollmode = FALSE;
161	mutex_exit(doneq_mutexp);
162
163	/* trigger software interrupt for the completion callbacks */
164	if (!L2_EMPTY(&cccp->ccc_doneq)) {
165		/*
166		 * If we are panicking we should just call the completion
167		 * function directly as we can not use soft interrupts
168		 * or timeouts during panic.
169		 */
170		if (!ddi_in_panic())
171			ddi_trigger_softintr(cccp->ccc_doneq_softid);
172		else
173			(void) ghd_doneq_process((caddr_t)cccp);
174	}
175}
176
177
178/* ***************************************************************** */
179
180/*
181 *
182 * ghd_doneq_process()
183 *
184 *	This function is called directly from the software interrupt
185 *	handler.
186 *
187 *	The doneq is protected by a separate mutex than the
188 *	HBA mutex in order to avoid mutex contention on MP systems.
189 *
190 */
191
192static uint_t
193ghd_doneq_process(caddr_t arg)
194{
195	ccc_t *cccp =	(ccc_t *)arg;
196	kmutex_t	*doneq_mutexp;
197	gcmd_t		*gcmdp;
198	int			rc = DDI_INTR_UNCLAIMED;
199
200	doneq_mutexp = &cccp->ccc_doneq_mutex;
201
202	for (;;) {
203		mutex_enter(doneq_mutexp);
204		/* skip if FLAG_NOINTR request in progress */
205		if (cccp->ccc_hba_pollmode)
206			break;
207		/* pop the first one from the done Q */
208		if ((gcmdp = L2_next(&cccp->ccc_doneq)) == NULL)
209			break;
210		L2_delete(&gcmdp->cmd_q);
211
212		if (gcmdp->cmd_flags & GCMDFLG_RESET_NOTIFY) {
213			/* special request; processed here and discarded */
214			ghd_do_reset_notify_callbacks(cccp);
215			ghd_gcmd_free(gcmdp);
216			mutex_exit(doneq_mutexp);
217			continue;
218		}
219
220		/*
221		 * drop the mutex since completion
222		 * function can re-enter the top half via
223		 * ghd_transport()
224		 */
225		mutex_exit(doneq_mutexp);
226		gcmdp->cmd_state = GCMD_STATE_IDLE;
227		(*cccp->ccc_hba_complete)(cccp->ccc_hba_handle, gcmdp, TRUE);
228#ifdef notyet
229		/* I don't think this is ever necessary */
230		rc = DDI_INTR_CLAIMED;
231#endif
232	}
233	mutex_exit(doneq_mutexp);
234	return (rc);
235}
236
237static void
238ghd_do_reset_notify_callbacks(ccc_t *cccp)
239{
240	ghd_reset_notify_list_t *rnp;
241	L2el_t *rnl = &cccp->ccc_reset_notify_list;
242
243	ASSERT(mutex_owned(&cccp->ccc_doneq_mutex));
244
245	/* lock the reset notify list while we operate on it */
246	mutex_enter(&cccp->ccc_reset_notify_mutex);
247
248	for (rnp = (ghd_reset_notify_list_t *)L2_next(rnl);
249	    rnp != NULL;
250	    rnp = (ghd_reset_notify_list_t *)L2_next(&rnp->l2_link)) {
251
252		/* don't call if HBA driver didn't set it */
253		if (cccp->ccc_hba_reset_notify_callback) {
254			(*cccp->ccc_hba_reset_notify_callback)(rnp->gtgtp,
255			    rnp->callback, rnp->arg);
256		}
257	}
258	mutex_exit(&cccp->ccc_reset_notify_mutex);
259}
260
261
262/* ***************************************************************** */
263
264
265/*
266 * ghd_register()
267 *
268 *	Do the usual interrupt handler setup stuff.
269 *
270 *	Also, set up three mutexes: the wait queue mutex, the HBA
271 *	mutex, and the done queue mutex. The permitted locking
272 *	orders are:
273 *
274 *		1. enter(waitq)
275 *		2. enter(activel)
276 *		3. enter(doneq)
277 *		4. enter(HBA) then enter(activel)
278 *		5. enter(HBA) then enter(doneq)
279 *		6. enter(HBA) then enter(waitq)
280 *		7. enter(waitq) then tryenter(HBA)
281 *
282 *	Note: cases 6 and 7 won't deadlock because case 7 is always
283 *	mutex_tryenter() call.
284 *
285 */
286
287
288int
289ghd_register(char *labelp,
290	ccc_t	*cccp,
291	dev_info_t *dip,
292	int	inumber,
293	void	*hba_handle,
294	int	(*ccballoc)(gtgt_t *, gcmd_t *, int, int, int, int),
295	void	(*ccbfree)(gcmd_t *),
296	void	(*sg_func)(gcmd_t *, ddi_dma_cookie_t *, int, int),
297	int	(*hba_start)(void *, gcmd_t *),
298	void    (*hba_complete)(void *, gcmd_t *, int),
299	uint_t	(*int_handler)(caddr_t),
300	int	(*get_status)(void *, void *),
301	void	(*process_intr)(void *, void *),
302	int	(*timeout_func)(void *, gcmd_t *, gtgt_t *, gact_t, int),
303	tmr_t	*tmrp,
304	void 	(*hba_reset_notify_callback)(gtgt_t *,
305			void (*)(caddr_t), caddr_t))
306{
307
308	cccp->ccc_label = labelp;
309	cccp->ccc_hba_dip = dip;
310	cccp->ccc_ccballoc = ccballoc;
311	cccp->ccc_ccbfree = ccbfree;
312	cccp->ccc_sg_func = sg_func;
313	cccp->ccc_hba_start = hba_start;
314	cccp->ccc_hba_complete = hba_complete;
315	cccp->ccc_process_intr = process_intr;
316	cccp->ccc_get_status = get_status;
317	cccp->ccc_hba_handle = hba_handle;
318	cccp->ccc_hba_reset_notify_callback = hba_reset_notify_callback;
319
320	/* initialize the HBA's list headers */
321	CCCP_INIT(cccp);
322
323	if (ddi_get_iblock_cookie(dip, inumber, &cccp->ccc_iblock)
324	    != DDI_SUCCESS) {
325
326		return (FALSE);
327	}
328
329	mutex_init(&cccp->ccc_hba_mutex, NULL, MUTEX_DRIVER, cccp->ccc_iblock);
330
331	mutex_init(&cccp->ccc_waitq_mutex, NULL, MUTEX_DRIVER,
332	    cccp->ccc_iblock);
333
334	mutex_init(&cccp->ccc_reset_notify_mutex, NULL, MUTEX_DRIVER,
335	    cccp->ccc_iblock);
336
337	/* Establish interrupt handler */
338	if (ddi_add_intr(dip, inumber, &cccp->ccc_iblock, NULL,
339	    int_handler, (caddr_t)hba_handle) != DDI_SUCCESS) {
340		mutex_destroy(&cccp->ccc_hba_mutex);
341		mutex_destroy(&cccp->ccc_waitq_mutex);
342		mutex_destroy(&cccp->ccc_reset_notify_mutex);
343
344		return (FALSE);
345	}
346
347	if (ghd_timer_attach(cccp, tmrp, timeout_func) == FALSE) {
348		ddi_remove_intr(cccp->ccc_hba_dip, 0, cccp->ccc_iblock);
349		mutex_destroy(&cccp->ccc_hba_mutex);
350		mutex_destroy(&cccp->ccc_waitq_mutex);
351		mutex_destroy(&cccp->ccc_reset_notify_mutex);
352
353		return (FALSE);
354	}
355
356	if (ghd_doneq_init(cccp)) {
357
358		return (TRUE);
359	}
360
361	/*
362	 * ghd_doneq_init() returned error:
363	 */
364
365	ghd_timer_detach(cccp);
366	ddi_remove_intr(cccp->ccc_hba_dip, 0, cccp->ccc_iblock);
367	mutex_destroy(&cccp->ccc_hba_mutex);
368	mutex_destroy(&cccp->ccc_waitq_mutex);
369	mutex_destroy(&cccp->ccc_reset_notify_mutex);
370
371	return (FALSE);
372
373}
374
375
376void
377ghd_unregister(ccc_t *cccp)
378{
379	ghd_timer_detach(cccp);
380	ddi_remove_intr(cccp->ccc_hba_dip, 0, cccp->ccc_iblock);
381	ddi_remove_softintr(cccp->ccc_doneq_softid);
382	mutex_destroy(&cccp->ccc_hba_mutex);
383	mutex_destroy(&cccp->ccc_waitq_mutex);
384	mutex_destroy(&cccp->ccc_doneq_mutex);
385}
386
387
388
389int
390ghd_intr(ccc_t *cccp, void *intr_status)
391{
392	int (*statfunc)(void *, void *) = cccp->ccc_get_status;
393	void (*processfunc)(void *, void *) = cccp->ccc_process_intr;
394	kmutex_t *waitq_mutexp = &cccp->ccc_waitq_mutex;
395	kmutex_t *hba_mutexp = &cccp->ccc_hba_mutex;
396	void		  *handle = cccp->ccc_hba_handle;
397	int		   rc = DDI_INTR_UNCLAIMED;
398	int		   more;
399
400
401	mutex_enter(hba_mutexp);
402
403	GDBG_INTR(("ghd_intr(): cccp=0x%p status=0x%p\n",
404	    (void *)cccp, intr_status));
405
406	for (;;) {
407		more = FALSE;
408
409		/* process the interrupt status */
410		while ((*statfunc)(handle, intr_status)) {
411			(*processfunc)(handle, intr_status);
412			rc = DDI_INTR_CLAIMED;
413			more = TRUE;
414		}
415		mutex_enter(waitq_mutexp);
416		if (ghd_waitq_process_and_mutex_hold(cccp)) {
417			ASSERT(mutex_owned(hba_mutexp));
418			mutex_exit(waitq_mutexp);
419			continue;
420		}
421		if (more) {
422			mutex_exit(waitq_mutexp);
423			continue;
424		}
425		GDBG_INTR(("ghd_intr(): done cccp=0x%p status=0x%p rc %d\n",
426		    (void *)cccp, intr_status, rc));
427		/*
428		 * Release the mutexes in the opposite order that they
429		 * were acquired to prevent requests queued by
430		 * ghd_transport() from getting hung up in the wait queue.
431		 */
432		mutex_exit(hba_mutexp);
433		mutex_exit(waitq_mutexp);
434		return (rc);
435	}
436}
437
438static int
439ghd_poll(ccc_t	*cccp,
440	gpoll_t	 polltype,
441	ulong_t	 polltime,
442	gcmd_t	*poll_gcmdp,
443	gtgt_t	*gtgtp,
444	void	*intr_status)
445{
446	gcmd_t	*gcmdp;
447	L2el_t	 gcmd_hold_queue;
448	int	 got_it = FALSE;
449	clock_t  poll_lbolt;
450	clock_t	 start_lbolt;
451	clock_t	 current_lbolt;
452
453
454	ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
455	L2_INIT(&gcmd_hold_queue);
456
457	/* Que hora es? */
458	poll_lbolt = drv_usectohz((clock_t)polltime);
459	start_lbolt = ddi_get_lbolt();
460
461	/* unqueue and save all CMD/CCBs until I find the right one */
462	while (!got_it) {
463
464		/* Give up yet? */
465		current_lbolt = ddi_get_lbolt();
466		if (poll_lbolt && (current_lbolt - start_lbolt >= poll_lbolt))
467			break;
468
469		/*
470		 * delay 1 msec each time around the loop (this is an
471		 * arbitrary delay value, any value should work) except
472		 * zero because some devices don't like being polled too
473		 * fast and it saturates the bus on an MP system.
474		 */
475		drv_usecwait(1000);
476
477		/*
478		 * check for any new device status
479		 */
480		if ((*cccp->ccc_get_status)(cccp->ccc_hba_handle, intr_status))
481			(*cccp->ccc_process_intr)(cccp->ccc_hba_handle,
482			    intr_status);
483
484		/*
485		 * If something completed then try to start the
486		 * next request from the wait queue. Don't release
487		 * the HBA mutex because I don't know whether my
488		 * request(s) is/are on the done queue yet.
489		 */
490		mutex_enter(&cccp->ccc_waitq_mutex);
491		(void) ghd_waitq_process_and_mutex_hold(cccp);
492		mutex_exit(&cccp->ccc_waitq_mutex);
493
494		/*
495		 * Process the first of any timed-out requests.
496		 */
497		ghd_timer_poll(cccp, GHD_TIMER_POLL_ONE);
498
499		/*
500		 * Unqueue all the completed requests, look for mine
501		 */
502		while (gcmdp = ghd_doneq_get(cccp)) {
503			/*
504			 * If we got one and it's my request, then
505			 * we're done.
506			 */
507			if (gcmdp == poll_gcmdp) {
508				poll_gcmdp->cmd_state = GCMD_STATE_IDLE;
509				got_it = TRUE;
510				continue;
511			}
512			/* fifo queue the other cmds on my local list */
513			L2_add(&gcmd_hold_queue, &gcmdp->cmd_q, gcmdp);
514		}
515
516
517		/*
518		 * Check whether we're done yet.
519		 */
520		switch (polltype) {
521		case GHD_POLL_DEVICE:
522			/*
523			 * wait for everything queued on a specific device
524			 */
525			if (GDEV_NACTIVE(gtgtp->gt_gdevp) == 0)
526				got_it = TRUE;
527			break;
528
529		case GHD_POLL_ALL:
530			/*
531			 * if waiting for all outstanding requests and
532			 * if active list is now empty then exit
533			 */
534			if (GHBA_NACTIVE(cccp) == 0)
535				got_it = TRUE;
536			break;
537
538		case GHD_POLL_REQUEST:
539			break;
540
541		}
542	}
543
544	if (L2_EMPTY(&gcmd_hold_queue)) {
545		ASSERT(!mutex_owned(&cccp->ccc_waitq_mutex));
546		ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
547		return (got_it);
548	}
549
550	/*
551	 * copy the local gcmd_hold_queue back to the doneq so
552	 * that the order of completion callbacks is preserved
553	 */
554	while (gcmdp = L2_next(&gcmd_hold_queue)) {
555		L2_delete(&gcmdp->cmd_q);
556		GHD_DONEQ_PUT_TAIL(cccp, gcmdp);
557	}
558
559	ASSERT(!mutex_owned(&cccp->ccc_waitq_mutex));
560	ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
561	return (got_it);
562}
563
564
565/*
566 * ghd_tran_abort()
567 *
568 *	Abort specific command on a target.
569 *
570 */
571
572int
573ghd_tran_abort(ccc_t *cccp, gcmd_t *gcmdp, gtgt_t *gtgtp, void *intr_status)
574{
575	gact_t	 action;
576	int	 rc;
577
578	/*
579	 * call the driver's abort_cmd function
580	 */
581
582	mutex_enter(&cccp->ccc_hba_mutex);
583	ghd_doneq_pollmode_enter(cccp);
584
585	switch (gcmdp->cmd_state) {
586	case GCMD_STATE_WAITQ:
587		/* not yet started */
588		action = GACTION_EARLY_ABORT;
589		break;
590
591	case GCMD_STATE_ACTIVE:
592		/* in progress */
593		action = GACTION_ABORT_CMD;
594		break;
595
596	default:
597		/* everything else, probably already being aborted */
598		rc = FALSE;
599		goto exit;
600	}
601
602	/* stop the timer and remove it from the active list */
603	GHD_TIMER_STOP(cccp, gcmdp);
604
605	/* start a new timer and send out the abort command */
606	ghd_timer_newstate(cccp, gcmdp, gtgtp, action, GHD_TGTREQ);
607
608	/* wait for the abort to complete */
609	if (rc = ghd_poll(cccp, GHD_POLL_REQUEST, ghd_tran_abort_timeout,
610	    gcmdp, gtgtp, intr_status)) {
611		gcmdp->cmd_state = GCMD_STATE_DONEQ;
612		GHD_DONEQ_PUT_TAIL(cccp, gcmdp);
613	}
614
615exit:
616	ghd_doneq_pollmode_exit(cccp);
617
618	mutex_enter(&cccp->ccc_waitq_mutex);
619	ghd_waitq_process_and_mutex_exit(cccp);
620
621	return (rc);
622}
623
624
625/*
626 * ghd_tran_abort_lun()
627 *
628 *	Abort all commands on a specific target.
629 *
630 */
631
632int
633ghd_tran_abort_lun(ccc_t *cccp,	gtgt_t *gtgtp, void *intr_status)
634{
635	int	 rc;
636
637	/*
638	 * call the HBA driver's abort_device function
639	 */
640
641	mutex_enter(&cccp->ccc_hba_mutex);
642	ghd_doneq_pollmode_enter(cccp);
643
644	/* send out the abort device request */
645	ghd_timer_newstate(cccp, NULL, gtgtp, GACTION_ABORT_DEV, GHD_TGTREQ);
646
647	/* wait for the device to go idle */
648	rc = ghd_poll(cccp, GHD_POLL_DEVICE, ghd_tran_abort_lun_timeout,
649	    NULL, gtgtp, intr_status);
650
651	ghd_doneq_pollmode_exit(cccp);
652
653	mutex_enter(&cccp->ccc_waitq_mutex);
654	ghd_waitq_process_and_mutex_exit(cccp);
655
656	return (rc);
657}
658
659
660
661/*
662 * ghd_tran_reset_target()
663 *
664 *	reset the target device
665 *
666 *
667 */
668
669int
670ghd_tran_reset_target(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status)
671{
672	int rc = TRUE;
673
674
675	mutex_enter(&cccp->ccc_hba_mutex);
676	ghd_doneq_pollmode_enter(cccp);
677
678	/* send out the device reset request */
679	ghd_timer_newstate(cccp, NULL, gtgtp, GACTION_RESET_TARGET, GHD_TGTREQ);
680
681	/* wait for the device to reset */
682	rc = ghd_poll(cccp, GHD_POLL_DEVICE, ghd_tran_reset_target_timeout,
683	    NULL, gtgtp, intr_status);
684
685	ghd_doneq_pollmode_exit(cccp);
686
687	mutex_enter(&cccp->ccc_waitq_mutex);
688	ghd_waitq_process_and_mutex_exit(cccp);
689
690	return (rc);
691}
692
693
694
695/*
696 * ghd_tran_reset_bus()
697 *
698 *	reset the scsi bus
699 *
700 */
701
702int
703ghd_tran_reset_bus(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status)
704{
705	int	rc;
706
707	mutex_enter(&cccp->ccc_hba_mutex);
708	ghd_doneq_pollmode_enter(cccp);
709
710	/* send out the bus reset request */
711	ghd_timer_newstate(cccp, NULL, gtgtp, GACTION_RESET_BUS, GHD_TGTREQ);
712
713	/*
714	 * Wait for all active requests on this HBA to complete
715	 */
716	rc = ghd_poll(cccp, GHD_POLL_ALL, ghd_tran_reset_bus_timeout,
717	    NULL, NULL, intr_status);
718
719
720	ghd_doneq_pollmode_exit(cccp);
721
722	mutex_enter(&cccp->ccc_waitq_mutex);
723	ghd_waitq_process_and_mutex_exit(cccp);
724
725	return (rc);
726}
727
728
729int
730ghd_transport(ccc_t	*cccp,
731		gcmd_t	*gcmdp,
732		gtgt_t	*gtgtp,
733		ulong_t	 timeout,
734		int	 polled,
735		void	*intr_status)
736{
737	gdev_t	*gdevp = gtgtp->gt_gdevp;
738
739	ASSERT(!mutex_owned(&cccp->ccc_hba_mutex));
740	ASSERT(!mutex_owned(&cccp->ccc_waitq_mutex));
741
742	if (polled) {
743		/*
744		 * Grab the HBA mutex so no other requests are started
745		 * until after this one completes.
746		 */
747		mutex_enter(&cccp->ccc_hba_mutex);
748
749		GDBG_START(("ghd_transport: polled"
750		    " cccp 0x%p gdevp 0x%p gtgtp 0x%p gcmdp 0x%p\n",
751		    (void *)cccp, (void *)gdevp, (void *)gtgtp, (void *)gcmdp));
752
753		/*
754		 * Lock the doneq so no other thread flushes the Q.
755		 */
756		ghd_doneq_pollmode_enter(cccp);
757	}
758#if defined(GHD_DEBUG) || defined(__lint)
759	else {
760		GDBG_START(("ghd_transport: non-polled"
761		    " cccp 0x%p gdevp 0x%p gtgtp 0x%p gcmdp 0x%p\n",
762		    (void *)cccp, (void *)gdevp, (void *)gtgtp, (void *)gcmdp));
763	}
764#endif
765	/*
766	 * add this request to the tail of the waitq
767	 */
768	gcmdp->cmd_waitq_level = 1;
769	mutex_enter(&cccp->ccc_waitq_mutex);
770	L2_add(&GDEV_QHEAD(gdevp), &gcmdp->cmd_q, gcmdp);
771
772	/*
773	 * Add this request to the packet timer active list and start its
774	 * abort timer.
775	 */
776	gcmdp->cmd_state = GCMD_STATE_WAITQ;
777	ghd_timer_start(cccp, gcmdp, timeout);
778
779
780	/*
781	 * Check the device wait queue throttle and perhaps move
782	 * some requests to the end of the HBA wait queue.
783	 */
784	ghd_waitq_shuffle_up(cccp, gdevp);
785
786	if (!polled) {
787		/*
788		 * See if the HBA mutex is available but use the
789		 * tryenter so I don't deadlock.
790		 */
791		if (!mutex_tryenter(&cccp->ccc_hba_mutex)) {
792			/* The HBA mutex isn't available */
793			GDBG_START(("ghd_transport: !mutex cccp 0x%p\n",
794			    (void *)cccp));
795			mutex_exit(&cccp->ccc_waitq_mutex);
796			return (TRAN_ACCEPT);
797		}
798		GDBG_START(("ghd_transport: got mutex cccp 0x%p\n",
799		    (void *)cccp));
800
801		/*
802		 * start as many requests as possible from the head
803		 * of the HBA wait queue
804		 */
805
806		ghd_waitq_process_and_mutex_exit(cccp);
807
808		ASSERT(!mutex_owned(&cccp->ccc_hba_mutex));
809		ASSERT(!mutex_owned(&cccp->ccc_waitq_mutex));
810
811		return (TRAN_ACCEPT);
812	}
813
814
815	/*
816	 * If polled mode (FLAG_NOINTR specified in scsi_pkt flags),
817	 * then ghd_poll() waits until the request completes or times out
818	 * before returning.
819	 */
820
821	mutex_exit(&cccp->ccc_waitq_mutex);
822	(void) ghd_poll(cccp, GHD_POLL_REQUEST, 0, gcmdp, gtgtp, intr_status);
823	ghd_doneq_pollmode_exit(cccp);
824
825	mutex_enter(&cccp->ccc_waitq_mutex);
826	ghd_waitq_process_and_mutex_exit(cccp);
827
828	/* call HBA's completion function but don't do callback to target */
829	(*cccp->ccc_hba_complete)(cccp->ccc_hba_handle, gcmdp, FALSE);
830
831	GDBG_START(("ghd_transport: polled done cccp 0x%p\n", (void *)cccp));
832	return (TRAN_ACCEPT);
833}
834
835int ghd_reset_notify(ccc_t 	*cccp,
836			gtgt_t *gtgtp,
837			int 	flag,
838			void 	(*callback)(caddr_t),
839			caddr_t arg)
840{
841	ghd_reset_notify_list_t *rnp;
842	int rc = FALSE;
843
844	switch (flag) {
845
846	case SCSI_RESET_NOTIFY:
847
848		rnp = (ghd_reset_notify_list_t *)kmem_zalloc(sizeof (*rnp),
849		    KM_SLEEP);
850		rnp->gtgtp = gtgtp;
851		rnp->callback = callback;
852		rnp->arg = arg;
853
854		mutex_enter(&cccp->ccc_reset_notify_mutex);
855		L2_add(&cccp->ccc_reset_notify_list, &rnp->l2_link,
856		    (void *)rnp);
857		mutex_exit(&cccp->ccc_reset_notify_mutex);
858
859		rc = TRUE;
860
861		break;
862
863	case SCSI_RESET_CANCEL:
864
865		mutex_enter(&cccp->ccc_reset_notify_mutex);
866		for (rnp = (ghd_reset_notify_list_t *)
867		    L2_next(&cccp->ccc_reset_notify_list);
868		    rnp != NULL;
869		    rnp = (ghd_reset_notify_list_t *)L2_next(&rnp->l2_link)) {
870			if (rnp->gtgtp == gtgtp &&
871			    rnp->callback == callback &&
872			    rnp->arg == arg) {
873				L2_delete(&rnp->l2_link);
874				kmem_free(rnp, sizeof (*rnp));
875				rc = TRUE;
876			}
877		}
878		mutex_exit(&cccp->ccc_reset_notify_mutex);
879		break;
880
881	default:
882		rc = FALSE;
883		break;
884	}
885
886	return (rc);
887}
888
889/*
890 * freeze the HBA waitq output (see ghd_waitq_process_and_mutex_hold),
891 * presumably because of a SCSI reset, for delay milliseconds.
892 */
893
894void
895ghd_freeze_waitq(ccc_t *cccp, int delay)
896{
897	ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
898
899	/* freeze the waitq for delay milliseconds */
900
901	mutex_enter(&cccp->ccc_waitq_mutex);
902	cccp->ccc_waitq_freezetime = ddi_get_lbolt();
903	cccp->ccc_waitq_freezedelay = delay;
904	cccp->ccc_waitq_frozen = 1;
905	mutex_exit(&cccp->ccc_waitq_mutex);
906}
907
908void
909ghd_queue_hold(ccc_t *cccp)
910{
911	ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
912
913	mutex_enter(&cccp->ccc_waitq_mutex);
914	cccp->ccc_waitq_held = 1;
915	mutex_exit(&cccp->ccc_waitq_mutex);
916}
917
918void
919ghd_queue_unhold(ccc_t *cccp)
920{
921	ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
922
923	mutex_enter(&cccp->ccc_waitq_mutex);
924	cccp->ccc_waitq_held = 0;
925	mutex_exit(&cccp->ccc_waitq_mutex);
926}
927
928
929
930/*
931 * Trigger previously-registered reset notifications
932 */
933
934void
935ghd_trigger_reset_notify(ccc_t *cccp)
936{
937	gcmd_t *gcmdp;
938
939	ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
940
941	/* create magic doneq entry */
942
943	gcmdp = ghd_gcmd_alloc((gtgt_t *)NULL, 0, TRUE);
944	gcmdp->cmd_flags = GCMDFLG_RESET_NOTIFY;
945
946	/* put at head of doneq so it's processed ASAP */
947
948	GHD_DONEQ_PUT_HEAD(cccp, gcmdp);
949}
950