10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51998Staylor * Common Development and Distribution License (the "License").
61998Staylor * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*12045SLi.He@Sun.COM
220Sstevel@tonic-gate /*
23*12045SLi.He@Sun.COM * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * Main Transport Routine for SCSA
280Sstevel@tonic-gate */
290Sstevel@tonic-gate #include <sys/scsi/scsi.h>
300Sstevel@tonic-gate #include <sys/thread.h>
316640Scth #include <sys/bitmap.h>
320Sstevel@tonic-gate
330Sstevel@tonic-gate #define A_TO_TRAN(ap) ((ap)->a_hba_tran)
340Sstevel@tonic-gate #define P_TO_TRAN(pkt) ((pkt)->pkt_address.a_hba_tran)
350Sstevel@tonic-gate #define P_TO_ADDR(pkt) (&((pkt)->pkt_address))
360Sstevel@tonic-gate
370Sstevel@tonic-gate #ifdef DEBUG
380Sstevel@tonic-gate #define SCSI_POLL_STAT
390Sstevel@tonic-gate #endif
400Sstevel@tonic-gate
410Sstevel@tonic-gate #ifdef SCSI_POLL_STAT
420Sstevel@tonic-gate int scsi_poll_user;
430Sstevel@tonic-gate int scsi_poll_intr;
440Sstevel@tonic-gate #endif
450Sstevel@tonic-gate
466640Scth int scsi_pkt_bad_alloc_msg = 1;
476640Scth extern ulong_t *scsi_pkt_bad_alloc_bitmap;
480Sstevel@tonic-gate extern kmutex_t scsi_flag_nointr_mutex;
490Sstevel@tonic-gate extern kcondvar_t scsi_flag_nointr_cv;
500Sstevel@tonic-gate
516640Scth extern int do_polled_io;
526640Scth
53*12045SLi.He@Sun.COM extern int scsi_pkt_allow_naca;
54*12045SLi.He@Sun.COM extern uchar_t scsi_cdb_size[];
55*12045SLi.He@Sun.COM #define NACA_IS_SET(cdb) \
56*12045SLi.He@Sun.COM (((cdb)[scsi_cdb_size[GETGROUP((union scsi_cdb *)(cdb))] - 1] \
57*12045SLi.He@Sun.COM & CDB_FLAG_NACA) ? 1 : 0)
58*12045SLi.He@Sun.COM
590Sstevel@tonic-gate /*
600Sstevel@tonic-gate * we used to set the callback_done value to NULL after the callback
610Sstevel@tonic-gate * but this interfered with esp/fas drivers that also set the callback
620Sstevel@tonic-gate * to NULL to prevent callbacks during error recovery
6310967SRandall.Ralphs@Sun.COM * to prevent confusion, create a truly unique value.
6410967SRandall.Ralphs@Sun.COM * The scsi_callback_done() function is used to detect a packet
6510967SRandall.Ralphs@Sun.COM * completion being called a second time.
660Sstevel@tonic-gate */
6710967SRandall.Ralphs@Sun.COM /* ARGSUSED */
6810967SRandall.Ralphs@Sun.COM void
scsi_callback_done(struct scsi_pkt * pkt)6910967SRandall.Ralphs@Sun.COM scsi_callback_done(struct scsi_pkt *pkt)
7010967SRandall.Ralphs@Sun.COM {
7110967SRandall.Ralphs@Sun.COM cmn_err(CE_PANIC,
7210967SRandall.Ralphs@Sun.COM "%s: duplicate scsi_callback_done() on same scsi_pkt(9s)",
7310967SRandall.Ralphs@Sun.COM mod_containing_pc(caller()));
7410967SRandall.Ralphs@Sun.COM }
7510967SRandall.Ralphs@Sun.COM
7610967SRandall.Ralphs@Sun.COM #define CALLBACK_DONE (scsi_callback_done)
770Sstevel@tonic-gate
780Sstevel@tonic-gate static void
scsi_flag_nointr_comp(struct scsi_pkt * pkt)790Sstevel@tonic-gate scsi_flag_nointr_comp(struct scsi_pkt *pkt)
800Sstevel@tonic-gate {
810Sstevel@tonic-gate mutex_enter(&scsi_flag_nointr_mutex);
820Sstevel@tonic-gate pkt->pkt_comp = CALLBACK_DONE;
830Sstevel@tonic-gate /*
840Sstevel@tonic-gate * We need cv_broadcast, because there can be more
850Sstevel@tonic-gate * than one thread sleeping on the cv. We
860Sstevel@tonic-gate * will wake all of them. The correct one will
870Sstevel@tonic-gate * continue and the rest will again go to sleep.
880Sstevel@tonic-gate */
890Sstevel@tonic-gate cv_broadcast(&scsi_flag_nointr_cv);
900Sstevel@tonic-gate mutex_exit(&scsi_flag_nointr_mutex);
910Sstevel@tonic-gate }
920Sstevel@tonic-gate
930Sstevel@tonic-gate /*
940Sstevel@tonic-gate * A packet can have FLAG_NOINTR set because of target driver or
950Sstevel@tonic-gate * scsi_poll(). If FLAG_NOINTR is set and we are in user context,
960Sstevel@tonic-gate * we can avoid busy waiting in HBA by replacing the callback
970Sstevel@tonic-gate * function with our own function and resetting FLAG_NOINTR. We
980Sstevel@tonic-gate * can't do this in interrupt context because cv_wait will
990Sstevel@tonic-gate * sleep with CPU priority raised high and in case of some failure,
1000Sstevel@tonic-gate * the CPU will be stuck in high priority.
1010Sstevel@tonic-gate */
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate int
scsi_transport(struct scsi_pkt * pkt)1040Sstevel@tonic-gate scsi_transport(struct scsi_pkt *pkt)
1050Sstevel@tonic-gate {
1060Sstevel@tonic-gate struct scsi_address *ap = P_TO_ADDR(pkt);
1076640Scth int rval = TRAN_ACCEPT;
1086640Scth major_t major;
1096640Scth
1106640Scth /*
111*12045SLi.He@Sun.COM * Add an assertion check for debugging as use of the NACA flag
112*12045SLi.He@Sun.COM * can cause problems. If an initiator sets it but does not clear
113*12045SLi.He@Sun.COM * it, other initiators would end up waiting indefinitely for the
114*12045SLi.He@Sun.COM * first to clear ACA.
115*12045SLi.He@Sun.COM */
116*12045SLi.He@Sun.COM if (!scsi_pkt_allow_naca) {
117*12045SLi.He@Sun.COM ASSERT(!NACA_IS_SET(pkt->pkt_cdbp));
118*12045SLi.He@Sun.COM }
119*12045SLi.He@Sun.COM
120*12045SLi.He@Sun.COM /*
1216640Scth * The DDI does not allow drivers to allocate their own scsi_pkt(9S),
1226640Scth * a driver can't have *any* compiled in dependencies on the
1236640Scth * "sizeof (struct scsi_pkt)". While this has been the case for years,
1246640Scth * many drivers have still not been fixed (or have regressed - tempted
1256640Scth * by kmem_cache_alloc()). The correct way to allocate a scsi_pkt
1266640Scth * is by calling scsi_hba_pkt_alloc(9F), or by implementing the
1276640Scth * tran_setup_pkt(9E) interfaces.
1286640Scth *
1296640Scth * The code below will identify drivers that violate this rule, and
1306640Scth * print a message. The message will identify broken drivers, and
1316640Scth * encourage getting these drivers fixed - after which this code
1326640Scth * can be removed. Getting HBA drivers fixed is important because
1336640Scth * broken drivers are an impediment to SCSA enhancement.
1346640Scth *
1356640Scth * We use the scsi_pkt_allocated_correctly() to determine if the
1366640Scth * scsi_pkt we are about to start was correctly allocated. The
1376640Scth * scsi_pkt_bad_alloc_bitmap is used to limit messages to one per
1386640Scth * driver per reboot, and with non-debug code we only check the
1396640Scth * first scsi_pkt.
1406640Scth */
1416640Scth if (scsi_pkt_bad_alloc_msg) {
1426640Scth major = ddi_driver_major(P_TO_TRAN(pkt)->tran_hba_dip);
1436640Scth if (!BT_TEST(scsi_pkt_bad_alloc_bitmap, major) &&
1446640Scth !scsi_pkt_allocated_correctly(pkt)) {
1456640Scth BT_SET(scsi_pkt_bad_alloc_bitmap, major);
1466640Scth cmn_err(CE_WARN, "%s: violates DDI scsi_pkt(9S) "
1476640Scth "allocation rules",
1486640Scth ddi_driver_name(P_TO_TRAN(pkt)->tran_hba_dip));
1496640Scth }
1506640Scth #ifndef DEBUG
1516640Scth /* On non-debug kernel, only check the first packet */
1526640Scth BT_SET(scsi_pkt_bad_alloc_bitmap, major);
1536640Scth #endif /* DEBUG */
1546640Scth }
1550Sstevel@tonic-gate
15610967SRandall.Ralphs@Sun.COM /* Some retryed packets come with this flag not cleared */
15710967SRandall.Ralphs@Sun.COM pkt->pkt_flags &= ~FLAG_PKT_COMP_CALLED;
15810967SRandall.Ralphs@Sun.COM
1590Sstevel@tonic-gate /*
1600Sstevel@tonic-gate * Check if we are required to do polled I/O. We can
1610Sstevel@tonic-gate * get scsi_pkts that don't have the FLAG_NOINTR bit
1620Sstevel@tonic-gate * set in the pkt_flags. When do_polled_io is set
1630Sstevel@tonic-gate * we will probably be at a high IPL and not get any
1640Sstevel@tonic-gate * command completion interrupts. We force polled I/Os
1650Sstevel@tonic-gate * for such packets and do a callback of the completion
1660Sstevel@tonic-gate * routine ourselves.
1670Sstevel@tonic-gate */
1680Sstevel@tonic-gate if (!do_polled_io && ((pkt->pkt_flags & FLAG_NOINTR) == 0)) {
1690Sstevel@tonic-gate return (*A_TO_TRAN(ap)->tran_start)(ap, pkt);
1700Sstevel@tonic-gate } else if ((curthread->t_flag & T_INTR_THREAD) || do_polled_io) {
1710Sstevel@tonic-gate #ifdef SCSI_POLL_STAT
1720Sstevel@tonic-gate mutex_enter(&scsi_flag_nointr_mutex);
1730Sstevel@tonic-gate scsi_poll_intr++;
1740Sstevel@tonic-gate mutex_exit(&scsi_flag_nointr_mutex);
1750Sstevel@tonic-gate #endif
1760Sstevel@tonic-gate /*
1770Sstevel@tonic-gate * If its an interrupt thread or we already have the
1780Sstevel@tonic-gate * the FLAG_NOINTR flag set, we go ahead and call the
1790Sstevel@tonic-gate * the hba's start routine directly. We force polling
1800Sstevel@tonic-gate * only if we have do_polled_io set and FLAG_NOINTR
1810Sstevel@tonic-gate * not set.
1820Sstevel@tonic-gate */
1830Sstevel@tonic-gate if (!do_polled_io || (pkt->pkt_flags & FLAG_NOINTR)) {
1840Sstevel@tonic-gate return ((*A_TO_TRAN(ap)->tran_start)(ap, pkt));
1850Sstevel@tonic-gate } else {
1860Sstevel@tonic-gate uint_t savef;
1870Sstevel@tonic-gate void (*savec)();
1880Sstevel@tonic-gate /*
1890Sstevel@tonic-gate * save the completion routine and pkt_flags
1900Sstevel@tonic-gate */
1910Sstevel@tonic-gate savef = pkt->pkt_flags;
1920Sstevel@tonic-gate savec = pkt->pkt_comp;
1930Sstevel@tonic-gate pkt->pkt_flags |= FLAG_NOINTR;
1940Sstevel@tonic-gate pkt->pkt_comp = 0;
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate rval = (*A_TO_TRAN(ap)->tran_start)(ap, pkt);
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate /* only continue of transport accepted request */
1990Sstevel@tonic-gate if (rval == TRAN_ACCEPT) {
2000Sstevel@tonic-gate /*
2010Sstevel@tonic-gate * Restore the pkt_completion routine
2020Sstevel@tonic-gate * and pkt flags and call the completion
2030Sstevel@tonic-gate * routine.
2040Sstevel@tonic-gate */
2050Sstevel@tonic-gate pkt->pkt_comp = savec;
2060Sstevel@tonic-gate pkt->pkt_flags = savef;
2078660SSrivijitha.Dugganapalli@Sun.COM scsi_hba_pkt_comp(pkt);
2080Sstevel@tonic-gate return (rval);
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate /*
2120Sstevel@tonic-gate * rval was not TRAN_ACCEPT -- don't want command
2130Sstevel@tonic-gate * to be retried
2140Sstevel@tonic-gate */
2150Sstevel@tonic-gate return (TRAN_FATAL_ERROR);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate } else {
2180Sstevel@tonic-gate uint_t savef;
2190Sstevel@tonic-gate void (*savec)();
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate #ifdef SCSI_POLL_STAT
2220Sstevel@tonic-gate mutex_enter(&scsi_flag_nointr_mutex);
2230Sstevel@tonic-gate scsi_poll_user++;
2240Sstevel@tonic-gate mutex_exit(&scsi_flag_nointr_mutex);
2250Sstevel@tonic-gate #endif
2260Sstevel@tonic-gate savef = pkt->pkt_flags;
2270Sstevel@tonic-gate savec = pkt->pkt_comp;
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate pkt->pkt_comp = scsi_flag_nointr_comp;
2300Sstevel@tonic-gate pkt->pkt_flags &= ~FLAG_NOINTR;
2310Sstevel@tonic-gate pkt->pkt_flags |= FLAG_IMMEDIATE_CB;
2320Sstevel@tonic-gate
23310696SDavid.Hollister@Sun.COM if ((rval = (*A_TO_TRAN(ap)->tran_start)(ap, pkt)) ==
2346640Scth TRAN_ACCEPT) {
2350Sstevel@tonic-gate mutex_enter(&scsi_flag_nointr_mutex);
2360Sstevel@tonic-gate while (pkt->pkt_comp != CALLBACK_DONE) {
2370Sstevel@tonic-gate cv_wait(&scsi_flag_nointr_cv,
2386640Scth &scsi_flag_nointr_mutex);
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate mutex_exit(&scsi_flag_nointr_mutex);
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate pkt->pkt_flags = savef;
2440Sstevel@tonic-gate pkt->pkt_comp = savec;
24510696SDavid.Hollister@Sun.COM return (rval);
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate }
248