17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
58faf39b2Staylor  * Common Development and Distribution License (the "License").
68faf39b2Staylor  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21*5bd3d017SNikko He 
227c478bd9Sstevel@tonic-gate /*
23*5bd3d017SNikko He  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * Main Transport Routine for SCSA
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h>
307c478bd9Sstevel@tonic-gate #include <sys/thread.h>
31602ca9eaScth #include <sys/bitmap.h>
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #define	A_TO_TRAN(ap)	((ap)->a_hba_tran)
347c478bd9Sstevel@tonic-gate #define	P_TO_TRAN(pkt)	((pkt)->pkt_address.a_hba_tran)
357c478bd9Sstevel@tonic-gate #define	P_TO_ADDR(pkt)	(&((pkt)->pkt_address))
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #ifdef DEBUG
387c478bd9Sstevel@tonic-gate #define	SCSI_POLL_STAT
397c478bd9Sstevel@tonic-gate #endif
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #ifdef SCSI_POLL_STAT
427c478bd9Sstevel@tonic-gate int	scsi_poll_user;
437c478bd9Sstevel@tonic-gate int	scsi_poll_intr;
447c478bd9Sstevel@tonic-gate #endif
457c478bd9Sstevel@tonic-gate 
46602ca9eaScth int			scsi_pkt_bad_alloc_msg = 1;
47602ca9eaScth extern	ulong_t		*scsi_pkt_bad_alloc_bitmap;
487c478bd9Sstevel@tonic-gate extern	kmutex_t	scsi_flag_nointr_mutex;
497c478bd9Sstevel@tonic-gate extern	kcondvar_t	scsi_flag_nointr_cv;
507c478bd9Sstevel@tonic-gate 
51602ca9eaScth extern int		do_polled_io;
52602ca9eaScth 
53*5bd3d017SNikko He extern int		scsi_pkt_allow_naca;
54*5bd3d017SNikko He extern uchar_t		scsi_cdb_size[];
55*5bd3d017SNikko He #define	NACA_IS_SET(cdb)						\
56*5bd3d017SNikko He 	(((cdb)[scsi_cdb_size[GETGROUP((union scsi_cdb *)(cdb))] - 1]	\
57*5bd3d017SNikko He 	& CDB_FLAG_NACA) ? 1 : 0)
58*5bd3d017SNikko He 
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate  * we used to set the callback_done value to NULL after the callback
617c478bd9Sstevel@tonic-gate  * but this interfered with esp/fas drivers that also set the callback
627c478bd9Sstevel@tonic-gate  * to NULL to prevent callbacks during error recovery
631cba8b6cSRandall Ralphs  * to prevent confusion, create a truly unique value.
641cba8b6cSRandall Ralphs  * The scsi_callback_done() function is used to detect a packet
651cba8b6cSRandall Ralphs  * completion being called a second time.
667c478bd9Sstevel@tonic-gate  */
671cba8b6cSRandall Ralphs /* ARGSUSED */
681cba8b6cSRandall Ralphs void
scsi_callback_done(struct scsi_pkt * pkt)691cba8b6cSRandall Ralphs scsi_callback_done(struct scsi_pkt *pkt)
701cba8b6cSRandall Ralphs {
711cba8b6cSRandall Ralphs 	cmn_err(CE_PANIC,
721cba8b6cSRandall Ralphs 	    "%s: duplicate scsi_callback_done() on same scsi_pkt(9s)",
731cba8b6cSRandall Ralphs 	    mod_containing_pc(caller()));
741cba8b6cSRandall Ralphs }
751cba8b6cSRandall Ralphs 
761cba8b6cSRandall Ralphs #define	CALLBACK_DONE (scsi_callback_done)
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate static void
scsi_flag_nointr_comp(struct scsi_pkt * pkt)797c478bd9Sstevel@tonic-gate scsi_flag_nointr_comp(struct scsi_pkt *pkt)
807c478bd9Sstevel@tonic-gate {
817c478bd9Sstevel@tonic-gate 	mutex_enter(&scsi_flag_nointr_mutex);
827c478bd9Sstevel@tonic-gate 	pkt->pkt_comp = CALLBACK_DONE;
837c478bd9Sstevel@tonic-gate 	/*
847c478bd9Sstevel@tonic-gate 	 * We need cv_broadcast, because there can be more
857c478bd9Sstevel@tonic-gate 	 * than one thread sleeping on the cv. We
867c478bd9Sstevel@tonic-gate 	 * will wake all of them. The correct  one will
877c478bd9Sstevel@tonic-gate 	 * continue and the rest will again go to sleep.
887c478bd9Sstevel@tonic-gate 	 */
897c478bd9Sstevel@tonic-gate 	cv_broadcast(&scsi_flag_nointr_cv);
907c478bd9Sstevel@tonic-gate 	mutex_exit(&scsi_flag_nointr_mutex);
917c478bd9Sstevel@tonic-gate }
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate /*
947c478bd9Sstevel@tonic-gate  * A packet can have FLAG_NOINTR set because of target driver or
957c478bd9Sstevel@tonic-gate  * scsi_poll(). If FLAG_NOINTR is set and we are in user context,
967c478bd9Sstevel@tonic-gate  * we can avoid busy waiting in HBA by replacing the callback
977c478bd9Sstevel@tonic-gate  * function with our own function and resetting FLAG_NOINTR. We
987c478bd9Sstevel@tonic-gate  * can't do this in interrupt context because cv_wait will
997c478bd9Sstevel@tonic-gate  * sleep with CPU priority raised high and in case of some failure,
1007c478bd9Sstevel@tonic-gate  * the CPU will be stuck in high priority.
1017c478bd9Sstevel@tonic-gate  */
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate int
scsi_transport(struct scsi_pkt * pkt)1047c478bd9Sstevel@tonic-gate scsi_transport(struct scsi_pkt *pkt)
1057c478bd9Sstevel@tonic-gate {
1067c478bd9Sstevel@tonic-gate 	struct scsi_address	*ap = P_TO_ADDR(pkt);
107602ca9eaScth 	int			rval = TRAN_ACCEPT;
108602ca9eaScth 	major_t			major;
109602ca9eaScth 
110*5bd3d017SNikko He 	/*
111*5bd3d017SNikko He 	 * Add an assertion check for debugging as use of the NACA flag
112*5bd3d017SNikko He 	 * can cause problems. If an initiator sets it but does not clear
113*5bd3d017SNikko He 	 * it, other initiators would end up waiting indefinitely for the
114*5bd3d017SNikko He 	 * first to clear ACA.
115*5bd3d017SNikko He 	 */
116*5bd3d017SNikko He 	if (!scsi_pkt_allow_naca) {
117*5bd3d017SNikko He 		ASSERT(!NACA_IS_SET(pkt->pkt_cdbp));
118*5bd3d017SNikko He 	}
119*5bd3d017SNikko He 
120602ca9eaScth 	/*
121602ca9eaScth 	 * The DDI does not allow drivers to allocate their own scsi_pkt(9S),
122602ca9eaScth 	 * a driver can't have *any* compiled in dependencies on the
123602ca9eaScth 	 * "sizeof (struct scsi_pkt)". While this has been the case for years,
124602ca9eaScth 	 * many drivers have still not been fixed (or have regressed - tempted
125602ca9eaScth 	 * by kmem_cache_alloc()).  The correct way to allocate a scsi_pkt
126602ca9eaScth 	 * is by calling scsi_hba_pkt_alloc(9F), or by implementing the
127602ca9eaScth 	 * tran_setup_pkt(9E) interfaces.
128602ca9eaScth 	 *
129602ca9eaScth 	 * The code below will identify drivers that violate this rule, and
130602ca9eaScth 	 * print a message. The message will identify broken drivers, and
131602ca9eaScth 	 * encourage getting these drivers fixed - after which this code
132602ca9eaScth 	 * can be removed. Getting HBA drivers fixed is important because
133602ca9eaScth 	 * broken drivers are an impediment to SCSA enhancement.
134602ca9eaScth 	 *
135602ca9eaScth 	 * We use the scsi_pkt_allocated_correctly() to determine if the
136602ca9eaScth 	 * scsi_pkt we are about to start was correctly allocated. The
137602ca9eaScth 	 * scsi_pkt_bad_alloc_bitmap is used to limit messages to one per
138602ca9eaScth 	 * driver per reboot, and with non-debug code we only check the
139602ca9eaScth 	 * first scsi_pkt.
140602ca9eaScth 	 */
141602ca9eaScth 	if (scsi_pkt_bad_alloc_msg) {
142602ca9eaScth 		major = ddi_driver_major(P_TO_TRAN(pkt)->tran_hba_dip);
143602ca9eaScth 		if (!BT_TEST(scsi_pkt_bad_alloc_bitmap, major) &&
144602ca9eaScth 		    !scsi_pkt_allocated_correctly(pkt)) {
145602ca9eaScth 			BT_SET(scsi_pkt_bad_alloc_bitmap, major);
146602ca9eaScth 			cmn_err(CE_WARN, "%s: violates DDI scsi_pkt(9S) "
147602ca9eaScth 			    "allocation rules",
148602ca9eaScth 			    ddi_driver_name(P_TO_TRAN(pkt)->tran_hba_dip));
149602ca9eaScth 		}
150602ca9eaScth #ifndef	DEBUG
151602ca9eaScth 		/* On non-debug kernel, only check the first packet */
152602ca9eaScth 		BT_SET(scsi_pkt_bad_alloc_bitmap, major);
153602ca9eaScth #endif	/* DEBUG */
154602ca9eaScth 	}
1557c478bd9Sstevel@tonic-gate 
1561cba8b6cSRandall Ralphs 	/* Some retryed packets come with this flag not cleared */
1571cba8b6cSRandall Ralphs 	pkt->pkt_flags &= ~FLAG_PKT_COMP_CALLED;
1581cba8b6cSRandall Ralphs 
1597c478bd9Sstevel@tonic-gate 	/*
1607c478bd9Sstevel@tonic-gate 	 * Check if we are required to do polled I/O. We can
1617c478bd9Sstevel@tonic-gate 	 * get scsi_pkts that don't have the FLAG_NOINTR bit
1627c478bd9Sstevel@tonic-gate 	 * set in the pkt_flags. When do_polled_io is set
1637c478bd9Sstevel@tonic-gate 	 * we will probably be at a high IPL and not get any
1647c478bd9Sstevel@tonic-gate 	 * command completion interrupts. We force polled I/Os
1657c478bd9Sstevel@tonic-gate 	 * for such packets and do a callback of the completion
1667c478bd9Sstevel@tonic-gate 	 * routine ourselves.
1677c478bd9Sstevel@tonic-gate 	 */
1687c478bd9Sstevel@tonic-gate 	if (!do_polled_io && ((pkt->pkt_flags & FLAG_NOINTR) == 0)) {
1697c478bd9Sstevel@tonic-gate 		return (*A_TO_TRAN(ap)->tran_start)(ap, pkt);
1707c478bd9Sstevel@tonic-gate 	} else if ((curthread->t_flag & T_INTR_THREAD) || do_polled_io) {
1717c478bd9Sstevel@tonic-gate #ifdef SCSI_POLL_STAT
1727c478bd9Sstevel@tonic-gate 		mutex_enter(&scsi_flag_nointr_mutex);
1737c478bd9Sstevel@tonic-gate 		scsi_poll_intr++;
1747c478bd9Sstevel@tonic-gate 		mutex_exit(&scsi_flag_nointr_mutex);
1757c478bd9Sstevel@tonic-gate #endif
1767c478bd9Sstevel@tonic-gate 		/*
1777c478bd9Sstevel@tonic-gate 		 * If its an interrupt thread or we already have the
1787c478bd9Sstevel@tonic-gate 		 * the FLAG_NOINTR flag set, we go ahead and call the
1797c478bd9Sstevel@tonic-gate 		 * the hba's start routine directly. We force polling
1807c478bd9Sstevel@tonic-gate 		 * only if we have do_polled_io set and FLAG_NOINTR
1817c478bd9Sstevel@tonic-gate 		 * not set.
1827c478bd9Sstevel@tonic-gate 		 */
1837c478bd9Sstevel@tonic-gate 		if (!do_polled_io || (pkt->pkt_flags & FLAG_NOINTR)) {
1847c478bd9Sstevel@tonic-gate 			return ((*A_TO_TRAN(ap)->tran_start)(ap, pkt));
1857c478bd9Sstevel@tonic-gate 		} else {
1867c478bd9Sstevel@tonic-gate 			uint_t		savef;
1877c478bd9Sstevel@tonic-gate 			void		(*savec)();
1887c478bd9Sstevel@tonic-gate 			/*
1897c478bd9Sstevel@tonic-gate 			 * save the completion routine and pkt_flags
1907c478bd9Sstevel@tonic-gate 			 */
1917c478bd9Sstevel@tonic-gate 			savef = pkt->pkt_flags;
1927c478bd9Sstevel@tonic-gate 			savec = pkt->pkt_comp;
1937c478bd9Sstevel@tonic-gate 			pkt->pkt_flags |= FLAG_NOINTR;
1947c478bd9Sstevel@tonic-gate 			pkt->pkt_comp = 0;
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 			rval = (*A_TO_TRAN(ap)->tran_start)(ap, pkt);
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 			/* only continue of transport accepted request */
1997c478bd9Sstevel@tonic-gate 			if (rval == TRAN_ACCEPT) {
2007c478bd9Sstevel@tonic-gate 				/*
2017c478bd9Sstevel@tonic-gate 				 * Restore the pkt_completion routine
2027c478bd9Sstevel@tonic-gate 				 * and pkt flags and call the completion
2037c478bd9Sstevel@tonic-gate 				 * routine.
2047c478bd9Sstevel@tonic-gate 				 */
2057c478bd9Sstevel@tonic-gate 				pkt->pkt_comp = savec;
2067c478bd9Sstevel@tonic-gate 				pkt->pkt_flags = savef;
207f6715e51Ssrivijitha dugganapalli 				scsi_hba_pkt_comp(pkt);
2087c478bd9Sstevel@tonic-gate 				return (rval);
2097c478bd9Sstevel@tonic-gate 			}
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 			/*
2127c478bd9Sstevel@tonic-gate 			 * rval was not TRAN_ACCEPT -- don't want command
2137c478bd9Sstevel@tonic-gate 			 * to be retried
2147c478bd9Sstevel@tonic-gate 			 */
2157c478bd9Sstevel@tonic-gate 			return (TRAN_FATAL_ERROR);
2167c478bd9Sstevel@tonic-gate 		}
2177c478bd9Sstevel@tonic-gate 	} else {
2187c478bd9Sstevel@tonic-gate 		uint_t	savef;
2197c478bd9Sstevel@tonic-gate 		void	(*savec)();
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate #ifdef SCSI_POLL_STAT
2227c478bd9Sstevel@tonic-gate 		mutex_enter(&scsi_flag_nointr_mutex);
2237c478bd9Sstevel@tonic-gate 		scsi_poll_user++;
2247c478bd9Sstevel@tonic-gate 		mutex_exit(&scsi_flag_nointr_mutex);
2257c478bd9Sstevel@tonic-gate #endif
2267c478bd9Sstevel@tonic-gate 		savef = pkt->pkt_flags;
2277c478bd9Sstevel@tonic-gate 		savec = pkt->pkt_comp;
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 		pkt->pkt_comp = scsi_flag_nointr_comp;
2307c478bd9Sstevel@tonic-gate 		pkt->pkt_flags &= ~FLAG_NOINTR;
2317c478bd9Sstevel@tonic-gate 		pkt->pkt_flags |= FLAG_IMMEDIATE_CB;
2327c478bd9Sstevel@tonic-gate 
2334c06356bSdh 		if ((rval = (*A_TO_TRAN(ap)->tran_start)(ap, pkt)) ==
234602ca9eaScth 		    TRAN_ACCEPT) {
2357c478bd9Sstevel@tonic-gate 			mutex_enter(&scsi_flag_nointr_mutex);
2367c478bd9Sstevel@tonic-gate 			while (pkt->pkt_comp != CALLBACK_DONE) {
2377c478bd9Sstevel@tonic-gate 				cv_wait(&scsi_flag_nointr_cv,
238602ca9eaScth 				    &scsi_flag_nointr_mutex);
2397c478bd9Sstevel@tonic-gate 			}
2407c478bd9Sstevel@tonic-gate 			mutex_exit(&scsi_flag_nointr_mutex);
2417c478bd9Sstevel@tonic-gate 		}
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 		pkt->pkt_flags = savef;
2447c478bd9Sstevel@tonic-gate 		pkt->pkt_comp = savec;
2454c06356bSdh 		return (rval);
2467c478bd9Sstevel@tonic-gate 	}
2477c478bd9Sstevel@tonic-gate }
248