iscsi_io.c revision 10156:a1ab3f203504
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 * Copyright 2000 by Cisco Systems, Inc.  All rights reserved.
23 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 *
26 * iSCSI Pseudo HBA Driver
27 */
28
29#include <sys/socket.h>		/* networking stuff */
30#include <sys/t_kuser.h>	/* networking stuff */
31#include <sys/tihdr.h>		/* networking stuff */
32#include <sys/strsubr.h>	/* networking stuff */
33#include <netinet/tcp.h>	/* TCP_NODELAY */
34#include <sys/socketvar.h>	/* _ALLOC_SLEEP */
35#include <sys/strsun.h>		/* DB_TYPE() */
36#include <sys/scsi/generic/sense.h>
37
38#include "iscsi.h"		/* iscsi driver */
39#include <sys/iscsi_protocol.h>	/* iscsi protocol */
40
41#define	ISCSI_INI_TASK_TTT	0xffffffff
42#define	ISCSI_CONN_TIEMOUT_DETECT	20
43
44boolean_t iscsi_io_logging = B_FALSE;
45
46#define	ISCSI_CHECK_SCSI_READ(ICHK_CMD, ICHK_HDR, ICHK_LEN, ICHK_TYPE)	\
47	if (idm_pattern_checking)  {					\
48		struct scsi_pkt *pkt = (ICHK_CMD)->cmd_un.scsi.pkt;	\
49		if (((ICHK_HDR)->response == 0) && 			\
50		    ((ICHK_HDR)->cmd_status == 0) &&			\
51		    ((pkt->pkt_cdbp[0] == SCMD_READ_G1) ||		\
52		    (pkt->pkt_cdbp[0] == SCMD_READ_G4) || 		\
53		    (pkt->pkt_cdbp[0] == SCMD_READ) || 			\
54		    (pkt->pkt_cdbp[0] == SCMD_READ_G5))) {		\
55			idm_buf_t *idb = (ICHK_CMD)->cmd_un.scsi.ibp_ibuf; \
56			IDM_BUFPAT_CHECK(idb, ICHK_LEN, ICHK_TYPE); \
57		}						\
58	}
59
60/* generic io helpers */
61static uint32_t n2h24(uchar_t *ptr);
62static int iscsi_sna_lt(uint32_t n1, uint32_t n2);
63void iscsi_update_flow_control(iscsi_sess_t *isp,
64    uint32_t max, uint32_t exp);
65static iscsi_status_t iscsi_rx_process_scsi_itt_to_icmdp(iscsi_sess_t *isp,
66    idm_conn_t *ic, iscsi_scsi_rsp_hdr_t *ihp, iscsi_cmd_t **icmdp);
67static iscsi_status_t iscsi_rx_process_itt_to_icmdp(iscsi_sess_t *isp,
68    iscsi_hdr_t *ihp, iscsi_cmd_t **icmdp);
69static void iscsi_process_rsp_status(iscsi_sess_t *isp, iscsi_conn_t *icp,
70    idm_status_t status);
71static void iscsi_drop_conn_cleanup(iscsi_conn_t *icp);
72static boolean_t iscsi_nop_timeout_checks(iscsi_cmd_t *icmdp);
73/* callbacks from idm */
74static idm_pdu_cb_t iscsi_tx_done;
75
76/* receivers */
77static idm_status_t iscsi_rx_process_nop(idm_conn_t *ic, idm_pdu_t *pdu);
78static idm_status_t iscsi_rx_process_data_rsp(idm_conn_t *ic,
79    idm_pdu_t *pdu);
80static idm_status_t iscsi_rx_process_cmd_rsp(idm_conn_t *ic, idm_pdu_t *pdu);
81static idm_status_t iscsi_rx_process_reject_rsp(idm_conn_t *ic,
82    idm_pdu_t *pdu);
83
84static idm_status_t iscsi_rx_process_rejected_tsk_mgt(idm_conn_t *ic,
85    iscsi_hdr_t *old_ihp);
86static idm_status_t iscsi_rx_process_task_mgt_rsp(idm_conn_t *ic,
87    idm_pdu_t *pdu);
88static idm_status_t iscsi_rx_process_logout_rsp(idm_conn_t *ic,
89    idm_pdu_t *pdu);
90static idm_status_t iscsi_rx_process_async_rsp(idm_conn_t *ic,
91    idm_pdu_t *pdu);
92static idm_status_t iscsi_rx_process_text_rsp(idm_conn_t *ic,
93    idm_pdu_t *pdu);
94
95/* senders */
96static iscsi_status_t iscsi_tx_scsi(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
97static iscsi_status_t iscsi_tx_nop(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
98static iscsi_status_t iscsi_tx_abort(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
99static iscsi_status_t iscsi_tx_reset(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
100static iscsi_status_t iscsi_tx_logout(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
101static iscsi_status_t iscsi_tx_text(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
102
103
104/* helpers */
105static void iscsi_logout_start(void *arg);
106static void iscsi_handle_passthru_callback(struct scsi_pkt *pkt);
107static void iscsi_handle_nop(iscsi_conn_t *icp, uint32_t itt, uint32_t ttt);
108
109static void iscsi_timeout_checks(iscsi_sess_t *isp);
110static void iscsi_nop_checks(iscsi_sess_t *isp);
111static boolean_t iscsi_decode_sense(uint8_t *sense_data);
112static void iscsi_flush_cmd_after_reset(uint32_t cmd_sn, uint16_t lun_num,
113    iscsi_conn_t *icp);
114
115/*
116 * This file contains the main guts of the iSCSI protocol layer.
117 * It's broken into 5 sections; Basic helper functions, RX IO path,
118 * TX IO path, Completion (IC) IO path, and watchdog (WD) routines.
119 *
120 * The IO flow model is similiar to the below diagram.  The
121 * iscsi session, connection and command state machines are used
122 * to drive IO through this flow diagram.  Reference those files
123 * to get a detailed description of their respective state models
124 * prior to their xxx_state_machine_function().
125 *
126 * tran_start() -> CMD_E1     TX_THREAD                   RX_THREAD
127 *                   |            T                           T
128 *                   V            T                           T
129 *                PENDING_Q  --CMD_E2--> ACTIVE_Q -      --CMD_E3--+
130 *                                T                \ C        T    |
131 *                                T                 \M        T    |
132 *                                                   D        T    |
133 *                                       WD_THREAD TT|TT      T    |
134 *                                                  /E        T    |
135 *                                                 / 6        T    |
136 *                                     ABORTING_Q<-      --CMD_E3--+
137 *                                                            T    |
138 *                                T                           T    |
139 *                                T                                |
140 *               callback()  <--CMD_E#-- COMPLETION_Q <------------+
141 *                                T
142 *                                T
143 *                            IC_THREAD
144 *
145 * External and internal command are ran thru this same state
146 * machine.  All commands enter the state machine by receiving an
147 * ISCSI_CMD_EVENT_E1.  This event places the command into the
148 * PENDING_Q.  Next when resources are available the TX_THREAD
149 * issues a E2 event on the command.  This sends the command
150 * to the TCP stack and places the command on the ACTIVE_Q.  While
151 * on the PENDIING_Q and ACTIVE_Q, the command is monitored via the
152 * WD_THREAD to ensure the pkt_time has not elapsed.  If elapsed the
153 * command is issued an E6(timeout) event which moves either (if pending)
154 * completed the command or (if active) moves the command to the
155 * aborting queue and issues a SCSI TASK MANAGEMENT ABORT command
156 * to cancel the IO request.  If the original command is completed
157 * or the TASK MANAGEMENT command completes the command is moved
158 * to the COMPLETION_Q via a E3 event.  The IC_THREAD then processes
159 * the COMPLETION_Q and issues the scsi_pkt callback.  This
160 * callback can not be processed directly from the RX_THREAD
161 * because the callback might call back into the iscsi driver
162 * causing a deadlock condition.
163 *
164 * For more details on the complete CMD state machine reference
165 * the state machine diagram in iscsi_cmd.c.  The connection state
166 * machine is driven via IO events in this file.  Then session
167 * events are driven by the connection events.  For complete
168 * details on these state machines reference iscsi_sess.c and
169 * iscsi_conn.c
170 */
171
172
173/*
174 * +--------------------------------------------------------------------+
175 * | io helper routines							|
176 * +--------------------------------------------------------------------+
177 */
178
179/*
180 * n2h24 - native to host 24 bit integer translation.
181 */
182static uint32_t
183n2h24(uchar_t *ptr)
184{
185	uint32_t idx;
186	bcopy(ptr, &idx, 3);
187	return (ntohl(idx) >> 8);
188}
189
190/*
191 * iscsi_sna_lt - Serial Number Arithmetic, 32 bits, less than, RFC1982
192 */
193static int
194iscsi_sna_lt(uint32_t n1, uint32_t n2)
195{
196	return ((n1 != n2) &&
197	    (((n1 < n2) && ((n2 - n1) < ISCSI_SNA32_CHECK)) ||
198	    ((n1 > n2) && ((n1 - n2) > ISCSI_SNA32_CHECK))));
199}
200
201/*
202 * iscsi_sna_lte - Serial Number Arithmetic, 32 bits, less than or equal,
203 * RFC1982
204 */
205int
206iscsi_sna_lte(uint32_t n1, uint32_t n2)
207{
208	return ((n1 == n2) ||
209	    (((n1 < n2) && ((n2 - n1) < ISCSI_SNA32_CHECK)) ||
210	    ((n1 > n2) && ((n1 - n2) > ISCSI_SNA32_CHECK))));
211}
212
213/*
214 * iscsi_update_flow_control - Update expcmdsn and maxcmdsn iSCSI
215 * flow control information for a session
216 */
217void
218iscsi_update_flow_control(iscsi_sess_t *isp, uint32_t max, uint32_t exp)
219{
220	ASSERT(isp != NULL);
221	ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
222
223	if (!iscsi_sna_lt(max, (exp - 1))) {
224
225		if (!iscsi_sna_lte(exp, isp->sess_expcmdsn)) {
226			isp->sess_expcmdsn = exp;
227		}
228
229		if (!iscsi_sna_lte(max, isp->sess_maxcmdsn)) {
230			isp->sess_maxcmdsn = max;
231			if (iscsi_sna_lte(isp->sess_cmdsn,
232			    isp->sess_maxcmdsn)) {
233				/*
234				 * the window is open again - schedule
235				 * to send any held tasks soon
236				 */
237				iscsi_sess_redrive_io(isp);
238			}
239		}
240	}
241}
242
243
244/*
245 * +--------------------------------------------------------------------+
246 * | io receive and processing routines					|
247 * +--------------------------------------------------------------------+
248 */
249
250/*
251 * iscsi_rx_scsi_rsp - called from idm
252 * For each opcode type fan out the processing.
253 */
254void
255iscsi_rx_scsi_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
256{
257	iscsi_conn_t	*icp;
258	iscsi_sess_t	*isp;
259	iscsi_hdr_t	*ihp;
260	idm_status_t	status;
261
262	ASSERT(ic != NULL);
263	ASSERT(pdu != NULL);
264	icp		= ic->ic_handle;
265	ASSERT(icp != NULL);
266	ihp		= (iscsi_hdr_t *)pdu->isp_hdr;
267	ASSERT(ihp != NULL);
268	isp		= icp->conn_sess;
269	ASSERT(isp != NULL);
270
271	/* reset the session timer when we receive the response */
272	isp->sess_rx_lbolt = icp->conn_rx_lbolt = ddi_get_lbolt();
273
274	/* fan out the hdr processing */
275	switch (ihp->opcode & ISCSI_OPCODE_MASK) {
276	case ISCSI_OP_SCSI_DATA_RSP:
277		status = iscsi_rx_process_data_rsp(ic, pdu);
278		break;
279	case ISCSI_OP_SCSI_RSP:
280		status = iscsi_rx_process_cmd_rsp(ic, pdu);
281		idm_pdu_complete(pdu, status);
282		break;
283	default:
284		cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
285		    "received pdu with unsupported opcode 0x%02x",
286		    icp->conn_oid, ihp->opcode);
287		status = IDM_STATUS_PROTOCOL_ERROR;
288	}
289	iscsi_process_rsp_status(isp, icp, status);
290}
291
292void
293iscsi_task_cleanup(int opcode, iscsi_cmd_t *icmdp)
294{
295	struct buf 	*bp;
296	idm_buf_t	*ibp, *obp;
297	idm_task_t	*itp;
298
299	itp = icmdp->cmd_itp;
300	ASSERT(itp != NULL);
301	ASSERT((opcode == ISCSI_OP_SCSI_DATA_RSP) ||
302	    (opcode == ISCSI_OP_SCSI_RSP));
303
304	bp = icmdp->cmd_un.scsi.bp;
305	ibp = icmdp->cmd_un.scsi.ibp_ibuf;
306	obp = icmdp->cmd_un.scsi.ibp_obuf;
307	ISCSI_IO_LOG(CE_NOTE, "DEBUG: task_cleanup: itp: %p opcode: %d "
308	    "icmdp: %p bp: %p ibp: %p", (void *)itp, opcode,
309	    (void *)icmdp, (void *)bp, (void *)ibp);
310	if (bp && bp->b_bcount) {
311		if (ibp != NULL && bp->b_flags & B_READ) {
312			idm_buf_unbind_in(itp, ibp);
313			idm_buf_free(ibp);
314			icmdp->cmd_un.scsi.ibp_ibuf = NULL;
315		} else if (obp != NULL && !(bp->b_flags & B_READ)) {
316			idm_buf_unbind_out(itp, obp);
317			idm_buf_free(obp);
318			icmdp->cmd_un.scsi.ibp_obuf = NULL;
319		}
320	}
321
322	idm_task_done(itp);
323}
324
325idm_status_t
326iscsi_rx_chk(iscsi_conn_t *icp, iscsi_sess_t *isp,
327    iscsi_scsi_rsp_hdr_t *irhp, iscsi_cmd_t **icmdp)
328{
329	iscsi_status_t rval;
330
331	mutex_enter(&isp->sess_cmdsn_mutex);
332
333	if (icp->conn_expstatsn == ntohl(irhp->statsn)) {
334		icp->conn_expstatsn++;
335	} else {
336		cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
337		    "received status out of order itt:0x%x statsn:0x%x "
338		    "expstatsn:0x%x", icp->conn_oid, irhp->opcode,
339		    irhp->itt, ntohl(irhp->statsn), icp->conn_expstatsn);
340		mutex_exit(&isp->sess_cmdsn_mutex);
341		return (IDM_STATUS_PROTOCOL_ERROR);
342	}
343
344	/* get icmdp so we can cleanup on error */
345	if ((irhp->opcode == ISCSI_OP_SCSI_DATA_RSP) ||
346	    (irhp->opcode == ISCSI_OP_SCSI_RSP)) {
347		rval = iscsi_rx_process_scsi_itt_to_icmdp(isp, icp->conn_ic,
348		    irhp, icmdp);
349	} else {
350		rval = iscsi_rx_process_itt_to_icmdp(isp,
351		    (iscsi_hdr_t *)irhp, icmdp);
352	}
353
354	if (!ISCSI_SUCCESS(rval)) {
355		mutex_exit(&isp->sess_cmdsn_mutex);
356		return (IDM_STATUS_PROTOCOL_ERROR);
357	}
358
359	/* update expcmdsn and maxcmdsn */
360	iscsi_update_flow_control(isp, ntohl(irhp->maxcmdsn),
361	    ntohl(irhp->expcmdsn));
362	mutex_exit(&isp->sess_cmdsn_mutex);
363	return (IDM_STATUS_SUCCESS);
364}
365
366static void
367iscsi_cmd_rsp_chk(iscsi_cmd_t *icmdp, iscsi_scsi_rsp_hdr_t *issrhp)
368{
369	struct scsi_pkt *pkt;
370	size_t data_transferred;
371
372	pkt = icmdp->cmd_un.scsi.pkt;
373	pkt->pkt_resid = 0;
374	data_transferred = icmdp->cmd_un.scsi.data_transferred;
375	/* Check the residual count */
376	if ((icmdp->cmd_un.scsi.bp) &&
377	    (data_transferred != icmdp->cmd_un.scsi.bp->b_bcount)) {
378		/*
379		 * We didn't xfer the expected amount of data -
380		 * the residual_count in the header is only
381		 * valid if the underflow flag is set.
382		 */
383		if (issrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
384			pkt->pkt_resid = ntohl(issrhp->residual_count);
385		} else {
386			if (icmdp->cmd_un.scsi.bp->b_bcount >
387			    data_transferred) {
388				/*
389				 * Some data fell on the floor
390				 * somehow - probably a CRC error
391				 */
392				pkt->pkt_resid =
393				    icmdp->cmd_un.scsi.bp->b_bcount -
394				    data_transferred;
395			}
396		}
397		ISCSI_IO_LOG(CE_NOTE,
398		    "DEBUG: iscsi_rx_cmd_rsp_chk: itt: %u"
399		    "data_trans != b_count data_transferred: %lu "
400		    "b_count: %lu cmd_status: %d flags: %d resid: %lu",
401		    issrhp->itt, data_transferred,
402		    icmdp->cmd_un.scsi.bp->b_bcount,
403		    issrhp->cmd_status & STATUS_MASK,
404		    issrhp->flags, pkt->pkt_resid);
405	}
406	/* set flags that tell SCSA that the command is complete */
407	if (icmdp->cmd_crc_error_seen == B_FALSE) {
408		/* Set successful completion */
409		pkt->pkt_reason = CMD_CMPLT;
410		if (icmdp->cmd_un.scsi.bp) {
411			pkt->pkt_state |= (STATE_XFERRED_DATA |
412			    STATE_GOT_STATUS);
413		} else {
414			pkt->pkt_state |= STATE_GOT_STATUS;
415		}
416	} else {
417		/*
418		 * Some of the data was found to have an incorrect
419		 * error at the protocol error.
420		 */
421		pkt->pkt_reason = CMD_PER_FAIL;
422		pkt->pkt_statistics |= STAT_PERR;
423		if (icmdp->cmd_un.scsi.bp) {
424			pkt->pkt_resid =
425			    icmdp->cmd_un.scsi.bp->b_bcount;
426		} else {
427			pkt->pkt_resid = 0;
428		}
429	}
430}
431
432static boolean_t
433iscsi_cmd_rsp_cmd_status(iscsi_cmd_t *icmdp, iscsi_scsi_rsp_hdr_t *issrhp,
434    uint8_t *data)
435{
436	int32_t			dlength		= 0;
437	struct scsi_arq_status	*arqstat	= NULL;
438	size_t			senselen	= 0;
439	int32_t			statuslen	= 0;
440	int32_t			senselen_to	= 0;
441	struct scsi_pkt		*pkt;
442	boolean_t		affect		= B_FALSE;
443
444	pkt = icmdp->cmd_un.scsi.pkt;
445	dlength = n2h24(issrhp->dlength);
446
447	/*
448	 * Process iSCSI Cmd Response Status
449	 * RFC 3720 Sectionn 10.4.2.
450	 */
451	switch (issrhp->cmd_status & STATUS_MASK) {
452	case STATUS_GOOD:
453		/* pass SCSI status up stack */
454		if (pkt->pkt_scbp) {
455			pkt->pkt_scbp[0] = issrhp->cmd_status;
456		}
457		break;
458	case STATUS_CHECK:
459		/*
460		 * Verify we received a sense buffer and
461		 * that there is the correct amount of
462		 * request sense space to copy it to.
463		 */
464		if ((dlength > 1) &&
465		    (pkt->pkt_scbp != NULL) &&
466		    (icmdp->cmd_un.scsi.statuslen >=
467		    sizeof (struct scsi_arq_status))) {
468			/*
469			 * If a bad command status is received we
470			 * need to reset the pkt_resid to zero.
471			 * The target driver compares its value
472			 * before checking other error flags.
473			 * (ex. check conditions)
474			 */
475			pkt->pkt_resid = 0;
476
477			/* get sense length from first 2 bytes */
478			senselen = ((data[0] << 8) | data[1]) &
479			    (size_t)0xFFFF;
480			ISCSI_IO_LOG(CE_NOTE,
481			    "DEBUG: iscsi_rx_cmd_rsp_cmd_status status_check: "
482			    "dlen: %d scbp: %p statuslen: %d arq: %d senselen:"
483			    " %lu", dlength, (void *)pkt->pkt_scbp,
484			    icmdp->cmd_un.scsi.statuslen,
485			    (int)sizeof (struct scsi_arq_status),
486			    senselen);
487
488			/* Sanity-check on the sense length */
489			if ((senselen + 2) > dlength) {
490				senselen = dlength - 2;
491			}
492
493			/*
494			 * If there was a Data Digest error then
495			 * the sense data cannot be trusted.
496			 */
497			if (icmdp->cmd_crc_error_seen) {
498				senselen = 0;
499			}
500
501			/* automatic request sense */
502			arqstat =
503			    (struct scsi_arq_status *)pkt->pkt_scbp;
504
505			/* pass SCSI status up stack */
506			*((uchar_t *)&arqstat->sts_status) =
507			    issrhp->cmd_status;
508
509			/*
510			 * Set the status for the automatic
511			 * request sense command
512			 */
513			arqstat->sts_rqpkt_state = (STATE_GOT_BUS |
514			    STATE_GOT_TARGET | STATE_SENT_CMD |
515			    STATE_XFERRED_DATA | STATE_GOT_STATUS |
516			    STATE_ARQ_DONE);
517
518			*((uchar_t *)&arqstat->sts_rqpkt_status) =
519			    STATUS_GOOD;
520
521			arqstat->sts_rqpkt_reason = CMD_CMPLT;
522			statuslen = icmdp->cmd_un.scsi.statuslen;
523
524			if (senselen == 0) {
525				/* auto request sense failed */
526				arqstat->sts_rqpkt_status.sts_chk = 1;
527				arqstat->sts_rqpkt_resid = statuslen;
528			} else if (senselen < statuslen) {
529				/* auto request sense short */
530				arqstat->sts_rqpkt_resid = statuslen - senselen;
531			} else {
532				/* auto request sense complete */
533				arqstat->sts_rqpkt_resid = 0;
534			}
535			arqstat->sts_rqpkt_statistics = 0;
536			pkt->pkt_state |= STATE_ARQ_DONE;
537
538			if (icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_XARQ) {
539				pkt->pkt_state |= STATE_XARQ_DONE;
540			}
541
542			senselen_to =  pkt->pkt_scblen -
543			    sizeof (struct scsi_arq_status) +
544			    sizeof (struct scsi_extended_sense);
545
546			/* copy auto request sense */
547			dlength = min(senselen, senselen_to);
548			if (dlength > 0) {
549				bcopy(&data[2], (uchar_t *)&arqstat->
550				    sts_sensedata, dlength);
551
552				affect = iscsi_decode_sense(
553				    (uint8_t *)&arqstat->sts_sensedata);
554			}
555			break;
556		}
557		/* FALLTHRU */
558	case STATUS_BUSY:
559	case STATUS_RESERVATION_CONFLICT:
560	case STATUS_QFULL:
561	case STATUS_ACA_ACTIVE:
562	default:
563		/*
564		 * If a bad command status is received we need to
565		 * reset the pkt_resid to zero.  The target driver
566		 * compares its value before checking other error
567		 * flags. (ex. check conditions)
568		 */
569		ISCSI_IO_LOG(CE_NOTE,
570		    "DEBUG: iscsi_rx_cmd_rsp_cmd_status: status: "
571		    "%d cmd_status: %d dlen: %u scbp: %p statuslen: %d "
572		    "arg_len: %d", issrhp->cmd_status & STATUS_MASK,
573		    issrhp->cmd_status, dlength, (void *)pkt->pkt_scbp,
574		    icmdp->cmd_un.scsi.statuslen,
575		    (int)sizeof (struct scsi_arq_status));
576		pkt->pkt_resid = 0;
577		/* pass SCSI status up stack */
578		if (pkt->pkt_scbp) {
579			pkt->pkt_scbp[0] = issrhp->cmd_status;
580		}
581	}
582
583	return (affect);
584}
585
586/*
587 * iscsi_rx_process_login_pdup - Process login response PDU.  This function
588 * copies the data into the connection context so that the login code can
589 * interpret it.
590 */
591
592idm_status_t
593iscsi_rx_process_login_pdu(idm_conn_t *ic, idm_pdu_t *pdu)
594{
595	iscsi_conn_t 		*icp;
596
597	icp = ic->ic_handle;
598
599	/*
600	 * Copy header and data into connection structure so iscsi_login()
601	 * can process it.
602	 */
603	mutex_enter(&icp->conn_login_mutex);
604	/*
605	 * If conn_login_state != LOGIN_TX then we are not ready to handle
606	 * this login response and we should just  drop it.
607	 */
608	if (icp->conn_login_state == LOGIN_TX) {
609		icp->conn_login_datalen = pdu->isp_datalen;
610		bcopy(pdu->isp_hdr, &icp->conn_login_resp_hdr,
611		    sizeof (iscsi_hdr_t));
612		/*
613		 * Login code is sloppy with it's NULL handling so make sure
614		 * we don't leave any stale data in there.
615		 */
616		bzero(icp->conn_login_data, icp->conn_login_max_data_length);
617		bcopy(pdu->isp_data, icp->conn_login_data,
618		    MIN(pdu->isp_datalen, icp->conn_login_max_data_length));
619		iscsi_login_update_state_locked(icp, LOGIN_RX);
620	}
621	mutex_exit(&icp->conn_login_mutex);
622
623	return (IDM_STATUS_SUCCESS);
624}
625
626/*
627 * iscsi_rx_process_cmd_rsp - Process received scsi command response.  This
628 * will contain sense data if the command was not successful.  This data needs
629 * to be copied into the scsi_pkt.  Otherwise we just complete the IO.
630 */
631static idm_status_t
632iscsi_rx_process_cmd_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
633{
634	iscsi_conn_t		*icp	= ic->ic_handle;
635	iscsi_sess_t		*isp	= icp->conn_sess;
636	iscsi_scsi_rsp_hdr_t	*issrhp	= (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr;
637	uint8_t			*data	= pdu->isp_data;
638	iscsi_cmd_t		*icmdp	= NULL;
639	struct scsi_pkt		*pkt	= NULL;
640	idm_status_t		rval;
641	struct buf		*bp;
642	boolean_t		flush	= B_FALSE;
643	uint32_t		cmd_sn	= 0;
644	uint16_t		lun_num = 0;
645
646	/* make sure we get status in order */
647	mutex_enter(&icp->conn_queue_active.mutex);
648
649	if ((rval = iscsi_rx_chk(icp, isp, issrhp,
650	    &icmdp)) != IDM_STATUS_SUCCESS) {
651		if (icmdp != NULL) {
652			iscsi_task_cleanup(issrhp->opcode, icmdp);
653		}
654		mutex_exit(&icp->conn_queue_active.mutex);
655		return (rval);
656	}
657
658	/*
659	 * If we are in "idm aborting" state then we shouldn't continue
660	 * to process this command.  By definition this command is no longer
661	 * on the active queue so we shouldn't try to remove it either.
662	 */
663	mutex_enter(&icmdp->cmd_mutex);
664	if (icmdp->cmd_state == ISCSI_CMD_STATE_IDM_ABORTING) {
665		mutex_exit(&icmdp->cmd_mutex);
666		mutex_exit(&icp->conn_queue_active.mutex);
667		return (IDM_STATUS_SUCCESS);
668	}
669	mutex_exit(&icmdp->cmd_mutex);
670
671	/* Get the IDM buffer and bytes transferred */
672	bp = icmdp->cmd_un.scsi.bp;
673	if (ic->ic_conn_flags & IDM_CONN_USE_SCOREBOARD) {
674		/* Transport tracks bytes transferred so use those counts */
675		if (bp && (bp->b_flags & B_READ)) {
676			icmdp->cmd_un.scsi.data_transferred +=
677			    icmdp->cmd_itp->idt_rx_bytes;
678		} else {
679			icmdp->cmd_un.scsi.data_transferred +=
680			    icmdp->cmd_itp->idt_tx_bytes;
681		}
682	} else {
683		/*
684		 * Some transports cannot track the bytes transferred on
685		 * the initiator side (like iSER) so we have to use the
686		 * status info.  If the response field indicates that
687		 * the command actually completed then we will assume
688		 * the data_transferred value represents the entire buffer
689		 * unless the resid field says otherwise.  This is a bit
690		 * unintuitive but it's really impossible to know what
691		 * has been transferred without detailed consideration
692		 * of the SCSI status and sense key and that is outside
693		 * the scope of the transport.  Instead the target/class driver
694		 * can consider these values along with the resid and figure
695		 * it out.  The data_transferred concept is just belt and
696		 * suspenders anyway -- RFC 3720 actually explicitly rejects
697		 * scoreboarding ("Initiators SHOULD NOT keep track of the
698		 * data transferred to or from the target (scoreboarding)")
699		 * perhaps for this very reason.
700		 */
701		if (issrhp->response != 0) {
702			icmdp->cmd_un.scsi.data_transferred = 0;
703		} else {
704			icmdp->cmd_un.scsi.data_transferred =
705			    (bp == NULL) ? 0 : bp->b_bcount;
706			if (issrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
707				icmdp->cmd_un.scsi.data_transferred -=
708				    ntohl(issrhp->residual_count);
709			}
710		}
711	}
712
713	ISCSI_CHECK_SCSI_READ(icmdp, issrhp,
714	    icmdp->cmd_un.scsi.data_transferred,
715	    BP_CHECK_THOROUGH);
716
717	ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_cmd_rsp: ic: %p pdu: %p itt:"
718	    " %x expcmdsn: %x sess_cmd: %x sess_expcmdsn: %x data_transfered:"
719	    " %lu ibp: %p obp: %p", (void *)ic, (void *)pdu, issrhp->itt,
720	    issrhp->expcmdsn, isp->sess_cmdsn, isp->sess_expcmdsn,
721	    icmdp->cmd_un.scsi.data_transferred,
722	    (void *)icmdp->cmd_un.scsi.ibp_ibuf,
723	    (void *)icmdp->cmd_un.scsi.ibp_obuf);
724
725	iscsi_task_cleanup(issrhp->opcode, icmdp);
726
727	if (issrhp->response) {
728		/* The target failed the command. */
729		ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_cmd_rsp: ic: %p pdu:"
730		    " %p response: %d bcount: %lu", (void *)ic, (void *)pdu,
731		    issrhp->response, icmdp->cmd_un.scsi.bp->b_bcount);
732		pkt = icmdp->cmd_un.scsi.pkt;
733		pkt->pkt_reason = CMD_TRAN_ERR;
734		if (icmdp->cmd_un.scsi.bp) {
735			pkt->pkt_resid = icmdp->cmd_un.scsi.bp->b_bcount;
736		} else {
737			pkt->pkt_resid = 0;
738		}
739	} else {
740		/* success */
741		iscsi_cmd_rsp_chk(icmdp, issrhp);
742		flush = iscsi_cmd_rsp_cmd_status(icmdp, issrhp, data);
743		if (flush == B_TRUE) {
744			cmd_sn = icmdp->cmd_sn;
745			ASSERT(icmdp->cmd_lun != NULL);
746			lun_num = icmdp->cmd_lun->lun_num;
747		}
748	}
749
750	iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
751	if (flush == B_TRUE) {
752		iscsi_flush_cmd_after_reset(cmd_sn, lun_num, icp);
753	}
754	mutex_exit(&icp->conn_queue_active.mutex);
755	return (IDM_STATUS_SUCCESS);
756}
757
758static void
759iscsi_data_rsp_pkt(iscsi_cmd_t *icmdp, iscsi_data_rsp_hdr_t *idrhp)
760{
761	struct buf		*bp	= NULL;
762	size_t			data_transferred;
763	struct scsi_pkt		*pkt;
764
765	bp = icmdp->cmd_un.scsi.bp;
766	pkt = icmdp->cmd_un.scsi.pkt;
767	data_transferred = icmdp->cmd_un.scsi.data_transferred;
768	/*
769	 * The command* must be completed now, since we won't get a command
770	 * response PDU. The cmd_status and residual_count are
771	 * not meaningful unless status_present is set.
772	 */
773	pkt->pkt_resid = 0;
774	/* Check the residual count */
775	if (bp && (data_transferred != bp->b_bcount)) {
776		/*
777		 * We didn't xfer the expected amount of data -
778		 * the residual_count in the header is only valid
779		 * if the underflow flag is set.
780		 */
781		if (idrhp->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
782			pkt->pkt_resid = ntohl(idrhp->residual_count);
783			ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_data_rsp_pkt: "
784			    "underflow: itt: %d "
785			    "transferred: %lu count: %lu", idrhp->itt,
786			    data_transferred, bp->b_bcount);
787		} else {
788			if (bp->b_bcount > data_transferred) {
789				/* Some data fell on the floor somehw */
790				ISCSI_IO_LOG(CE_NOTE, "DEBUG: "
791				    "iscsi_data_rsp_pkt: data fell: itt: %d "
792				    "transferred: %lu count: %lu", idrhp->itt,
793				    data_transferred, bp->b_bcount);
794				pkt->pkt_resid =
795				    bp->b_bcount - data_transferred;
796			}
797		}
798	}
799
800	pkt->pkt_reason = CMD_CMPLT;
801	pkt->pkt_state |= (STATE_XFERRED_DATA | STATE_GOT_STATUS);
802
803	if (((idrhp->cmd_status & STATUS_MASK) != STATUS_GOOD) &&
804	    (icmdp->cmd_un.scsi.statuslen >=
805	    sizeof (struct scsi_arq_status)) && pkt->pkt_scbp) {
806
807		/*
808		 * Not supposed to get exception status here!
809		 * We have no request sense data so just do the
810		 * best we can
811		 */
812		struct scsi_arq_status *arqstat =
813		    (struct scsi_arq_status *)pkt->pkt_scbp;
814
815
816		bzero(arqstat, sizeof (struct scsi_arq_status));
817
818		*((uchar_t *)&arqstat->sts_status) =
819		    idrhp->cmd_status;
820
821		arqstat->sts_rqpkt_resid =
822		    sizeof (struct scsi_extended_sense);
823		ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_data_rsp_pkt: "
824		    "exception status: itt: %d resid: %d",
825		    idrhp->itt, arqstat->sts_rqpkt_resid);
826
827	} else if (pkt->pkt_scbp) {
828		/* just pass along the status we got */
829		pkt->pkt_scbp[0] = idrhp->cmd_status;
830	}
831}
832
833/*
834 * iscsi_rx_process_data_rsp -
835 * This currently processes the final data sequence denoted by the data response
836 * PDU Status bit being set.  We will not receive the SCSI response.
837 * This bit denotes that the PDU is the successful completion of the
838 * command.
839 */
840static idm_status_t
841iscsi_rx_process_data_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
842{
843	iscsi_sess_t		*isp	= NULL;
844	iscsi_data_rsp_hdr_t	*idrhp	= (iscsi_data_rsp_hdr_t *)pdu->isp_hdr;
845	iscsi_cmd_t		*icmdp	= NULL;
846	struct buf		*bp	= NULL;
847	iscsi_conn_t		*icp	= ic->ic_handle;
848	idm_buf_t		*ibp;
849	idm_status_t		rval;
850
851
852	/* should only call this when the data rsp contains final rsp */
853	ASSERT(idrhp->flags & ISCSI_FLAG_DATA_STATUS);
854	isp = icp->conn_sess;
855
856	mutex_enter(&icp->conn_queue_active.mutex);
857	if ((rval = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)idrhp,
858	    &icmdp)) != IDM_STATUS_SUCCESS) {
859		if (icmdp != NULL) {
860			iscsi_task_cleanup(idrhp->opcode, icmdp);
861		}
862		mutex_exit(&icp->conn_queue_active.mutex);
863		return (rval);
864	}
865
866	/*
867	 * If we are in "idm aborting" state then we shouldn't continue
868	 * to process this command.  By definition this command is no longer
869	 * on the active queue so we shouldn't try to remove it either.
870	 */
871	mutex_enter(&icmdp->cmd_mutex);
872	if (icmdp->cmd_state == ISCSI_CMD_STATE_IDM_ABORTING) {
873		mutex_exit(&icmdp->cmd_mutex);
874		mutex_exit(&icp->conn_queue_active.mutex);
875		return (IDM_STATUS_SUCCESS);
876	}
877	mutex_exit(&icmdp->cmd_mutex);
878
879	/*
880	 * Holding the pending/active queue locks across the
881	 * iscsi_rx_data call later in this function may cause
882	 * deadlock during fault injections.  Instead remove
883	 * the cmd from the active queue and release the locks.
884	 * Then before returning or completing the command
885	 * return the cmd to the active queue and reacquire
886	 * the locks.
887	 */
888	iscsi_dequeue_active_cmd(icp, icmdp);
889
890	mutex_exit(&icp->conn_queue_active.mutex);
891
892	/* shorthand some values */
893	bp = icmdp->cmd_un.scsi.bp;
894
895	/*
896	 * some poorly behaved targets have been observed
897	 * sending data-in pdu's during a write operation
898	 */
899	if (bp != NULL) {
900		if (!(bp->b_flags & B_READ)) {
901			cmn_err(CE_WARN,
902			    "iscsi connection(%u) protocol error - "
903			    "received data response during write operation "
904			    "itt:0x%x",
905			    icp->conn_oid, idrhp->itt);
906			mutex_enter(&icp->conn_queue_active.mutex);
907			iscsi_enqueue_active_cmd(icp, icmdp);
908			mutex_exit(&icp->conn_queue_active.mutex);
909			return (IDM_STATUS_PROTOCOL_ERROR);
910		}
911	}
912
913	ibp = icmdp->cmd_un.scsi.ibp_ibuf;
914	if (ibp == NULL) {
915		/*
916		 * After the check of bp above we *should* have a corresponding
917		 * idm_buf_t (ibp).  It's possible that the original call
918		 * to idm_buf_alloc failed due to a pending connection state
919		 * transition in which case this value can be NULL.  It's
920		 * highly unlikely that the connection would be shutting down
921		 * *and* we manage to process a data response and get to this
922		 * point in the code but just in case we should check for it.
923		 * This isn't really a protocol error -- we are almost certainly
924		 * closing the connection anyway so just return a generic error.
925		 */
926		mutex_enter(&icp->conn_queue_active.mutex);
927		iscsi_enqueue_active_cmd(icp, icmdp);
928		mutex_exit(&icp->conn_queue_active.mutex);
929		return (IDM_STATUS_FAIL);
930	}
931
932	if (ic->ic_conn_flags & IDM_CONN_USE_SCOREBOARD) {
933		icmdp->cmd_un.scsi.data_transferred =
934		    icmdp->cmd_itp->idt_rx_bytes;
935	} else {
936		icmdp->cmd_un.scsi.data_transferred = bp->b_bcount;
937		if (idrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
938			icmdp->cmd_un.scsi.data_transferred -=
939			    ntohl(idrhp->residual_count);
940		}
941	}
942
943	ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_data_rsp: icp: %p pdu: %p "
944	    "itt: %d ibp: %p icmdp: %p xfer_len: %lu transferred: %lu dlen: %u",
945	    (void *)icp, (void *)pdu, idrhp->itt, (void *)bp, (void *)icmdp,
946	    (ibp == NULL) ? 0 : ibp->idb_xfer_len,
947	    icmdp->cmd_un.scsi.data_transferred,
948	    n2h24(idrhp->dlength));
949
950	iscsi_task_cleanup(idrhp->opcode, icmdp);
951
952	iscsi_data_rsp_pkt(icmdp, idrhp);
953
954	mutex_enter(&icp->conn_queue_active.mutex);
955	iscsi_enqueue_active_cmd(icp, icmdp);
956	iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
957	mutex_exit(&icp->conn_queue_active.mutex);
958
959	return (IDM_STATUS_SUCCESS);
960}
961
962/*
963 * iscsi_rx_process_nop - Process a received nop.  If nop is in response
964 * to a ping we sent update stats.  If initiated by the target we need
965 * to response back to the target with a nop.  Schedule the response.
966 */
967/* ARGSUSED */
968static idm_status_t
969iscsi_rx_process_nop(idm_conn_t *ic, idm_pdu_t *pdu)
970{
971	iscsi_sess_t		*isp	= NULL;
972	iscsi_nop_in_hdr_t	*inihp	= (iscsi_nop_in_hdr_t *)pdu->isp_hdr;
973	iscsi_cmd_t		*icmdp	= NULL;
974	iscsi_conn_t		*icp	= ic->ic_handle;
975
976	if (icp->conn_expstatsn != ntohl(inihp->statsn)) {
977		cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
978		    "received status out of order itt:0x%x statsn:0x%x "
979		    "expstatsn:0x%x", icp->conn_oid, inihp->opcode, inihp->itt,
980		    ntohl(inihp->statsn), icp->conn_expstatsn);
981		return (IDM_STATUS_PROTOCOL_ERROR);
982	}
983	isp = icp->conn_sess;
984	ASSERT(isp != NULL);
985	mutex_enter(&isp->sess_queue_pending.mutex);
986	mutex_enter(&icp->conn_queue_active.mutex);
987	mutex_enter(&isp->sess_cmdsn_mutex);
988	if (inihp->itt != ISCSI_RSVD_TASK_TAG) {
989		if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
990		    isp, (iscsi_hdr_t *)inihp, &icmdp))) {
991			cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
992			    "- can not find cmd for itt:0x%x",
993			    icp->conn_oid, inihp->itt);
994			mutex_exit(&isp->sess_cmdsn_mutex);
995			mutex_exit(&icp->conn_queue_active.mutex);
996			mutex_exit(&isp->sess_queue_pending.mutex);
997			return (IDM_STATUS_PROTOCOL_ERROR);
998		}
999	}
1000
1001	/* update expcmdsn and maxcmdsn */
1002	iscsi_update_flow_control(isp, ntohl(inihp->maxcmdsn),
1003	    ntohl(inihp->expcmdsn));
1004	mutex_exit(&isp->sess_cmdsn_mutex);
1005
1006	if ((inihp->itt != ISCSI_RSVD_TASK_TAG) &&
1007	    (inihp->ttt == ISCSI_RSVD_TASK_TAG)) {
1008		/* This is the only type of nop that incs. the expstatsn */
1009		icp->conn_expstatsn++;
1010
1011		/*
1012		 * This is a targets response to our nop
1013		 */
1014		iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1015	} else if (inihp->ttt != ISCSI_RSVD_TASK_TAG) {
1016		/*
1017		 * Target requested a nop.  Send one.
1018		 */
1019		iscsi_handle_nop(icp, ISCSI_RSVD_TASK_TAG, inihp->ttt);
1020	} else {
1021		/*
1022		 * This is a target-initiated ping that doesn't expect
1023		 * a response; nothing to do except update our flow control
1024		 * (which we do in all cases above).
1025		 */
1026		/* EMPTY */
1027	}
1028	mutex_exit(&icp->conn_queue_active.mutex);
1029	mutex_exit(&isp->sess_queue_pending.mutex);
1030
1031	return (IDM_STATUS_SUCCESS);
1032}
1033
1034
1035/*
1036 * iscsi_rx_process_reject_rsp - The server rejected a PDU
1037 */
1038static idm_status_t
1039iscsi_rx_process_reject_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1040{
1041	iscsi_reject_rsp_hdr_t	*irrhp = (iscsi_reject_rsp_hdr_t *)pdu->isp_hdr;
1042	iscsi_sess_t		*isp		= NULL;
1043	uint32_t		dlength		= 0;
1044	iscsi_hdr_t		*old_ihp	= NULL;
1045	iscsi_conn_t		*icp		= ic->ic_handle;
1046	uint8_t			*data 		= pdu->isp_data;
1047	iscsi_hdr_t		*ihp		= (iscsi_hdr_t *)irrhp;
1048	idm_status_t		status;
1049	iscsi_cmd_t		*icmdp	= NULL;
1050
1051	ASSERT(data != NULL);
1052	isp = icp->conn_sess;
1053	ASSERT(isp != NULL);
1054
1055	mutex_enter(&icp->conn_queue_active.mutex);
1056	if ((status = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)irrhp,
1057	    &icmdp)) != IDM_STATUS_SUCCESS) {
1058		mutex_exit(&icp->conn_queue_active.mutex);
1059		return (status);
1060	}
1061
1062	/* If we don't have the rejected header we can't do anything */
1063	dlength = n2h24(irrhp->dlength);
1064	if (dlength < sizeof (iscsi_hdr_t)) {
1065		return (IDM_STATUS_PROTOCOL_ERROR);
1066	}
1067
1068	/* map old ihp */
1069	old_ihp = (iscsi_hdr_t *)data;
1070
1071	switch (irrhp->reason) {
1072	/*
1073	 * ISCSI_REJECT_IMM_CMD_REJECT - Immediate Command Reject
1074	 * too many immediate commands (original cmd can be resent)
1075	 */
1076	case ISCSI_REJECT_IMM_CMD_REJECT:
1077		/*
1078		 * We have exceeded the server's capacity for outstanding
1079		 * immediate commands.   This must be a task management
1080		 * command so try to find it in the abortingqueue and
1081		 * complete it.
1082		 */
1083		if (!(old_ihp->opcode & ISCSI_OP_IMMEDIATE)) {
1084			/* Rejecting IMM but old old_hdr wasn't IMM */
1085			return (IDM_STATUS_PROTOCOL_ERROR);
1086		}
1087
1088		/*
1089		 * We only send NOP and TASK_MGT as IMM.  All other
1090		 * cases should be considered as a protocol error.
1091		 */
1092		switch (old_ihp->opcode & ISCSI_OPCODE_MASK) {
1093		case ISCSI_OP_NOOP_OUT:
1094			/*
1095			 * A ping was rejected - treat this like
1096			 * ping response.  The down side is we
1097			 * didn't get an updated MaxCmdSn.
1098			 */
1099			break;
1100		case ISCSI_OP_SCSI_TASK_MGT_MSG:
1101			(void) iscsi_rx_process_rejected_tsk_mgt(ic, old_ihp);
1102			break;
1103		default:
1104			cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
1105			    "- received a reject for a command(0x%02x) not "
1106			    "sent as an immediate", icp->conn_oid,
1107			    old_ihp->opcode);
1108			status = IDM_STATUS_PROTOCOL_ERROR;
1109			break;
1110		}
1111		break;
1112
1113	/*
1114	 * For the rest of the reject cases just use the general
1115	 * hammer of dis/reconnecting.  This will resolve all
1116	 * noted issues although could be more graceful.
1117	 */
1118	case ISCSI_REJECT_DATA_DIGEST_ERROR:
1119	case ISCSI_REJECT_CMD_BEFORE_LOGIN:
1120	case ISCSI_REJECT_SNACK_REJECT:
1121	case ISCSI_REJECT_PROTOCOL_ERROR:
1122	case ISCSI_REJECT_CMD_NOT_SUPPORTED:
1123	case ISCSI_REJECT_TASK_IN_PROGRESS:
1124	case ISCSI_REJECT_INVALID_DATA_ACK:
1125	case ISCSI_REJECT_INVALID_PDU_FIELD:
1126	case ISCSI_REJECT_LONG_OPERATION_REJECT:
1127	case ISCSI_REJECT_NEGOTIATION_RESET:
1128	default:
1129		cmn_err(CE_WARN, "iscsi connection(%u) closing connection - "
1130		    "target requested itt:0x%x reason:0x%x",
1131		    icp->conn_oid, ihp->itt, irrhp->reason);
1132		status = IDM_STATUS_PROTOCOL_ERROR;
1133		break;
1134	}
1135
1136	return (IDM_STATUS_SUCCESS);
1137}
1138
1139
1140/*
1141 * iscsi_rx_process_rejected_tsk_mgt -
1142 */
1143/* ARGSUSED */
1144static idm_status_t
1145iscsi_rx_process_rejected_tsk_mgt(idm_conn_t *ic, iscsi_hdr_t *old_ihp)
1146{
1147	iscsi_sess_t		*isp	= NULL;
1148	iscsi_cmd_t		*icmdp	= NULL;
1149	iscsi_conn_t		*icp 	= NULL;
1150
1151	isp = icp->conn_sess;
1152	ASSERT(old_ihp != NULL);
1153	ASSERT(isp != NULL);
1154
1155	mutex_enter(&icp->conn_queue_active.mutex);
1156	mutex_enter(&isp->sess_cmdsn_mutex);
1157	if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
1158	    isp, old_ihp, &icmdp))) {
1159		mutex_exit(&isp->sess_cmdsn_mutex);
1160		mutex_exit(&icp->conn_queue_active.mutex);
1161		return (IDM_STATUS_PROTOCOL_ERROR);
1162	}
1163	mutex_exit(&isp->sess_cmdsn_mutex);
1164
1165	switch (icmdp->cmd_type) {
1166	case ISCSI_CMD_TYPE_ABORT:
1167	case ISCSI_CMD_TYPE_RESET:
1168		iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E4,
1169		    icp->conn_sess);
1170		break;
1171	/* We don't send any other task mgr types */
1172	default:
1173		ASSERT(B_FALSE);
1174		break;
1175	}
1176	mutex_exit(&icp->conn_queue_active.mutex);
1177
1178	return (IDM_STATUS_SUCCESS);
1179}
1180
1181
1182/*
1183 * iscsi_rx_process_task_mgt_rsp -
1184 */
1185/* ARGSUSED */
1186static idm_status_t
1187iscsi_rx_process_task_mgt_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1188{
1189	iscsi_sess_t			*isp		= NULL;
1190	iscsi_scsi_task_mgt_rsp_hdr_t	*istmrhp	= NULL;
1191	iscsi_cmd_t			*icmdp		= NULL;
1192	iscsi_conn_t			*icp		= ic->ic_handle;
1193	idm_status_t			status = IDM_STATUS_SUCCESS;
1194
1195	isp = icp->conn_sess;
1196	istmrhp = (iscsi_scsi_task_mgt_rsp_hdr_t *)pdu->isp_hdr;
1197
1198	mutex_enter(&icp->conn_queue_active.mutex);
1199	if ((status = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)istmrhp,
1200	    &icmdp)) != IDM_STATUS_SUCCESS) {
1201		mutex_exit(&icp->conn_queue_active.mutex);
1202		return (status);
1203	}
1204
1205	switch (icmdp->cmd_type) {
1206	case ISCSI_CMD_TYPE_ABORT:
1207	case ISCSI_CMD_TYPE_RESET:
1208		switch (istmrhp->response) {
1209		case SCSI_TCP_TM_RESP_COMPLETE:
1210			/* success */
1211			iscsi_cmd_state_machine(icmdp,
1212			    ISCSI_CMD_EVENT_E3, isp);
1213			break;
1214		case SCSI_TCP_TM_RESP_NO_TASK:
1215			/*
1216			 * If the array no longer knows about
1217			 * an ABORT RTT and we no longer have
1218			 * a parent SCSI command it was just
1219			 * completed, free this ABORT resource.
1220			 * Otherwise FALLTHRU this will flag a
1221			 * protocol problem.
1222			 */
1223			if ((icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT) &&
1224			    (icmdp->cmd_un.abort.icmdp == NULL)) {
1225				iscsi_cmd_state_machine(icmdp,
1226				    ISCSI_CMD_EVENT_E4, isp);
1227				break;
1228			}
1229			/* FALLTHRU */
1230		case SCSI_TCP_TM_RESP_REJECTED:
1231			/*
1232			 * If the target rejects our reset task,
1233			 * we should record the response and complete
1234			 * this command with the result.
1235			 */
1236			if (icmdp->cmd_type == ISCSI_CMD_TYPE_RESET) {
1237				icmdp->cmd_un.reset.response =
1238				    istmrhp->response;
1239				iscsi_cmd_state_machine(icmdp,
1240				    ISCSI_CMD_EVENT_E3, isp);
1241				break;
1242			}
1243			/* FALLTHRU */
1244		case SCSI_TCP_TM_RESP_NO_LUN:
1245		case SCSI_TCP_TM_RESP_TASK_ALLEGIANT:
1246		case SCSI_TCP_TM_RESP_NO_FAILOVER:
1247		case SCSI_TCP_TM_RESP_IN_PRGRESS:
1248		default:
1249			/*
1250			 * Something is out of sync.  Flush
1251			 * active queues and resync the
1252			 * the connection to try and recover
1253			 * to a known state.
1254			 */
1255			status = IDM_STATUS_PROTOCOL_ERROR;
1256		}
1257		break;
1258
1259	default:
1260		cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1261		    "received a task mgt response for a non-task mgt "
1262		    "cmd itt:0x%x type:%d", icp->conn_oid, istmrhp->itt,
1263		    icmdp->cmd_type);
1264		status = IDM_STATUS_PROTOCOL_ERROR;
1265		break;
1266	}
1267
1268	mutex_exit(&icp->conn_queue_active.mutex);
1269	return (status);
1270}
1271
1272
1273/*
1274 * iscsi_rx_process_logout_rsp -
1275 *
1276 */
1277/* ARGSUSED */
1278idm_status_t
1279iscsi_rx_process_logout_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1280{
1281	iscsi_conn_t		*icp	= ic->ic_handle;
1282	iscsi_logout_rsp_hdr_t	*ilrhp	=
1283	    (iscsi_logout_rsp_hdr_t *)pdu->isp_hdr;
1284	iscsi_cmd_t		*icmdp	= NULL;
1285	iscsi_sess_t		*isp;
1286	idm_status_t		status = IDM_STATUS_SUCCESS;
1287
1288	isp = icp->conn_sess;
1289
1290	if (icp->conn_expstatsn != ntohl(ilrhp->statsn)) {
1291		cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
1292		    "received status out of order itt:0x%x statsn:0x%x "
1293		    "expstatsn:0x%x", icp->conn_oid, ilrhp->opcode, ilrhp->itt,
1294		    ntohl(ilrhp->statsn), icp->conn_expstatsn);
1295		return (IDM_STATUS_PROTOCOL_ERROR);
1296	}
1297
1298	mutex_enter(&icp->conn_queue_active.mutex);
1299	mutex_enter(&isp->sess_cmdsn_mutex);
1300	if (ilrhp->itt != ISCSI_RSVD_TASK_TAG) {
1301		if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
1302		    isp, (iscsi_hdr_t *)ilrhp, &icmdp))) {
1303			mutex_exit(&isp->sess_cmdsn_mutex);
1304			mutex_exit(&icp->conn_queue_active.mutex);
1305			return (IDM_STATUS_PROTOCOL_ERROR);
1306		}
1307	}
1308
1309	/* update expcmdsn and maxcmdsn */
1310	iscsi_update_flow_control(isp, ntohl(ilrhp->maxcmdsn),
1311	    ntohl(ilrhp->expcmdsn));
1312	mutex_exit(&isp->sess_cmdsn_mutex);
1313
1314	ISCSI_IO_LOG(CE_NOTE,
1315	    "DEBUG: iscsi_rx_process_logout_rsp: response: %d",
1316	    ilrhp->response);
1317	switch (ilrhp->response) {
1318	case ISCSI_LOGOUT_CID_NOT_FOUND:
1319		/*
1320		 * If the target doesn't know about our connection
1321		 * then we can consider our self disconnected.
1322		 */
1323		/* FALLTHRU */
1324	case ISCSI_LOGOUT_RECOVERY_UNSUPPORTED:
1325		/*
1326		 * We don't support ErrorRecovery levels above 0
1327		 * currently so consider this success.
1328		 */
1329		/* FALLTHRU */
1330	case ISCSI_LOGOUT_CLEANUP_FAILED:
1331		/*
1332		 * per spec. "cleanup failed for various reasons."
1333		 * Although those various reasons are undefined.
1334		 * Not sure what to do here.  So fake success,
1335		 * which will disconnect the connection.
1336		 */
1337		/* FALLTHRU */
1338	case ISCSI_LOGOUT_SUCCESS:
1339		iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1340		mutex_exit(&icp->conn_queue_active.mutex);
1341		iscsi_drop_conn_cleanup(icp);
1342		break;
1343	default:
1344		mutex_exit(&icp->conn_queue_active.mutex);
1345		status = IDM_STATUS_PROTOCOL_ERROR;
1346		break;
1347
1348	}
1349	return (status);
1350}
1351
1352/*
1353 * iscsi_rx_process_async_rsp
1354 *
1355 */
1356/* ARGSUSED */
1357static idm_status_t
1358iscsi_rx_process_async_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1359{
1360	iscsi_conn_t		*icp	= ic->ic_handle;
1361	iscsi_sess_t		*isp	= icp->conn_sess;
1362	idm_status_t		rval	= IDM_STATUS_SUCCESS;
1363	iscsi_task_t		*itp;
1364	iscsi_async_evt_hdr_t	*iaehp	=
1365	    (iscsi_async_evt_hdr_t *)pdu->isp_hdr;
1366
1367	ASSERT(icp != NULL);
1368	ASSERT(pdu != NULL);
1369	ASSERT(isp != NULL);
1370
1371	mutex_enter(&isp->sess_cmdsn_mutex);
1372	if (icp->conn_expstatsn == ntohl(iaehp->statsn)) {
1373		icp->conn_expstatsn++;
1374	} else {
1375		cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1376		    "received status out of order statsn:0x%x "
1377		    "expstatsn:0x%x", icp->conn_oid,
1378		    ntohl(iaehp->statsn), icp->conn_expstatsn);
1379		mutex_exit(&isp->sess_cmdsn_mutex);
1380		return (IDM_STATUS_PROTOCOL_ERROR);
1381	}
1382	mutex_exit(&isp->sess_cmdsn_mutex);
1383
1384	switch (iaehp->async_event) {
1385	case ISCSI_ASYNC_EVENT_SCSI_EVENT:
1386		/*
1387		 * SCSI asynchronous event is reported in
1388		 * the sense data.  Sense data that accompanies
1389		 * the report in the data segment identifies the
1390		 * condition.  If the target supports SCSI
1391		 * asynchronous events reporting (see [SAM2])
1392		 * as indicated in the stardard INQUIRY data
1393		 * (see [SPC3]), its use may be enabled by
1394		 * parameters in the SCSI control mode page
1395		 * (see [SPC3]).
1396		 *
1397		 * T-10 has removed SCSI asunchronous events
1398		 * from the standard.  Although we have seen
1399		 * a couple targets still spending these requests.
1400		 * Those targets were specifically sending them
1401		 * for notification of a LUN/Volume change
1402		 * (ex. LUN addition/removal).  Take a general
1403		 * action to these events of dis/reconnecting.
1404		 * Once reconnected we perform a reenumeration.
1405		 */
1406		idm_ini_conn_disconnect(ic);
1407		break;
1408
1409	case ISCSI_ASYNC_EVENT_REQUEST_LOGOUT:
1410		/*
1411		 * We've been asked to logout by the target --
1412		 * we need to treat this differently from a normal logout
1413		 * due to a discovery failure.  Normal logouts result in
1414		 * an N3 event to the session state machine and an offline
1415		 * of the lun.  In this case we want to put the connection
1416		 * into "failed" state and generate N5 to the session state
1417		 * machine since the initiator logged out at the target's
1418		 * request.  To track this we set a flag indicating we
1419		 * received this async logout request from the tharget
1420		 */
1421		mutex_enter(&icp->conn_state_mutex);
1422		icp->conn_async_logout = B_TRUE;
1423		mutex_exit(&icp->conn_state_mutex);
1424
1425		/* Target has requested this connection to logout. */
1426		itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP);
1427		itp->t_arg = icp;
1428		itp->t_blocking = B_FALSE;
1429		if (ddi_taskq_dispatch(isp->sess_taskq,
1430		    (void(*)())iscsi_logout_start, itp, DDI_SLEEP) !=
1431		    DDI_SUCCESS) {
1432			/* Disconnect if we couldn't dispatch the task */
1433			idm_ini_conn_disconnect(ic);
1434		}
1435		break;
1436
1437	case ISCSI_ASYNC_EVENT_DROPPING_CONNECTION:
1438		/*
1439		 * Target is going to drop our connection.
1440		 *	param1 - CID which will be dropped.
1441		 *	param2 - Min time to reconnect.
1442		 *	param3 - Max time to reconnect.
1443		 *
1444		 * For now just let fail as another disconnect.
1445		 *
1446		 * MC/S Once we support > 1 connections then
1447		 * we need to check the CID and drop that
1448		 * specific connection.
1449		 */
1450		iscsi_conn_set_login_min_max(icp, iaehp->param2,
1451		    iaehp->param3);
1452		idm_ini_conn_disconnect(ic);
1453		break;
1454
1455	case ISCSI_ASYNC_EVENT_DROPPING_ALL_CONNECTIONS:
1456		/*
1457		 * Target is going to drop ALL connections.
1458		 *	param2 - Min time to reconnect.
1459		 *	param3 - Max time to reconnect.
1460		 *
1461		 * For now just let fail as anyother disconnect.
1462		 *
1463		 * MC/S Once we support more than > 1 connections
1464		 * then we need to drop all connections on the
1465		 * session.
1466		 */
1467		iscsi_conn_set_login_min_max(icp, iaehp->param2,
1468		    iaehp->param3);
1469		idm_ini_conn_disconnect(ic);
1470		break;
1471
1472	case ISCSI_ASYNC_EVENT_PARAM_NEGOTIATION:
1473		/*
1474		 * Target requests parameter negotiation
1475		 * on this connection.
1476		 *
1477		 * The initiator must honor this request.  For
1478		 * now we will request a logout.  We can't
1479		 * just ignore this or it might force corruption?
1480		 */
1481		itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP);
1482		itp->t_arg = icp;
1483		itp->t_blocking = B_FALSE;
1484		if (ddi_taskq_dispatch(isp->sess_taskq,
1485		    (void(*)())iscsi_logout_start, itp, DDI_SLEEP) !=
1486		    DDI_SUCCESS) {
1487			/* Disconnect if we couldn't dispatch the task */
1488			idm_ini_conn_disconnect(ic);
1489		}
1490		break;
1491
1492	case ISCSI_ASYNC_EVENT_VENDOR_SPECIFIC:
1493		/*
1494		 * We currently don't handle any vendor
1495		 * specific async events.  So just ignore
1496		 * the request.
1497		 */
1498		idm_ini_conn_disconnect(ic);
1499		break;
1500	default:
1501		rval = IDM_STATUS_PROTOCOL_ERROR;
1502	}
1503
1504	return (rval);
1505}
1506
1507/*
1508 * iscsi_rx_process_text_rsp - processes iSCSI text response.  It sets
1509 * the cmd_result field of the command data structure with the actual
1510 * status value instead of returning the status value.  The return value
1511 * is SUCCESS in order to let iscsi_handle_text control the operation of
1512 * a text request.
1513 * Text requests are a handled a little different than other types of
1514 * iSCSI commands because the initiator sends additional empty text requests
1515 * in order to obtain the remaining responses required to complete the
1516 * request.  iscsi_handle_text controls the operation of text request, while
1517 * iscsi_rx_process_text_rsp just process the current response.
1518 */
1519static idm_status_t
1520iscsi_rx_process_text_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1521{
1522	iscsi_sess_t		*isp	= NULL;
1523	iscsi_text_rsp_hdr_t	*ithp	=
1524	    (iscsi_text_rsp_hdr_t *)pdu->isp_hdr;
1525	iscsi_conn_t		*icp	= ic->ic_handle;
1526	iscsi_cmd_t		*icmdp	= NULL;
1527	boolean_t		final	= B_FALSE;
1528	uint32_t		data_len;
1529	uint8_t			*data = pdu->isp_data;
1530	idm_status_t		rval;
1531
1532	isp = icp->conn_sess;
1533
1534	mutex_enter(&icp->conn_queue_active.mutex);
1535	if ((rval = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)ithp,
1536	    &icmdp)) != IDM_STATUS_SUCCESS) {
1537		mutex_exit(&icp->conn_queue_active.mutex);
1538		return (rval);
1539	}
1540
1541	/* update local final response flag */
1542	if (ithp->flags & ISCSI_FLAG_FINAL) {
1543		final = B_TRUE;
1544	}
1545
1546	/*
1547	 * validate received TTT value.  RFC3720 specifies the following:
1548	 * - F bit set to 1 MUST have a reserved TTT value 0xffffffff
1549	 * - F bit set to 0 MUST have a non-reserved TTT value !0xffffffff
1550	 * In addition, the received TTT value must not change between
1551	 * responses of a long text response
1552	 */
1553	if (((final == B_TRUE) && (ithp->ttt != ISCSI_RSVD_TASK_TAG)) ||
1554	    ((final == B_FALSE) && (ithp->ttt == ISCSI_RSVD_TASK_TAG))) {
1555		icmdp->cmd_result = ISCSI_STATUS_PROTOCOL_ERROR;
1556		icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1557		mutex_exit(&icp->conn_queue_active.mutex);
1558		cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1559		    "received text response with invalid flags:0x%x or "
1560		    "ttt:0x%x", icp->conn_oid, ithp->flags, ithp->itt);
1561		return (IDM_STATUS_PROTOCOL_ERROR);
1562	}
1563
1564	if ((icmdp->cmd_un.text.stage == ISCSI_CMD_TEXT_INITIAL_REQ) &&
1565	    (ithp->ttt == ISCSI_RSVD_TASK_TAG) &&
1566	    (final == B_FALSE)) {
1567		/* TTT should have matched reserved value */
1568		icmdp->cmd_result = ISCSI_STATUS_PROTOCOL_ERROR;
1569		icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1570		mutex_exit(&icp->conn_queue_active.mutex);
1571		cmn_err(CE_WARN, "iscsi connection(%u) protocol "
1572		    "error - received text response with invalid "
1573		    "ttt:0x%x", icp->conn_oid, ithp->ttt);
1574		return (IDM_STATUS_PROTOCOL_ERROR);
1575	}
1576
1577	/*
1578	 * If this is first response, save away TTT value for later use
1579	 * in a long text request/response sequence
1580	 */
1581	if (icmdp->cmd_un.text.stage == ISCSI_CMD_TEXT_INITIAL_REQ) {
1582		icmdp->cmd_un.text.ttt = ithp->ttt;
1583	}
1584
1585	data_len = ntoh24(ithp->dlength);
1586
1587	/* check whether enough buffer available to copy data */
1588	if ((icmdp->cmd_un.text.total_rx_len + data_len) >
1589	    icmdp->cmd_un.text.buf_len) {
1590		icmdp->cmd_un.text.total_rx_len += data_len;
1591		icmdp->cmd_result = ISCSI_STATUS_DATA_OVERFLOW;
1592		/*
1593		 * DATA_OVERFLOW will result in a SUCCESS return so that
1594		 * iscsi_handle_text can continue to obtain the remaining
1595		 * text response if needed.
1596		 */
1597	} else {
1598		char *buf_data = (icmdp->cmd_un.text.buf +
1599		    icmdp->cmd_un.text.offset);
1600
1601		bcopy(data, buf_data, data_len);
1602		icmdp->cmd_un.text.offset += data_len;
1603		icmdp->cmd_un.text.total_rx_len += data_len;
1604		icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
1605		bcopy(ithp->rsvd4, icmdp->cmd_un.text.lun,
1606		    sizeof (icmdp->cmd_un.text.lun));
1607	}
1608
1609	/* update stage  */
1610	if (final == B_TRUE) {
1611		icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1612	} else {
1613		icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_CONTINUATION;
1614	}
1615
1616	iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1617	mutex_exit(&icp->conn_queue_active.mutex);
1618	return (IDM_STATUS_SUCCESS);
1619}
1620
1621/*
1622 * iscsi_rx_process_scsi_itt_to_icmdp - Lookup itt using IDM to find matching
1623 * icmdp.  Verify itt in hdr and icmdp are the same.
1624 */
1625static iscsi_status_t
1626iscsi_rx_process_scsi_itt_to_icmdp(iscsi_sess_t *isp, idm_conn_t *ic,
1627    iscsi_scsi_rsp_hdr_t *ihp, iscsi_cmd_t **icmdp)
1628{
1629	idm_task_t *itp;
1630
1631	ASSERT(isp != NULL);
1632	ASSERT(ihp != NULL);
1633	ASSERT(icmdp != NULL);
1634	ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
1635	itp = idm_task_find_and_complete(ic, ihp->itt, ISCSI_INI_TASK_TTT);
1636	if (itp == NULL) {
1637		cmn_err(CE_WARN, "iscsi session(%u) protocol error - "
1638		    "received unknown itt:0x%x - protocol error",
1639		    isp->sess_oid, ihp->itt);
1640		return (ISCSI_STATUS_INTERNAL_ERROR);
1641	}
1642	*icmdp = itp->idt_private;
1643
1644	idm_task_rele(itp);
1645
1646	return (ISCSI_STATUS_SUCCESS);
1647
1648}
1649
1650/*
1651 * iscsi_rx_process_itt_to_icmdp - Lookup itt in the session's
1652 * cmd table to find matching icmdp.  Verify itt in hdr and
1653 * icmdp are the same.
1654 */
1655static iscsi_status_t
1656iscsi_rx_process_itt_to_icmdp(iscsi_sess_t *isp, iscsi_hdr_t *ihp,
1657    iscsi_cmd_t **icmdp)
1658{
1659	int cmd_table_idx = 0;
1660
1661	ASSERT(isp != NULL);
1662	ASSERT(ihp != NULL);
1663	ASSERT(icmdp != NULL);
1664	ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
1665
1666	/* try to find an associated iscsi_pkt */
1667	cmd_table_idx = (ihp->itt - IDM_TASKIDS_MAX) % ISCSI_CMD_TABLE_SIZE;
1668	if (isp->sess_cmd_table[cmd_table_idx] == NULL) {
1669		cmn_err(CE_WARN, "iscsi session(%u) protocol error - "
1670		    "received unknown itt:0x%x - protocol error",
1671		    isp->sess_oid, ihp->itt);
1672		return (ISCSI_STATUS_INTERNAL_ERROR);
1673	}
1674
1675	/* verify itt */
1676	if (isp->sess_cmd_table[cmd_table_idx]->cmd_itt != ihp->itt) {
1677		cmn_err(CE_WARN, "iscsi session(%u) received itt:0x%x "
1678		    " which is out of sync with itt:0x%x", isp->sess_oid,
1679		    ihp->itt, isp->sess_cmd_table[cmd_table_idx]->cmd_itt);
1680		return (ISCSI_STATUS_INTERNAL_ERROR);
1681	}
1682
1683	/* ensure that icmdp is still in Active state */
1684	if (isp->sess_cmd_table[cmd_table_idx]->cmd_state !=
1685	    ISCSI_CMD_STATE_ACTIVE) {
1686		cmn_err(CE_WARN, "iscsi session(%u) received itt:0x%x "
1687		    "but icmdp (%p) is not in active state",
1688		    isp->sess_oid, ihp->itt,
1689		    (void *)isp->sess_cmd_table[cmd_table_idx]);
1690		return (ISCSI_STATUS_INTERNAL_ERROR);
1691	}
1692
1693	/* make sure this is a SCSI cmd */
1694	*icmdp = isp->sess_cmd_table[cmd_table_idx];
1695
1696	return (ISCSI_STATUS_SUCCESS);
1697}
1698
1699/*
1700 * +--------------------------------------------------------------------+
1701 * | End of protocol receive routines					|
1702 * +--------------------------------------------------------------------+
1703 */
1704
1705/*
1706 * +--------------------------------------------------------------------+
1707 * | Beginning of protocol send routines				|
1708 * +--------------------------------------------------------------------+
1709 */
1710
1711
1712/*
1713 * iscsi_tx_thread - This thread is the driving point for all
1714 * iSCSI PDUs after login.  No PDUs should call idm_pdu_tx()
1715 * directly they should be funneled through iscsi_tx_thread.
1716 */
1717void
1718iscsi_tx_thread(iscsi_thread_t *thread, void *arg)
1719{
1720	iscsi_conn_t	*icp	= (iscsi_conn_t *)arg;
1721	iscsi_sess_t	*isp	= NULL;
1722	iscsi_cmd_t	*icmdp	= NULL;
1723	clock_t		tout;
1724	int		ret	= 1;
1725
1726	ASSERT(icp != NULL);
1727	isp = icp->conn_sess;
1728	ASSERT(isp != NULL);
1729	ASSERT(thread != NULL);
1730	ASSERT(thread->signature == SIG_ISCSI_THREAD);
1731
1732	tout = SEC_TO_TICK(1);
1733	/*
1734	 * Transfer icmdps until shutdown by owning session.
1735	 */
1736	while (ret != 0) {
1737
1738		isp->sess_window_open = B_TRUE;
1739		/*
1740		 * While the window is open, there are commands available
1741		 * to send and the session state allows those commands to
1742		 * be sent try to transfer them.
1743		 */
1744		mutex_enter(&isp->sess_queue_pending.mutex);
1745		while ((isp->sess_window_open == B_TRUE) &&
1746		    ((icmdp = isp->sess_queue_pending.head) != NULL) &&
1747		    (((icmdp->cmd_type != ISCSI_CMD_TYPE_SCSI) &&
1748		    (ISCSI_CONN_STATE_FULL_FEATURE(icp->conn_state))) ||
1749		    (icp->conn_state == ISCSI_CONN_STATE_LOGGED_IN))) {
1750
1751			/* update command with this connection info */
1752			icmdp->cmd_conn = icp;
1753			/* attempt to send this command */
1754			iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E2, isp);
1755
1756			ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex));
1757			mutex_enter(&isp->sess_queue_pending.mutex);
1758		}
1759		mutex_exit(&isp->sess_queue_pending.mutex);
1760
1761		/*
1762		 * Go to sleep until there is something new
1763		 * to process (awoken via cv_boardcast).
1764		 * Or the timer goes off.
1765		 */
1766		ret = iscsi_thread_wait(thread, tout);
1767	}
1768
1769}
1770
1771
1772/*
1773 * iscsi_tx_cmd - transfers icmdp across wire as iscsi pdu
1774 *
1775 * Just prior to sending the command to the networking layer the
1776 * pending queue lock will be dropped.  At this point only local
1777 * resources will be used, not the icmdp.  Holding the queue lock
1778 * across the networking call can lead to a hang.  (This is due
1779 * to the the target driver and networking layers competing use
1780 * of the timeout() resources and the queue lock being held for
1781 * both sides.)  Upon the completion of this command the lock
1782 * will have been re-acquired.
1783 */
1784iscsi_status_t
1785iscsi_tx_cmd(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
1786{
1787	iscsi_status_t	rval = ISCSI_STATUS_INTERNAL_ERROR;
1788
1789	ASSERT(isp != NULL);
1790	ASSERT(icmdp != NULL);
1791
1792	/* transfer specific command type */
1793	switch (icmdp->cmd_type) {
1794	case ISCSI_CMD_TYPE_SCSI:
1795		rval = iscsi_tx_scsi(isp, icmdp);
1796		break;
1797	case ISCSI_CMD_TYPE_NOP:
1798		rval = iscsi_tx_nop(isp, icmdp);
1799		break;
1800	case ISCSI_CMD_TYPE_ABORT:
1801		rval = iscsi_tx_abort(isp, icmdp);
1802		break;
1803	case ISCSI_CMD_TYPE_RESET:
1804		rval = iscsi_tx_reset(isp, icmdp);
1805		break;
1806	case ISCSI_CMD_TYPE_LOGOUT:
1807		rval = iscsi_tx_logout(isp, icmdp);
1808		break;
1809	case ISCSI_CMD_TYPE_TEXT:
1810		rval = iscsi_tx_text(isp, icmdp);
1811		break;
1812	default:
1813		cmn_err(CE_WARN, "iscsi_tx_cmd: invalid cmdtype: %d",
1814		    icmdp->cmd_type);
1815		ASSERT(FALSE);
1816	}
1817
1818	ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex));
1819	return (rval);
1820}
1821
1822/*
1823 * a variable length cdb can be up to 16K, but we obviously don't want
1824 * to put that on the stack; go with 200 bytes; if we get something
1825 * bigger than that we will kmem_alloc a buffer
1826 */
1827#define	DEF_CDB_LEN	200
1828
1829/*
1830 * given the size of the cdb, return how many bytes the header takes,
1831 * which is the sizeof addl_hdr_t + the CDB size, minus the 16 bytes
1832 * stored in the basic header, minus sizeof (ahs_extscb)
1833 */
1834#define	ADDLHDRSZ(x)		(sizeof (iscsi_addl_hdr_t) + (x) - \
1835					16 - 4)
1836
1837static void
1838iscsi_tx_init_hdr(iscsi_sess_t *isp, iscsi_conn_t *icp,
1839    iscsi_text_hdr_t *ihp, int opcode, iscsi_cmd_t *icmdp)
1840{
1841	ihp->opcode		= opcode;
1842	ihp->itt		= icmdp->cmd_itt;
1843	mutex_enter(&isp->sess_cmdsn_mutex);
1844	icmdp->cmd_sn		= isp->sess_cmdsn;
1845	ihp->cmdsn		= htonl(isp->sess_cmdsn);
1846	isp->sess_cmdsn++;
1847	mutex_exit(&isp->sess_cmdsn_mutex);
1848	ihp->expstatsn		= htonl(icp->conn_expstatsn);
1849	icp->conn_laststatsn = icp->conn_expstatsn;
1850}
1851
1852
1853static void
1854iscsi_tx_scsi_data(iscsi_cmd_t *icmdp, iscsi_scsi_cmd_hdr_t *ihp,
1855    iscsi_conn_t *icp, idm_pdu_t *pdu)
1856{
1857	struct buf		*bp		= NULL;
1858	size_t			buflen		= 0;
1859	uint32_t		first_burst_length = 0;
1860	struct scsi_pkt		*pkt;
1861
1862	pkt = icmdp->cmd_un.scsi.pkt;
1863	bp = icmdp->cmd_un.scsi.bp;
1864	if ((bp != NULL) && bp->b_bcount) {
1865		buflen = bp->b_bcount;
1866		first_burst_length =
1867		    icp->conn_params.first_burst_length;
1868
1869		if (bp->b_flags & B_READ) {
1870			ihp->flags = ISCSI_FLAG_FINAL;
1871			/*
1872			 * fix problem where OS sends bp (B_READ &
1873			 * b_bcount!=0) for a TUR or START_STOP.
1874			 * (comment came from cisco code.)
1875			 */
1876			if ((pkt->pkt_cdbp[0] != SCMD_TEST_UNIT_READY) &&
1877			    (pkt->pkt_cdbp[0] != SCMD_START_STOP)) {
1878				ihp->flags |= ISCSI_FLAG_CMD_READ;
1879				ihp->data_length = htonl(buflen);
1880			}
1881		} else {
1882			ihp->flags = ISCSI_FLAG_CMD_WRITE;
1883			/*
1884			 * FinalBit on the the iSCSI PDU denotes this
1885			 * is the last PDU in the sequence.
1886			 *
1887			 * initial_r2t = true means R2T is required
1888			 * for additional PDU, so there will be no more
1889			 * unsolicited PDUs following
1890			 */
1891			if (icp->conn_params.initial_r2t) {
1892				ihp->flags |= ISCSI_FLAG_FINAL;
1893			}
1894
1895			/* Check if we should send ImmediateData */
1896			if (icp->conn_params.immediate_data) {
1897				pdu->isp_data =
1898				    (uint8_t *)icmdp->
1899				    cmd_un.scsi.bp->b_un.b_addr;
1900
1901				pdu->isp_datalen = MIN(MIN(buflen,
1902				    first_burst_length),
1903				    icmdp->cmd_conn->conn_params.
1904				    max_xmit_data_seg_len);
1905
1906				/*
1907				 * if everything fits immediate, or
1908				 * we can send all burst data immediate
1909				 * (not unsol), set F
1910				 */
1911				/*
1912				 * XXX This doesn't look right -- it's not
1913				 * clear how we can handle transmitting
1914				 * any unsolicited data.  It looks like
1915				 * we only support immediate data.  So what
1916				 * happens if we don't set ISCSI_FLAG_FINAL?
1917				 *
1918				 * Unless there's magic code somewhere that
1919				 * is sending the remaining PDU's we should
1920				 * simply set ISCSI_FLAG_FINAL and forget
1921				 * about sending unsolicited data.  The big
1922				 * win is the immediate data anyway for small
1923				 * PDU's.
1924				 */
1925				if ((pdu->isp_datalen == buflen) ||
1926				    (pdu->isp_datalen == first_burst_length)) {
1927					ihp->flags |= ISCSI_FLAG_FINAL;
1928				}
1929
1930				hton24(ihp->dlength, pdu->isp_datalen);
1931			}
1932			/* total data transfer length */
1933			ihp->data_length = htonl(buflen);
1934		}
1935	} else {
1936		ihp->flags = ISCSI_FLAG_FINAL;
1937	}
1938	icmdp->cmd_un.scsi.data_transferred += pdu->isp_datalen;
1939	/* XXX How is this different from the code above? */
1940	/* will idm send the next data command up to burst length? */
1941	/* send the burstlen if we haven't sent immediate data */
1942	/* CRM: should idm send difference min(buflen, first_burst) and  imm? */
1943	/*    (MIN(first_burst_length, buflen) - imdata > 0) */
1944	/* CRM_LATER: change this to generate unsolicited pdu */
1945	if ((buflen > 0) &&
1946	    ((bp->b_flags & B_READ) == 0) &&
1947	    (icp->conn_params.initial_r2t == 0) &&
1948	    pdu->isp_datalen == 0) {
1949
1950		pdu->isp_datalen = MIN(first_burst_length, buflen);
1951		if ((pdu->isp_datalen == buflen) ||
1952		    (pdu->isp_datalen == first_burst_length)) {
1953			ihp->flags |= ISCSI_FLAG_FINAL;
1954		}
1955		pdu->isp_data = (uint8_t *)icmdp->cmd_un.scsi.bp->b_un.b_addr;
1956		hton24(ihp->dlength, pdu->isp_datalen);
1957	}
1958}
1959
1960static void
1961iscsi_tx_scsi_init_pkt(iscsi_cmd_t *icmdp, iscsi_scsi_cmd_hdr_t *ihp)
1962{
1963	struct scsi_pkt *pkt;
1964
1965	pkt = icmdp->cmd_un.scsi.pkt;
1966	pkt->pkt_state = (STATE_GOT_BUS | STATE_GOT_TARGET);
1967	pkt->pkt_reason = CMD_INCOMPLETE;
1968
1969	/* tagged queuing */
1970	if (pkt->pkt_flags & FLAG_HTAG) {
1971		ihp->flags |= ISCSI_ATTR_HEAD_OF_QUEUE;
1972	} else if (pkt->pkt_flags & FLAG_OTAG) {
1973		ihp->flags |= ISCSI_ATTR_ORDERED;
1974	} else if (pkt->pkt_flags & FLAG_STAG) {
1975		ihp->flags |= ISCSI_ATTR_SIMPLE;
1976	} else {
1977		/* ihp->flags |= ISCSI_ATTR_UNTAGGED; */
1978		/* EMPTY */
1979	}
1980
1981	/* iscsi states lun is based on spc.2 */
1982	ISCSI_LUN_BYTE_COPY(ihp->lun, icmdp->cmd_un.scsi.lun);
1983
1984	if (icmdp->cmd_un.scsi.cmdlen <= 16) {
1985		/* copy the SCSI Command Block into the PDU */
1986		bcopy(pkt->pkt_cdbp, ihp->scb,
1987		    icmdp->cmd_un.scsi.cmdlen);
1988	} else {
1989		iscsi_addl_hdr_t *iahp;
1990
1991		iahp = (iscsi_addl_hdr_t *)ihp;
1992
1993		ihp->hlength = (ADDLHDRSZ(icmdp->cmd_un.scsi.cmdlen) -
1994		    sizeof (iscsi_scsi_cmd_hdr_t) + 3) / 4;
1995		iahp->ahs_hlen_hi = 0;
1996		iahp->ahs_hlen_lo = (icmdp->cmd_un.scsi.cmdlen - 15);
1997		iahp->ahs_key = 0x01;
1998		iahp->ahs_resv = 0;
1999		bcopy(pkt->pkt_cdbp, ihp->scb, 16);
2000		bcopy(((char *)pkt->pkt_cdbp) + 16, &iahp->ahs_extscb[0],
2001		    icmdp->cmd_un.scsi.cmdlen);
2002	}
2003
2004	/*
2005	 * Update all values before transfering.
2006	 * We should never touch the icmdp after
2007	 * transfering if there is no more data
2008	 * to send.  The only case the idm_pdu_tx()
2009	 * will fail is a on a connection disconnect
2010	 * in that case the command will be flushed.
2011	 */
2012	pkt->pkt_state |= STATE_SENT_CMD;
2013}
2014
2015static void
2016iscsi_tx_scsi_init_task(iscsi_cmd_t *icmdp, iscsi_conn_t *icp,
2017    iscsi_scsi_cmd_hdr_t *ihp)
2018{
2019	idm_task_t		*itp;
2020	struct buf		*bp		= NULL;
2021	uint32_t		data_length;
2022
2023	bp = icmdp->cmd_un.scsi.bp;
2024
2025	itp = icmdp->cmd_itp;
2026	ASSERT(itp != NULL);
2027	data_length = ntohl(ihp->data_length);
2028	ISCSI_IO_LOG(CE_NOTE,
2029	    "DEBUG: iscsi_tx_init_task: task_start: %p idt_tt: %x cmdsn: %x "
2030	    "sess_cmdsn: %x cmd: %p "
2031	    "cmdtype: %d datalen: %u",
2032	    (void *)itp, itp->idt_tt, ihp->cmdsn, icp->conn_sess->sess_cmdsn,
2033	    (void *)icmdp, icmdp->cmd_type, data_length);
2034	if (data_length > 0) {
2035		if (bp->b_flags & B_READ) {
2036			icmdp->cmd_un.scsi.ibp_ibuf =
2037			    idm_buf_alloc(icp->conn_ic,
2038			    bp->b_un.b_addr, bp->b_bcount);
2039			if (icmdp->cmd_un.scsi.ibp_ibuf)
2040				idm_buf_bind_in(itp,
2041				    icmdp->cmd_un.scsi.ibp_ibuf);
2042		} else {
2043			icmdp->cmd_un.scsi.ibp_obuf =
2044			    idm_buf_alloc(icp->conn_ic,
2045			    bp->b_un.b_addr, bp->b_bcount);
2046			if (icmdp->cmd_un.scsi.ibp_obuf)
2047				idm_buf_bind_out(itp,
2048				    icmdp->cmd_un.scsi.ibp_obuf);
2049		}
2050		ISCSI_IO_LOG(CE_NOTE,
2051		    "DEBUG: pdu_tx: task_start(%s): %p ic: %p idt_tt: %x "
2052		    "cmdsn: %x sess_cmdsn: %x sess_expcmdsn: %x obuf: %p "
2053		    "cmdp: %p cmdtype: %d "
2054		    "buflen: %lu " "bpaddr: %p datalen: %u ",
2055		    bp->b_flags & B_READ ? "B_READ" : "B_WRITE",
2056		    (void *)itp, (void *)icp->conn_ic,
2057		    itp->idt_tt, ihp->cmdsn,
2058		    icp->conn_sess->sess_cmdsn,
2059		    icp->conn_sess->sess_expcmdsn,
2060		    (void *)icmdp->cmd_un.scsi.ibp_ibuf,
2061		    (void *)icmdp, icmdp->cmd_type, bp->b_bcount,
2062		    (void *)bp->b_un.b_addr,
2063		    data_length);
2064	}
2065
2066	/*
2067	 * Task is now active
2068	 */
2069	idm_task_start(itp, ISCSI_INI_TASK_TTT);
2070}
2071
2072/*
2073 * iscsi_tx_scsi -
2074 *
2075 */
2076static iscsi_status_t
2077iscsi_tx_scsi(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2078{
2079	iscsi_status_t		rval		= ISCSI_STATUS_SUCCESS;
2080	iscsi_conn_t		*icp		= NULL;
2081	struct scsi_pkt		*pkt		= NULL;
2082	iscsi_scsi_cmd_hdr_t	*ihp		= NULL;
2083	int			cdblen		= 0;
2084	idm_pdu_t		*pdu;
2085	int			len;
2086
2087	ASSERT(isp != NULL);
2088	ASSERT(icmdp != NULL);
2089
2090	pdu = kmem_zalloc(sizeof (idm_pdu_t), KM_SLEEP);
2091
2092	pkt = icmdp->cmd_un.scsi.pkt;
2093	ASSERT(pkt != NULL);
2094	icp = icmdp->cmd_conn;
2095	ASSERT(icp != NULL);
2096
2097	/* Reset counts in case we are on a retry */
2098	icmdp->cmd_un.scsi.data_transferred = 0;
2099
2100	if (icmdp->cmd_un.scsi.cmdlen > DEF_CDB_LEN) {
2101		cdblen = icmdp->cmd_un.scsi.cmdlen;
2102		ihp = kmem_zalloc(ADDLHDRSZ(cdblen), KM_SLEEP);
2103		len = ADDLHDRSZ(cdblen);
2104	} else {
2105		/*
2106		 * only bzero the basic header; the additional header
2107		 * will be set up correctly later, if needed
2108		 */
2109		ihp = kmem_zalloc(sizeof (iscsi_scsi_cmd_hdr_t), KM_SLEEP);
2110		len = sizeof (iscsi_scsi_cmd_hdr_t);
2111	}
2112
2113	iscsi_tx_init_hdr(isp, icp, (iscsi_text_hdr_t *)ihp,
2114	    ISCSI_OP_SCSI_CMD, icmdp);
2115
2116	idm_pdu_init(pdu, icp->conn_ic, (void *)icmdp, &iscsi_tx_done);
2117	idm_pdu_init_hdr(pdu, (uint8_t *)ihp, len);
2118	pdu->isp_data = NULL;
2119	pdu->isp_datalen = 0;
2120
2121	/*
2122	 * Sestion 12.11 of the iSCSI specification has a good table
2123	 * describing when uncolicited data and/or immediate data
2124	 * should be sent.
2125	 */
2126
2127	iscsi_tx_scsi_data(icmdp, ihp, icp, pdu);
2128
2129	iscsi_tx_scsi_init_pkt(icmdp, ihp);
2130
2131	/* Calls idm_task_start */
2132	iscsi_tx_scsi_init_task(icmdp, icp, ihp);
2133
2134	mutex_exit(&isp->sess_queue_pending.mutex);
2135
2136	idm_pdu_tx(pdu);
2137
2138	icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_SENT;
2139
2140	return (rval);
2141}
2142
2143
2144/* ARGSUSED */
2145static void
2146iscsi_tx_done(idm_pdu_t *pdu, idm_status_t status)
2147{
2148	kmem_free((iscsi_hdr_t *)pdu->isp_hdr, pdu->isp_hdrlen);
2149	kmem_free(pdu, sizeof (idm_pdu_t));
2150}
2151
2152
2153static void
2154iscsi_tx_pdu(iscsi_conn_t *icp, int opcode, void *hdr, int hdrlen,
2155    iscsi_cmd_t *icmdp)
2156{
2157	idm_pdu_t	*tx_pdu;
2158	iscsi_hdr_t	*ihp = (iscsi_hdr_t *)hdr;
2159
2160	tx_pdu = kmem_zalloc(sizeof (idm_pdu_t), KM_SLEEP);
2161	ASSERT(tx_pdu != NULL);
2162
2163	idm_pdu_init(tx_pdu, icp->conn_ic, icmdp, &iscsi_tx_done);
2164	idm_pdu_init_hdr(tx_pdu, hdr, hdrlen);
2165	if (opcode == ISCSI_OP_TEXT_CMD) {
2166		idm_pdu_init_data(tx_pdu,
2167		    (uint8_t *)icmdp->cmd_un.text.buf,
2168		    ntoh24(ihp->dlength));
2169	}
2170
2171	mutex_exit(&icp->conn_sess->sess_queue_pending.mutex);
2172	idm_pdu_tx(tx_pdu);
2173	icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_SENT;
2174}
2175
2176
2177/*
2178 * iscsi_tx_nop -
2179 *
2180 */
2181static iscsi_status_t
2182iscsi_tx_nop(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2183{
2184	iscsi_status_t		rval	= ISCSI_STATUS_SUCCESS;
2185	iscsi_conn_t		*icp	= NULL;
2186	iscsi_nop_out_hdr_t	*inohp;
2187
2188	ASSERT(isp != NULL);
2189	ASSERT(icmdp != NULL);
2190	icp = icmdp->cmd_conn;
2191	ASSERT(icp != NULL);
2192
2193	inohp = kmem_zalloc(sizeof (iscsi_nop_out_hdr_t), KM_SLEEP);
2194	ASSERT(inohp != NULL);
2195
2196	inohp->opcode	= ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
2197	inohp->flags	= ISCSI_FLAG_FINAL;
2198	inohp->itt	= icmdp->cmd_itt;
2199	inohp->ttt	= icmdp->cmd_ttt;
2200	mutex_enter(&isp->sess_cmdsn_mutex);
2201	icmdp->cmd_sn	= isp->sess_cmdsn;
2202	inohp->cmdsn	= htonl(isp->sess_cmdsn);
2203	mutex_exit(&isp->sess_cmdsn_mutex);
2204	inohp->expstatsn	= htonl(icp->conn_expstatsn);
2205	icp->conn_laststatsn = icp->conn_expstatsn;
2206	iscsi_tx_pdu(icp, ISCSI_OP_NOOP_OUT, inohp,
2207	    sizeof (iscsi_nop_out_hdr_t), icmdp);
2208	return (rval);
2209}
2210
2211
2212/*
2213 * iscsi_tx_abort -
2214 *
2215 */
2216static iscsi_status_t
2217iscsi_tx_abort(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2218{
2219	iscsi_status_t			rval	= ISCSI_STATUS_SUCCESS;
2220	iscsi_conn_t			*icp	= NULL;
2221	iscsi_scsi_task_mgt_hdr_t	*istmh;
2222
2223	ASSERT(isp != NULL);
2224	ASSERT(icmdp != NULL);
2225	icp = icmdp->cmd_conn;
2226	ASSERT(icp != NULL);
2227
2228	istmh = kmem_zalloc(sizeof (iscsi_scsi_task_mgt_hdr_t), KM_SLEEP);
2229	ASSERT(istmh != NULL);
2230	mutex_enter(&isp->sess_cmdsn_mutex);
2231	icmdp->cmd_sn	= isp->sess_cmdsn;
2232	istmh->cmdsn	= htonl(isp->sess_cmdsn);
2233	mutex_exit(&isp->sess_cmdsn_mutex);
2234	istmh->expstatsn = htonl(icp->conn_expstatsn);
2235	icp->conn_laststatsn = icp->conn_expstatsn;
2236	istmh->itt	= icmdp->cmd_itt;
2237	istmh->opcode	= ISCSI_OP_SCSI_TASK_MGT_MSG | ISCSI_OP_IMMEDIATE;
2238	istmh->function	= ISCSI_FLAG_FINAL | ISCSI_TM_FUNC_ABORT_TASK;
2239	ISCSI_LUN_BYTE_COPY(istmh->lun,
2240	    icmdp->cmd_un.abort.icmdp->cmd_un.scsi.lun);
2241	istmh->rtt	= icmdp->cmd_un.abort.icmdp->cmd_itt;
2242	iscsi_tx_pdu(icp, ISCSI_OP_SCSI_TASK_MGT_MSG, istmh,
2243	    sizeof (iscsi_scsi_task_mgt_hdr_t), icmdp);
2244
2245	return (rval);
2246}
2247
2248
2249/*
2250 * iscsi_tx_reset -
2251 *
2252 */
2253static iscsi_status_t
2254iscsi_tx_reset(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2255{
2256	iscsi_status_t			rval	= ISCSI_STATUS_SUCCESS;
2257	iscsi_conn_t			*icp	= NULL;
2258	iscsi_scsi_task_mgt_hdr_t	*istmh;
2259
2260	ASSERT(isp != NULL);
2261	ASSERT(icmdp != NULL);
2262	icp = icmdp->cmd_conn;
2263	ASSERT(icp != NULL);
2264
2265	istmh = kmem_zalloc(sizeof (iscsi_scsi_task_mgt_hdr_t), KM_SLEEP);
2266	ASSERT(istmh != NULL);
2267	istmh->opcode	= ISCSI_OP_SCSI_TASK_MGT_MSG | ISCSI_OP_IMMEDIATE;
2268	mutex_enter(&isp->sess_cmdsn_mutex);
2269	icmdp->cmd_sn	= isp->sess_cmdsn;
2270	istmh->cmdsn	= htonl(isp->sess_cmdsn);
2271	mutex_exit(&isp->sess_cmdsn_mutex);
2272	istmh->expstatsn	= htonl(icp->conn_expstatsn);
2273	istmh->itt	= icmdp->cmd_itt;
2274
2275	switch (icmdp->cmd_un.reset.level) {
2276	case RESET_LUN:
2277		istmh->function	= ISCSI_FLAG_FINAL |
2278		    ISCSI_TM_FUNC_LOGICAL_UNIT_RESET;
2279		ISCSI_LUN_BYTE_COPY(istmh->lun, icmdp->cmd_lun->lun_num);
2280		break;
2281	case RESET_TARGET:
2282	case RESET_BUS:
2283		istmh->function	= ISCSI_FLAG_FINAL |
2284		    ISCSI_TM_FUNC_TARGET_WARM_RESET;
2285		break;
2286	default:
2287		/* unsupported / unknown level */
2288		ASSERT(FALSE);
2289		break;
2290	}
2291
2292	iscsi_tx_pdu(icp, ISCSI_OP_SCSI_TASK_MGT_MSG, istmh,
2293	    sizeof (iscsi_scsi_task_mgt_hdr_t), icmdp);
2294
2295	return (rval);
2296}
2297
2298
2299/*
2300 * iscsi_tx_logout -
2301 *
2302 */
2303static iscsi_status_t
2304iscsi_tx_logout(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2305{
2306	iscsi_status_t		rval	= ISCSI_STATUS_SUCCESS;
2307	iscsi_conn_t		*icp	= NULL;
2308	iscsi_logout_hdr_t	*ilh;
2309
2310	ASSERT(isp != NULL);
2311	ASSERT(icmdp != NULL);
2312	icp = icmdp->cmd_conn;
2313	ASSERT(icp != NULL);
2314
2315	ilh = kmem_zalloc(sizeof (iscsi_logout_hdr_t), KM_SLEEP);
2316	ilh->opcode	= ISCSI_OP_LOGOUT_CMD | ISCSI_OP_IMMEDIATE;
2317	ilh->flags	= ISCSI_FLAG_FINAL | ISCSI_LOGOUT_REASON_CLOSE_SESSION;
2318	ilh->itt		= icmdp->cmd_itt;
2319	ilh->cid		= icp->conn_cid;
2320	mutex_enter(&isp->sess_cmdsn_mutex);
2321	icmdp->cmd_sn	= isp->sess_cmdsn;
2322	ilh->cmdsn	= htonl(isp->sess_cmdsn);
2323	mutex_exit(&isp->sess_cmdsn_mutex);
2324	ilh->expstatsn	= htonl(icp->conn_expstatsn);
2325	iscsi_tx_pdu(icp, ISCSI_OP_LOGOUT_CMD, ilh,
2326	    sizeof (iscsi_logout_hdr_t), icmdp);
2327
2328	return (rval);
2329}
2330
2331/*
2332 * iscsi_tx_text - setup iSCSI text request header and send PDU with
2333 * data given in the buffer attached to the command.  For a single
2334 * text request, the target may need to send its response in multiple
2335 * text response.  In this case, empty text requests are sent after
2336 * each received response to notify the target the initiator is ready
2337 * for more response.  For the initial request, the data_len field in
2338 * the text specific portion of a command is set to the amount of data
2339 * the initiator wants to send as part of the request. If additional
2340 * empty text requests are required for long responses, the data_len
2341 * field is set to 0 by the iscsi_handle_text function.
2342 */
2343static iscsi_status_t
2344iscsi_tx_text(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2345{
2346	iscsi_status_t		rval	= ISCSI_STATUS_SUCCESS;
2347	iscsi_conn_t		*icp	= NULL;
2348	iscsi_text_hdr_t	*ith;
2349
2350	ASSERT(icmdp != NULL);
2351	icp = icmdp->cmd_conn;
2352	ASSERT(icp != NULL);
2353
2354	ith = kmem_zalloc(sizeof (iscsi_text_hdr_t), KM_SLEEP);
2355	ASSERT(ith != NULL);
2356	ith->flags	= ISCSI_FLAG_FINAL;
2357	hton24(ith->dlength, icmdp->cmd_un.text.data_len);
2358	ith->ttt		= icmdp->cmd_un.text.ttt;
2359	iscsi_tx_init_hdr(isp, icp, (iscsi_text_hdr_t *)ith,
2360	    ISCSI_OP_TEXT_CMD, icmdp);
2361	bcopy(icmdp->cmd_un.text.lun, ith->rsvd4, sizeof (ith->rsvd4));
2362
2363	iscsi_tx_pdu(icp, ISCSI_OP_TEXT_CMD, ith, sizeof (iscsi_text_hdr_t),
2364	    icmdp);
2365
2366	return (rval);
2367}
2368
2369/*
2370 * +--------------------------------------------------------------------+
2371 * | End of protocol send routines					|
2372 * +--------------------------------------------------------------------+
2373 */
2374
2375/*
2376 * iscsi_handle_abort -
2377 *
2378 */
2379void
2380iscsi_handle_abort(void *arg)
2381{
2382	iscsi_sess_t	*isp		= NULL;
2383	iscsi_cmd_t	*icmdp		= (iscsi_cmd_t *)arg;
2384	iscsi_cmd_t	*new_icmdp;
2385	iscsi_conn_t	*icp;
2386
2387	ASSERT(icmdp != NULL);
2388	icp = icmdp->cmd_conn;
2389	ASSERT(icp != NULL);
2390	isp = icp->conn_sess;
2391	ASSERT(isp != NULL);
2392
2393	/* there should only be one abort */
2394	ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
2395
2396	new_icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2397	new_icmdp->cmd_type		    = ISCSI_CMD_TYPE_ABORT;
2398	new_icmdp->cmd_lun		    = icmdp->cmd_lun;
2399	new_icmdp->cmd_un.abort.icmdp	    = icmdp;
2400	new_icmdp->cmd_conn		    = icmdp->cmd_conn;
2401	icmdp->cmd_un.scsi.abort_icmdp	    = new_icmdp;
2402
2403	/* pending queue mutex is already held by timeout_checks */
2404	iscsi_cmd_state_machine(new_icmdp, ISCSI_CMD_EVENT_E1, isp);
2405}
2406
2407/*
2408 * Callback from IDM indicating that the task has been suspended or aborted.
2409 */
2410void
2411iscsi_task_aborted(idm_task_t *idt, idm_status_t status)
2412{
2413	iscsi_cmd_t *icmdp = idt->idt_private;
2414	iscsi_conn_t *icp = icmdp->cmd_conn;
2415	iscsi_sess_t *isp = icp->conn_sess;
2416
2417	ASSERT(icmdp->cmd_conn != NULL);
2418
2419	switch (status) {
2420	case IDM_STATUS_SUSPENDED:
2421		/*
2422		 * If the task is suspended, it may be aborted later,
2423		 * so we can ignore this notification.
2424		 */
2425		break;
2426
2427	case IDM_STATUS_ABORTED:
2428		mutex_enter(&icp->conn_queue_active.mutex);
2429		iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E9, isp);
2430		mutex_exit(&icp->conn_queue_active.mutex);
2431		break;
2432
2433	default:
2434		/*
2435		 * Unexpected status.
2436		 */
2437		ASSERT(0);
2438	}
2439
2440}
2441
2442/*
2443 * iscsi_handle_nop -
2444 *
2445 */
2446static void
2447iscsi_handle_nop(iscsi_conn_t *icp, uint32_t itt, uint32_t ttt)
2448{
2449	iscsi_sess_t	*isp	= NULL;
2450	iscsi_cmd_t	*icmdp	= NULL;
2451
2452	ASSERT(icp != NULL);
2453	isp = icp->conn_sess;
2454	ASSERT(isp != NULL);
2455
2456	icmdp = iscsi_cmd_alloc(icp, KM_NOSLEEP);
2457	if (icmdp == NULL) {
2458		return;
2459	}
2460
2461	icmdp->cmd_type		= ISCSI_CMD_TYPE_NOP;
2462	icmdp->cmd_itt		= itt;
2463	icmdp->cmd_ttt		= ttt;
2464	icmdp->cmd_lun		= NULL;
2465	icp->conn_nop_lbolt	= ddi_get_lbolt();
2466
2467	iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2468}
2469
2470/*
2471 * iscsi_handle_reset - send reset request to the target
2472 *
2473 */
2474iscsi_status_t
2475iscsi_handle_reset(iscsi_sess_t *isp, int level, iscsi_lun_t *ilp)
2476{
2477	iscsi_status_t	rval	= ISCSI_STATUS_SUCCESS;
2478	iscsi_conn_t	*icp;
2479	iscsi_cmd_t	icmd;
2480
2481	ASSERT(isp != NULL);
2482
2483	if (level == RESET_LUN) {
2484		rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2485		ASSERT(ilp != NULL);
2486		if (ilp->lun_state & ISCSI_LUN_STATE_BUSY) {
2487			rw_exit(&isp->sess_lun_list_rwlock);
2488			return (ISCSI_STATUS_SUCCESS);
2489		}
2490		ilp->lun_state |= ISCSI_LUN_STATE_BUSY;
2491		rw_exit(&isp->sess_lun_list_rwlock);
2492	} else {
2493		mutex_enter(&isp->sess_reset_mutex);
2494		if (isp->sess_reset_in_progress == B_TRUE) {
2495			/*
2496			 * If the reset is in progress, it is unnecessary
2497			 * to send reset to the target redunantly.
2498			 */
2499			mutex_exit(&isp->sess_reset_mutex);
2500			return (ISCSI_STATUS_SUCCESS);
2501		}
2502		isp->sess_reset_in_progress = B_TRUE;
2503		mutex_exit(&isp->sess_reset_mutex);
2504	}
2505
2506	bzero(&icmd, sizeof (iscsi_cmd_t));
2507	icmd.cmd_sig		= ISCSI_SIG_CMD;
2508	icmd.cmd_state		= ISCSI_CMD_STATE_FREE;
2509	icmd.cmd_type		= ISCSI_CMD_TYPE_RESET;
2510	icmd.cmd_lun		= ilp;
2511	icmd.cmd_un.reset.level	= level;
2512	icmd.cmd_result		= ISCSI_STATUS_SUCCESS;
2513	icmd.cmd_completed	= B_FALSE;
2514	icmd.cmd_un.reset.response = SCSI_TCP_TM_RESP_COMPLETE;
2515
2516	mutex_init(&icmd.cmd_mutex, NULL, MUTEX_DRIVER, NULL);
2517	cv_init(&icmd.cmd_completion, NULL, CV_DRIVER, NULL);
2518	/*
2519	 * If we received an IO and we are not in the
2520	 * LOGGED_IN state we are in the process of
2521	 * failing.  Just respond that we are BUSY.
2522	 */
2523	mutex_enter(&isp->sess_state_mutex);
2524	if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
2525		/* We aren't connected to the target fake success */
2526		mutex_exit(&isp->sess_state_mutex);
2527
2528		if (level == RESET_LUN) {
2529			rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2530			ilp->lun_state &= ~ISCSI_LUN_STATE_BUSY;
2531			rw_exit(&isp->sess_lun_list_rwlock);
2532		} else {
2533			mutex_enter(&isp->sess_reset_mutex);
2534			isp->sess_reset_in_progress = B_FALSE;
2535			mutex_exit(&isp->sess_reset_mutex);
2536		}
2537
2538		return (ISCSI_STATUS_SUCCESS);
2539	}
2540
2541	mutex_enter(&isp->sess_queue_pending.mutex);
2542	iscsi_cmd_state_machine(&icmd, ISCSI_CMD_EVENT_E1, isp);
2543	mutex_exit(&isp->sess_queue_pending.mutex);
2544	mutex_exit(&isp->sess_state_mutex);
2545
2546	/* stall until completed */
2547	mutex_enter(&icmd.cmd_mutex);
2548	while (icmd.cmd_completed == B_FALSE) {
2549		cv_wait(&icmd.cmd_completion, &icmd.cmd_mutex);
2550	}
2551	mutex_exit(&icmd.cmd_mutex);
2552
2553	/* copy rval */
2554	rval = icmd.cmd_result;
2555
2556	if (rval == ISCSI_STATUS_SUCCESS) {
2557		/*
2558		 * Reset was successful.  We need to flush
2559		 * all active IOs.
2560		 */
2561		rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
2562		icp = isp->sess_conn_list;
2563		while (icp != NULL) {
2564			iscsi_cmd_t *t_icmdp = NULL;
2565			iscsi_cmd_t *next_icmdp = NULL;
2566
2567			mutex_enter(&icp->conn_queue_active.mutex);
2568			t_icmdp = icp->conn_queue_active.head;
2569			while (t_icmdp != NULL) {
2570				next_icmdp = t_icmdp->cmd_next;
2571				mutex_enter(&t_icmdp->cmd_mutex);
2572				if (!(t_icmdp->cmd_misc_flags &
2573				    ISCSI_CMD_MISCFLAG_SENT)) {
2574					/*
2575					 * Although this command is in the
2576					 * active queue, it has not been sent.
2577					 * Skip it.
2578					 */
2579					mutex_exit(&t_icmdp->cmd_mutex);
2580					t_icmdp = next_icmdp;
2581					continue;
2582				}
2583				if (level == RESET_LUN) {
2584					if (icmd.cmd_lun == NULL ||
2585					    t_icmdp->cmd_lun == NULL ||
2586					    (icmd.cmd_lun->lun_num !=
2587					    t_icmdp->cmd_lun->lun_num)) {
2588						mutex_exit(&t_icmdp->cmd_mutex);
2589						t_icmdp = next_icmdp;
2590						continue;
2591					}
2592				}
2593
2594				if (icmd.cmd_sn == t_icmdp->cmd_sn) {
2595					/*
2596					 * This command may be replied with
2597					 * UA sense key later. So currently
2598					 * it is not a suitable time to flush
2599					 * it. Mark its flag with FLUSH. There
2600					 * is no harm to keep it for a while.
2601					 */
2602					t_icmdp->cmd_misc_flags |=
2603					    ISCSI_CMD_MISCFLAG_FLUSH;
2604					if (t_icmdp->cmd_type ==
2605					    ISCSI_CMD_TYPE_SCSI) {
2606						t_icmdp->cmd_un.scsi.pkt_stat |=
2607						    STAT_BUS_RESET;
2608					}
2609					mutex_exit(&t_icmdp->cmd_mutex);
2610				} else if ((icmd.cmd_sn > t_icmdp->cmd_sn) ||
2611				    ((t_icmdp->cmd_sn - icmd.cmd_sn) >
2612				    ISCSI_CMD_SN_WRAP)) {
2613					/*
2614					 * This reset request must act on all
2615					 * the commnds from the same session
2616					 * having a CmdSN lower than the task
2617					 * mangement CmdSN. So flush these
2618					 * commands here.
2619					 */
2620					if (t_icmdp->cmd_type ==
2621					    ISCSI_CMD_TYPE_SCSI) {
2622						t_icmdp->cmd_un.scsi.pkt_stat |=
2623						    STAT_BUS_RESET;
2624					}
2625					mutex_exit(&t_icmdp->cmd_mutex);
2626					iscsi_cmd_state_machine(t_icmdp,
2627					    ISCSI_CMD_EVENT_E7, isp);
2628				} else {
2629					mutex_exit(&t_icmdp->cmd_mutex);
2630				}
2631
2632				t_icmdp = next_icmdp;
2633			}
2634
2635			mutex_exit(&icp->conn_queue_active.mutex);
2636			icp = icp->conn_next;
2637		}
2638		rw_exit(&isp->sess_conn_list_rwlock);
2639	}
2640
2641	/* clean up */
2642	cv_destroy(&icmd.cmd_completion);
2643	mutex_destroy(&icmd.cmd_mutex);
2644
2645	if (level == RESET_LUN) {
2646		rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2647		ilp->lun_state &= ~ISCSI_LUN_STATE_BUSY;
2648		rw_exit(&isp->sess_lun_list_rwlock);
2649	} else {
2650		mutex_enter(&isp->sess_reset_mutex);
2651		isp->sess_reset_in_progress = B_FALSE;
2652		mutex_exit(&isp->sess_reset_mutex);
2653	}
2654
2655	return (rval);
2656}
2657
2658/*
2659 * iscsi_lgoout_start - task handler for deferred logout
2660 */
2661static void
2662iscsi_logout_start(void *arg)
2663{
2664	iscsi_task_t		*itp = (iscsi_task_t *)arg;
2665	iscsi_conn_t		*icp;
2666
2667	icp = (iscsi_conn_t *)itp->t_arg;
2668
2669	mutex_enter(&icp->conn_state_mutex);
2670	(void) iscsi_handle_logout(icp);
2671	mutex_exit(&icp->conn_state_mutex);
2672}
2673
2674/*
2675 * iscsi_handle_logout - This function will issue a logout for
2676 * the session from a specific connection.
2677 */
2678iscsi_status_t
2679iscsi_handle_logout(iscsi_conn_t *icp)
2680{
2681	iscsi_sess_t	*isp;
2682	idm_conn_t	*ic;
2683	iscsi_cmd_t	*icmdp;
2684	int		rval;
2685
2686	ASSERT(icp != NULL);
2687	isp = icp->conn_sess;
2688	ic = icp->conn_ic;
2689	ASSERT(isp != NULL);
2690	ASSERT(isp->sess_hba != NULL);
2691	ASSERT(mutex_owned(&icp->conn_state_mutex));
2692
2693	/*
2694	 * We may want to explicitly disconnect if something goes wrong so
2695	 * grab a hold to ensure that the IDM connection context can't
2696	 * disappear.
2697	 */
2698	idm_conn_hold(ic);
2699
2700	icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2701	ASSERT(icmdp != NULL);
2702	icmdp->cmd_type		= ISCSI_CMD_TYPE_LOGOUT;
2703	icmdp->cmd_result	= ISCSI_STATUS_SUCCESS;
2704	icmdp->cmd_completed	= B_FALSE;
2705
2706	mutex_enter(&isp->sess_queue_pending.mutex);
2707	iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2708	mutex_exit(&isp->sess_queue_pending.mutex);
2709
2710	/*
2711	 * release connection state mutex to avoid a deadlock.  This
2712	 * function is called from within the connection state
2713	 * machine with the lock held.  When the logout response is
2714	 * received another call to the connection state machine
2715	 * occurs which causes the deadlock
2716	 */
2717	mutex_exit(&icp->conn_state_mutex);
2718
2719	/* stall until completed */
2720	mutex_enter(&icmdp->cmd_mutex);
2721	while (icmdp->cmd_completed == B_FALSE) {
2722		cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
2723	}
2724	mutex_exit(&icmdp->cmd_mutex);
2725	mutex_enter(&icp->conn_state_mutex);
2726
2727	/* copy rval */
2728	rval = icmdp->cmd_result;
2729
2730	/* clean up */
2731	iscsi_cmd_free(icmdp);
2732
2733	if (rval != 0) {
2734		/* If the logout failed then drop the connection */
2735		idm_ini_conn_disconnect(icp->conn_ic);
2736	}
2737
2738	/* stall until connection settles */
2739	while ((icp->conn_state != ISCSI_CONN_STATE_FREE) &&
2740	    (icp->conn_state != ISCSI_CONN_STATE_FAILED) &&
2741	    (icp->conn_state != ISCSI_CONN_STATE_POLLING)) {
2742		/* wait for transition */
2743		cv_wait(&icp->conn_state_change, &icp->conn_state_mutex);
2744	}
2745
2746	idm_conn_rele(ic);
2747
2748	/*
2749	 * Return value reflects whether the logout command completed --
2750	 * regardless of the return value the connection is closed and
2751	 * ready for reconnection.
2752	 */
2753	return (rval);
2754}
2755
2756
2757/*
2758 * iscsi_handle_text - main control function for iSCSI text requests.  This
2759 * function handles allocating the command, sending initial text request, and
2760 * handling long response sequence.
2761 * If a data overflow condition occurs, iscsi_handle_text continues to
2762 * receive responses until the all data has been recieved.  This allows
2763 * the full data length to be returned to the caller.
2764 */
2765iscsi_status_t
2766iscsi_handle_text(iscsi_conn_t *icp, char *buf, uint32_t buf_len,
2767    uint32_t data_len, uint32_t *rx_data_len)
2768{
2769	iscsi_sess_t	*isp;
2770	iscsi_cmd_t	*icmdp;
2771	iscsi_status_t	rval	= ISCSI_STATUS_SUCCESS;
2772
2773	ASSERT(icp != NULL);
2774	ASSERT(buf != NULL);
2775	ASSERT(rx_data_len != NULL);
2776
2777	isp = icp->conn_sess;
2778	ASSERT(isp != NULL);
2779
2780	/*
2781	 * Ensure data for text request command is not greater
2782	 * than the negotiated maximum receive data seqment length.
2783	 *
2784	 * Although iSCSI allows for long text requests (multiple
2785	 * pdus), this function places a restriction on text
2786	 * requests to ensure it is handled by a single PDU.
2787	 */
2788	if (data_len > icp->conn_params.max_xmit_data_seg_len) {
2789		return (ISCSI_STATUS_CMD_FAILED);
2790	}
2791
2792	icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2793	ASSERT(icmdp != NULL);
2794
2795	icmdp->cmd_type		= ISCSI_CMD_TYPE_TEXT;
2796	icmdp->cmd_result	= ISCSI_STATUS_SUCCESS;
2797	icmdp->cmd_misc_flags	&= ~ISCSI_CMD_MISCFLAG_FREE;
2798	icmdp->cmd_completed	= B_FALSE;
2799
2800	icmdp->cmd_un.text.buf		= buf;
2801	icmdp->cmd_un.text.buf_len	= buf_len;
2802	icmdp->cmd_un.text.offset	= 0;
2803	icmdp->cmd_un.text.data_len	= data_len;
2804	icmdp->cmd_un.text.total_rx_len	= 0;
2805	icmdp->cmd_un.text.ttt		= ISCSI_RSVD_TASK_TAG;
2806	icmdp->cmd_un.text.stage	= ISCSI_CMD_TEXT_INITIAL_REQ;
2807
2808long_text_response:
2809	mutex_enter(&isp->sess_state_mutex);
2810	if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
2811		iscsi_cmd_free(icmdp);
2812		mutex_exit(&isp->sess_state_mutex);
2813		return (ISCSI_STATUS_NO_CONN_LOGGED_IN);
2814	}
2815
2816	mutex_enter(&isp->sess_queue_pending.mutex);
2817	iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2818	mutex_exit(&isp->sess_queue_pending.mutex);
2819	mutex_exit(&isp->sess_state_mutex);
2820
2821	/* stall until completed */
2822	mutex_enter(&icmdp->cmd_mutex);
2823	while (icmdp->cmd_completed == B_FALSE) {
2824		cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
2825	}
2826	mutex_exit(&icmdp->cmd_mutex);
2827
2828	/*
2829	 * check if error occured.  If data overflow occured, continue on
2830	 * to ensure we get all data so that the full data length can be
2831	 * returned to the user
2832	 */
2833	if ((icmdp->cmd_result != ISCSI_STATUS_SUCCESS) &&
2834	    (icmdp->cmd_result != ISCSI_STATUS_DATA_OVERFLOW)) {
2835		cmn_err(CE_NOTE, "iscsi: SendTarget discovery failed (%d)",
2836		    icmdp->cmd_result);
2837		rval = icmdp->cmd_result;
2838		iscsi_cmd_free(icmdp);
2839		return (rval);
2840	}
2841
2842	/* check if this was a partial text PDU  */
2843	if (icmdp->cmd_un.text.stage != ISCSI_CMD_TEXT_FINAL_RSP) {
2844		/*
2845		 * If a paritial text rexponse received, send an empty
2846		 * text request.  This follows the behaviour specified
2847		 * in RFC3720 regarding long text responses.
2848		 */
2849		icmdp->cmd_misc_flags		&= ~ISCSI_CMD_MISCFLAG_FREE;
2850		icmdp->cmd_completed		= B_FALSE;
2851		icmdp->cmd_un.text.data_len	= 0;
2852		icmdp->cmd_un.text.stage	= ISCSI_CMD_TEXT_CONTINUATION;
2853		goto long_text_response;
2854	}
2855
2856	/*
2857	 * set total received data length.  If data overflow this would be
2858	 * amount of data that would have been received if buffer large
2859	 * enough.
2860	 */
2861	*rx_data_len = icmdp->cmd_un.text.total_rx_len;
2862
2863	/* copy rval */
2864	rval = icmdp->cmd_result;
2865
2866	/* clean up  */
2867	iscsi_cmd_free(icmdp);
2868
2869	return (rval);
2870}
2871
2872/*
2873 * iscsi_handle_passthru - This function is used to send a uscsi_cmd
2874 * to a specific target lun.  This routine is used for internal purposes
2875 * during enumeration and via the ISCSI_USCSICMD IOCTL.  We restrict
2876 * the CDBs that can be issued to a target/lun to INQUIRY, REPORT_LUNS,
2877 * and READ_CAPACITY for security purposes.
2878 *
2879 * The logic here is broken into three phases.
2880 * 1) Allocate and initialize a pkt/icmdp
2881 * 2) Send the pkt/icmdp
2882 * 3) cv_wait for completion
2883 */
2884iscsi_status_t
2885iscsi_handle_passthru(iscsi_sess_t *isp, uint16_t lun, struct uscsi_cmd *ucmdp)
2886{
2887	iscsi_status_t		rval		= ISCSI_STATUS_SUCCESS;
2888	iscsi_cmd_t		*icmdp		= NULL;
2889	struct scsi_pkt		*pkt		= NULL;
2890	struct buf		*bp		= NULL;
2891	struct scsi_arq_status  *arqstat	= NULL;
2892	int			rqlen		= SENSE_LENGTH;
2893
2894	ASSERT(isp != NULL);
2895	ASSERT(ucmdp != NULL);
2896
2897	/*
2898	 * If the caller didn't provide a sense buffer we need
2899	 * to allocation one to get the scsi status.
2900	 */
2901	if (ucmdp->uscsi_rqlen > SENSE_LENGTH) {
2902		rqlen = ucmdp->uscsi_rqlen;
2903	}
2904
2905	/*
2906	 * Step 1. Setup structs - KM_SLEEP will always succeed
2907	 */
2908	bp = kmem_zalloc(sizeof (struct buf), KM_SLEEP);
2909	ASSERT(bp != NULL);
2910	pkt = kmem_zalloc(sizeof (struct scsi_pkt), KM_SLEEP);
2911	ASSERT(pkt != NULL);
2912	icmdp = iscsi_cmd_alloc(NULL, KM_SLEEP);
2913	ASSERT(icmdp != NULL);
2914
2915	/* setup bp structure */
2916	bp->b_flags		= B_READ;
2917	bp->b_bcount		= ucmdp->uscsi_buflen;
2918	bp->b_un.b_addr		= ucmdp->uscsi_bufaddr;
2919
2920	/* setup scsi_pkt structure */
2921	pkt->pkt_ha_private	= icmdp;
2922	pkt->pkt_scbp		= kmem_zalloc(rqlen, KM_SLEEP);
2923	pkt->pkt_cdbp		= kmem_zalloc(ucmdp->uscsi_cdblen, KM_SLEEP);
2924	/* callback routine for passthru, will wake cv_wait */
2925	pkt->pkt_comp		= iscsi_handle_passthru_callback;
2926	pkt->pkt_time		= ucmdp->uscsi_timeout;
2927
2928	/* setup iscsi_cmd structure */
2929	icmdp->cmd_lun			= NULL;
2930	icmdp->cmd_type			= ISCSI_CMD_TYPE_SCSI;
2931	icmdp->cmd_un.scsi.lun		= lun;
2932	icmdp->cmd_un.scsi.pkt		= pkt;
2933	icmdp->cmd_un.scsi.bp		= bp;
2934	bcopy(ucmdp->uscsi_cdb, pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
2935	icmdp->cmd_un.scsi.cmdlen	= ucmdp->uscsi_cdblen;
2936	icmdp->cmd_un.scsi.statuslen	= rqlen;
2937	icmdp->cmd_crc_error_seen	= B_FALSE;
2938	icmdp->cmd_completed		= B_FALSE;
2939	icmdp->cmd_result		= ISCSI_STATUS_SUCCESS;
2940
2941	/*
2942	 * Step 2. Push IO onto pending queue.  If we aren't in
2943	 * FULL_FEATURE we need to fail the IO.
2944	 */
2945	mutex_enter(&isp->sess_state_mutex);
2946	if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
2947		mutex_exit(&isp->sess_state_mutex);
2948
2949		iscsi_cmd_free(icmdp);
2950		kmem_free(pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
2951		kmem_free(pkt->pkt_scbp, rqlen);
2952		kmem_free(pkt, sizeof (struct scsi_pkt));
2953		kmem_free(bp, sizeof (struct buf));
2954
2955		return (ISCSI_STATUS_CMD_FAILED);
2956	}
2957
2958	mutex_enter(&isp->sess_queue_pending.mutex);
2959	iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2960	mutex_exit(&isp->sess_queue_pending.mutex);
2961	mutex_exit(&isp->sess_state_mutex);
2962
2963	/*
2964	 * Step 3. Wait on cv_wait for completion routine
2965	 */
2966	mutex_enter(&icmdp->cmd_mutex);
2967	while (icmdp->cmd_completed == B_FALSE) {
2968		cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
2969	}
2970	mutex_exit(&icmdp->cmd_mutex);
2971
2972	/* copy rval */
2973	rval = icmdp->cmd_result;
2974
2975	ucmdp->uscsi_resid = pkt->pkt_resid;
2976
2977	/* update scsi status */
2978	arqstat = (struct scsi_arq_status *)pkt->pkt_scbp;
2979	ucmdp->uscsi_status = ((char *)&arqstat->sts_status)[0];
2980
2981	/* copy request sense buffers if caller gave space */
2982	if ((ucmdp->uscsi_rqlen > 0) &&
2983	    (ucmdp->uscsi_rqbuf != NULL)) {
2984		bcopy(arqstat, ucmdp->uscsi_rqbuf,
2985		    MIN(sizeof (struct scsi_arq_status), rqlen));
2986	}
2987
2988	/* clean up */
2989	iscsi_cmd_free(icmdp);
2990	kmem_free(pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
2991	kmem_free(pkt->pkt_scbp, rqlen);
2992	kmem_free(pkt, sizeof (struct scsi_pkt));
2993	kmem_free(bp, sizeof (struct buf));
2994
2995	return (rval);
2996}
2997
2998
2999/*
3000 * iscsi_handle_passthru_callback -
3001 *
3002 */
3003static void
3004iscsi_handle_passthru_callback(struct scsi_pkt *pkt)
3005{
3006	iscsi_cmd_t		*icmdp  = NULL;
3007
3008	ASSERT(pkt != NULL);
3009	icmdp = (iscsi_cmd_t *)pkt->pkt_ha_private;
3010	ASSERT(icmdp != NULL);
3011
3012	mutex_enter(&icmdp->cmd_mutex);
3013	icmdp->cmd_completed    = B_TRUE;
3014	icmdp->cmd_result	= ISCSI_STATUS_SUCCESS;
3015	cv_broadcast(&icmdp->cmd_completion);
3016	mutex_exit(&icmdp->cmd_mutex);
3017
3018}
3019
3020/*
3021 * IDM callbacks
3022 */
3023void
3024iscsi_build_hdr(idm_task_t *idm_task, idm_pdu_t *pdu, uint8_t opcode)
3025{
3026	iscsi_cmd_t *icmdp = idm_task->idt_private;
3027	iscsi_conn_t *icp = icmdp->cmd_conn;
3028	iscsi_data_hdr_t *ihp = (iscsi_data_hdr_t *)pdu->isp_hdr;
3029
3030	mutex_enter(&icmdp->cmd_mutex);
3031	if (opcode == ISCSI_OP_SCSI_DATA) {
3032		uint32_t	data_sn;
3033		uint32_t	lun;
3034		icmdp = idm_task->idt_private;
3035		icp = icmdp->cmd_conn;
3036		ihp->opcode	= opcode;
3037		ihp->itt	= icmdp->cmd_itt;
3038		ihp->ttt	= idm_task->idt_r2t_ttt;
3039		ihp->expstatsn	= htonl(icp->conn_expstatsn);
3040		icp->conn_laststatsn = icp->conn_expstatsn;
3041		data_sn = ntohl(ihp->datasn);
3042		data_sn++;
3043		lun = icmdp->cmd_un.scsi.lun;
3044		ISCSI_LUN_BYTE_COPY(ihp->lun, lun);
3045		/* CRM: upate_flow_control */
3046		ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_build_hdr"
3047		    "(ISCSI_OP_SCSI_DATA): task: %p icp: %p ic: %p itt: %x "
3048		    "exp: %d data_sn: %d", (void *)idm_task, (void *)icp,
3049		    (void *)icp->conn_ic, ihp->itt, icp->conn_expstatsn,
3050		    data_sn);
3051	} else {
3052		cmn_err(CE_WARN, "iscsi_build_hdr: unprocessed build "
3053		    "header opcode: %x", opcode);
3054	}
3055	mutex_exit(&icmdp->cmd_mutex);
3056}
3057
3058static void
3059iscsi_process_rsp_status(iscsi_sess_t *isp, iscsi_conn_t *icp,
3060    idm_status_t status)
3061{
3062	switch (status) {
3063	case IDM_STATUS_SUCCESS:
3064		if ((isp->sess_state == ISCSI_SESS_STATE_IN_FLUSH) &&
3065		    (icp->conn_queue_active.count == 0)) {
3066			iscsi_drop_conn_cleanup(icp);
3067		}
3068		break;
3069	case IDM_STATUS_PROTOCOL_ERROR:
3070		KSTAT_INC_CONN_ERR_PROTOCOL(icp);
3071		iscsi_drop_conn_cleanup(icp);
3072		break;
3073	default:
3074		break;
3075	}
3076}
3077
3078static void
3079iscsi_drop_conn_cleanup(iscsi_conn_t *icp) {
3080	mutex_enter(&icp->conn_state_mutex);
3081	idm_ini_conn_disconnect(icp->conn_ic);
3082	mutex_exit(&icp->conn_state_mutex);
3083}
3084
3085void
3086iscsi_rx_error_pdu(idm_conn_t *ic, idm_pdu_t *pdu, idm_status_t status)
3087{
3088	iscsi_conn_t *icp = (iscsi_conn_t *)ic->ic_handle;
3089	iscsi_sess_t *isp;
3090
3091	ASSERT(icp != NULL);
3092	isp = icp->conn_sess;
3093	ASSERT(isp != NULL);
3094	iscsi_process_rsp_status(isp, icp, status);
3095	idm_pdu_complete(pdu, status);
3096}
3097
3098void
3099iscsi_rx_misc_pdu(idm_conn_t *ic, idm_pdu_t *pdu)
3100{
3101	iscsi_conn_t 		*icp;
3102	iscsi_hdr_t		*ihp	= (iscsi_hdr_t *)pdu->isp_hdr;
3103	iscsi_sess_t		*isp;
3104	idm_status_t		status;
3105
3106	icp = ic->ic_handle;
3107	isp = icp->conn_sess;
3108	isp->sess_rx_lbolt = icp->conn_rx_lbolt = ddi_get_lbolt();
3109	switch (ihp->opcode & ISCSI_OPCODE_MASK) {
3110	case ISCSI_OP_LOGIN_RSP:
3111		status = iscsi_rx_process_login_pdu(ic, pdu);
3112		idm_pdu_complete(pdu, status);
3113		break;
3114	case ISCSI_OP_LOGOUT_RSP:
3115		status = iscsi_rx_process_logout_rsp(ic, pdu);
3116		idm_pdu_complete(pdu, status);
3117		break;
3118	case ISCSI_OP_REJECT_MSG:
3119		status = iscsi_rx_process_reject_rsp(ic, pdu);
3120		break;
3121	case ISCSI_OP_SCSI_TASK_MGT_RSP:
3122		status = iscsi_rx_process_task_mgt_rsp(ic, pdu);
3123		idm_pdu_complete(pdu, status);
3124		break;
3125	case ISCSI_OP_NOOP_IN:
3126		status = iscsi_rx_process_nop(ic, pdu);
3127		idm_pdu_complete(pdu, status);
3128		break;
3129	case ISCSI_OP_ASYNC_EVENT:
3130		status = iscsi_rx_process_async_rsp(ic, pdu);
3131		break;
3132	case ISCSI_OP_TEXT_RSP:
3133		status = iscsi_rx_process_text_rsp(ic, pdu);
3134		idm_pdu_complete(pdu, status);
3135		break;
3136	default:
3137		cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
3138		    "- received misc unsupported opcode 0x%02x",
3139		    icp->conn_oid, ihp->opcode);
3140		status = IDM_STATUS_PROTOCOL_ERROR;
3141		break;
3142	}
3143	iscsi_process_rsp_status(isp, icp, status);
3144}
3145
3146/*
3147 * +--------------------------------------------------------------------+
3148 * | Beginning of completion routines					|
3149 * +--------------------------------------------------------------------+
3150 */
3151
3152/*
3153 * iscsi_ic_thread -
3154 */
3155void
3156iscsi_ic_thread(iscsi_thread_t *thread, void *arg)
3157{
3158	iscsi_sess_t	*isp = (iscsi_sess_t *)arg;
3159	int		ret;
3160	iscsi_queue_t	q;
3161	iscsi_cmd_t	*icmdp;
3162	iscsi_cmd_t	*next_icmdp;
3163
3164	ASSERT(isp != NULL);
3165	ASSERT(thread != NULL);
3166	ASSERT(thread->signature == SIG_ISCSI_THREAD);
3167
3168	for (;;) {
3169
3170		/*
3171		 * We wait till iodone or somebody else wakes us up.
3172		 */
3173		ret = iscsi_thread_wait(thread, -1);
3174
3175		/*
3176		 * The value should never be negative since we never timeout.
3177		 */
3178		ASSERT(ret >= 0);
3179
3180		q.count = 0;
3181		q.head  = NULL;
3182		q.tail  = NULL;
3183		mutex_enter(&isp->sess_queue_completion.mutex);
3184		icmdp = isp->sess_queue_completion.head;
3185		while (icmdp != NULL) {
3186			next_icmdp = icmdp->cmd_next;
3187			mutex_enter(&icmdp->cmd_mutex);
3188			/*
3189			 * check if the associated r2t/abort has finished
3190			 * yet.  If not, don't complete the command.
3191			 */
3192			if ((icmdp->cmd_un.scsi.r2t_icmdp == NULL) &&
3193			    (icmdp->cmd_un.scsi.abort_icmdp == NULL)) {
3194				mutex_exit(&icmdp->cmd_mutex);
3195				(void) iscsi_dequeue_cmd(&isp->
3196				    sess_queue_completion.head,
3197				    &isp->sess_queue_completion.tail,
3198				    icmdp);
3199				--isp->sess_queue_completion.count;
3200				iscsi_enqueue_cmd_head(&q.head,
3201				    &q.tail, icmdp);
3202			} else {
3203				mutex_exit(&icmdp->cmd_mutex);
3204			}
3205			icmdp = next_icmdp;
3206		}
3207		mutex_exit(&isp->sess_queue_completion.mutex);
3208		icmdp = q.head;
3209		while (icmdp != NULL) {
3210			next_icmdp = icmdp->cmd_next;
3211			iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E8, isp);
3212			icmdp = next_icmdp;
3213		}
3214
3215		if (ret > 0)
3216			/* Somebody woke us up to work */
3217			continue;
3218		else
3219			/*
3220			 * Somebody woke us up to kill ourselves. We will
3221			 * make sure, however that the completion queue is
3222			 * empty before leaving.  After we've done that it
3223			 * is the originator of the signal that has to make
3224			 * sure no other SCSI command is posted.
3225			 */
3226			break;
3227	}
3228
3229}
3230
3231/*
3232 * iscsi_iodone -
3233 *
3234 */
3235void
3236iscsi_iodone(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
3237{
3238	struct scsi_pkt		*pkt	= NULL;
3239	struct buf		*bp	= icmdp->cmd_un.scsi.bp;
3240
3241	ASSERT(isp != NULL);
3242	ASSERT(icmdp != NULL);
3243	pkt = icmdp->cmd_un.scsi.pkt;
3244	ASSERT(pkt != NULL);
3245
3246	ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
3247	ASSERT(icmdp->cmd_un.scsi.r2t_icmdp == NULL);
3248	if (pkt->pkt_reason == CMD_CMPLT) {
3249		if (bp) {
3250			if (bp->b_flags & B_READ) {
3251				KSTAT_SESS_RX_IO_DONE(isp, bp->b_bcount);
3252			} else {
3253				KSTAT_SESS_TX_IO_DONE(isp, bp->b_bcount);
3254			}
3255		}
3256	}
3257
3258	if (pkt->pkt_flags & FLAG_NOINTR) {
3259		cv_broadcast(&icmdp->cmd_completion);
3260		mutex_exit(&icmdp->cmd_mutex);
3261	} else {
3262		/*
3263		 * Release mutex.  As soon as callback is
3264		 * issued the caller may destroy the command.
3265		 */
3266		mutex_exit(&icmdp->cmd_mutex);
3267		/*
3268		 * We can't just directly call the pk_comp routine.  In
3269		 * many error cases the target driver will use the calling
3270		 * thread to re-drive error handling (reset, retries...)
3271		 * back into the hba driver (iscsi).  If the target redrives
3272		 * a reset back into the iscsi driver off this thead we have
3273		 * a chance of deadlocking. So instead use the io completion
3274		 * thread.
3275		 */
3276		(*icmdp->cmd_un.scsi.pkt->pkt_comp)(icmdp->cmd_un.scsi.pkt);
3277	}
3278}
3279
3280/*
3281 * +--------------------------------------------------------------------+
3282 * | End of completion routines						|
3283 * +--------------------------------------------------------------------+
3284 */
3285
3286/*
3287 * +--------------------------------------------------------------------+
3288 * | Beginning of watchdog routines					|
3289 * +--------------------------------------------------------------------+
3290 */
3291
3292/*
3293 * iscsi_watchdog_thread -
3294 *
3295 */
3296void
3297iscsi_wd_thread(iscsi_thread_t *thread, void *arg)
3298{
3299	iscsi_sess_t	*isp = (iscsi_sess_t *)arg;
3300	int		rc = 1;
3301
3302	ASSERT(isp != NULL);
3303
3304	while (rc != NULL) {
3305
3306		iscsi_timeout_checks(isp);
3307		iscsi_nop_checks(isp);
3308
3309		rc = iscsi_thread_wait(thread, SEC_TO_TICK(1));
3310	}
3311}
3312
3313/*
3314 * iscsi_timeout_checks -
3315 *
3316 */
3317static void
3318iscsi_timeout_checks(iscsi_sess_t *isp)
3319{
3320	clock_t		now = ddi_get_lbolt();
3321	iscsi_conn_t	*icp;
3322	iscsi_cmd_t	*icmdp, *nicmdp;
3323
3324	ASSERT(isp != NULL);
3325
3326	/* PENDING */
3327	mutex_enter(&isp->sess_state_mutex);
3328	mutex_enter(&isp->sess_queue_pending.mutex);
3329	for (icmdp = isp->sess_queue_pending.head;
3330	    icmdp; icmdp = nicmdp) {
3331		nicmdp = icmdp->cmd_next;
3332
3333		/* Skip entries with no timeout */
3334		if (icmdp->cmd_lbolt_timeout == 0)
3335			continue;
3336
3337		/*
3338		 * Skip pending queue entries for cmd_type values that depend
3339		 * on having an open cmdsn window for successfull transition
3340		 * from pending to the active (i.e. ones that depend on
3341		 * sess_cmdsn .vs. sess_maxcmdsn). For them, the timer starts
3342		 * when they are successfully moved to the active queue by
3343		 * iscsi_cmd_state_pending() code.
3344		 */
3345		/*
3346		 * If the cmd is stuck, at least give it a chance
3347		 * to timeout
3348		 */
3349		if (((icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) ||
3350		    (icmdp->cmd_type == ISCSI_CMD_TYPE_TEXT)) &&
3351		    !(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_STUCK))
3352			continue;
3353
3354		/* Skip if timeout still in the future */
3355		if (now <= icmdp->cmd_lbolt_timeout)
3356			continue;
3357
3358		/* timeout */
3359		iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E6, isp);
3360	}
3361	mutex_exit(&isp->sess_queue_pending.mutex);
3362	mutex_exit(&isp->sess_state_mutex);
3363
3364	rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
3365	icp = isp->sess_conn_list;
3366	while (icp != NULL) {
3367
3368		icp->conn_timeout = B_FALSE;
3369		/* ACTIVE */
3370		mutex_enter(&icp->conn_state_mutex);
3371		mutex_enter(&isp->sess_queue_pending.mutex);
3372		mutex_enter(&icp->conn_queue_active.mutex);
3373		for (icmdp = icp->conn_queue_active.head;
3374		    icmdp; icmdp = nicmdp) {
3375			nicmdp = icmdp->cmd_next;
3376
3377			if (iscsi_nop_timeout_checks(icmdp) == B_TRUE) {
3378				icp->conn_timeout = B_TRUE;
3379			}
3380
3381			/* Skip entries with no timeout */
3382			if (icmdp->cmd_lbolt_timeout == 0)
3383				continue;
3384
3385			/*
3386			 * Skip if command is not active or not needed
3387			 * to flush.
3388			 */
3389			if (icmdp->cmd_state != ISCSI_CMD_STATE_ACTIVE &&
3390			    !(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_FLUSH))
3391				continue;
3392
3393			/* Skip if timeout still in the future */
3394			if (now <= icmdp->cmd_lbolt_timeout)
3395				continue;
3396
3397			if (icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_FLUSH) {
3398				/*
3399				 * This command is left during target reset,
3400				 * we can flush it now.
3401				 */
3402				iscsi_cmd_state_machine(icmdp,
3403				    ISCSI_CMD_EVENT_E7, isp);
3404			} else if (icmdp->cmd_state == ISCSI_CMD_STATE_ACTIVE) {
3405				/* timeout */
3406				iscsi_cmd_state_machine(icmdp,
3407				    ISCSI_CMD_EVENT_E6, isp);
3408			}
3409
3410		}
3411		mutex_exit(&icp->conn_queue_active.mutex);
3412		mutex_exit(&isp->sess_queue_pending.mutex);
3413		mutex_exit(&icp->conn_state_mutex);
3414
3415		icp = icp->conn_next;
3416	}
3417
3418	icp = isp->sess_conn_list;
3419	while (icp != NULL) {
3420		if (icp->conn_timeout == B_TRUE) {
3421			/* timeout on this connect detected */
3422			idm_ini_conn_disconnect(icp->conn_ic);
3423			icp->conn_timeout = B_FALSE;
3424		}
3425		icp = icp->conn_next;
3426	}
3427	rw_exit(&isp->sess_conn_list_rwlock);
3428}
3429
3430/*
3431 * iscsi_nop_checks - sends a NOP on idle connections
3432 *
3433 * This function walks the connections on a session and
3434 * issues NOPs on those connections that are in FULL
3435 * FEATURE mode and have not received data for the
3436 * time period specified by iscsi_nop_delay (global).
3437 */
3438static void
3439iscsi_nop_checks(iscsi_sess_t *isp)
3440{
3441	iscsi_conn_t	*icp;
3442
3443	ASSERT(isp != NULL);
3444
3445	if (isp->sess_type == ISCSI_SESS_TYPE_DISCOVERY) {
3446		return;
3447	}
3448
3449	rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
3450	icp = isp->sess_conn_act;
3451	if (icp != NULL) {
3452
3453		mutex_enter(&icp->conn_state_mutex);
3454		if ((ISCSI_CONN_STATE_FULL_FEATURE(icp->conn_state)) &&
3455		    (ddi_get_lbolt() > isp->sess_conn_act->conn_rx_lbolt +
3456		    SEC_TO_TICK(iscsi_nop_delay)) && (ddi_get_lbolt() >
3457		    isp->sess_conn_act->conn_nop_lbolt +
3458		    SEC_TO_TICK(iscsi_nop_delay))) {
3459
3460			/*
3461			 * We haven't received anything from the
3462			 * target is a defined period of time,
3463			 * send NOP to see if the target is alive.
3464			 */
3465			mutex_enter(&isp->sess_queue_pending.mutex);
3466			iscsi_handle_nop(isp->sess_conn_act,
3467			    0, ISCSI_RSVD_TASK_TAG);
3468			mutex_exit(&isp->sess_queue_pending.mutex);
3469		}
3470		mutex_exit(&icp->conn_state_mutex);
3471
3472		icp = icp->conn_next;
3473	}
3474	rw_exit(&isp->sess_conn_list_rwlock);
3475}
3476
3477static boolean_t
3478iscsi_nop_timeout_checks(iscsi_cmd_t *icmdp)
3479{
3480	if (icmdp->cmd_type == ISCSI_CMD_TYPE_NOP) {
3481		if ((ddi_get_lbolt() - icmdp->cmd_lbolt_active) >
3482		    SEC_TO_TICK(ISCSI_CONN_TIEMOUT_DETECT)) {
3483			return (B_TRUE);
3484		} else {
3485			return (B_FALSE);
3486		}
3487	}
3488	return (B_FALSE);
3489}
3490/*
3491 * +--------------------------------------------------------------------+
3492 * | End of wd routines						|
3493 * +--------------------------------------------------------------------+
3494 */
3495
3496/*
3497 * iscsi_flush_cmd_after_reset - flush commands after reset
3498 *
3499 * Here we will flush all the commands in the same connection whose cmdsn is
3500 * less than the one received with the Unit Attention.
3501 */
3502static void
3503iscsi_flush_cmd_after_reset(uint32_t cmd_sn, uint16_t lun_num,
3504    iscsi_conn_t *icp)
3505{
3506	iscsi_cmd_t	*t_icmdp    = NULL;
3507	iscsi_cmd_t	*next_icmdp = NULL;
3508
3509	ASSERT(icp != NULL);
3510
3511	t_icmdp = icp->conn_queue_active.head;
3512	while (t_icmdp != NULL) {
3513		next_icmdp = t_icmdp->cmd_next;
3514		mutex_enter(&t_icmdp->cmd_mutex);
3515		/*
3516		 * We will flush the commands whose cmdsn is less than the one
3517		 * got Unit Attention.
3518		 * Here we will check for wrap by subtracting and compare to
3519		 * 1/2 of a 32 bit number, if greater then we wrapped.
3520		 */
3521		if ((t_icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_SENT) &&
3522		    ((cmd_sn > t_icmdp->cmd_sn) ||
3523		    ((t_icmdp->cmd_sn - cmd_sn) >
3524		    ISCSI_CMD_SN_WRAP))) {
3525			if (t_icmdp->cmd_lun != NULL &&
3526			    t_icmdp->cmd_lun->lun_num == lun_num) {
3527				t_icmdp->cmd_misc_flags |=
3528				    ISCSI_CMD_MISCFLAG_FLUSH;
3529				if (t_icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
3530					t_icmdp->cmd_un.scsi.pkt_stat |=
3531					    STAT_BUS_RESET;
3532				}
3533			}
3534		}
3535		mutex_exit(&t_icmdp->cmd_mutex);
3536		t_icmdp = next_icmdp;
3537	}
3538}
3539
3540/*
3541 * iscsi_decode_sense - decode the sense data in the cmd response
3542 *
3543 * Here we only care about Unit Attention with 0x29.
3544 */
3545static boolean_t
3546iscsi_decode_sense(uint8_t *sense_data)
3547{
3548	uint8_t	sense_key   = 0;
3549	uint8_t	asc	    = 0;
3550	boolean_t affect    = B_FALSE;
3551
3552	ASSERT(sense_data != NULL);
3553
3554	sense_key = scsi_sense_key(sense_data);
3555	switch (sense_key) {
3556		case KEY_UNIT_ATTENTION:
3557			asc = scsi_sense_asc(sense_data);
3558			switch (asc) {
3559				case ISCSI_SCSI_RESET_SENSE_CODE:
3560					/*
3561					 * POWER ON, RESET, OR BUS_DEVICE RESET
3562					 * OCCURRED
3563					 */
3564					affect = B_TRUE;
3565					break;
3566				default:
3567					/*
3568					 * Currently we don't care
3569					 * about other sense key.
3570					 */
3571					break;
3572			}
3573			break;
3574		default:
3575			/*
3576			 * Currently we don't care
3577			 * about other sense key.
3578			 */
3579			break;
3580	}
3581	return (affect);
3582}
3583