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