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