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