1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte /*
2230e7468fSPeter Dunlap  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23fcf3ce44SJohn Forte  * Use is subject to license terms.
24fcf3ce44SJohn Forte  *
25fcf3ce44SJohn Forte  * iSCSI command interfaces
26fcf3ce44SJohn Forte  */
27fcf3ce44SJohn Forte 
28fcf3ce44SJohn Forte #include "iscsi.h"
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte /* internal interfaces */
31fcf3ce44SJohn Forte static void iscsi_cmd_state_free(iscsi_cmd_t *icmdp,
32fcf3ce44SJohn Forte     iscsi_cmd_event_t event, void *arg);
33fcf3ce44SJohn Forte static void iscsi_cmd_state_pending(iscsi_cmd_t *icmdp,
34fcf3ce44SJohn Forte     iscsi_cmd_event_t event, void *arg);
35fcf3ce44SJohn Forte static void iscsi_cmd_state_active(iscsi_cmd_t *icmdp,
36fcf3ce44SJohn Forte     iscsi_cmd_event_t event, void *arg);
37fcf3ce44SJohn Forte static void iscsi_cmd_state_aborting(iscsi_cmd_t *icmdp,
38fcf3ce44SJohn Forte     iscsi_cmd_event_t event, void *arg);
3930e7468fSPeter Dunlap static void iscsi_cmd_state_idm_aborting(iscsi_cmd_t *icmdp,
4030e7468fSPeter Dunlap     iscsi_cmd_event_t event, void *arg);
41fcf3ce44SJohn Forte static void iscsi_cmd_state_completed(iscsi_cmd_t *icmdp,
42fcf3ce44SJohn Forte     iscsi_cmd_event_t event, void *arg);
43fcf3ce44SJohn Forte static char *iscsi_cmd_state_str(iscsi_cmd_state_t state);
44fcf3ce44SJohn Forte static char *iscsi_cmd_event_str(iscsi_cmd_event_t event);
45fcf3ce44SJohn Forte /* LINTED E_STATIC_UNUSED */
46fcf3ce44SJohn Forte static char *iscsi_cmd_type_str(iscsi_cmd_type_t type);
47fcf3ce44SJohn Forte 
48fcf3ce44SJohn Forte #define	ISCSI_INTERNAL_CMD_TIMEOUT	60
49fcf3ce44SJohn Forte 
50fcf3ce44SJohn Forte #define	ISCSI_CMD_ISSUE_CALLBACK(icmdp, status)	\
51fcf3ce44SJohn Forte 	icmdp->cmd_completed = B_TRUE;		\
52fcf3ce44SJohn Forte 	icmdp->cmd_result = status;		\
53fcf3ce44SJohn Forte 	cv_broadcast(&icmdp->cmd_completion);
54fcf3ce44SJohn Forte 
55fcf3ce44SJohn Forte #define	ISCSI_CMD_SET_REASON_STAT(icmdp, reason, stat)	\
56fcf3ce44SJohn Forte 	icmdp->cmd_un.scsi.pkt->pkt_reason = reason;	\
57fcf3ce44SJohn Forte 	icmdp->cmd_un.scsi.pkt->pkt_statistics = stat;
58fcf3ce44SJohn Forte 
59fcf3ce44SJohn Forte /*
60fcf3ce44SJohn Forte  * The following private tunable, settable via
61fcf3ce44SJohn Forte  *	set iscsi:iscsi_cmd_timeout_factor = 2
62fcf3ce44SJohn Forte  * in /etc/system, provides customer relief for configurations experiencing
63fcf3ce44SJohn Forte  * SCSI command timeouts due to high-latency/high-loss network connections
64fcf3ce44SJohn Forte  * or slow target response (possibly due to backing store issues). If frequent
65fcf3ce44SJohn Forte  * use of this tunable is necessary, a beter mechanism must be provided.
66fcf3ce44SJohn Forte  */
67fcf3ce44SJohn Forte int	iscsi_cmd_timeout_factor = 1;
68fcf3ce44SJohn Forte 
69fcf3ce44SJohn Forte /*
70fcf3ce44SJohn Forte  * +--------------------------------------------------------------------+
71fcf3ce44SJohn Forte  * | External Command Interfaces					|
72fcf3ce44SJohn Forte  * +--------------------------------------------------------------------+
73fcf3ce44SJohn Forte  */
74fcf3ce44SJohn Forte 
75fcf3ce44SJohn Forte /*
76fcf3ce44SJohn Forte  * iscsi_cmd_state_machine - This function is used to drive the
77fcf3ce44SJohn Forte  * state machine of the internal iscsi commands.  It takes in a command
78fcf3ce44SJohn Forte  * and the associated event affecting the command.
79fcf3ce44SJohn Forte  *
80fcf3ce44SJohn Forte  * 7.1.3  Command State Diagram for an Initiator
81fcf3ce44SJohn Forte  *      Symbolic Names for States:
82fcf3ce44SJohn Forte  *      C1: FREE        - State on instantiation, or after successful
83fcf3ce44SJohn Forte  *                        completion.
84fcf3ce44SJohn Forte  *      C2: PENDING     - Command is in the session's pending queue awaiting
85fcf3ce44SJohn Forte  *                        its turn to be sent on the wire.
86fcf3ce44SJohn Forte  *      C3: ACTIVE      - Command has been sent on the wire and is
87fcf3ce44SJohn Forte  *                        awaiting completion.
88fcf3ce44SJohn Forte  *      C4: ABORTING    - Command which was sent on the wire has not timed
89fcf3ce44SJohn Forte  *                        out or been requested to abort by an upper layer
90fcf3ce44SJohn Forte  *                        driver.  At this point there is a task management
91fcf3ce44SJohn Forte  *                        command in the active queue trying to abort the task.
9230e7468fSPeter Dunlap  *	C4': IDM ABORTING - SCSI command is owned by IDM and idm_task_abort
9330e7468fSPeter Dunlap  *                          has been called for this command.
94fcf3ce44SJohn Forte  *      C5: COMPLETED	- Command which is ready to complete via pkt callback.
95fcf3ce44SJohn Forte  *
96fcf3ce44SJohn Forte  *      The state diagram is as follows:
97fcf3ce44SJohn Forte  *               -------
98fcf3ce44SJohn Forte  *              / C1    \
99fcf3ce44SJohn Forte  *    I-------->\       /<------------
100fcf3ce44SJohn Forte  *    N|         ---+---             |
101fcf3ce44SJohn Forte  *    T|            |E1              |
102fcf3ce44SJohn Forte  *    E|            V                |
103fcf3ce44SJohn Forte  *    R|         -------             |
104fcf3ce44SJohn Forte  *    N+--------/ C2    \            |
105fcf3ce44SJohn Forte  *    A|  E4/6/7\       /--------    |
106fcf3ce44SJohn Forte  *    L|         ---+---  E4/6/7|    |
10730e7468fSPeter Dunlap  *     |            |E2    E10  |    |
108fcf3ce44SJohn Forte  *    C|            V           | S  |
109fcf3ce44SJohn Forte  *    M|         _______        | C  |
110fcf3ce44SJohn Forte  *    D+--------/ C3    \       | S  |
111fcf3ce44SJohn Forte  *    S E3/4/6/7\       /-------+ I  |
11230e7468fSPeter Dunlap  *              /---+---E3/4/6/7|    |
11330e7468fSPeter Dunlap  *             /    |      E9/10|    |
11430e7468fSPeter Dunlap  *      ------/ E4/6|           | C  |
11530e7468fSPeter Dunlap  *      |           V           | M  |
11630e7468fSPeter Dunlap  *    E7|        -------        | D  |
11730e7468fSPeter Dunlap  *  SCSI|    - >/ C4    \       | S  |
11830e7468fSPeter Dunlap  *      |   /   \       /-------+    |
11930e7468fSPeter Dunlap  *      |   |    ---+---E3/6/7/9|    |
12030e7468fSPeter Dunlap  *      |   |  E4|  |           V   /E8
12130e7468fSPeter Dunlap  *      |   ------  |        -------
12230e7468fSPeter Dunlap  *      +-\         /       / C5    \
12330e7468fSPeter Dunlap  *      V  \-------/  /---->\       /
12430e7468fSPeter Dunlap  *   -------    E7   /       ---+---
12530e7468fSPeter Dunlap  *  / C4'   \       /
12630e7468fSPeter Dunlap  *  \       /------/ E9
12730e7468fSPeter Dunlap  *   -------
128fcf3ce44SJohn Forte  *
129fcf3ce44SJohn Forte  * The state transition table is as follows:
130fcf3ce44SJohn Forte  *
13130e7468fSPeter Dunlap  *         +---------+---+---+-----+----+--------------+
13230e7468fSPeter Dunlap  *         |C1       |C2 |C3 |C4   |C4' |C5            |
13330e7468fSPeter Dunlap  *      ---+---------+---+---+-----+----+--------------+
13430e7468fSPeter Dunlap  *       C1| -       |E1 | - | -   | -  |              |
13530e7468fSPeter Dunlap  *      ---+---------+---+---+-----+----+--------------+
13630e7468fSPeter Dunlap  *       C2|E4/6/7   |-  |E2 | -   | -  |E4/6/7/10     |
13730e7468fSPeter Dunlap  *      ---+---------+---+---+-----+----+--------------+
13830e7468fSPeter Dunlap  *       C3|E3/4/6/7 |-  |-  |E4/6 |E7  |E3/4/6/7/9/10 |
13930e7468fSPeter Dunlap  *      ---+---------+---+---+-----+----+--------------+
14030e7468fSPeter Dunlap  *       C4|         |-  |-  |E4   |E7  |E3/6/7/9      |
14130e7468fSPeter Dunlap  *      ---+---------+---+---+-----+----+--------------+
14230e7468fSPeter Dunlap  *      C4'|         |-  |-  |-    |-   |E9            |
14330e7468fSPeter Dunlap  *      ---+---------+---+---+-----+----+--------------+
14430e7468fSPeter Dunlap  *       C5|E8       |   |   |     |    |              |
14530e7468fSPeter Dunlap  *      ---+---------+---+---+-----+----+--------------+
146fcf3ce44SJohn Forte  *
147fcf3ce44SJohn Forte  * Event definitions:
148fcf3ce44SJohn Forte  *
149fcf3ce44SJohn Forte  * -E1: Command was requested to be sent on wire
150fcf3ce44SJohn Forte  * -E2: Command was submitted and now active on wire
151fcf3ce44SJohn Forte  * -E3: Command was successfully completed
152fcf3ce44SJohn Forte  *	- SCSI command is move to completion queue
153fcf3ce44SJohn Forte  *	- ABORT/RESET/etc are completed.
154fcf3ce44SJohn Forte  * -E4: Command has been requested to abort
155fcf3ce44SJohn Forte  *	- SCSI command in pending queue will be returned
156fcf3ce44SJohn Forte  *		to caller with aborted status.
157fcf3ce44SJohn Forte  *	- SCSI command state updated and iscsi_handle_abort()
158fcf3ce44SJohn Forte  *		will be called.
159fcf3ce44SJohn Forte  *	- SCSI command with ABORTING state has already
160fcf3ce44SJohn Forte  *		been requested to abort ignore request.
161fcf3ce44SJohn Forte  *	- ABORT/RESET commands will be destroyed and the
162fcf3ce44SJohn Forte  *		caller will be notify of the failure.
163fcf3ce44SJohn Forte  *	- All other commands will just be destroyed.
164fcf3ce44SJohn Forte  * -E6: Command has timed out
165fcf3ce44SJohn Forte  *	- SCSI commands in pending queue will be returned up the
166fcf3ce44SJohn Forte  *		stack with TIMEOUT errors.
167fcf3ce44SJohn Forte  *	- SCSI commands in the active queue and timed out
168fcf3ce44SJohn Forte  *		will be moved to the aborting queue.
169fcf3ce44SJohn Forte  *	- SCSI commands in ABORTING state will be returned up
170fcf3ce44SJohn Forte  *		up the stack with TIMEOUT errors.
171fcf3ce44SJohn Forte  *	- ABORT/RESET commands will be destroyed and the caller
172fcf3ce44SJohn Forte  *		notified of the failure.
173fcf3ce44SJohn Forte  *	- All other commands will just be detroyed.
174fcf3ce44SJohn Forte  * -E7: Connection has encountered a problem
175fcf3ce44SJohn Forte  * -E8:	Command has completed
176fcf3ce44SJohn Forte  *	- Only SCSI cmds should receive these events
177fcf3ce44SJohn Forte  *		and reach the command state.
17830e7468fSPeter Dunlap  * -E9: Callback received for previous idm_task_abort request
17930e7468fSPeter Dunlap  * -E10: The command this abort was associated with has terminated on its own
180fcf3ce44SJohn Forte  */
181fcf3ce44SJohn Forte void
182fcf3ce44SJohn Forte iscsi_cmd_state_machine(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
183fcf3ce44SJohn Forte {
184fcf3ce44SJohn Forte 	boolean_t	release_lock = B_TRUE;
185fcf3ce44SJohn Forte 
186fcf3ce44SJohn Forte 	ASSERT(icmdp != NULL);
187fcf3ce44SJohn Forte 	ASSERT(arg != NULL);
188fcf3ce44SJohn Forte 
189fcf3ce44SJohn Forte 	DTRACE_PROBE3(event, iscsi_cmd_t *, icmdp, char *,
190fcf3ce44SJohn Forte 	    iscsi_cmd_state_str(icmdp->cmd_state),
191fcf3ce44SJohn Forte 	    char *, iscsi_cmd_event_str(event));
192fcf3ce44SJohn Forte 
193fcf3ce44SJohn Forte 	mutex_enter(&icmdp->cmd_mutex);
19430e7468fSPeter Dunlap 
19530e7468fSPeter Dunlap 	/* Audit event */
19630e7468fSPeter Dunlap 	idm_sm_audit_event(&icmdp->cmd_state_audit,
19730e7468fSPeter Dunlap 	    SAS_ISCSI_CMD, icmdp->cmd_state, event, (uintptr_t)arg);
19830e7468fSPeter Dunlap 
199fcf3ce44SJohn Forte 	icmdp->cmd_prev_state = icmdp->cmd_state;
200fcf3ce44SJohn Forte 	switch (icmdp->cmd_state) {
201fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_FREE:
202fcf3ce44SJohn Forte 		iscsi_cmd_state_free(icmdp, event, arg);
203fcf3ce44SJohn Forte 		break;
204fcf3ce44SJohn Forte 
205fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_PENDING:
206fcf3ce44SJohn Forte 		iscsi_cmd_state_pending(icmdp, event, arg);
207fcf3ce44SJohn Forte 		break;
208fcf3ce44SJohn Forte 
209fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_ACTIVE:
210fcf3ce44SJohn Forte 		iscsi_cmd_state_active(icmdp, event, arg);
211fcf3ce44SJohn Forte 		break;
212fcf3ce44SJohn Forte 
213fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_ABORTING:
214fcf3ce44SJohn Forte 		iscsi_cmd_state_aborting(icmdp, event, arg);
215fcf3ce44SJohn Forte 		break;
216fcf3ce44SJohn Forte 
21730e7468fSPeter Dunlap 	case ISCSI_CMD_STATE_IDM_ABORTING:
21830e7468fSPeter Dunlap 		iscsi_cmd_state_idm_aborting(icmdp, event, arg);
21930e7468fSPeter Dunlap 		break;
22030e7468fSPeter Dunlap 
221fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_COMPLETED:
222fcf3ce44SJohn Forte 		iscsi_cmd_state_completed(icmdp, event, arg);
223fcf3ce44SJohn Forte 
224fcf3ce44SJohn Forte 		/*
225fcf3ce44SJohn Forte 		 * Once completed event is processed we DO NOT
226fcf3ce44SJohn Forte 		 * want to touch it again because the caller
227fcf3ce44SJohn Forte 		 * (sd, st, etc) may have freed the command.
228fcf3ce44SJohn Forte 		 */
229fcf3ce44SJohn Forte 		release_lock = B_FALSE;
230fcf3ce44SJohn Forte 		break;
231fcf3ce44SJohn Forte 
232fcf3ce44SJohn Forte 	default:
233fcf3ce44SJohn Forte 		ASSERT(FALSE);
234fcf3ce44SJohn Forte 	}
235fcf3ce44SJohn Forte 
236fcf3ce44SJohn Forte 	if (release_lock == B_TRUE) {
23730e7468fSPeter Dunlap 		/* Audit state if not completed */
23830e7468fSPeter Dunlap 		idm_sm_audit_state_change(&icmdp->cmd_state_audit,
23930e7468fSPeter Dunlap 		    SAS_ISCSI_CMD, icmdp->cmd_prev_state, icmdp->cmd_state);
24030e7468fSPeter Dunlap 
241d233de7eSJack Meng 		if (!(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_FREE) ||
242d233de7eSJack Meng 		    !(icmdp->cmd_misc_flags &
243d233de7eSJack Meng 		    ISCSI_CMD_MISCFLAG_INTERNAL)) {
244fcf3ce44SJohn Forte 			mutex_exit(&icmdp->cmd_mutex);
245fcf3ce44SJohn Forte 			return;
246fcf3ce44SJohn Forte 		}
247fcf3ce44SJohn Forte 		mutex_exit(&icmdp->cmd_mutex);
248fcf3ce44SJohn Forte 		iscsi_cmd_free(icmdp);
249fcf3ce44SJohn Forte 	}
250fcf3ce44SJohn Forte }
251fcf3ce44SJohn Forte 
252fcf3ce44SJohn Forte /*
253fcf3ce44SJohn Forte  * iscsi_cmd_alloc -
254fcf3ce44SJohn Forte  *
255fcf3ce44SJohn Forte  */
256fcf3ce44SJohn Forte iscsi_cmd_t *
257fcf3ce44SJohn Forte iscsi_cmd_alloc(iscsi_conn_t *icp, int km_flags)
258fcf3ce44SJohn Forte {
259fcf3ce44SJohn Forte 	iscsi_cmd_t	*icmdp;
260fcf3ce44SJohn Forte 
261fcf3ce44SJohn Forte 	icmdp = kmem_zalloc(sizeof (iscsi_cmd_t), km_flags);
262fcf3ce44SJohn Forte 	if (icmdp) {
263fcf3ce44SJohn Forte 		icmdp->cmd_sig		= ISCSI_SIG_CMD;
264fcf3ce44SJohn Forte 		icmdp->cmd_state	= ISCSI_CMD_STATE_FREE;
265fcf3ce44SJohn Forte 		icmdp->cmd_conn		= icp;
266d233de7eSJack Meng 		icmdp->cmd_misc_flags	|= ISCSI_CMD_MISCFLAG_INTERNAL;
26730e7468fSPeter Dunlap 		idm_sm_audit_init(&icmdp->cmd_state_audit);
268fcf3ce44SJohn Forte 		mutex_init(&icmdp->cmd_mutex, NULL, MUTEX_DRIVER, NULL);
269fcf3ce44SJohn Forte 		cv_init(&icmdp->cmd_completion, NULL, CV_DRIVER, NULL);
270fcf3ce44SJohn Forte 	}
271fcf3ce44SJohn Forte 	return (icmdp);
272fcf3ce44SJohn Forte }
273fcf3ce44SJohn Forte 
274fcf3ce44SJohn Forte /*
275fcf3ce44SJohn Forte  * iscsi_cmd_free -
276fcf3ce44SJohn Forte  *
277fcf3ce44SJohn Forte  */
278fcf3ce44SJohn Forte void
279fcf3ce44SJohn Forte iscsi_cmd_free(iscsi_cmd_t *icmdp)
280fcf3ce44SJohn Forte {
281fcf3ce44SJohn Forte 	ASSERT(icmdp != NULL);
282fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_sig == ISCSI_SIG_CMD);
283fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_FREE);
284fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_next == NULL);
285fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_prev == NULL);
286d233de7eSJack Meng 	ASSERT(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_INTERNAL);
28730e7468fSPeter Dunlap 	if (icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT)
288fcf3ce44SJohn Forte 		ASSERT(icmdp->cmd_un.abort.icmdp == NULL);
289fcf3ce44SJohn Forte 	else if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
290fcf3ce44SJohn Forte 		ASSERT(icmdp->cmd_un.scsi.r2t_icmdp == NULL);
291fcf3ce44SJohn Forte 		ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
292fcf3ce44SJohn Forte 	}
293fcf3ce44SJohn Forte 	mutex_destroy(&icmdp->cmd_mutex);
294fcf3ce44SJohn Forte 	cv_destroy(&icmdp->cmd_completion);
295fcf3ce44SJohn Forte 	kmem_free(icmdp, sizeof (iscsi_cmd_t));
296fcf3ce44SJohn Forte }
297fcf3ce44SJohn Forte 
298fcf3ce44SJohn Forte /*
299fcf3ce44SJohn Forte  * +--------------------------------------------------------------------+
300fcf3ce44SJohn Forte  * | Internal Command Interfaces					|
301fcf3ce44SJohn Forte  * +--------------------------------------------------------------------+
302fcf3ce44SJohn Forte  */
303fcf3ce44SJohn Forte /*
304fcf3ce44SJohn Forte  * iscsi_cmd_state_free -
305fcf3ce44SJohn Forte  *
306fcf3ce44SJohn Forte  */
307fcf3ce44SJohn Forte static void
308fcf3ce44SJohn Forte iscsi_cmd_state_free(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
309fcf3ce44SJohn Forte {
310fcf3ce44SJohn Forte 	iscsi_sess_t	*isp		= (iscsi_sess_t *)arg;
311fcf3ce44SJohn Forte 
312fcf3ce44SJohn Forte 	ASSERT(icmdp != NULL);
313fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_FREE);
314fcf3ce44SJohn Forte 	ASSERT(isp != NULL);
315fcf3ce44SJohn Forte 
316fcf3ce44SJohn Forte 	/* switch on event change */
317fcf3ce44SJohn Forte 	switch (event) {
318fcf3ce44SJohn Forte 	/* -E1: Command was requested to be sent on wire */
319fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E1:
320fcf3ce44SJohn Forte 
321fcf3ce44SJohn Forte 		/* setup timestamps and timeouts for this command */
322fcf3ce44SJohn Forte 		icmdp->cmd_lbolt_pending = ddi_get_lbolt();
323fcf3ce44SJohn Forte 		if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
324fcf3ce44SJohn Forte 			/*
325fcf3ce44SJohn Forte 			 * Establish absolute time when command should timeout.
32630e7468fSPeter Dunlap 			 * For commands that depend on cmdsn window to go
327fcf3ce44SJohn Forte 			 * active, the timeout will be ignored while on
328fcf3ce44SJohn Forte 			 * the pending queue and a new timeout will be
329fcf3ce44SJohn Forte 			 * established when the command goes active.
330fcf3ce44SJohn Forte 			 */
331fcf3ce44SJohn Forte 			if (icmdp->cmd_un.scsi.pkt &&
332fcf3ce44SJohn Forte 			    icmdp->cmd_un.scsi.pkt->pkt_time)
333fcf3ce44SJohn Forte 				icmdp->cmd_lbolt_timeout =
334fcf3ce44SJohn Forte 				    icmdp->cmd_lbolt_pending + SEC_TO_TICK(
335fcf3ce44SJohn Forte 				    icmdp->cmd_un.scsi.pkt->pkt_time *
336fcf3ce44SJohn Forte 				    iscsi_cmd_timeout_factor);
337fcf3ce44SJohn Forte 			else
338fcf3ce44SJohn Forte 				icmdp->cmd_lbolt_timeout = 0;
339*2b79d384Sbing zhao - Sun Microsystems - Beijing China 
340*2b79d384Sbing zhao - Sun Microsystems - Beijing China 			icmdp->cmd_un.scsi.pkt_stat &=
341*2b79d384Sbing zhao - Sun Microsystems - Beijing China 			    ISCSI_CMD_PKT_STAT_INIT;
342fcf3ce44SJohn Forte 		} else {
343fcf3ce44SJohn Forte 			icmdp->cmd_lbolt_timeout = icmdp->cmd_lbolt_pending +
344fcf3ce44SJohn Forte 			    SEC_TO_TICK(ISCSI_INTERNAL_CMD_TIMEOUT *
345fcf3ce44SJohn Forte 			    iscsi_cmd_timeout_factor);
346fcf3ce44SJohn Forte 		}
347fcf3ce44SJohn Forte 
348fcf3ce44SJohn Forte 		/* place into pending queue */
349fcf3ce44SJohn Forte 		iscsi_enqueue_pending_cmd(isp, icmdp);
350fcf3ce44SJohn Forte 
351fcf3ce44SJohn Forte 		break;
352fcf3ce44SJohn Forte 
353fcf3ce44SJohn Forte 	/* All other events are invalid for this state */
354fcf3ce44SJohn Forte 	default:
355fcf3ce44SJohn Forte 		ASSERT(FALSE);
356fcf3ce44SJohn Forte 	}
357fcf3ce44SJohn Forte }
358fcf3ce44SJohn Forte 
359fcf3ce44SJohn Forte /*
360fcf3ce44SJohn Forte  * iscsi_cmd_state_pending -
361fcf3ce44SJohn Forte  *
362fcf3ce44SJohn Forte  */
363fcf3ce44SJohn Forte static void
364fcf3ce44SJohn Forte iscsi_cmd_state_pending(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
365fcf3ce44SJohn Forte {
366fcf3ce44SJohn Forte 	iscsi_status_t	status;
367fcf3ce44SJohn Forte 	iscsi_sess_t	*isp		= (iscsi_sess_t *)arg;
368fcf3ce44SJohn Forte 	boolean_t	free_icmdp	= B_FALSE;
369fcf3ce44SJohn Forte 	int		rval;
370fcf3ce44SJohn Forte 
371fcf3ce44SJohn Forte 	ASSERT(icmdp != NULL);
372fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_PENDING);
373fcf3ce44SJohn Forte 	ASSERT(isp != NULL);
374fcf3ce44SJohn Forte 
375fcf3ce44SJohn Forte 	/* switch on event change */
376fcf3ce44SJohn Forte 	switch (event) {
377fcf3ce44SJohn Forte 	/* -E2: Command was submitted and now active on wire */
378fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E2:
379fcf3ce44SJohn Forte 
380fcf3ce44SJohn Forte 		/* A connection should have already been assigned */
38130e7468fSPeter Dunlap 		ASSERT(mutex_owned(&isp->sess_queue_pending.mutex));
382fcf3ce44SJohn Forte 		ASSERT(icmdp->cmd_conn != NULL);
383fcf3ce44SJohn Forte 
384fcf3ce44SJohn Forte 		/*
385fcf3ce44SJohn Forte 		 * RESERVE RESOURSES
386fcf3ce44SJohn Forte 		 */
387fcf3ce44SJohn Forte 		switch (icmdp->cmd_type) {
388fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_SCSI:
389fcf3ce44SJohn Forte 			/* check cmdsn window */
390fcf3ce44SJohn Forte 			mutex_enter(&isp->sess_cmdsn_mutex);
391fcf3ce44SJohn Forte 			if (!iscsi_sna_lte(isp->sess_cmdsn,
392fcf3ce44SJohn Forte 			    isp->sess_maxcmdsn)) {
393fcf3ce44SJohn Forte 				/* cmdsn window closed */
394fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_cmdsn_mutex);
395fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_queue_pending.mutex);
396fcf3ce44SJohn Forte 				isp->sess_window_open = B_FALSE;
397d233de7eSJack Meng 				icmdp->cmd_misc_flags |=
398d233de7eSJack Meng 				    ISCSI_CMD_MISCFLAG_STUCK;
399fcf3ce44SJohn Forte 				return;
400fcf3ce44SJohn Forte 			}
401fcf3ce44SJohn Forte 
402fcf3ce44SJohn Forte 			/* assign itt */
40330e7468fSPeter Dunlap 			status = iscsi_sess_reserve_scsi_itt(icmdp);
404fcf3ce44SJohn Forte 			if (!ISCSI_SUCCESS(status)) {
405fcf3ce44SJohn Forte 				/* no available itt slots */
406fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_cmdsn_mutex);
407fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_queue_pending.mutex);
408fcf3ce44SJohn Forte 				isp->sess_window_open = B_FALSE;
409d233de7eSJack Meng 				icmdp->cmd_misc_flags |=
410d233de7eSJack Meng 				    ISCSI_CMD_MISCFLAG_STUCK;
411fcf3ce44SJohn Forte 				return;
412fcf3ce44SJohn Forte 			}
413fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
414fcf3ce44SJohn Forte 			break;
415fcf3ce44SJohn Forte 
416fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_ABORT:
417fcf3ce44SJohn Forte 			/*
418fcf3ce44SJohn Forte 			 * Verify ABORT's parent SCSI command is still
419fcf3ce44SJohn Forte 			 * there.  If parent SCSI command is completed
420fcf3ce44SJohn Forte 			 * then there is no longer any reason to abort
421fcf3ce44SJohn Forte 			 * the parent command.  This could occur due
422fcf3ce44SJohn Forte 			 * to a connection or target reset.
423fcf3ce44SJohn Forte 			 */
424fcf3ce44SJohn Forte 			ASSERT(icmdp->cmd_un.abort.icmdp != NULL);
425fcf3ce44SJohn Forte 			if (icmdp->cmd_un.abort.icmdp->cmd_state ==
426fcf3ce44SJohn Forte 			    ISCSI_CMD_STATE_COMPLETED) {
427fcf3ce44SJohn Forte 				iscsi_dequeue_pending_cmd(isp, icmdp);
428fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_queue_pending.mutex);
429fcf3ce44SJohn Forte 
430fcf3ce44SJohn Forte 				mutex_enter(&icmdp->cmd_un.abort.icmdp->
431fcf3ce44SJohn Forte 				    cmd_mutex);
432fcf3ce44SJohn Forte 				icmdp->cmd_un.abort.icmdp->
433fcf3ce44SJohn Forte 				    cmd_un.scsi.abort_icmdp = NULL;
434fcf3ce44SJohn Forte 				cv_broadcast(&icmdp->cmd_un.abort.icmdp->
435fcf3ce44SJohn Forte 				    cmd_completion);
436fcf3ce44SJohn Forte 				mutex_exit(&icmdp->cmd_un.abort.icmdp->
437fcf3ce44SJohn Forte 				    cmd_mutex);
438fcf3ce44SJohn Forte 				icmdp->cmd_un.abort.icmdp = NULL;
439fcf3ce44SJohn Forte 
440fcf3ce44SJohn Forte 				icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
441d233de7eSJack Meng 				icmdp->cmd_misc_flags |=
442d233de7eSJack Meng 				    ISCSI_CMD_MISCFLAG_FREE;
443fcf3ce44SJohn Forte 				return;
444fcf3ce44SJohn Forte 			}
445fcf3ce44SJohn Forte 			/* FALLTHRU */
446fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_RESET:
447fcf3ce44SJohn Forte 			/* FALLTHRU */
448fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_LOGOUT:
449fcf3ce44SJohn Forte 			mutex_enter(&isp->sess_cmdsn_mutex);
450fcf3ce44SJohn Forte 			/* assign itt */
451fcf3ce44SJohn Forte 			status = iscsi_sess_reserve_itt(isp, icmdp);
452fcf3ce44SJohn Forte 			if (!ISCSI_SUCCESS(status)) {
453fcf3ce44SJohn Forte 				/* no available itt slots */
454fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_cmdsn_mutex);
455fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_queue_pending.mutex);
456fcf3ce44SJohn Forte 				isp->sess_window_open = B_FALSE;
457fcf3ce44SJohn Forte 				return;
458fcf3ce44SJohn Forte 			}
459fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
460fcf3ce44SJohn Forte 			break;
461fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_NOP:
462fcf3ce44SJohn Forte 			/* assign itt, if needed */
463fcf3ce44SJohn Forte 			if (icmdp->cmd_itt == ISCSI_RSVD_TASK_TAG) {
464fcf3ce44SJohn Forte 				/* not expecting a response */
465fcf3ce44SJohn Forte 				free_icmdp = B_TRUE;
466fcf3ce44SJohn Forte 			} else {
467fcf3ce44SJohn Forte 				/* expecting response, assign an itt */
468fcf3ce44SJohn Forte 				mutex_enter(&isp->sess_cmdsn_mutex);
469fcf3ce44SJohn Forte 				/* assign itt */
470fcf3ce44SJohn Forte 				status = iscsi_sess_reserve_itt(isp, icmdp);
471fcf3ce44SJohn Forte 				if (!ISCSI_SUCCESS(status)) {
472fcf3ce44SJohn Forte 					/* no available itt slots */
473fcf3ce44SJohn Forte 					mutex_exit(&isp->sess_cmdsn_mutex);
474fcf3ce44SJohn Forte 					mutex_exit(&isp->sess_queue_pending.
475fcf3ce44SJohn Forte 					    mutex);
476fcf3ce44SJohn Forte 					isp->sess_window_open = B_FALSE;
477fcf3ce44SJohn Forte 					return;
478fcf3ce44SJohn Forte 				}
479fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_cmdsn_mutex);
480fcf3ce44SJohn Forte 			}
481fcf3ce44SJohn Forte 			break;
482fcf3ce44SJohn Forte 
483fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_TEXT:
484fcf3ce44SJohn Forte 			mutex_enter(&isp->sess_cmdsn_mutex);
485fcf3ce44SJohn Forte 			/* check cmdsn window */
486fcf3ce44SJohn Forte 			if (!iscsi_sna_lte(isp->sess_cmdsn,
487fcf3ce44SJohn Forte 			    isp->sess_maxcmdsn)) {
488fcf3ce44SJohn Forte 				/* cmdsn window closed */
489fcf3ce44SJohn Forte 				isp->sess_window_open = B_FALSE;
490fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_cmdsn_mutex);
491fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_queue_pending.mutex);
492d233de7eSJack Meng 				icmdp->cmd_misc_flags |=
493d233de7eSJack Meng 				    ISCSI_CMD_MISCFLAG_STUCK;
494fcf3ce44SJohn Forte 				return;
495fcf3ce44SJohn Forte 			}
496fcf3ce44SJohn Forte 			if (icmdp->cmd_un.text.stage ==
497fcf3ce44SJohn Forte 			    ISCSI_CMD_TEXT_INITIAL_REQ) {
498fcf3ce44SJohn Forte 				/* assign itt */
499fcf3ce44SJohn Forte 				status = iscsi_sess_reserve_itt(isp, icmdp);
500fcf3ce44SJohn Forte 				if (!ISCSI_SUCCESS(status)) {
501fcf3ce44SJohn Forte 					/* no available itt slots */
502fcf3ce44SJohn Forte 					mutex_exit(&isp->sess_cmdsn_mutex);
503fcf3ce44SJohn Forte 					mutex_exit(&isp->sess_queue_pending.
504fcf3ce44SJohn Forte 					    mutex);
505fcf3ce44SJohn Forte 					isp->sess_window_open = B_FALSE;
506d233de7eSJack Meng 					icmdp->cmd_misc_flags |=
507d233de7eSJack Meng 					    ISCSI_CMD_MISCFLAG_STUCK;
508fcf3ce44SJohn Forte 					return;
509fcf3ce44SJohn Forte 				}
510fcf3ce44SJohn Forte 			}
511fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
512fcf3ce44SJohn Forte 			break;
513fcf3ce44SJohn Forte 
514fcf3ce44SJohn Forte 		default:
515fcf3ce44SJohn Forte 			ASSERT(FALSE);
516fcf3ce44SJohn Forte 		}
517fcf3ce44SJohn Forte 
518fcf3ce44SJohn Forte 		/*
519fcf3ce44SJohn Forte 		 * RESOURCES RESERVED
520fcf3ce44SJohn Forte 		 *
521fcf3ce44SJohn Forte 		 * Now that we have the resources reserved, establish timeout
522fcf3ce44SJohn Forte 		 * for cmd_type values that depend on having an open cmdsn
523fcf3ce44SJohn Forte 		 * window (i.e. cmd_type that called iscsi_sna_lte() above).
524fcf3ce44SJohn Forte 		 */
525fcf3ce44SJohn Forte 		if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
526fcf3ce44SJohn Forte 			if (icmdp->cmd_un.scsi.pkt &&
527fcf3ce44SJohn Forte 			    icmdp->cmd_un.scsi.pkt->pkt_time)
528fcf3ce44SJohn Forte 				icmdp->cmd_lbolt_timeout =
529fcf3ce44SJohn Forte 				    ddi_get_lbolt() + SEC_TO_TICK(
530fcf3ce44SJohn Forte 				    icmdp->cmd_un.scsi.pkt->pkt_time *
531fcf3ce44SJohn Forte 				    iscsi_cmd_timeout_factor);
532fcf3ce44SJohn Forte 			else
533fcf3ce44SJohn Forte 				icmdp->cmd_lbolt_timeout = 0;
534fcf3ce44SJohn Forte 		} else if (icmdp->cmd_type == ISCSI_CMD_TYPE_TEXT) {
535fcf3ce44SJohn Forte 			icmdp->cmd_lbolt_timeout = ddi_get_lbolt() +
536fcf3ce44SJohn Forte 			    SEC_TO_TICK(ISCSI_INTERNAL_CMD_TIMEOUT *
537fcf3ce44SJohn Forte 			    iscsi_cmd_timeout_factor);
538fcf3ce44SJohn Forte 		}
539fcf3ce44SJohn Forte 
540fcf3ce44SJohn Forte 		/* remove command from pending queue */
541fcf3ce44SJohn Forte 		iscsi_dequeue_pending_cmd(isp, icmdp);
542fcf3ce44SJohn Forte 		/* check if expecting a response */
543fcf3ce44SJohn Forte 		if (free_icmdp == B_FALSE) {
544fcf3ce44SJohn Forte 			/* response expected, move to active queue */
545fcf3ce44SJohn Forte 			mutex_enter(&icmdp->cmd_conn->conn_queue_active.mutex);
546fcf3ce44SJohn Forte 			iscsi_enqueue_active_cmd(icmdp->cmd_conn, icmdp);
547fcf3ce44SJohn Forte 			mutex_exit(&icmdp->cmd_conn->conn_queue_active.mutex);
548fcf3ce44SJohn Forte 		}
549fcf3ce44SJohn Forte 
550fcf3ce44SJohn Forte 		/*
551fcf3ce44SJohn Forte 		 * TRANSFER COMMAND
552fcf3ce44SJohn Forte 		 */
553fcf3ce44SJohn Forte 		rval = iscsi_tx_cmd(isp, icmdp);
554fcf3ce44SJohn Forte 
555fcf3ce44SJohn Forte 		ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex));
556fcf3ce44SJohn Forte 
557fcf3ce44SJohn Forte 		/*
558fcf3ce44SJohn Forte 		 * CHECK SUCCESS/FAILURE
559fcf3ce44SJohn Forte 		 */
560fcf3ce44SJohn Forte 		if (!ISCSI_SUCCESS(rval)) {
561fcf3ce44SJohn Forte 			/*
562fcf3ce44SJohn Forte 			 * iscsi_tx_cmd failed.  No cleanup is required
563fcf3ce44SJohn Forte 			 * of commands that were put in the active queue.
564fcf3ce44SJohn Forte 			 * If the tx failed then rx will also fail and cleanup
565fcf3ce44SJohn Forte 			 * all items in the active/aborted queue in a common.
566fcf3ce44SJohn Forte 			 */
567fcf3ce44SJohn Forte 
568fcf3ce44SJohn Forte 			/* EMPTY */
569fcf3ce44SJohn Forte 		}
570fcf3ce44SJohn Forte 
571fcf3ce44SJohn Forte 		/* free temporary commands */
572fcf3ce44SJohn Forte 		if (free_icmdp == B_TRUE) {
573fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
574d233de7eSJack Meng 			icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_FREE;
575fcf3ce44SJohn Forte 		}
576fcf3ce44SJohn Forte 		break;
577fcf3ce44SJohn Forte 
57830e7468fSPeter Dunlap 	/* -E10: Abort is no longer required for this command */
57930e7468fSPeter Dunlap 	case ISCSI_CMD_EVENT_E10:
58030e7468fSPeter Dunlap 		/*
58130e7468fSPeter Dunlap 		 * Acquiring the sess_queue_pending lock while the
58230e7468fSPeter Dunlap 		 * conn_queue_active lock is held conflicts with the
58330e7468fSPeter Dunlap 		 * locking order in iscsi_cmd_state_pending where
58430e7468fSPeter Dunlap 		 * conn_queue_active is acquired while sess_queue_pending
58530e7468fSPeter Dunlap 		 * is held.  Normally this would be a dangerous lock
58630e7468fSPeter Dunlap 		 * order conflict, except that we know that if we are
58730e7468fSPeter Dunlap 		 * seeing ISCSI_CMD_EVENT_E10 then the command being
58830e7468fSPeter Dunlap 		 * aborted is in "aborting" state and by extension
58930e7468fSPeter Dunlap 		 * is not in "pending" state.  Therefore the code
59030e7468fSPeter Dunlap 		 * path with that alternate lock order will not execute.
59130e7468fSPeter Dunlap 		 * That's good because we can't drop the lock here without
59230e7468fSPeter Dunlap 		 * risking a deadlock.
59330e7468fSPeter Dunlap 		 */
59430e7468fSPeter Dunlap 		ASSERT(mutex_owned(&icmdp->cmd_conn->conn_queue_active.mutex));
59530e7468fSPeter Dunlap 		mutex_enter(&isp->sess_queue_pending.mutex);
59630e7468fSPeter Dunlap 
59730e7468fSPeter Dunlap 		icmdp->cmd_lbolt_aborting = ddi_get_lbolt();
59830e7468fSPeter Dunlap 
59930e7468fSPeter Dunlap 		iscsi_dequeue_pending_cmd(isp, icmdp);
60030e7468fSPeter Dunlap 
60130e7468fSPeter Dunlap 		icmdp->cmd_un.abort.icmdp->cmd_un.scsi.abort_icmdp = NULL;
60230e7468fSPeter Dunlap 		icmdp->cmd_un.abort.icmdp = NULL;
60330e7468fSPeter Dunlap 		icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_FREE;
60430e7468fSPeter Dunlap 		icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
60530e7468fSPeter Dunlap 
60630e7468fSPeter Dunlap 		mutex_exit(&isp->sess_queue_pending.mutex);
60730e7468fSPeter Dunlap 		break;
60830e7468fSPeter Dunlap 
609fcf3ce44SJohn Forte 	/* -E4: Command has been requested to abort */
610fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E4:
61130e7468fSPeter Dunlap 		ASSERT(mutex_owned(&isp->sess_queue_pending.mutex));
612fcf3ce44SJohn Forte 
613fcf3ce44SJohn Forte 		icmdp->cmd_lbolt_aborting = ddi_get_lbolt();
614fcf3ce44SJohn Forte 		ISCSI_CMD_SET_REASON_STAT(icmdp,
615fcf3ce44SJohn Forte 		    CMD_ABORTED, STAT_ABORTED);
616fcf3ce44SJohn Forte 
617fcf3ce44SJohn Forte 		iscsi_dequeue_pending_cmd(isp, icmdp);
618fcf3ce44SJohn Forte 		iscsi_enqueue_completed_cmd(isp, icmdp);
619fcf3ce44SJohn Forte 
620fcf3ce44SJohn Forte 		icmdp->cmd_lbolt_aborting = ddi_get_lbolt();
621fcf3ce44SJohn Forte 
622fcf3ce44SJohn Forte 		break;
623fcf3ce44SJohn Forte 
624fcf3ce44SJohn Forte 	/* -E7: Command has been reset */
625fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E7:
626fcf3ce44SJohn Forte 
627fcf3ce44SJohn Forte 		/* FALLTHRU */
628fcf3ce44SJohn Forte 
629fcf3ce44SJohn Forte 	/* -E6: Command has timed out */
630fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E6:
63130e7468fSPeter Dunlap 		ASSERT(mutex_owned(&isp->sess_queue_pending.mutex));
632fcf3ce44SJohn Forte 		iscsi_dequeue_pending_cmd(isp, icmdp);
633fcf3ce44SJohn Forte 
634fcf3ce44SJohn Forte 		switch (icmdp->cmd_type) {
635fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_SCSI:
636fcf3ce44SJohn Forte 			/* Complete to caller as TIMEOUT */
637fcf3ce44SJohn Forte 			if (event == ISCSI_CMD_EVENT_E6) {
638fcf3ce44SJohn Forte 				ISCSI_CMD_SET_REASON_STAT(icmdp,
639fcf3ce44SJohn Forte 				    CMD_TIMEOUT, STAT_TIMEOUT);
640fcf3ce44SJohn Forte 			} else {
641fcf3ce44SJohn Forte 				ISCSI_CMD_SET_REASON_STAT(icmdp,
642*2b79d384Sbing zhao - Sun Microsystems - Beijing China 				    CMD_TRAN_ERR, icmdp->cmd_un.scsi.pkt_stat);
643fcf3ce44SJohn Forte 			}
644fcf3ce44SJohn Forte 			iscsi_enqueue_completed_cmd(isp, icmdp);
645fcf3ce44SJohn Forte 			break;
646fcf3ce44SJohn Forte 
647fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_NOP:
648fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
649fcf3ce44SJohn Forte 			/*
650fcf3ce44SJohn Forte 			 * Timeout occured.  Just free NOP.  Another
651fcf3ce44SJohn Forte 			 * NOP request will be spawned to replace
652fcf3ce44SJohn Forte 			 * this one.
653fcf3ce44SJohn Forte 			 */
654d233de7eSJack Meng 			icmdp->cmd_misc_flags |=
655d233de7eSJack Meng 			    ISCSI_CMD_MISCFLAG_FREE;
656d233de7eSJack Meng 
657fcf3ce44SJohn Forte 			break;
658fcf3ce44SJohn Forte 
659fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_ABORT:
660fcf3ce44SJohn Forte 			mutex_enter(&icmdp->cmd_un.abort.icmdp->cmd_mutex);
661fcf3ce44SJohn Forte 			icmdp->cmd_un.abort.icmdp->
662fcf3ce44SJohn Forte 			    cmd_un.scsi.abort_icmdp = NULL;
663fcf3ce44SJohn Forte 			cv_broadcast(&icmdp->cmd_un.abort.icmdp->
664fcf3ce44SJohn Forte 			    cmd_completion);
665fcf3ce44SJohn Forte 			mutex_exit(&icmdp->cmd_un.abort.icmdp->cmd_mutex);
666fcf3ce44SJohn Forte 			icmdp->cmd_un.abort.icmdp = NULL;
667fcf3ce44SJohn Forte 
668fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
669d233de7eSJack Meng 			icmdp->cmd_misc_flags |=
670d233de7eSJack Meng 			    ISCSI_CMD_MISCFLAG_FREE;
671fcf3ce44SJohn Forte 			break;
672fcf3ce44SJohn Forte 
673fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_RESET:
674fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
675fcf3ce44SJohn Forte 			/*
676fcf3ce44SJohn Forte 			 * If we are failing a RESET we need
677fcf3ce44SJohn Forte 			 * to notify the tran_reset caller.
678fcf3ce44SJohn Forte 			 * with the cmd and notify caller.
679fcf3ce44SJohn Forte 			 */
680fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
681fcf3ce44SJohn Forte 			    ISCSI_STATUS_CMD_FAILED);
682fcf3ce44SJohn Forte 			break;
683fcf3ce44SJohn Forte 
684fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_LOGOUT:
685fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
686fcf3ce44SJohn Forte 			/* notify requester of failure */
687fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
688fcf3ce44SJohn Forte 			    ISCSI_STATUS_CMD_FAILED);
689fcf3ce44SJohn Forte 			break;
690fcf3ce44SJohn Forte 
691fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_TEXT:
692fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
693fcf3ce44SJohn Forte 			icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
694fcf3ce44SJohn Forte 			/*
695fcf3ce44SJohn Forte 			 * If a TEXT command fails, notify the owner.
696fcf3ce44SJohn Forte 			 */
697fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
698fcf3ce44SJohn Forte 			    ISCSI_STATUS_CMD_FAILED);
699fcf3ce44SJohn Forte 			break;
700fcf3ce44SJohn Forte 
701fcf3ce44SJohn Forte 		default:
702fcf3ce44SJohn Forte 			ASSERT(FALSE);
703fcf3ce44SJohn Forte 			break;
704fcf3ce44SJohn Forte 		}
705fcf3ce44SJohn Forte 		break;
706fcf3ce44SJohn Forte 
707fcf3ce44SJohn Forte 	/* All other events are invalid for this state */
708fcf3ce44SJohn Forte 	default:
709fcf3ce44SJohn Forte 		ASSERT(FALSE);
710fcf3ce44SJohn Forte 	}
711fcf3ce44SJohn Forte }
712fcf3ce44SJohn Forte 
713fcf3ce44SJohn Forte 
714fcf3ce44SJohn Forte /*
715fcf3ce44SJohn Forte  * iscsi_cmd_state_active -
716fcf3ce44SJohn Forte  *
717fcf3ce44SJohn Forte  */
718fcf3ce44SJohn Forte static void
719fcf3ce44SJohn Forte iscsi_cmd_state_active(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
720fcf3ce44SJohn Forte {
721fcf3ce44SJohn Forte 	iscsi_sess_t	*isp		= (iscsi_sess_t *)arg;
722fcf3ce44SJohn Forte 	iscsi_hba_t	*ihp;
723fcf3ce44SJohn Forte 	iscsi_cmd_t	*t_icmdp	= NULL;
724fcf3ce44SJohn Forte 	iscsi_conn_t	*icp		= NULL;
725fcf3ce44SJohn Forte 
726fcf3ce44SJohn Forte 	ASSERT(icmdp != NULL);
727fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_ACTIVE);
728fcf3ce44SJohn Forte 	ASSERT(isp != NULL);
729fcf3ce44SJohn Forte 
730fcf3ce44SJohn Forte 	ihp = isp->sess_hba;
731fcf3ce44SJohn Forte 	ASSERT(ihp != NULL);
732fcf3ce44SJohn Forte 
733fcf3ce44SJohn Forte 	icp = icmdp->cmd_conn;
734fcf3ce44SJohn Forte 	ASSERT(icp != NULL);
735fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&icp->conn_queue_active.mutex));
736fcf3ce44SJohn Forte 
737fcf3ce44SJohn Forte 	/* switch on event change */
738fcf3ce44SJohn Forte 	switch (event) {
739fcf3ce44SJohn Forte 	/* -E3: Command was successfully completed */
740fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E3:
741fcf3ce44SJohn Forte 		/*
742fcf3ce44SJohn Forte 		 * Remove command from the active list.  We need to protect
743fcf3ce44SJohn Forte 		 * someone from looking up this command ITT until it's
744fcf3ce44SJohn Forte 		 * freed of the command is moved to a new queue location.
745fcf3ce44SJohn Forte 		 */
746fcf3ce44SJohn Forte 		mutex_enter(&isp->sess_cmdsn_mutex);
747fcf3ce44SJohn Forte 		iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
748fcf3ce44SJohn Forte 
749fcf3ce44SJohn Forte 		switch (icmdp->cmd_type) {
750fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_SCSI:
75130e7468fSPeter Dunlap 			iscsi_sess_release_scsi_itt(icmdp);
752fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
753fcf3ce44SJohn Forte 			iscsi_enqueue_completed_cmd(isp, icmdp);
754fcf3ce44SJohn Forte 			break;
755fcf3ce44SJohn Forte 
756fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_NOP:
757fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
758fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
759fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
760fcf3ce44SJohn Forte 
761fcf3ce44SJohn Forte 			/* free alloc */
762d233de7eSJack Meng 			icmdp->cmd_misc_flags |=
763d233de7eSJack Meng 			    ISCSI_CMD_MISCFLAG_FREE;
764d233de7eSJack Meng 
765fcf3ce44SJohn Forte 			break;
766fcf3ce44SJohn Forte 
767fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_ABORT:
768fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
769fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
770fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
771fcf3ce44SJohn Forte 
772fcf3ce44SJohn Forte 			/*
773fcf3ce44SJohn Forte 			 * Abort was completed successfully.  We should
774fcf3ce44SJohn Forte 			 * complete the parent scsi command if it still
775fcf3ce44SJohn Forte 			 * exists as timed out, and the state is not
776fcf3ce44SJohn Forte 			 * COMPLETED
777fcf3ce44SJohn Forte 			 */
778fcf3ce44SJohn Forte 			t_icmdp = icmdp->cmd_un.abort.icmdp;
779fcf3ce44SJohn Forte 			ASSERT(t_icmdp != NULL);
780fcf3ce44SJohn Forte 			mutex_enter(&t_icmdp->cmd_mutex);
78130e7468fSPeter Dunlap 			t_icmdp->cmd_un.scsi.abort_icmdp = NULL;
782fcf3ce44SJohn Forte 			if (t_icmdp->cmd_state != ISCSI_CMD_STATE_COMPLETED) {
783fcf3ce44SJohn Forte 				iscsi_dequeue_active_cmd(
784fcf3ce44SJohn Forte 				    t_icmdp->cmd_conn, t_icmdp);
78530e7468fSPeter Dunlap 				mutex_enter(
78630e7468fSPeter Dunlap 				    &icp->conn_queue_idm_aborting.mutex);
78730e7468fSPeter Dunlap 				iscsi_enqueue_idm_aborting_cmd(
78830e7468fSPeter Dunlap 				    t_icmdp->cmd_conn,
78930e7468fSPeter Dunlap 				    t_icmdp);
79030e7468fSPeter Dunlap 				mutex_exit(&icp->conn_queue_idm_aborting.mutex);
791fcf3ce44SJohn Forte 
79230e7468fSPeter Dunlap 				/*
79330e7468fSPeter Dunlap 				 * Complete abort processing after IDM
79430e7468fSPeter Dunlap 				 * calls us back.  Set the status to use
79530e7468fSPeter Dunlap 				 * when we complete the command.
79630e7468fSPeter Dunlap 				 */
797fcf3ce44SJohn Forte 				ISCSI_CMD_SET_REASON_STAT(
798*2b79d384Sbing zhao - Sun Microsystems - Beijing China 				    t_icmdp, CMD_TIMEOUT, STAT_ABORTED);
79930e7468fSPeter Dunlap 				idm_task_abort(icp->conn_ic, t_icmdp->cmd_itp,
80030e7468fSPeter Dunlap 				    AT_TASK_MGMT_ABORT);
80130e7468fSPeter Dunlap 			} else {
80230e7468fSPeter Dunlap 				cv_broadcast(&t_icmdp->cmd_completion);
803fcf3ce44SJohn Forte 			}
804fcf3ce44SJohn Forte 			mutex_exit(&t_icmdp->cmd_mutex);
805fcf3ce44SJohn Forte 			icmdp->cmd_un.abort.icmdp = NULL;
806fcf3ce44SJohn Forte 
807d233de7eSJack Meng 			icmdp->cmd_misc_flags |=
808d233de7eSJack Meng 			    ISCSI_CMD_MISCFLAG_FREE;
809d233de7eSJack Meng 
810fcf3ce44SJohn Forte 			break;
811fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_RESET:
812fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
813fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
814fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
815fcf3ce44SJohn Forte 
816fcf3ce44SJohn Forte 			/*
817*2b79d384Sbing zhao - Sun Microsystems - Beijing China 			 * Complete the abort/reset command.
818fcf3ce44SJohn Forte 			 */
819*2b79d384Sbing zhao - Sun Microsystems - Beijing China 			if (icmdp->cmd_un.reset.response !=
820*2b79d384Sbing zhao - Sun Microsystems - Beijing China 			    SCSI_TCP_TM_RESP_COMPLETE) {
821*2b79d384Sbing zhao - Sun Microsystems - Beijing China 				ISCSI_CMD_ISSUE_CALLBACK(icmdp,
822*2b79d384Sbing zhao - Sun Microsystems - Beijing China 				    ISCSI_STATUS_CMD_FAILED);
823*2b79d384Sbing zhao - Sun Microsystems - Beijing China 			} else {
824*2b79d384Sbing zhao - Sun Microsystems - Beijing China 				ISCSI_CMD_ISSUE_CALLBACK(icmdp,
825*2b79d384Sbing zhao - Sun Microsystems - Beijing China 				    ISCSI_STATUS_SUCCESS);
826*2b79d384Sbing zhao - Sun Microsystems - Beijing China 			}
827*2b79d384Sbing zhao - Sun Microsystems - Beijing China 
828fcf3ce44SJohn Forte 			break;
829fcf3ce44SJohn Forte 
830fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_LOGOUT:
831fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
832fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
833fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
834fcf3ce44SJohn Forte 
835fcf3ce44SJohn Forte 			/*
836fcf3ce44SJohn Forte 			 * Complete the logout successfully.
837fcf3ce44SJohn Forte 			 */
838fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp, ISCSI_STATUS_SUCCESS);
839fcf3ce44SJohn Forte 			break;
840fcf3ce44SJohn Forte 
841fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_TEXT:
842fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
843fcf3ce44SJohn Forte 			if (icmdp->cmd_un.text.stage ==
844fcf3ce44SJohn Forte 			    ISCSI_CMD_TEXT_FINAL_RSP) {
845fcf3ce44SJohn Forte 				iscsi_sess_release_itt(isp, icmdp);
846fcf3ce44SJohn Forte 			}
847fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
848fcf3ce44SJohn Forte 
849fcf3ce44SJohn Forte 			/*
850fcf3ce44SJohn Forte 			 * Complete the text command successfully.
851fcf3ce44SJohn Forte 			 */
852fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp, icmdp->cmd_result);
853fcf3ce44SJohn Forte 			break;
854fcf3ce44SJohn Forte 
855fcf3ce44SJohn Forte 		default:
856fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
857fcf3ce44SJohn Forte 			ASSERT(FALSE);
858fcf3ce44SJohn Forte 		}
859fcf3ce44SJohn Forte 
860fcf3ce44SJohn Forte 		ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex));
861fcf3ce44SJohn Forte 		break;
862fcf3ce44SJohn Forte 
86330e7468fSPeter Dunlap 	/* -E10,E4: Command has been requested to abort */
86430e7468fSPeter Dunlap 	case ISCSI_CMD_EVENT_E10:
86530e7468fSPeter Dunlap 		/* FALLTHRU */
866fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E4:
867fcf3ce44SJohn Forte 
868fcf3ce44SJohn Forte 		/* E4 is only for resets and aborts */
869fcf3ce44SJohn Forte 		ASSERT((icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT) ||
870fcf3ce44SJohn Forte 		    (icmdp->cmd_type == ISCSI_CMD_TYPE_RESET));
871fcf3ce44SJohn Forte 		/* FALLTHRU */
872fcf3ce44SJohn Forte 
873fcf3ce44SJohn Forte 	/* -E6: Command has timed out */
874fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E6:
875fcf3ce44SJohn Forte 
876fcf3ce44SJohn Forte 		switch (icmdp->cmd_type) {
877fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_SCSI:
878fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_ABORTING;
879fcf3ce44SJohn Forte 			iscsi_handle_abort(icmdp);
880fcf3ce44SJohn Forte 			break;
881fcf3ce44SJohn Forte 
882fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_NOP:
883fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
884fcf3ce44SJohn Forte 
885fcf3ce44SJohn Forte 			mutex_enter(&isp->sess_cmdsn_mutex);
886fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
887fcf3ce44SJohn Forte 			iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
888fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
889fcf3ce44SJohn Forte 
890d233de7eSJack Meng 			icmdp->cmd_misc_flags |=
891d233de7eSJack Meng 			    ISCSI_CMD_MISCFLAG_FREE;
892d233de7eSJack Meng 
893fcf3ce44SJohn Forte 			break;
894fcf3ce44SJohn Forte 
895fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_ABORT:
896fcf3ce44SJohn Forte 			icmdp->cmd_state =
897fcf3ce44SJohn Forte 			    ISCSI_CMD_STATE_FREE;
898fcf3ce44SJohn Forte 
899fcf3ce44SJohn Forte 			mutex_enter(&isp->sess_cmdsn_mutex);
900fcf3ce44SJohn Forte 			iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
901fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
902fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
903fcf3ce44SJohn Forte 
904fcf3ce44SJohn Forte 			/*
90530e7468fSPeter Dunlap 			 * If this is an E4 then we may need to deal with
90630e7468fSPeter Dunlap 			 * the abort's associated SCSI command.  If this
90730e7468fSPeter Dunlap 			 * is an E10 then IDM is already cleaning up the
90830e7468fSPeter Dunlap 			 * SCSI command and all we need to do is break the
90930e7468fSPeter Dunlap 			 * linkage between them and free the abort command.
910fcf3ce44SJohn Forte 			 */
91130e7468fSPeter Dunlap 			t_icmdp = icmdp->cmd_un.abort.icmdp;
91230e7468fSPeter Dunlap 			ASSERT(t_icmdp != NULL);
91330e7468fSPeter Dunlap 			if (event != ISCSI_CMD_EVENT_E10) {
91430e7468fSPeter Dunlap 
91530e7468fSPeter Dunlap 				mutex_enter(&t_icmdp->cmd_mutex);
91630e7468fSPeter Dunlap 				t_icmdp->cmd_un.scsi.abort_icmdp = NULL;
91730e7468fSPeter Dunlap 				/*
91830e7468fSPeter Dunlap 				 * If abort command is aborted then we should
91930e7468fSPeter Dunlap 				 * not act on the parent scsi command.  If the
92030e7468fSPeter Dunlap 				 * abort command timed out then we need to
92130e7468fSPeter Dunlap 				 * complete the parent command if it still
92230e7468fSPeter Dunlap 				 * exists with a timeout failure.
92330e7468fSPeter Dunlap 				 */
92430e7468fSPeter Dunlap 				if ((event == ISCSI_CMD_EVENT_E6) &&
92530e7468fSPeter Dunlap 				    (t_icmdp->cmd_state !=
92630e7468fSPeter Dunlap 				    ISCSI_CMD_STATE_IDM_ABORTING) &&
92730e7468fSPeter Dunlap 				    (t_icmdp->cmd_state !=
92830e7468fSPeter Dunlap 				    ISCSI_CMD_STATE_COMPLETED)) {
92930e7468fSPeter Dunlap 
93030e7468fSPeter Dunlap 					iscsi_dequeue_active_cmd(
93130e7468fSPeter Dunlap 					    t_icmdp->cmd_conn, t_icmdp);
93230e7468fSPeter Dunlap 					mutex_enter(&icp->
93330e7468fSPeter Dunlap 					    conn_queue_idm_aborting.mutex);
93430e7468fSPeter Dunlap 					iscsi_enqueue_idm_aborting_cmd(
93530e7468fSPeter Dunlap 					    t_icmdp->cmd_conn,  t_icmdp);
93630e7468fSPeter Dunlap 					mutex_exit(&icp->
93730e7468fSPeter Dunlap 					    conn_queue_idm_aborting.mutex);
93830e7468fSPeter Dunlap 					/*
93930e7468fSPeter Dunlap 					 * Complete abort processing after IDM
94030e7468fSPeter Dunlap 					 * calls us back.  Set the status to use
94130e7468fSPeter Dunlap 					 * when we complete the command.
94230e7468fSPeter Dunlap 					 */
94330e7468fSPeter Dunlap 					ISCSI_CMD_SET_REASON_STAT(t_icmdp,
94430e7468fSPeter Dunlap 					    CMD_TIMEOUT, STAT_TIMEOUT);
94530e7468fSPeter Dunlap 					idm_task_abort(icp->conn_ic,
94630e7468fSPeter Dunlap 					    t_icmdp->cmd_itp,
94730e7468fSPeter Dunlap 					    AT_TASK_MGMT_ABORT);
94830e7468fSPeter Dunlap 				} else {
94930e7468fSPeter Dunlap 					cv_broadcast(&t_icmdp->cmd_completion);
95030e7468fSPeter Dunlap 				}
95130e7468fSPeter Dunlap 				mutex_exit(&t_icmdp->cmd_mutex);
95230e7468fSPeter Dunlap 			} else {
95330e7468fSPeter Dunlap 				t_icmdp->cmd_un.scsi.abort_icmdp = NULL;
954fcf3ce44SJohn Forte 			}
955fcf3ce44SJohn Forte 			icmdp->cmd_un.abort.icmdp = NULL;
956d233de7eSJack Meng 			icmdp->cmd_misc_flags |=
957d233de7eSJack Meng 			    ISCSI_CMD_MISCFLAG_FREE;
958fcf3ce44SJohn Forte 			break;
959fcf3ce44SJohn Forte 
960fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_RESET:
961fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
962fcf3ce44SJohn Forte 
963fcf3ce44SJohn Forte 			mutex_enter(&isp->sess_cmdsn_mutex);
964fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
965fcf3ce44SJohn Forte 			iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
966fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
967fcf3ce44SJohn Forte 
968fcf3ce44SJohn Forte 			/*
969fcf3ce44SJohn Forte 			 * If we are failing a RESET we need
970fcf3ce44SJohn Forte 			 * to notify the tran_reset caller.
971fcf3ce44SJohn Forte 			 * It will free the memory associated
972fcf3ce44SJohn Forte 			 * with the cmd and notify caller.
973fcf3ce44SJohn Forte 			 */
974fcf3ce44SJohn Forte 
975fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
976fcf3ce44SJohn Forte 			    ISCSI_STATUS_CMD_FAILED);
977fcf3ce44SJohn Forte 			break;
978fcf3ce44SJohn Forte 
979fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_LOGOUT:
980fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
981fcf3ce44SJohn Forte 
982fcf3ce44SJohn Forte 			mutex_enter(&isp->sess_cmdsn_mutex);
983fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
984fcf3ce44SJohn Forte 			iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
985fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
986fcf3ce44SJohn Forte 
987fcf3ce44SJohn Forte 			/*
988fcf3ce44SJohn Forte 			 * Notify caller of failure.
989fcf3ce44SJohn Forte 			 */
990fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
991fcf3ce44SJohn Forte 			    ISCSI_STATUS_CMD_FAILED);
992fcf3ce44SJohn Forte 			break;
993fcf3ce44SJohn Forte 
994fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_TEXT:
995fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
996fcf3ce44SJohn Forte 			icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
997fcf3ce44SJohn Forte 			mutex_enter(&isp->sess_cmdsn_mutex);
998fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
999fcf3ce44SJohn Forte 			iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
1000fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
1001fcf3ce44SJohn Forte 
1002fcf3ce44SJohn Forte 			/*
1003fcf3ce44SJohn Forte 			 * If a TEXT command fails, notify caller so
1004fcf3ce44SJohn Forte 			 * it can free assocated command
1005fcf3ce44SJohn Forte 			 */
1006fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
1007fcf3ce44SJohn Forte 			    ISCSI_STATUS_CMD_FAILED);
1008fcf3ce44SJohn Forte 			break;
1009fcf3ce44SJohn Forte 
1010fcf3ce44SJohn Forte 		default:
1011fcf3ce44SJohn Forte 			ASSERT(FALSE);
1012fcf3ce44SJohn Forte 		}
1013fcf3ce44SJohn Forte 
1014fcf3ce44SJohn Forte 		ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex));
1015fcf3ce44SJohn Forte 		break;
1016fcf3ce44SJohn Forte 
1017fcf3ce44SJohn Forte 	/* -E7: Connection has encountered a problem */
1018fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E7:
1019fcf3ce44SJohn Forte 		mutex_enter(&isp->sess_cmdsn_mutex);
1020fcf3ce44SJohn Forte 		iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
1021fcf3ce44SJohn Forte 
1022fcf3ce44SJohn Forte 		switch (icmdp->cmd_type) {
1023fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_SCSI:
1024fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
102530e7468fSPeter Dunlap 			mutex_enter(&icp->conn_queue_idm_aborting.mutex);
102630e7468fSPeter Dunlap 			iscsi_enqueue_idm_aborting_cmd(icmdp->cmd_conn, icmdp);
102730e7468fSPeter Dunlap 			mutex_exit(&icp->conn_queue_idm_aborting.mutex);
1028*2b79d384Sbing zhao - Sun Microsystems - Beijing China 			ISCSI_CMD_SET_REASON_STAT(icmdp,
1029*2b79d384Sbing zhao - Sun Microsystems - Beijing China 			    CMD_TRAN_ERR, icmdp->cmd_un.scsi.pkt_stat);
103030e7468fSPeter Dunlap 			idm_task_abort(icp->conn_ic, icmdp->cmd_itp,
103130e7468fSPeter Dunlap 			    AT_TASK_MGMT_ABORT);
1032fcf3ce44SJohn Forte 			break;
1033fcf3ce44SJohn Forte 
1034fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_NOP:
1035fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
1036fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
1037fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
1038fcf3ce44SJohn Forte 
1039d233de7eSJack Meng 			icmdp->cmd_misc_flags |=
1040d233de7eSJack Meng 			    ISCSI_CMD_MISCFLAG_FREE;
1041fcf3ce44SJohn Forte 			break;
1042fcf3ce44SJohn Forte 
1043fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_ABORT:
1044fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
1045fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
1046fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
1047fcf3ce44SJohn Forte 
1048fcf3ce44SJohn Forte 			mutex_enter(&icmdp->cmd_un.abort.icmdp->cmd_mutex);
1049fcf3ce44SJohn Forte 			icmdp->cmd_un.abort.icmdp->
1050fcf3ce44SJohn Forte 			    cmd_un.scsi.abort_icmdp = NULL;
1051fcf3ce44SJohn Forte 			cv_broadcast(&icmdp->cmd_un.abort.icmdp->
1052fcf3ce44SJohn Forte 			    cmd_completion);
1053fcf3ce44SJohn Forte 			mutex_exit(&icmdp->cmd_un.abort.icmdp->cmd_mutex);
1054fcf3ce44SJohn Forte 			/*
1055fcf3ce44SJohn Forte 			 * Nullify the abort command's pointer to its
1056fcf3ce44SJohn Forte 			 * parent command. It does not have to complete its
1057fcf3ce44SJohn Forte 			 * parent command because the parent command will
1058fcf3ce44SJohn Forte 			 * also get an E7.
1059fcf3ce44SJohn Forte 			 */
1060fcf3ce44SJohn Forte 			icmdp->cmd_un.abort.icmdp = NULL;
1061fcf3ce44SJohn Forte 
1062d233de7eSJack Meng 			icmdp->cmd_misc_flags |=
1063d233de7eSJack Meng 			    ISCSI_CMD_MISCFLAG_FREE;
1064fcf3ce44SJohn Forte 			break;
1065fcf3ce44SJohn Forte 
1066fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_RESET:
1067fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
1068fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
1069fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
1070fcf3ce44SJohn Forte 			/*
1071fcf3ce44SJohn Forte 			 * If we are failing a ABORT we need
1072fcf3ce44SJohn Forte 			 * to notify the tran_abort caller.
1073fcf3ce44SJohn Forte 			 * It will free the memory associated
1074fcf3ce44SJohn Forte 			 * with the cmd and notify caller.
1075fcf3ce44SJohn Forte 			 */
1076fcf3ce44SJohn Forte 
1077fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
1078fcf3ce44SJohn Forte 			    ISCSI_STATUS_CMD_FAILED);
1079fcf3ce44SJohn Forte 			break;
1080fcf3ce44SJohn Forte 
1081fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_LOGOUT:
1082fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
1083fcf3ce44SJohn Forte 			/*
1084fcf3ce44SJohn Forte 			 * A connection problem and we attempted to
1085fcf3ce44SJohn Forte 			 * logout?  I guess we can just free the
1086fcf3ce44SJohn Forte 			 * request.  Someone has already pushed the
1087fcf3ce44SJohn Forte 			 * connection state.
1088fcf3ce44SJohn Forte 			 */
1089fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
1090fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
1091fcf3ce44SJohn Forte 
1092fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp, ISCSI_STATUS_SUCCESS);
1093fcf3ce44SJohn Forte 			break;
1094fcf3ce44SJohn Forte 
1095fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_TEXT:
1096fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
1097fcf3ce44SJohn Forte 			icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1098fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
1099fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
1100fcf3ce44SJohn Forte 
1101fcf3ce44SJohn Forte 			/*
1102fcf3ce44SJohn Forte 			 * If a TEXT command fails, notify caller so
1103fcf3ce44SJohn Forte 			 * it can free assocated command
1104fcf3ce44SJohn Forte 			 */
1105fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
1106fcf3ce44SJohn Forte 			    ISCSI_STATUS_CMD_FAILED);
1107fcf3ce44SJohn Forte 			break;
1108fcf3ce44SJohn Forte 
1109fcf3ce44SJohn Forte 		default:
1110fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
1111fcf3ce44SJohn Forte 			ASSERT(FALSE);
1112fcf3ce44SJohn Forte 			break;
1113fcf3ce44SJohn Forte 		}
1114fcf3ce44SJohn Forte 
1115fcf3ce44SJohn Forte 		ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex));
1116fcf3ce44SJohn Forte 		break;
1117fcf3ce44SJohn Forte 
111830e7468fSPeter Dunlap 	/* -E9: IDM is no longer processing this command */
111930e7468fSPeter Dunlap 	case ISCSI_CMD_EVENT_E9:
112030e7468fSPeter Dunlap 		iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
112130e7468fSPeter Dunlap 
112230e7468fSPeter Dunlap 		iscsi_task_cleanup(ISCSI_OP_SCSI_RSP, icmdp);
112330e7468fSPeter Dunlap 		iscsi_sess_release_scsi_itt(icmdp);
112430e7468fSPeter Dunlap 
1125*2b79d384Sbing zhao - Sun Microsystems - Beijing China 		ISCSI_CMD_SET_REASON_STAT(icmdp, CMD_TRAN_ERR,
1126*2b79d384Sbing zhao - Sun Microsystems - Beijing China 		    icmdp->cmd_un.scsi.pkt_stat);
112730e7468fSPeter Dunlap 		iscsi_enqueue_completed_cmd(isp, icmdp);
112830e7468fSPeter Dunlap 		break;
112930e7468fSPeter Dunlap 
1130fcf3ce44SJohn Forte 	/* All other events are invalid for this state */
1131fcf3ce44SJohn Forte 	default:
1132fcf3ce44SJohn Forte 		ASSERT(FALSE);
1133fcf3ce44SJohn Forte 	}
1134fcf3ce44SJohn Forte }
1135fcf3ce44SJohn Forte 
1136fcf3ce44SJohn Forte 
1137fcf3ce44SJohn Forte /*
1138fcf3ce44SJohn Forte  * iscsi_cmd_state_aborting -
1139fcf3ce44SJohn Forte  *
1140fcf3ce44SJohn Forte  */
1141fcf3ce44SJohn Forte static void
1142fcf3ce44SJohn Forte iscsi_cmd_state_aborting(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
1143fcf3ce44SJohn Forte {
1144fcf3ce44SJohn Forte 	iscsi_sess_t	*isp	= (iscsi_sess_t *)arg;
114530e7468fSPeter Dunlap 	iscsi_cmd_t	*a_icmdp;
1146fcf3ce44SJohn Forte 
1147fcf3ce44SJohn Forte 	ASSERT(icmdp != NULL);
1148fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI);
1149fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_ABORTING);
1150fcf3ce44SJohn Forte 	ASSERT(isp != NULL);
1151fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&icmdp->cmd_conn->conn_queue_active.mutex));
1152fcf3ce44SJohn Forte 
1153fcf3ce44SJohn Forte 	/* switch on event change */
1154fcf3ce44SJohn Forte 	switch (event) {
1155fcf3ce44SJohn Forte 	/* -E3: Command was successfully completed */
1156fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E3:
1157fcf3ce44SJohn Forte 		/*
1158fcf3ce44SJohn Forte 		 * Remove command from the aborting list
1159fcf3ce44SJohn Forte 		 */
1160fcf3ce44SJohn Forte 		mutex_enter(&isp->sess_cmdsn_mutex);
1161fcf3ce44SJohn Forte 		iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
116230e7468fSPeter Dunlap 		iscsi_sess_release_scsi_itt(icmdp);
1163fcf3ce44SJohn Forte 		mutex_exit(&isp->sess_cmdsn_mutex);
1164fcf3ce44SJohn Forte 
1165fcf3ce44SJohn Forte 		iscsi_enqueue_completed_cmd(isp, icmdp);
1166fcf3ce44SJohn Forte 		break;
1167fcf3ce44SJohn Forte 
1168fcf3ce44SJohn Forte 	/* -E4: Command has been requested to abort */
1169fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E4:
1170fcf3ce44SJohn Forte 		/*
1171fcf3ce44SJohn Forte 		 * An upper level driver might attempt to
1172fcf3ce44SJohn Forte 		 * abort a command that we are already
1173fcf3ce44SJohn Forte 		 * aborting due to a nop.  Since we are
1174fcf3ce44SJohn Forte 		 * already in the process of aborting
1175fcf3ce44SJohn Forte 		 * ignore the request.
1176fcf3ce44SJohn Forte 		 */
1177fcf3ce44SJohn Forte 		break;
1178fcf3ce44SJohn Forte 
1179fcf3ce44SJohn Forte 	/* -E6: Command has timed out */
1180fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E6:
1181fcf3ce44SJohn Forte 		ASSERT(FALSE);
1182fcf3ce44SJohn Forte 		/*
1183fcf3ce44SJohn Forte 		 * Timeouts should not occur on command in abort queue
1184fcf3ce44SJohn Forte 		 * they are already be processed due to a timeout.
1185fcf3ce44SJohn Forte 		 */
1186fcf3ce44SJohn Forte 		break;
1187fcf3ce44SJohn Forte 
1188fcf3ce44SJohn Forte 	/* -E7: Connection has encountered a problem */
1189fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E7:
1190fcf3ce44SJohn Forte 		iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
119130e7468fSPeter Dunlap 		mutex_enter(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex);
119230e7468fSPeter Dunlap 		iscsi_enqueue_idm_aborting_cmd(icmdp->cmd_conn, icmdp);
119330e7468fSPeter Dunlap 		mutex_exit(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex);
1194fcf3ce44SJohn Forte 
119530e7468fSPeter Dunlap 		/*
119630e7468fSPeter Dunlap 		 * Since we are in "aborting" state there is another command
119730e7468fSPeter Dunlap 		 * representing the abort of this command.  This command
119830e7468fSPeter Dunlap 		 * will cleanup at some indeterminate time after the call
119930e7468fSPeter Dunlap 		 * to idm_task_abort so we can't leave the abort request
120030e7468fSPeter Dunlap 		 * active.  An E10 event to the abort command will cause
120130e7468fSPeter Dunlap 		 * it to complete immediately.
120230e7468fSPeter Dunlap 		 */
120330e7468fSPeter Dunlap 		if ((a_icmdp = icmdp->cmd_un.scsi.abort_icmdp) != NULL) {
120430e7468fSPeter Dunlap 			iscsi_cmd_state_machine(a_icmdp,
120530e7468fSPeter Dunlap 			    ISCSI_CMD_EVENT_E10, arg);
120630e7468fSPeter Dunlap 		}
120730e7468fSPeter Dunlap 
1208*2b79d384Sbing zhao - Sun Microsystems - Beijing China 		ISCSI_CMD_SET_REASON_STAT(icmdp,
1209*2b79d384Sbing zhao - Sun Microsystems - Beijing China 		    CMD_TRAN_ERR, icmdp->cmd_un.scsi.pkt_stat);
1210*2b79d384Sbing zhao - Sun Microsystems - Beijing China 
121130e7468fSPeter Dunlap 		idm_task_abort(icmdp->cmd_conn->conn_ic, icmdp->cmd_itp,
121230e7468fSPeter Dunlap 		    AT_TASK_MGMT_ABORT);
121330e7468fSPeter Dunlap 		break;
121430e7468fSPeter Dunlap 
121530e7468fSPeter Dunlap 	/* -E9: IDM is no longer processing this command */
121630e7468fSPeter Dunlap 	case ISCSI_CMD_EVENT_E9:
121730e7468fSPeter Dunlap 		iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
121830e7468fSPeter Dunlap 
121930e7468fSPeter Dunlap 		iscsi_task_cleanup(ISCSI_OP_SCSI_RSP, icmdp);
122030e7468fSPeter Dunlap 		iscsi_sess_release_scsi_itt(icmdp);
122130e7468fSPeter Dunlap 
1222*2b79d384Sbing zhao - Sun Microsystems - Beijing China 		ISCSI_CMD_SET_REASON_STAT(icmdp, CMD_TRAN_ERR,
1223*2b79d384Sbing zhao - Sun Microsystems - Beijing China 		    icmdp->cmd_un.scsi.pkt_stat);
122430e7468fSPeter Dunlap 		iscsi_enqueue_completed_cmd(isp, icmdp);
122530e7468fSPeter Dunlap 		break;
122630e7468fSPeter Dunlap 
122730e7468fSPeter Dunlap 	/* All other events are invalid for this state */
122830e7468fSPeter Dunlap 	default:
122930e7468fSPeter Dunlap 		ASSERT(FALSE);
123030e7468fSPeter Dunlap 	}
123130e7468fSPeter Dunlap }
123230e7468fSPeter Dunlap 
123330e7468fSPeter Dunlap static void
123430e7468fSPeter Dunlap iscsi_cmd_state_idm_aborting(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event,
123530e7468fSPeter Dunlap     void *arg)
123630e7468fSPeter Dunlap {
123730e7468fSPeter Dunlap 	iscsi_sess_t	*isp	= (iscsi_sess_t *)arg;
123830e7468fSPeter Dunlap 
123930e7468fSPeter Dunlap 	ASSERT(icmdp != NULL);
124030e7468fSPeter Dunlap 	ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI);
124130e7468fSPeter Dunlap 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_IDM_ABORTING);
124230e7468fSPeter Dunlap 	ASSERT(isp != NULL);
124330e7468fSPeter Dunlap 
124430e7468fSPeter Dunlap 	/* switch on event change */
124530e7468fSPeter Dunlap 	switch (event) {
124630e7468fSPeter Dunlap 	/* -E3: Command was successfully completed */
124730e7468fSPeter Dunlap 	case ISCSI_CMD_EVENT_E3:
124830e7468fSPeter Dunlap 		/*
124930e7468fSPeter Dunlap 		 * iscsi_rx_process_cmd_rsp() and iscsi_rx_process_data_rsp()
125030e7468fSPeter Dunlap 		 * are supposed to confirm the cmd state is appropriate before
125130e7468fSPeter Dunlap 		 * generating an E3 event.  E3 is not allowed in this state.
125230e7468fSPeter Dunlap 		 */
125330e7468fSPeter Dunlap 		ASSERT(0);
125430e7468fSPeter Dunlap 		break;
125530e7468fSPeter Dunlap 
125630e7468fSPeter Dunlap 	/* -E4: Command has been requested to abort */
125730e7468fSPeter Dunlap 	case ISCSI_CMD_EVENT_E4:
125830e7468fSPeter Dunlap 		/*
125930e7468fSPeter Dunlap 		 * An upper level driver might attempt to
126030e7468fSPeter Dunlap 		 * abort a command that we are already
126130e7468fSPeter Dunlap 		 * aborting due to a nop.  Since we are
126230e7468fSPeter Dunlap 		 * already in the process of aborting
126330e7468fSPeter Dunlap 		 * ignore the request.
126430e7468fSPeter Dunlap 		 */
126530e7468fSPeter Dunlap 		break;
126630e7468fSPeter Dunlap 
126730e7468fSPeter Dunlap 	/* -E6: Command has timed out */
126830e7468fSPeter Dunlap 	case ISCSI_CMD_EVENT_E6:
126930e7468fSPeter Dunlap 		ASSERT(FALSE);
127030e7468fSPeter Dunlap 		/*
127130e7468fSPeter Dunlap 		 * Timeouts should not occur on aborting commands
127230e7468fSPeter Dunlap 		 */
127330e7468fSPeter Dunlap 		break;
127430e7468fSPeter Dunlap 
127530e7468fSPeter Dunlap 	/* -E7: Connection has encountered a problem */
127630e7468fSPeter Dunlap 	case ISCSI_CMD_EVENT_E7:
127730e7468fSPeter Dunlap 		/*
127830e7468fSPeter Dunlap 		 * We have already requested IDM to stop processing this
1279*2b79d384Sbing zhao - Sun Microsystems - Beijing China 		 * command so just update the pkt_statistics.
128030e7468fSPeter Dunlap 		 */
1281*2b79d384Sbing zhao - Sun Microsystems - Beijing China 		ISCSI_CMD_SET_REASON_STAT(icmdp,
1282*2b79d384Sbing zhao - Sun Microsystems - Beijing China 		    CMD_TRAN_ERR, icmdp->cmd_un.scsi.pkt_stat);
128330e7468fSPeter Dunlap 		break;
128430e7468fSPeter Dunlap 
128530e7468fSPeter Dunlap 	/* -E9: IDM is no longer processing this command */
128630e7468fSPeter Dunlap 	case ISCSI_CMD_EVENT_E9:
128730e7468fSPeter Dunlap 		mutex_enter(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex);
128830e7468fSPeter Dunlap 		iscsi_dequeue_idm_aborting_cmd(icmdp->cmd_conn, icmdp);
128930e7468fSPeter Dunlap 		mutex_exit(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex);
129030e7468fSPeter Dunlap 
129130e7468fSPeter Dunlap 		/* This is always an error so make sure an error has been set */
129230e7468fSPeter Dunlap 		ASSERT(icmdp->cmd_un.scsi.pkt->pkt_reason != CMD_CMPLT);
129330e7468fSPeter Dunlap 		iscsi_task_cleanup(ISCSI_OP_SCSI_RSP, icmdp);
129430e7468fSPeter Dunlap 		iscsi_sess_release_scsi_itt(icmdp);
129530e7468fSPeter Dunlap 
129630e7468fSPeter Dunlap 		/*
129730e7468fSPeter Dunlap 		 * Whoever called idm_task_abort should have set the completion
129830e7468fSPeter Dunlap 		 * status beforehand.
129930e7468fSPeter Dunlap 		 */
1300fcf3ce44SJohn Forte 		iscsi_enqueue_completed_cmd(isp, icmdp);
130130e7468fSPeter Dunlap 		cv_broadcast(&icmdp->cmd_completion);
1302fcf3ce44SJohn Forte 		break;
1303fcf3ce44SJohn Forte 
1304fcf3ce44SJohn Forte 	/* All other events are invalid for this state */
1305fcf3ce44SJohn Forte 	default:
1306fcf3ce44SJohn Forte 		ASSERT(FALSE);
1307fcf3ce44SJohn Forte 	}
1308fcf3ce44SJohn Forte }
1309fcf3ce44SJohn Forte 
1310fcf3ce44SJohn Forte 
1311fcf3ce44SJohn Forte /*
1312fcf3ce44SJohn Forte  * iscsi_cmd_state_completed -
1313fcf3ce44SJohn Forte  *
1314fcf3ce44SJohn Forte  */
1315fcf3ce44SJohn Forte static void
1316fcf3ce44SJohn Forte iscsi_cmd_state_completed(iscsi_cmd_t *icmdp,
1317fcf3ce44SJohn Forte     iscsi_cmd_event_t event, void *arg)
1318fcf3ce44SJohn Forte {
1319fcf3ce44SJohn Forte 	iscsi_sess_t	*isp	= (iscsi_sess_t *)arg;
1320fcf3ce44SJohn Forte 
1321fcf3ce44SJohn Forte 	ASSERT(icmdp != NULL);
1322fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI);
1323fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_COMPLETED);
1324fcf3ce44SJohn Forte 	ASSERT(isp != NULL);
1325fcf3ce44SJohn Forte 
1326fcf3ce44SJohn Forte 	/* switch on event change */
1327fcf3ce44SJohn Forte 	switch (event) {
1328fcf3ce44SJohn Forte 	/* -E8: */
1329fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E8:
1330fcf3ce44SJohn Forte 		icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
1331fcf3ce44SJohn Forte 
1332fcf3ce44SJohn Forte 		/* the caller has already remove cmd from queue */
1333fcf3ce44SJohn Forte 
1334fcf3ce44SJohn Forte 		icmdp->cmd_next = NULL;
1335fcf3ce44SJohn Forte 		icmdp->cmd_prev = NULL;
1336fcf3ce44SJohn Forte 		iscsi_iodone(isp, icmdp);
1337fcf3ce44SJohn Forte 		break;
1338fcf3ce44SJohn Forte 	/* All other events are invalid for this state */
1339fcf3ce44SJohn Forte 	default:
1340fcf3ce44SJohn Forte 		ASSERT(FALSE);
1341fcf3ce44SJohn Forte 	}
1342fcf3ce44SJohn Forte }
1343fcf3ce44SJohn Forte 
1344fcf3ce44SJohn Forte 
1345fcf3ce44SJohn Forte /*
1346fcf3ce44SJohn Forte  * iscsi_cmd_state_str -
1347fcf3ce44SJohn Forte  *
1348fcf3ce44SJohn Forte  */
1349fcf3ce44SJohn Forte static char *
1350fcf3ce44SJohn Forte iscsi_cmd_state_str(iscsi_cmd_state_t state)
1351fcf3ce44SJohn Forte {
1352fcf3ce44SJohn Forte 	switch (state) {
1353fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_FREE:
1354fcf3ce44SJohn Forte 		return ("free");
1355fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_PENDING:
1356fcf3ce44SJohn Forte 		return ("pending");
1357fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_ACTIVE:
1358fcf3ce44SJohn Forte 		return ("active");
1359fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_ABORTING:
1360fcf3ce44SJohn Forte 		return ("aborting");
136130e7468fSPeter Dunlap 	case ISCSI_CMD_STATE_IDM_ABORTING:
136230e7468fSPeter Dunlap 		return ("idm-aborting");
1363fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_COMPLETED:
1364fcf3ce44SJohn Forte 		return ("completed");
1365fcf3ce44SJohn Forte 	default:
1366fcf3ce44SJohn Forte 		return ("unknown");
1367fcf3ce44SJohn Forte 	}
1368fcf3ce44SJohn Forte }
1369fcf3ce44SJohn Forte 
1370fcf3ce44SJohn Forte 
1371fcf3ce44SJohn Forte /*
1372fcf3ce44SJohn Forte  * iscsi_cmd_event_str -
1373fcf3ce44SJohn Forte  *
1374fcf3ce44SJohn Forte  */
1375fcf3ce44SJohn Forte static char *
1376fcf3ce44SJohn Forte iscsi_cmd_event_str(iscsi_cmd_event_t event)
1377fcf3ce44SJohn Forte {
1378fcf3ce44SJohn Forte 	switch (event) {
1379fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E1:
1380fcf3ce44SJohn Forte 		return ("E1");
1381fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E2:
1382fcf3ce44SJohn Forte 		return ("E2");
1383fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E3:
1384fcf3ce44SJohn Forte 		return ("E3");
1385fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E4:
1386fcf3ce44SJohn Forte 		return ("E4");
1387fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E6:
1388fcf3ce44SJohn Forte 		return ("E6");
1389fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E7:
1390fcf3ce44SJohn Forte 		return ("E7");
1391fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E8:
1392fcf3ce44SJohn Forte 		return ("E8");
139330e7468fSPeter Dunlap 	case ISCSI_CMD_EVENT_E9:
139430e7468fSPeter Dunlap 		return ("E9");
139530e7468fSPeter Dunlap 	case ISCSI_CMD_EVENT_E10:
139630e7468fSPeter Dunlap 		return ("E10");
1397fcf3ce44SJohn Forte 	default:
1398fcf3ce44SJohn Forte 		return ("unknown");
1399fcf3ce44SJohn Forte 	}
1400fcf3ce44SJohn Forte }
1401fcf3ce44SJohn Forte 
1402fcf3ce44SJohn Forte 
1403fcf3ce44SJohn Forte /*
1404fcf3ce44SJohn Forte  * iscsi_cmd_event_str -
1405fcf3ce44SJohn Forte  *
1406fcf3ce44SJohn Forte  */
1407fcf3ce44SJohn Forte static char *
1408fcf3ce44SJohn Forte iscsi_cmd_type_str(iscsi_cmd_type_t type)
1409fcf3ce44SJohn Forte {
1410fcf3ce44SJohn Forte 	switch (type) {
1411fcf3ce44SJohn Forte 	case ISCSI_CMD_TYPE_SCSI:
1412fcf3ce44SJohn Forte 		return ("scsi");
1413fcf3ce44SJohn Forte 	case ISCSI_CMD_TYPE_NOP:
1414fcf3ce44SJohn Forte 		return ("nop");
1415fcf3ce44SJohn Forte 	case ISCSI_CMD_TYPE_ABORT:
1416fcf3ce44SJohn Forte 		return ("abort");
1417fcf3ce44SJohn Forte 	case ISCSI_CMD_TYPE_RESET:
1418fcf3ce44SJohn Forte 		return ("reset");
1419fcf3ce44SJohn Forte 	case ISCSI_CMD_TYPE_LOGOUT:
1420fcf3ce44SJohn Forte 		return ("logout");
1421fcf3ce44SJohn Forte 	default:
1422fcf3ce44SJohn Forte 		return ("unknown");
1423fcf3ce44SJohn Forte 	}
1424fcf3ce44SJohn Forte }
1425