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