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  *
25*61dfa509SRick McNeal  * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
26fcf3ce44SJohn Forte  * iSCSI command interfaces
27fcf3ce44SJohn Forte  */
28fcf3ce44SJohn Forte 
29fcf3ce44SJohn Forte #include "iscsi.h"
30fcf3ce44SJohn Forte 
31fcf3ce44SJohn Forte /* internal interfaces */
32fcf3ce44SJohn Forte static void iscsi_cmd_state_free(iscsi_cmd_t *icmdp,
33fcf3ce44SJohn Forte     iscsi_cmd_event_t event, void *arg);
34fcf3ce44SJohn Forte static void iscsi_cmd_state_pending(iscsi_cmd_t *icmdp,
35fcf3ce44SJohn Forte     iscsi_cmd_event_t event, void *arg);
36fcf3ce44SJohn Forte static void iscsi_cmd_state_active(iscsi_cmd_t *icmdp,
37fcf3ce44SJohn Forte     iscsi_cmd_event_t event, void *arg);
38fcf3ce44SJohn Forte static void iscsi_cmd_state_aborting(iscsi_cmd_t *icmdp,
39fcf3ce44SJohn Forte     iscsi_cmd_event_t event, void *arg);
4030e7468fSPeter Dunlap static void iscsi_cmd_state_idm_aborting(iscsi_cmd_t *icmdp,
4130e7468fSPeter Dunlap     iscsi_cmd_event_t event, void *arg);
42fcf3ce44SJohn Forte static void iscsi_cmd_state_completed(iscsi_cmd_t *icmdp,
43fcf3ce44SJohn Forte     iscsi_cmd_event_t event, void *arg);
44fcf3ce44SJohn Forte static char *iscsi_cmd_state_str(iscsi_cmd_state_t state);
45fcf3ce44SJohn Forte static char *iscsi_cmd_event_str(iscsi_cmd_event_t event);
46fcf3ce44SJohn Forte /* LINTED E_STATIC_UNUSED */
47fcf3ce44SJohn Forte static char *iscsi_cmd_type_str(iscsi_cmd_type_t type);
48fcf3ce44SJohn Forte 
49fcf3ce44SJohn Forte #define	ISCSI_INTERNAL_CMD_TIMEOUT	60
50fcf3ce44SJohn Forte 
51fcf3ce44SJohn Forte #define	ISCSI_CMD_ISSUE_CALLBACK(icmdp, status)	\
52fcf3ce44SJohn Forte 	icmdp->cmd_completed = B_TRUE;		\
53fcf3ce44SJohn Forte 	icmdp->cmd_result = status;		\
54fcf3ce44SJohn Forte 	cv_broadcast(&icmdp->cmd_completion);
55fcf3ce44SJohn Forte 
56fcf3ce44SJohn Forte #define	ISCSI_CMD_SET_REASON_STAT(icmdp, reason, stat)	\
57fcf3ce44SJohn Forte 	icmdp->cmd_un.scsi.pkt->pkt_reason = reason;	\
58fcf3ce44SJohn Forte 	icmdp->cmd_un.scsi.pkt->pkt_statistics = stat;
59fcf3ce44SJohn Forte 
60fcf3ce44SJohn Forte /*
61fcf3ce44SJohn Forte  * The following private tunable, settable via
62fcf3ce44SJohn Forte  *	set iscsi:iscsi_cmd_timeout_factor = 2
63fcf3ce44SJohn Forte  * in /etc/system, provides customer relief for configurations experiencing
64fcf3ce44SJohn Forte  * SCSI command timeouts due to high-latency/high-loss network connections
65fcf3ce44SJohn Forte  * or slow target response (possibly due to backing store issues). If frequent
66fcf3ce44SJohn Forte  * use of this tunable is necessary, a beter mechanism must be provided.
67fcf3ce44SJohn Forte  */
68fcf3ce44SJohn Forte int	iscsi_cmd_timeout_factor = 1;
69fcf3ce44SJohn Forte 
70fcf3ce44SJohn Forte /*
71fcf3ce44SJohn Forte  * +--------------------------------------------------------------------+
72fcf3ce44SJohn Forte  * | External Command Interfaces					|
73fcf3ce44SJohn Forte  * +--------------------------------------------------------------------+
74fcf3ce44SJohn Forte  */
75fcf3ce44SJohn Forte 
76fcf3ce44SJohn Forte /*
77fcf3ce44SJohn Forte  * iscsi_cmd_state_machine - This function is used to drive the
78fcf3ce44SJohn Forte  * state machine of the internal iscsi commands.  It takes in a command
79fcf3ce44SJohn Forte  * and the associated event affecting the command.
80fcf3ce44SJohn Forte  *
81fcf3ce44SJohn Forte  * 7.1.3  Command State Diagram for an Initiator
82fcf3ce44SJohn Forte  *      Symbolic Names for States:
83fcf3ce44SJohn Forte  *      C1: FREE        - State on instantiation, or after successful
84fcf3ce44SJohn Forte  *                        completion.
85fcf3ce44SJohn Forte  *      C2: PENDING     - Command is in the session's pending queue awaiting
86fcf3ce44SJohn Forte  *                        its turn to be sent on the wire.
87fcf3ce44SJohn Forte  *      C3: ACTIVE      - Command has been sent on the wire and is
88fcf3ce44SJohn Forte  *                        awaiting completion.
89fcf3ce44SJohn Forte  *      C4: ABORTING    - Command which was sent on the wire has not timed
90fcf3ce44SJohn Forte  *                        out or been requested to abort by an upper layer
91fcf3ce44SJohn Forte  *                        driver.  At this point there is a task management
92fcf3ce44SJohn Forte  *                        command in the active queue trying to abort the task.
9330e7468fSPeter Dunlap  *	C4': IDM ABORTING - SCSI command is owned by IDM and idm_task_abort
9430e7468fSPeter Dunlap  *                          has been called for this command.
95fcf3ce44SJohn Forte  *      C5: COMPLETED	- Command which is ready to complete via pkt callback.
96fcf3ce44SJohn Forte  *
97fcf3ce44SJohn Forte  *      The state diagram is as follows:
98fcf3ce44SJohn Forte  *               -------
99fcf3ce44SJohn Forte  *              / C1    \
100fcf3ce44SJohn Forte  *    I-------->\       /<------------
101fcf3ce44SJohn Forte  *    N|         ---+---             |
102fcf3ce44SJohn Forte  *    T|            |E1              |
103fcf3ce44SJohn Forte  *    E|            V                |
104fcf3ce44SJohn Forte  *    R|         -------             |
105fcf3ce44SJohn Forte  *    N+--------/ C2    \            |
106fcf3ce44SJohn Forte  *    A|  E4/6/7\       /--------    |
107fcf3ce44SJohn Forte  *    L|         ---+---  E4/6/7|    |
10830e7468fSPeter Dunlap  *     |            |E2    E10  |    |
109fcf3ce44SJohn Forte  *    C|            V           | S  |
110fcf3ce44SJohn Forte  *    M|         _______        | C  |
111fcf3ce44SJohn Forte  *    D+--------/ C3    \       | S  |
112fcf3ce44SJohn Forte  *    S E3/4/6/7\       /-------+ I  |
11330e7468fSPeter Dunlap  *              /---+---E3/4/6/7|    |
11430e7468fSPeter Dunlap  *             /    |      E9/10|    |
11530e7468fSPeter Dunlap  *      ------/ E4/6|           | C  |
11630e7468fSPeter Dunlap  *      |           V           | M  |
11730e7468fSPeter Dunlap  *    E7|        -------        | D  |
11830e7468fSPeter Dunlap  *  SCSI|    - >/ C4    \       | S  |
11930e7468fSPeter Dunlap  *      |   /   \       /-------+    |
12030e7468fSPeter Dunlap  *      |   |    ---+---E3/6/7/9|    |
12130e7468fSPeter Dunlap  *      |   |  E4|  |           V   /E8
12230e7468fSPeter Dunlap  *      |   ------  |        -------
12330e7468fSPeter Dunlap  *      +-\         /       / C5    \
12430e7468fSPeter Dunlap  *      V  \-------/  /---->\       /
12530e7468fSPeter Dunlap  *   -------    E7   /       ---+---
12630e7468fSPeter Dunlap  *  / C4'   \       /
12730e7468fSPeter Dunlap  *  \       /------/ E9
12830e7468fSPeter Dunlap  *   -------
129fcf3ce44SJohn Forte  *
130fcf3ce44SJohn Forte  * The state transition table is as follows:
131fcf3ce44SJohn Forte  *
13230e7468fSPeter Dunlap  *         +---------+---+---+-----+----+--------------+
13330e7468fSPeter Dunlap  *         |C1       |C2 |C3 |C4   |C4' |C5            |
13430e7468fSPeter Dunlap  *      ---+---------+---+---+-----+----+--------------+
13530e7468fSPeter Dunlap  *       C1| -       |E1 | - | -   | -  |              |
13630e7468fSPeter Dunlap  *      ---+---------+---+---+-----+----+--------------+
13730e7468fSPeter Dunlap  *       C2|E4/6/7   |-  |E2 | -   | -  |E4/6/7/10     |
13830e7468fSPeter Dunlap  *      ---+---------+---+---+-----+----+--------------+
13930e7468fSPeter Dunlap  *       C3|E3/4/6/7 |-  |-  |E4/6 |E7  |E3/4/6/7/9/10 |
14030e7468fSPeter Dunlap  *      ---+---------+---+---+-----+----+--------------+
14130e7468fSPeter Dunlap  *       C4|         |-  |-  |E4   |E7  |E3/6/7/9      |
14230e7468fSPeter Dunlap  *      ---+---------+---+---+-----+----+--------------+
14330e7468fSPeter Dunlap  *      C4'|         |-  |-  |-    |-   |E9            |
14430e7468fSPeter Dunlap  *      ---+---------+---+---+-----+----+--------------+
14530e7468fSPeter Dunlap  *       C5|E8       |   |   |     |    |              |
14630e7468fSPeter Dunlap  *      ---+---------+---+---+-----+----+--------------+
147fcf3ce44SJohn Forte  *
148fcf3ce44SJohn Forte  * Event definitions:
149fcf3ce44SJohn Forte  *
150fcf3ce44SJohn Forte  * -E1: Command was requested to be sent on wire
151fcf3ce44SJohn Forte  * -E2: Command was submitted and now active on wire
152fcf3ce44SJohn Forte  * -E3: Command was successfully completed
153fcf3ce44SJohn Forte  *	- SCSI command is move to completion queue
154fcf3ce44SJohn Forte  *	- ABORT/RESET/etc are completed.
155fcf3ce44SJohn Forte  * -E4: Command has been requested to abort
156fcf3ce44SJohn Forte  *	- SCSI command in pending queue will be returned
157fcf3ce44SJohn Forte  *		to caller with aborted status.
158fcf3ce44SJohn Forte  *	- SCSI command state updated and iscsi_handle_abort()
159fcf3ce44SJohn Forte  *		will be called.
160fcf3ce44SJohn Forte  *	- SCSI command with ABORTING state has already
161fcf3ce44SJohn Forte  *		been requested to abort ignore request.
162fcf3ce44SJohn Forte  *	- ABORT/RESET commands will be destroyed and the
163fcf3ce44SJohn Forte  *		caller will be notify of the failure.
164fcf3ce44SJohn Forte  *	- All other commands will just be destroyed.
165fcf3ce44SJohn Forte  * -E6: Command has timed out
166fcf3ce44SJohn Forte  *	- SCSI commands in pending queue will be returned up the
167fcf3ce44SJohn Forte  *		stack with TIMEOUT errors.
168fcf3ce44SJohn Forte  *	- SCSI commands in the active queue and timed out
169fcf3ce44SJohn Forte  *		will be moved to the aborting queue.
170fcf3ce44SJohn Forte  *	- SCSI commands in ABORTING state will be returned up
171fcf3ce44SJohn Forte  *		up the stack with TIMEOUT errors.
172fcf3ce44SJohn Forte  *	- ABORT/RESET commands will be destroyed and the caller
173fcf3ce44SJohn Forte  *		notified of the failure.
174fcf3ce44SJohn Forte  *	- All other commands will just be detroyed.
175fcf3ce44SJohn Forte  * -E7: Connection has encountered a problem
176fcf3ce44SJohn Forte  * -E8:	Command has completed
177fcf3ce44SJohn Forte  *	- Only SCSI cmds should receive these events
178fcf3ce44SJohn Forte  *		and reach the command state.
17930e7468fSPeter Dunlap  * -E9: Callback received for previous idm_task_abort request
18030e7468fSPeter Dunlap  * -E10: The command this abort was associated with has terminated on its own
181fcf3ce44SJohn Forte  */
182fcf3ce44SJohn Forte void
iscsi_cmd_state_machine(iscsi_cmd_t * icmdp,iscsi_cmd_event_t event,void * arg)183fcf3ce44SJohn Forte iscsi_cmd_state_machine(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
184fcf3ce44SJohn Forte {
185fcf3ce44SJohn Forte 	boolean_t	release_lock = B_TRUE;
186fcf3ce44SJohn Forte 
187fcf3ce44SJohn Forte 	ASSERT(icmdp != NULL);
188fcf3ce44SJohn Forte 	ASSERT(arg != NULL);
189fcf3ce44SJohn Forte 
190fcf3ce44SJohn Forte 	DTRACE_PROBE3(event, iscsi_cmd_t *, icmdp, char *,
191fcf3ce44SJohn Forte 	    iscsi_cmd_state_str(icmdp->cmd_state),
192fcf3ce44SJohn Forte 	    char *, iscsi_cmd_event_str(event));
193fcf3ce44SJohn Forte 
194fcf3ce44SJohn Forte 	mutex_enter(&icmdp->cmd_mutex);
19530e7468fSPeter Dunlap 
19630e7468fSPeter Dunlap 	/* Audit event */
19730e7468fSPeter Dunlap 	idm_sm_audit_event(&icmdp->cmd_state_audit,
19830e7468fSPeter Dunlap 	    SAS_ISCSI_CMD, icmdp->cmd_state, event, (uintptr_t)arg);
19930e7468fSPeter Dunlap 
200fcf3ce44SJohn Forte 	icmdp->cmd_prev_state = icmdp->cmd_state;
201fcf3ce44SJohn Forte 	switch (icmdp->cmd_state) {
202fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_FREE:
203fcf3ce44SJohn Forte 		iscsi_cmd_state_free(icmdp, event, arg);
204fcf3ce44SJohn Forte 		break;
205fcf3ce44SJohn Forte 
206fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_PENDING:
207fcf3ce44SJohn Forte 		iscsi_cmd_state_pending(icmdp, event, arg);
208fcf3ce44SJohn Forte 		break;
209fcf3ce44SJohn Forte 
210fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_ACTIVE:
211fcf3ce44SJohn Forte 		iscsi_cmd_state_active(icmdp, event, arg);
212fcf3ce44SJohn Forte 		break;
213fcf3ce44SJohn Forte 
214fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_ABORTING:
215fcf3ce44SJohn Forte 		iscsi_cmd_state_aborting(icmdp, event, arg);
216fcf3ce44SJohn Forte 		break;
217fcf3ce44SJohn Forte 
21830e7468fSPeter Dunlap 	case ISCSI_CMD_STATE_IDM_ABORTING:
21930e7468fSPeter Dunlap 		iscsi_cmd_state_idm_aborting(icmdp, event, arg);
22030e7468fSPeter Dunlap 		break;
22130e7468fSPeter Dunlap 
222fcf3ce44SJohn Forte 	case ISCSI_CMD_STATE_COMPLETED:
223fcf3ce44SJohn Forte 		iscsi_cmd_state_completed(icmdp, event, arg);
224fcf3ce44SJohn Forte 
225fcf3ce44SJohn Forte 		/*
226fcf3ce44SJohn Forte 		 * Once completed event is processed we DO NOT
227fcf3ce44SJohn Forte 		 * want to touch it again because the caller
228fcf3ce44SJohn Forte 		 * (sd, st, etc) may have freed the command.
229fcf3ce44SJohn Forte 		 */
230fcf3ce44SJohn Forte 		release_lock = B_FALSE;
231fcf3ce44SJohn Forte 		break;
232fcf3ce44SJohn Forte 
233fcf3ce44SJohn Forte 	default:
234fcf3ce44SJohn Forte 		ASSERT(FALSE);
235fcf3ce44SJohn Forte 	}
236fcf3ce44SJohn Forte 
237fcf3ce44SJohn Forte 	if (release_lock == B_TRUE) {
23830e7468fSPeter Dunlap 		/* Audit state if not completed */
23930e7468fSPeter Dunlap 		idm_sm_audit_state_change(&icmdp->cmd_state_audit,
24030e7468fSPeter Dunlap 		    SAS_ISCSI_CMD, icmdp->cmd_prev_state, icmdp->cmd_state);
24130e7468fSPeter Dunlap 
242d233de7eSJack Meng 		if (!(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_FREE) ||
243d233de7eSJack Meng 		    !(icmdp->cmd_misc_flags &
244d233de7eSJack Meng 		    ISCSI_CMD_MISCFLAG_INTERNAL)) {
245fcf3ce44SJohn Forte 			mutex_exit(&icmdp->cmd_mutex);
246fcf3ce44SJohn Forte 			return;
247fcf3ce44SJohn Forte 		}
248fcf3ce44SJohn Forte 		mutex_exit(&icmdp->cmd_mutex);
249fcf3ce44SJohn Forte 		iscsi_cmd_free(icmdp);
250fcf3ce44SJohn Forte 	}
251fcf3ce44SJohn Forte }
252fcf3ce44SJohn Forte 
253fcf3ce44SJohn Forte /*
254fcf3ce44SJohn Forte  * iscsi_cmd_alloc -
255fcf3ce44SJohn Forte  *
256fcf3ce44SJohn Forte  */
257fcf3ce44SJohn Forte iscsi_cmd_t *
iscsi_cmd_alloc(iscsi_conn_t * icp,int km_flags)258fcf3ce44SJohn Forte iscsi_cmd_alloc(iscsi_conn_t *icp, int km_flags)
259fcf3ce44SJohn Forte {
260fcf3ce44SJohn Forte 	iscsi_cmd_t	*icmdp;
261fcf3ce44SJohn Forte 
262fcf3ce44SJohn Forte 	icmdp = kmem_zalloc(sizeof (iscsi_cmd_t), km_flags);
263fcf3ce44SJohn Forte 	if (icmdp) {
264fcf3ce44SJohn Forte 		icmdp->cmd_sig		= ISCSI_SIG_CMD;
265fcf3ce44SJohn Forte 		icmdp->cmd_state	= ISCSI_CMD_STATE_FREE;
266fcf3ce44SJohn Forte 		icmdp->cmd_conn		= icp;
267d233de7eSJack Meng 		icmdp->cmd_misc_flags	|= ISCSI_CMD_MISCFLAG_INTERNAL;
26830e7468fSPeter Dunlap 		idm_sm_audit_init(&icmdp->cmd_state_audit);
269fcf3ce44SJohn Forte 		mutex_init(&icmdp->cmd_mutex, NULL, MUTEX_DRIVER, NULL);
270fcf3ce44SJohn Forte 		cv_init(&icmdp->cmd_completion, NULL, CV_DRIVER, NULL);
271fcf3ce44SJohn Forte 	}
272fcf3ce44SJohn Forte 	return (icmdp);
273fcf3ce44SJohn Forte }
274fcf3ce44SJohn Forte 
275fcf3ce44SJohn Forte /*
276fcf3ce44SJohn Forte  * iscsi_cmd_free -
277fcf3ce44SJohn Forte  *
278fcf3ce44SJohn Forte  */
279fcf3ce44SJohn Forte void
iscsi_cmd_free(iscsi_cmd_t * icmdp)280fcf3ce44SJohn Forte iscsi_cmd_free(iscsi_cmd_t *icmdp)
281fcf3ce44SJohn Forte {
282fcf3ce44SJohn Forte 	ASSERT(icmdp != NULL);
283fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_sig == ISCSI_SIG_CMD);
284fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_FREE);
285fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_next == NULL);
286fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_prev == NULL);
287d233de7eSJack Meng 	ASSERT(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_INTERNAL);
28830e7468fSPeter Dunlap 	if (icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT)
289fcf3ce44SJohn Forte 		ASSERT(icmdp->cmd_un.abort.icmdp == NULL);
290fcf3ce44SJohn Forte 	else if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
291fcf3ce44SJohn Forte 		ASSERT(icmdp->cmd_un.scsi.r2t_icmdp == NULL);
292fcf3ce44SJohn Forte 		ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
293fcf3ce44SJohn Forte 	}
294fcf3ce44SJohn Forte 	mutex_destroy(&icmdp->cmd_mutex);
295fcf3ce44SJohn Forte 	cv_destroy(&icmdp->cmd_completion);
296fcf3ce44SJohn Forte 	kmem_free(icmdp, sizeof (iscsi_cmd_t));
297fcf3ce44SJohn Forte }
298fcf3ce44SJohn Forte 
299fcf3ce44SJohn Forte /*
300fcf3ce44SJohn Forte  * +--------------------------------------------------------------------+
301fcf3ce44SJohn Forte  * | Internal Command Interfaces					|
302fcf3ce44SJohn Forte  * +--------------------------------------------------------------------+
303fcf3ce44SJohn Forte  */
304fcf3ce44SJohn Forte /*
305fcf3ce44SJohn Forte  * iscsi_cmd_state_free -
306fcf3ce44SJohn Forte  *
307fcf3ce44SJohn Forte  */
308fcf3ce44SJohn Forte static void
iscsi_cmd_state_free(iscsi_cmd_t * icmdp,iscsi_cmd_event_t event,void * arg)309fcf3ce44SJohn Forte iscsi_cmd_state_free(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
310fcf3ce44SJohn Forte {
311fcf3ce44SJohn Forte 	iscsi_sess_t	*isp		= (iscsi_sess_t *)arg;
312fcf3ce44SJohn Forte 
313fcf3ce44SJohn Forte 	ASSERT(icmdp != NULL);
314fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_FREE);
315fcf3ce44SJohn Forte 	ASSERT(isp != NULL);
316fcf3ce44SJohn Forte 
317fcf3ce44SJohn Forte 	/* switch on event change */
318fcf3ce44SJohn Forte 	switch (event) {
319fcf3ce44SJohn Forte 	/* -E1: Command was requested to be sent on wire */
320fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E1:
321fcf3ce44SJohn Forte 
322fcf3ce44SJohn Forte 		/* setup timestamps and timeouts for this command */
323fcf3ce44SJohn Forte 		icmdp->cmd_lbolt_pending = ddi_get_lbolt();
324fcf3ce44SJohn Forte 		if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
325fcf3ce44SJohn Forte 			/*
326fcf3ce44SJohn Forte 			 * Establish absolute time when command should timeout.
32730e7468fSPeter Dunlap 			 * For commands that depend on cmdsn window to go
328fcf3ce44SJohn Forte 			 * active, the timeout will be ignored while on
329fcf3ce44SJohn Forte 			 * the pending queue and a new timeout will be
330fcf3ce44SJohn Forte 			 * established when the command goes active.
331fcf3ce44SJohn Forte 			 */
332fcf3ce44SJohn Forte 			if (icmdp->cmd_un.scsi.pkt &&
333fcf3ce44SJohn Forte 			    icmdp->cmd_un.scsi.pkt->pkt_time)
334fcf3ce44SJohn Forte 				icmdp->cmd_lbolt_timeout =
335fcf3ce44SJohn Forte 				    icmdp->cmd_lbolt_pending + SEC_TO_TICK(
336fcf3ce44SJohn Forte 				    icmdp->cmd_un.scsi.pkt->pkt_time *
337fcf3ce44SJohn Forte 				    iscsi_cmd_timeout_factor);
338fcf3ce44SJohn Forte 			else
339fcf3ce44SJohn Forte 				icmdp->cmd_lbolt_timeout = 0;
3402b79d384Sbing zhao - Sun Microsystems - Beijing China 
3412b79d384Sbing zhao - Sun Microsystems - Beijing China 			icmdp->cmd_un.scsi.pkt_stat &=
3422b79d384Sbing zhao - Sun Microsystems - Beijing China 			    ISCSI_CMD_PKT_STAT_INIT;
343fcf3ce44SJohn Forte 		} else {
344fcf3ce44SJohn Forte 			icmdp->cmd_lbolt_timeout = icmdp->cmd_lbolt_pending +
345fcf3ce44SJohn Forte 			    SEC_TO_TICK(ISCSI_INTERNAL_CMD_TIMEOUT *
346fcf3ce44SJohn Forte 			    iscsi_cmd_timeout_factor);
347fcf3ce44SJohn Forte 		}
348fcf3ce44SJohn Forte 
349fcf3ce44SJohn Forte 		/* place into pending queue */
350fcf3ce44SJohn Forte 		iscsi_enqueue_pending_cmd(isp, icmdp);
351fcf3ce44SJohn Forte 
352fcf3ce44SJohn Forte 		break;
353fcf3ce44SJohn Forte 
354fcf3ce44SJohn Forte 	/* All other events are invalid for this state */
355fcf3ce44SJohn Forte 	default:
356fcf3ce44SJohn Forte 		ASSERT(FALSE);
357fcf3ce44SJohn Forte 	}
358fcf3ce44SJohn Forte }
359fcf3ce44SJohn Forte 
360fcf3ce44SJohn Forte /*
361fcf3ce44SJohn Forte  * iscsi_cmd_state_pending -
362fcf3ce44SJohn Forte  *
363fcf3ce44SJohn Forte  */
364fcf3ce44SJohn Forte static void
iscsi_cmd_state_pending(iscsi_cmd_t * icmdp,iscsi_cmd_event_t event,void * arg)365fcf3ce44SJohn Forte iscsi_cmd_state_pending(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
366fcf3ce44SJohn Forte {
367fcf3ce44SJohn Forte 	iscsi_status_t	status;
368fcf3ce44SJohn Forte 	iscsi_sess_t	*isp		= (iscsi_sess_t *)arg;
369fcf3ce44SJohn Forte 	boolean_t	free_icmdp	= B_FALSE;
370fcf3ce44SJohn Forte 	int		rval;
371fcf3ce44SJohn Forte 
372fcf3ce44SJohn Forte 	ASSERT(icmdp != NULL);
373fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_PENDING);
374fcf3ce44SJohn Forte 	ASSERT(isp != NULL);
375fcf3ce44SJohn Forte 
376fcf3ce44SJohn Forte 	/* switch on event change */
377fcf3ce44SJohn Forte 	switch (event) {
378fcf3ce44SJohn Forte 	/* -E2: Command was submitted and now active on wire */
379fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E2:
380fcf3ce44SJohn Forte 
381fcf3ce44SJohn Forte 		/* A connection should have already been assigned */
38230e7468fSPeter Dunlap 		ASSERT(mutex_owned(&isp->sess_queue_pending.mutex));
383fcf3ce44SJohn Forte 		ASSERT(icmdp->cmd_conn != NULL);
384fcf3ce44SJohn Forte 
385fcf3ce44SJohn Forte 		/*
386fcf3ce44SJohn Forte 		 * RESERVE RESOURSES
387fcf3ce44SJohn Forte 		 */
388fcf3ce44SJohn Forte 		switch (icmdp->cmd_type) {
389fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_SCSI:
390fcf3ce44SJohn Forte 			/* check cmdsn window */
391fcf3ce44SJohn Forte 			mutex_enter(&isp->sess_cmdsn_mutex);
392fcf3ce44SJohn Forte 			if (!iscsi_sna_lte(isp->sess_cmdsn,
393fcf3ce44SJohn Forte 			    isp->sess_maxcmdsn)) {
394fcf3ce44SJohn Forte 				/* cmdsn window closed */
395fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_cmdsn_mutex);
396fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_queue_pending.mutex);
397fcf3ce44SJohn Forte 				isp->sess_window_open = B_FALSE;
398d233de7eSJack Meng 				icmdp->cmd_misc_flags |=
399d233de7eSJack Meng 				    ISCSI_CMD_MISCFLAG_STUCK;
400fcf3ce44SJohn Forte 				return;
401fcf3ce44SJohn Forte 			}
402fcf3ce44SJohn Forte 
403fcf3ce44SJohn Forte 			/* assign itt */
40430e7468fSPeter Dunlap 			status = iscsi_sess_reserve_scsi_itt(icmdp);
405fcf3ce44SJohn Forte 			if (!ISCSI_SUCCESS(status)) {
406fcf3ce44SJohn Forte 				/* no available itt slots */
407fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_cmdsn_mutex);
408fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_queue_pending.mutex);
409fcf3ce44SJohn Forte 				isp->sess_window_open = B_FALSE;
410d233de7eSJack Meng 				icmdp->cmd_misc_flags |=
411d233de7eSJack Meng 				    ISCSI_CMD_MISCFLAG_STUCK;
412fcf3ce44SJohn Forte 				return;
413fcf3ce44SJohn Forte 			}
414fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
415fcf3ce44SJohn Forte 			break;
416fcf3ce44SJohn Forte 
417fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_ABORT:
418fcf3ce44SJohn Forte 			/*
419fcf3ce44SJohn Forte 			 * Verify ABORT's parent SCSI command is still
420fcf3ce44SJohn Forte 			 * there.  If parent SCSI command is completed
421fcf3ce44SJohn Forte 			 * then there is no longer any reason to abort
422fcf3ce44SJohn Forte 			 * the parent command.  This could occur due
423fcf3ce44SJohn Forte 			 * to a connection or target reset.
424fcf3ce44SJohn Forte 			 */
425fcf3ce44SJohn Forte 			ASSERT(icmdp->cmd_un.abort.icmdp != NULL);
426fcf3ce44SJohn Forte 			if (icmdp->cmd_un.abort.icmdp->cmd_state ==
427fcf3ce44SJohn Forte 			    ISCSI_CMD_STATE_COMPLETED) {
428fcf3ce44SJohn Forte 				iscsi_dequeue_pending_cmd(isp, icmdp);
429fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_queue_pending.mutex);
430fcf3ce44SJohn Forte 
431fcf3ce44SJohn Forte 				mutex_enter(&icmdp->cmd_un.abort.icmdp->
432fcf3ce44SJohn Forte 				    cmd_mutex);
433fcf3ce44SJohn Forte 				icmdp->cmd_un.abort.icmdp->
434fcf3ce44SJohn Forte 				    cmd_un.scsi.abort_icmdp = NULL;
435fcf3ce44SJohn Forte 				cv_broadcast(&icmdp->cmd_un.abort.icmdp->
436fcf3ce44SJohn Forte 				    cmd_completion);
437fcf3ce44SJohn Forte 				mutex_exit(&icmdp->cmd_un.abort.icmdp->
438fcf3ce44SJohn Forte 				    cmd_mutex);
439fcf3ce44SJohn Forte 				icmdp->cmd_un.abort.icmdp = NULL;
440fcf3ce44SJohn Forte 
441fcf3ce44SJohn Forte 				icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
442d233de7eSJack Meng 				icmdp->cmd_misc_flags |=
443d233de7eSJack Meng 				    ISCSI_CMD_MISCFLAG_FREE;
444fcf3ce44SJohn Forte 				return;
445fcf3ce44SJohn Forte 			}
446fcf3ce44SJohn Forte 			/* FALLTHRU */
447fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_RESET:
448fcf3ce44SJohn Forte 			/* FALLTHRU */
449fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_LOGOUT:
450fcf3ce44SJohn Forte 			mutex_enter(&isp->sess_cmdsn_mutex);
451fcf3ce44SJohn Forte 			/* assign itt */
452fcf3ce44SJohn Forte 			status = iscsi_sess_reserve_itt(isp, icmdp);
453fcf3ce44SJohn Forte 			if (!ISCSI_SUCCESS(status)) {
454fcf3ce44SJohn Forte 				/* no available itt slots */
455fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_cmdsn_mutex);
456fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_queue_pending.mutex);
457fcf3ce44SJohn Forte 				isp->sess_window_open = B_FALSE;
458fcf3ce44SJohn Forte 				return;
459fcf3ce44SJohn Forte 			}
460fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
461fcf3ce44SJohn Forte 			break;
462fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_NOP:
463fcf3ce44SJohn Forte 			/* assign itt, if needed */
464fcf3ce44SJohn Forte 			if (icmdp->cmd_itt == ISCSI_RSVD_TASK_TAG) {
465fcf3ce44SJohn Forte 				/* not expecting a response */
466fcf3ce44SJohn Forte 				free_icmdp = B_TRUE;
467fcf3ce44SJohn Forte 			} else {
468fcf3ce44SJohn Forte 				/* expecting response, assign an itt */
469fcf3ce44SJohn Forte 				mutex_enter(&isp->sess_cmdsn_mutex);
470fcf3ce44SJohn Forte 				/* assign itt */
471fcf3ce44SJohn Forte 				status = iscsi_sess_reserve_itt(isp, icmdp);
472fcf3ce44SJohn Forte 				if (!ISCSI_SUCCESS(status)) {
473fcf3ce44SJohn Forte 					/* no available itt slots */
474fcf3ce44SJohn Forte 					mutex_exit(&isp->sess_cmdsn_mutex);
475fcf3ce44SJohn Forte 					mutex_exit(&isp->sess_queue_pending.
476fcf3ce44SJohn Forte 					    mutex);
477fcf3ce44SJohn Forte 					isp->sess_window_open = B_FALSE;
478fcf3ce44SJohn Forte 					return;
479fcf3ce44SJohn Forte 				}
480fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_cmdsn_mutex);
481fcf3ce44SJohn Forte 			}
482fcf3ce44SJohn Forte 			break;
483fcf3ce44SJohn Forte 
484fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_TEXT:
485fcf3ce44SJohn Forte 			mutex_enter(&isp->sess_cmdsn_mutex);
486fcf3ce44SJohn Forte 			/* check cmdsn window */
487fcf3ce44SJohn Forte 			if (!iscsi_sna_lte(isp->sess_cmdsn,
488fcf3ce44SJohn Forte 			    isp->sess_maxcmdsn)) {
489fcf3ce44SJohn Forte 				/* cmdsn window closed */
490fcf3ce44SJohn Forte 				isp->sess_window_open = B_FALSE;
491fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_cmdsn_mutex);
492fcf3ce44SJohn Forte 				mutex_exit(&isp->sess_queue_pending.mutex);
493d233de7eSJack Meng 				icmdp->cmd_misc_flags |=
494d233de7eSJack Meng 				    ISCSI_CMD_MISCFLAG_STUCK;
495fcf3ce44SJohn Forte 				return;
496fcf3ce44SJohn Forte 			}
497fcf3ce44SJohn Forte 			if (icmdp->cmd_un.text.stage ==
498fcf3ce44SJohn Forte 			    ISCSI_CMD_TEXT_INITIAL_REQ) {
499fcf3ce44SJohn Forte 				/* assign itt */
500fcf3ce44SJohn Forte 				status = iscsi_sess_reserve_itt(isp, icmdp);
501fcf3ce44SJohn Forte 				if (!ISCSI_SUCCESS(status)) {
502fcf3ce44SJohn Forte 					/* no available itt slots */
503fcf3ce44SJohn Forte 					mutex_exit(&isp->sess_cmdsn_mutex);
504fcf3ce44SJohn Forte 					mutex_exit(&isp->sess_queue_pending.
505fcf3ce44SJohn Forte 					    mutex);
506fcf3ce44SJohn Forte 					isp->sess_window_open = B_FALSE;
507d233de7eSJack Meng 					icmdp->cmd_misc_flags |=
508d233de7eSJack Meng 					    ISCSI_CMD_MISCFLAG_STUCK;
509fcf3ce44SJohn Forte 					return;
510fcf3ce44SJohn Forte 				}
511fcf3ce44SJohn Forte 			}
512fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
513fcf3ce44SJohn Forte 			break;
514fcf3ce44SJohn Forte 
515fcf3ce44SJohn Forte 		default:
516fcf3ce44SJohn Forte 			ASSERT(FALSE);
517fcf3ce44SJohn Forte 		}
518fcf3ce44SJohn Forte 
519fcf3ce44SJohn Forte 		/*
520fcf3ce44SJohn Forte 		 * RESOURCES RESERVED
521fcf3ce44SJohn Forte 		 *
522fcf3ce44SJohn Forte 		 * Now that we have the resources reserved, establish timeout
523fcf3ce44SJohn Forte 		 * for cmd_type values that depend on having an open cmdsn
524fcf3ce44SJohn Forte 		 * window (i.e. cmd_type that called iscsi_sna_lte() above).
525fcf3ce44SJohn Forte 		 */
526fcf3ce44SJohn Forte 		if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
527fcf3ce44SJohn Forte 			if (icmdp->cmd_un.scsi.pkt &&
528fcf3ce44SJohn Forte 			    icmdp->cmd_un.scsi.pkt->pkt_time)
529fcf3ce44SJohn Forte 				icmdp->cmd_lbolt_timeout =
530fcf3ce44SJohn Forte 				    ddi_get_lbolt() + SEC_TO_TICK(
531fcf3ce44SJohn Forte 				    icmdp->cmd_un.scsi.pkt->pkt_time *
532fcf3ce44SJohn Forte 				    iscsi_cmd_timeout_factor);
533fcf3ce44SJohn Forte 			else
534fcf3ce44SJohn Forte 				icmdp->cmd_lbolt_timeout = 0;
535fcf3ce44SJohn Forte 		} else if (icmdp->cmd_type == ISCSI_CMD_TYPE_TEXT) {
536fcf3ce44SJohn Forte 			icmdp->cmd_lbolt_timeout = ddi_get_lbolt() +
537fcf3ce44SJohn Forte 			    SEC_TO_TICK(ISCSI_INTERNAL_CMD_TIMEOUT *
538fcf3ce44SJohn Forte 			    iscsi_cmd_timeout_factor);
539fcf3ce44SJohn Forte 		}
540fcf3ce44SJohn Forte 
541fcf3ce44SJohn Forte 		/* remove command from pending queue */
542fcf3ce44SJohn Forte 		iscsi_dequeue_pending_cmd(isp, icmdp);
543fcf3ce44SJohn Forte 		/* check if expecting a response */
544fcf3ce44SJohn Forte 		if (free_icmdp == B_FALSE) {
545fcf3ce44SJohn Forte 			/* response expected, move to active queue */
546fcf3ce44SJohn Forte 			mutex_enter(&icmdp->cmd_conn->conn_queue_active.mutex);
547fcf3ce44SJohn Forte 			iscsi_enqueue_active_cmd(icmdp->cmd_conn, icmdp);
548fcf3ce44SJohn Forte 			mutex_exit(&icmdp->cmd_conn->conn_queue_active.mutex);
549fcf3ce44SJohn Forte 		}
550fcf3ce44SJohn Forte 
551fcf3ce44SJohn Forte 		/*
552fcf3ce44SJohn Forte 		 * TRANSFER COMMAND
553fcf3ce44SJohn Forte 		 */
554fcf3ce44SJohn Forte 		rval = iscsi_tx_cmd(isp, icmdp);
555fcf3ce44SJohn Forte 
556fcf3ce44SJohn Forte 		ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex));
557fcf3ce44SJohn Forte 
558fcf3ce44SJohn Forte 		/*
559fcf3ce44SJohn Forte 		 * CHECK SUCCESS/FAILURE
560fcf3ce44SJohn Forte 		 */
561fcf3ce44SJohn Forte 		if (!ISCSI_SUCCESS(rval)) {
562fcf3ce44SJohn Forte 			/*
563fcf3ce44SJohn Forte 			 * iscsi_tx_cmd failed.  No cleanup is required
564fcf3ce44SJohn Forte 			 * of commands that were put in the active queue.
565fcf3ce44SJohn Forte 			 * If the tx failed then rx will also fail and cleanup
566fcf3ce44SJohn Forte 			 * all items in the active/aborted queue in a common.
567fcf3ce44SJohn Forte 			 */
568fcf3ce44SJohn Forte 
569fcf3ce44SJohn Forte 			/* EMPTY */
570fcf3ce44SJohn Forte 		}
571fcf3ce44SJohn Forte 
572fcf3ce44SJohn Forte 		/* free temporary commands */
573fcf3ce44SJohn Forte 		if (free_icmdp == B_TRUE) {
574fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
575d233de7eSJack Meng 			icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_FREE;
576fcf3ce44SJohn Forte 		}
577fcf3ce44SJohn Forte 		break;
578fcf3ce44SJohn Forte 
57930e7468fSPeter Dunlap 	/* -E10: Abort is no longer required for this command */
58030e7468fSPeter Dunlap 	case ISCSI_CMD_EVENT_E10:
58130e7468fSPeter Dunlap 		/*
58230e7468fSPeter Dunlap 		 * Acquiring the sess_queue_pending lock while the
58330e7468fSPeter Dunlap 		 * conn_queue_active lock is held conflicts with the
58430e7468fSPeter Dunlap 		 * locking order in iscsi_cmd_state_pending where
58530e7468fSPeter Dunlap 		 * conn_queue_active is acquired while sess_queue_pending
58630e7468fSPeter Dunlap 		 * is held.  Normally this would be a dangerous lock
58730e7468fSPeter Dunlap 		 * order conflict, except that we know that if we are
58830e7468fSPeter Dunlap 		 * seeing ISCSI_CMD_EVENT_E10 then the command being
58930e7468fSPeter Dunlap 		 * aborted is in "aborting" state and by extension
59030e7468fSPeter Dunlap 		 * is not in "pending" state.  Therefore the code
59130e7468fSPeter Dunlap 		 * path with that alternate lock order will not execute.
59230e7468fSPeter Dunlap 		 * That's good because we can't drop the lock here without
59330e7468fSPeter Dunlap 		 * risking a deadlock.
59430e7468fSPeter Dunlap 		 */
59530e7468fSPeter Dunlap 		ASSERT(mutex_owned(&icmdp->cmd_conn->conn_queue_active.mutex));
59630e7468fSPeter Dunlap 		mutex_enter(&isp->sess_queue_pending.mutex);
59730e7468fSPeter Dunlap 
59830e7468fSPeter Dunlap 		icmdp->cmd_lbolt_aborting = ddi_get_lbolt();
59930e7468fSPeter Dunlap 
60030e7468fSPeter Dunlap 		iscsi_dequeue_pending_cmd(isp, icmdp);
60130e7468fSPeter Dunlap 
60230e7468fSPeter Dunlap 		icmdp->cmd_un.abort.icmdp->cmd_un.scsi.abort_icmdp = NULL;
60330e7468fSPeter Dunlap 		icmdp->cmd_un.abort.icmdp = NULL;
60430e7468fSPeter Dunlap 		icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_FREE;
60530e7468fSPeter Dunlap 		icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
60630e7468fSPeter Dunlap 
60730e7468fSPeter Dunlap 		mutex_exit(&isp->sess_queue_pending.mutex);
60830e7468fSPeter Dunlap 		break;
60930e7468fSPeter Dunlap 
610fcf3ce44SJohn Forte 	/* -E4: Command has been requested to abort */
611fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E4:
61230e7468fSPeter Dunlap 		ASSERT(mutex_owned(&isp->sess_queue_pending.mutex));
613fcf3ce44SJohn Forte 
614fcf3ce44SJohn Forte 		icmdp->cmd_lbolt_aborting = ddi_get_lbolt();
615fcf3ce44SJohn Forte 		ISCSI_CMD_SET_REASON_STAT(icmdp,
616fcf3ce44SJohn Forte 		    CMD_ABORTED, STAT_ABORTED);
617fcf3ce44SJohn Forte 
618fcf3ce44SJohn Forte 		iscsi_dequeue_pending_cmd(isp, icmdp);
619fcf3ce44SJohn Forte 		iscsi_enqueue_completed_cmd(isp, icmdp);
620fcf3ce44SJohn Forte 
621fcf3ce44SJohn Forte 		icmdp->cmd_lbolt_aborting = ddi_get_lbolt();
622fcf3ce44SJohn Forte 
623fcf3ce44SJohn Forte 		break;
624fcf3ce44SJohn Forte 
625fcf3ce44SJohn Forte 	/* -E7: Command has been reset */
626fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E7:
627fcf3ce44SJohn Forte 
628fcf3ce44SJohn Forte 		/* FALLTHRU */
629fcf3ce44SJohn Forte 
630fcf3ce44SJohn Forte 	/* -E6: Command has timed out */
631fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E6:
63230e7468fSPeter Dunlap 		ASSERT(mutex_owned(&isp->sess_queue_pending.mutex));
633fcf3ce44SJohn Forte 		iscsi_dequeue_pending_cmd(isp, icmdp);
634fcf3ce44SJohn Forte 
635fcf3ce44SJohn Forte 		switch (icmdp->cmd_type) {
636fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_SCSI:
637fcf3ce44SJohn Forte 			/* Complete to caller as TIMEOUT */
638fcf3ce44SJohn Forte 			if (event == ISCSI_CMD_EVENT_E6) {
639fcf3ce44SJohn Forte 				ISCSI_CMD_SET_REASON_STAT(icmdp,
640fcf3ce44SJohn Forte 				    CMD_TIMEOUT, STAT_TIMEOUT);
641fcf3ce44SJohn Forte 			} else {
642fcf3ce44SJohn Forte 				ISCSI_CMD_SET_REASON_STAT(icmdp,
6432b79d384Sbing zhao - Sun Microsystems - Beijing China 				    CMD_TRAN_ERR, icmdp->cmd_un.scsi.pkt_stat);
644fcf3ce44SJohn Forte 			}
645fcf3ce44SJohn Forte 			iscsi_enqueue_completed_cmd(isp, icmdp);
646fcf3ce44SJohn Forte 			break;
647fcf3ce44SJohn Forte 
648fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_NOP:
649fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
650fcf3ce44SJohn Forte 			/*
651fcf3ce44SJohn Forte 			 * Timeout occured.  Just free NOP.  Another
652fcf3ce44SJohn Forte 			 * NOP request will be spawned to replace
653fcf3ce44SJohn Forte 			 * this one.
654fcf3ce44SJohn Forte 			 */
655d233de7eSJack Meng 			icmdp->cmd_misc_flags |=
656d233de7eSJack Meng 			    ISCSI_CMD_MISCFLAG_FREE;
657d233de7eSJack Meng 
658fcf3ce44SJohn Forte 			break;
659fcf3ce44SJohn Forte 
660fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_ABORT:
661fcf3ce44SJohn Forte 			mutex_enter(&icmdp->cmd_un.abort.icmdp->cmd_mutex);
662fcf3ce44SJohn Forte 			icmdp->cmd_un.abort.icmdp->
663fcf3ce44SJohn Forte 			    cmd_un.scsi.abort_icmdp = NULL;
664fcf3ce44SJohn Forte 			cv_broadcast(&icmdp->cmd_un.abort.icmdp->
665fcf3ce44SJohn Forte 			    cmd_completion);
666fcf3ce44SJohn Forte 			mutex_exit(&icmdp->cmd_un.abort.icmdp->cmd_mutex);
667fcf3ce44SJohn Forte 			icmdp->cmd_un.abort.icmdp = NULL;
668fcf3ce44SJohn Forte 
669fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
670d233de7eSJack Meng 			icmdp->cmd_misc_flags |=
671d233de7eSJack Meng 			    ISCSI_CMD_MISCFLAG_FREE;
672fcf3ce44SJohn Forte 			break;
673fcf3ce44SJohn Forte 
674fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_RESET:
675fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
676fcf3ce44SJohn Forte 			/*
677fcf3ce44SJohn Forte 			 * If we are failing a RESET we need
678fcf3ce44SJohn Forte 			 * to notify the tran_reset caller.
679fcf3ce44SJohn Forte 			 * with the cmd and notify caller.
680fcf3ce44SJohn Forte 			 */
681fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
682fcf3ce44SJohn Forte 			    ISCSI_STATUS_CMD_FAILED);
683fcf3ce44SJohn Forte 			break;
684fcf3ce44SJohn Forte 
685fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_LOGOUT:
686fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
687fcf3ce44SJohn Forte 			/* notify requester of failure */
688fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
689fcf3ce44SJohn Forte 			    ISCSI_STATUS_CMD_FAILED);
690fcf3ce44SJohn Forte 			break;
691fcf3ce44SJohn Forte 
692fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_TEXT:
693fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
694fcf3ce44SJohn Forte 			icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
695fcf3ce44SJohn Forte 			/*
696fcf3ce44SJohn Forte 			 * If a TEXT command fails, notify the owner.
697fcf3ce44SJohn Forte 			 */
698fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
699fcf3ce44SJohn Forte 			    ISCSI_STATUS_CMD_FAILED);
700fcf3ce44SJohn Forte 			break;
701fcf3ce44SJohn Forte 
702fcf3ce44SJohn Forte 		default:
703fcf3ce44SJohn Forte 			ASSERT(FALSE);
704fcf3ce44SJohn Forte 			break;
705fcf3ce44SJohn Forte 		}
706fcf3ce44SJohn Forte 		break;
707fcf3ce44SJohn Forte 
708fcf3ce44SJohn Forte 	/* All other events are invalid for this state */
709fcf3ce44SJohn Forte 	default:
710fcf3ce44SJohn Forte 		ASSERT(FALSE);
711fcf3ce44SJohn Forte 	}
712fcf3ce44SJohn Forte }
713fcf3ce44SJohn Forte 
714fcf3ce44SJohn Forte 
715fcf3ce44SJohn Forte /*
716fcf3ce44SJohn Forte  * iscsi_cmd_state_active -
717fcf3ce44SJohn Forte  *
718fcf3ce44SJohn Forte  */
719fcf3ce44SJohn Forte static void
iscsi_cmd_state_active(iscsi_cmd_t * icmdp,iscsi_cmd_event_t event,void * arg)720fcf3ce44SJohn Forte iscsi_cmd_state_active(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
721fcf3ce44SJohn Forte {
722fcf3ce44SJohn Forte 	iscsi_sess_t	*isp		= (iscsi_sess_t *)arg;
723fcf3ce44SJohn Forte 	iscsi_hba_t	*ihp;
724fcf3ce44SJohn Forte 	iscsi_cmd_t	*t_icmdp	= NULL;
725fcf3ce44SJohn Forte 	iscsi_conn_t	*icp		= NULL;
726fcf3ce44SJohn Forte 
727fcf3ce44SJohn Forte 	ASSERT(icmdp != NULL);
728fcf3ce44SJohn Forte 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_ACTIVE);
729fcf3ce44SJohn Forte 	ASSERT(isp != NULL);
730fcf3ce44SJohn Forte 
731fcf3ce44SJohn Forte 	ihp = isp->sess_hba;
732fcf3ce44SJohn Forte 	ASSERT(ihp != NULL);
733fcf3ce44SJohn Forte 
734fcf3ce44SJohn Forte 	icp = icmdp->cmd_conn;
735fcf3ce44SJohn Forte 	ASSERT(icp != NULL);
736fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&icp->conn_queue_active.mutex));
737fcf3ce44SJohn Forte 
738fcf3ce44SJohn Forte 	/* switch on event change */
739fcf3ce44SJohn Forte 	switch (event) {
740fcf3ce44SJohn Forte 	/* -E3: Command was successfully completed */
741fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E3:
742fcf3ce44SJohn Forte 		/*
743fcf3ce44SJohn Forte 		 * Remove command from the active list.  We need to protect
744fcf3ce44SJohn Forte 		 * someone from looking up this command ITT until it's
745fcf3ce44SJohn Forte 		 * freed of the command is moved to a new queue location.
746fcf3ce44SJohn Forte 		 */
747fcf3ce44SJohn Forte 		mutex_enter(&isp->sess_cmdsn_mutex);
748fcf3ce44SJohn Forte 		iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
749fcf3ce44SJohn Forte 
750fcf3ce44SJohn Forte 		switch (icmdp->cmd_type) {
751fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_SCSI:
75230e7468fSPeter Dunlap 			iscsi_sess_release_scsi_itt(icmdp);
753fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
754fcf3ce44SJohn Forte 			iscsi_enqueue_completed_cmd(isp, icmdp);
755fcf3ce44SJohn Forte 			break;
756fcf3ce44SJohn Forte 
757fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_NOP:
758fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
759fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
760fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
761fcf3ce44SJohn Forte 
762fcf3ce44SJohn Forte 			/* free alloc */
763d233de7eSJack Meng 			icmdp->cmd_misc_flags |=
764d233de7eSJack Meng 			    ISCSI_CMD_MISCFLAG_FREE;
765d233de7eSJack Meng 
766fcf3ce44SJohn Forte 			break;
767fcf3ce44SJohn Forte 
768fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_ABORT:
769fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
770fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
771fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
772fcf3ce44SJohn Forte 
773fcf3ce44SJohn Forte 			/*
774fcf3ce44SJohn Forte 			 * Abort was completed successfully.  We should
775fcf3ce44SJohn Forte 			 * complete the parent scsi command if it still
776fcf3ce44SJohn Forte 			 * exists as timed out, and the state is not
777fcf3ce44SJohn Forte 			 * COMPLETED
778fcf3ce44SJohn Forte 			 */
779fcf3ce44SJohn Forte 			t_icmdp = icmdp->cmd_un.abort.icmdp;
780fcf3ce44SJohn Forte 			ASSERT(t_icmdp != NULL);
781fcf3ce44SJohn Forte 			mutex_enter(&t_icmdp->cmd_mutex);
78230e7468fSPeter Dunlap 			t_icmdp->cmd_un.scsi.abort_icmdp = NULL;
783fcf3ce44SJohn Forte 			if (t_icmdp->cmd_state != ISCSI_CMD_STATE_COMPLETED) {
784fcf3ce44SJohn Forte 				iscsi_dequeue_active_cmd(
785fcf3ce44SJohn Forte 				    t_icmdp->cmd_conn, t_icmdp);
78630e7468fSPeter Dunlap 				mutex_enter(
78730e7468fSPeter Dunlap 				    &icp->conn_queue_idm_aborting.mutex);
78830e7468fSPeter Dunlap 				iscsi_enqueue_idm_aborting_cmd(
78930e7468fSPeter Dunlap 				    t_icmdp->cmd_conn,
79030e7468fSPeter Dunlap 				    t_icmdp);
79130e7468fSPeter Dunlap 				mutex_exit(&icp->conn_queue_idm_aborting.mutex);
792fcf3ce44SJohn Forte 
79330e7468fSPeter Dunlap 				/*
79430e7468fSPeter Dunlap 				 * Complete abort processing after IDM
79530e7468fSPeter Dunlap 				 * calls us back.  Set the status to use
79630e7468fSPeter Dunlap 				 * when we complete the command.
79730e7468fSPeter Dunlap 				 */
798fcf3ce44SJohn Forte 				ISCSI_CMD_SET_REASON_STAT(
7992b79d384Sbing zhao - Sun Microsystems - Beijing China 				    t_icmdp, CMD_TIMEOUT, STAT_ABORTED);
800*61dfa509SRick McNeal 				(void) idm_task_abort(icp->conn_ic,
801*61dfa509SRick McNeal 				    t_icmdp->cmd_itp, AT_TASK_MGMT_ABORT);
80230e7468fSPeter Dunlap 			} else {
80330e7468fSPeter Dunlap 				cv_broadcast(&t_icmdp->cmd_completion);
804fcf3ce44SJohn Forte 			}
805fcf3ce44SJohn Forte 			mutex_exit(&t_icmdp->cmd_mutex);
806fcf3ce44SJohn Forte 			icmdp->cmd_un.abort.icmdp = NULL;
807fcf3ce44SJohn Forte 
808d233de7eSJack Meng 			icmdp->cmd_misc_flags |=
809d233de7eSJack Meng 			    ISCSI_CMD_MISCFLAG_FREE;
810d233de7eSJack Meng 
811fcf3ce44SJohn Forte 			break;
812fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_RESET:
813fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
814fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
815fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
816fcf3ce44SJohn Forte 
817fcf3ce44SJohn Forte 			/*
8182b79d384Sbing zhao - Sun Microsystems - Beijing China 			 * Complete the abort/reset command.
819fcf3ce44SJohn Forte 			 */
8202b79d384Sbing zhao - Sun Microsystems - Beijing China 			if (icmdp->cmd_un.reset.response !=
8212b79d384Sbing zhao - Sun Microsystems - Beijing China 			    SCSI_TCP_TM_RESP_COMPLETE) {
8222b79d384Sbing zhao - Sun Microsystems - Beijing China 				ISCSI_CMD_ISSUE_CALLBACK(icmdp,
8232b79d384Sbing zhao - Sun Microsystems - Beijing China 				    ISCSI_STATUS_CMD_FAILED);
8242b79d384Sbing zhao - Sun Microsystems - Beijing China 			} else {
8252b79d384Sbing zhao - Sun Microsystems - Beijing China 				ISCSI_CMD_ISSUE_CALLBACK(icmdp,
8262b79d384Sbing zhao - Sun Microsystems - Beijing China 				    ISCSI_STATUS_SUCCESS);
8272b79d384Sbing zhao - Sun Microsystems - Beijing China 			}
8282b79d384Sbing zhao - Sun Microsystems - Beijing China 
829fcf3ce44SJohn Forte 			break;
830fcf3ce44SJohn Forte 
831fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_LOGOUT:
832fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
833fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
834fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
835fcf3ce44SJohn Forte 
836fcf3ce44SJohn Forte 			/*
837fcf3ce44SJohn Forte 			 * Complete the logout successfully.
838fcf3ce44SJohn Forte 			 */
840fcf3ce44SJohn Forte 			break;
841fcf3ce44SJohn Forte 
842fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_TEXT:
843fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
844fcf3ce44SJohn Forte 			if (icmdp->cmd_un.text.stage ==
845fcf3ce44SJohn Forte 			    ISCSI_CMD_TEXT_FINAL_RSP) {
846fcf3ce44SJohn Forte 				iscsi_sess_release_itt(isp, icmdp);
847fcf3ce44SJohn Forte 			}
848fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
849fcf3ce44SJohn Forte 
850fcf3ce44SJohn Forte 			/*
851fcf3ce44SJohn Forte 			 * Complete the text command successfully.
852fcf3ce44SJohn Forte 			 */
853fcf3ce44SJohn Forte 			ISCSI_CMD_ISSUE_CALLBACK(icmdp, icmdp->cmd_result);
854fcf3ce44SJohn Forte 			break;
855fcf3ce44SJohn Forte 
856fcf3ce44SJohn Forte 		default:
857fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
858fcf3ce44SJohn Forte 			ASSERT(FALSE);
859fcf3ce44SJohn Forte 		}
860fcf3ce44SJohn Forte 
861fcf3ce44SJohn Forte 		ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex));
862fcf3ce44SJohn Forte 		break;
863fcf3ce44SJohn Forte 
86430e7468fSPeter Dunlap 	/* -E10,E4: Command has been requested to abort */
86530e7468fSPeter Dunlap 	case ISCSI_CMD_EVENT_E10:
86630e7468fSPeter Dunlap 		/* FALLTHRU */
867fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E4:
868fcf3ce44SJohn Forte 
869fcf3ce44SJohn Forte 		/* E4 is only for resets and aborts */
870fcf3ce44SJohn Forte 		ASSERT((icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT) ||
871fcf3ce44SJohn Forte 		    (icmdp->cmd_type == ISCSI_CMD_TYPE_RESET));
872fcf3ce44SJohn Forte 		/* FALLTHRU */
873fcf3ce44SJohn Forte 
874fcf3ce44SJohn Forte 	/* -E6: Command has timed out */
875fcf3ce44SJohn Forte 	case ISCSI_CMD_EVENT_E6:
876fcf3ce44SJohn Forte 
877fcf3ce44SJohn Forte 		switch (icmdp->cmd_type) {
878fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_SCSI:
879fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_ABORTING;
880fcf3ce44SJohn Forte 			iscsi_handle_abort(icmdp);
881fcf3ce44SJohn Forte 			break;
882fcf3ce44SJohn Forte 
883fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_NOP:
884fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
885fcf3ce44SJohn Forte 
886fcf3ce44SJohn Forte 			mutex_enter(&isp->sess_cmdsn_mutex);
887fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
888fcf3ce44SJohn Forte 			iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
889fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
890fcf3ce44SJohn Forte 
891d233de7eSJack Meng 			icmdp->cmd_misc_flags |=
892d233de7eSJack Meng 			    ISCSI_CMD_MISCFLAG_FREE;
893d233de7eSJack Meng 
894fcf3ce44SJohn Forte 			break;
895fcf3ce44SJohn Forte 
896fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_ABORT:
897fcf3ce44SJohn Forte 			icmdp->cmd_state =
898fcf3ce44SJohn Forte 			    ISCSI_CMD_STATE_FREE;
899fcf3ce44SJohn Forte 
900fcf3ce44SJohn Forte 			mutex_enter(&isp->sess_cmdsn_mutex);
901fcf3ce44SJohn Forte 			iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
902fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
903fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);
904fcf3ce44SJohn Forte 
905fcf3ce44SJohn Forte 			/*
90630e7468fSPeter Dunlap 			 * If this is an E4 then we may need to deal with
90730e7468fSPeter Dunlap 			 * the abort's associated SCSI command.  If this
90830e7468fSPeter Dunlap 			 * is an E10 then IDM is already cleaning up the
90930e7468fSPeter Dunlap 			 * SCSI command and all we need to do is break the
91030e7468fSPeter Dunlap 			 * linkage between them and free the abort command.
911fcf3ce44SJohn Forte 			 */
91230e7468fSPeter Dunlap 			t_icmdp = icmdp->cmd_un.abort.icmdp;
91330e7468fSPeter Dunlap 			ASSERT(t_icmdp != NULL);
91430e7468fSPeter Dunlap 			if (event != ISCSI_CMD_EVENT_E10) {
91530e7468fSPeter Dunlap 
91630e7468fSPeter Dunlap 				mutex_enter(&t_icmdp->cmd_mutex);
91730e7468fSPeter Dunlap 				t_icmdp->cmd_un.scsi.abort_icmdp = NULL;
91830e7468fSPeter Dunlap 				/*
91930e7468fSPeter Dunlap 				 * If abort command is aborted then we should
92030e7468fSPeter Dunlap 				 * not act on the parent scsi command.  If the
92130e7468fSPeter Dunlap 				 * abort command timed out then we need to
92230e7468fSPeter Dunlap 				 * complete the parent command if it still
92330e7468fSPeter Dunlap 				 * exists with a timeout failure.
92430e7468fSPeter Dunlap 				 */
92530e7468fSPeter Dunlap 				if ((event == ISCSI_CMD_EVENT_E6) &&
92630e7468fSPeter Dunlap 				    (t_icmdp->cmd_state !=
92730e7468fSPeter Dunlap 				    ISCSI_CMD_STATE_IDM_ABORTING) &&
92830e7468fSPeter Dunlap 				    (t_icmdp->cmd_state !=
92930e7468fSPeter Dunlap 				    ISCSI_CMD_STATE_COMPLETED)) {
93030e7468fSPeter Dunlap 
93130e7468fSPeter Dunlap 					iscsi_dequeue_active_cmd(
93230e7468fSPeter Dunlap 					    t_icmdp->cmd_conn, t_icmdp);
93330e7468fSPeter Dunlap 					mutex_enter(&icp->
93430e7468fSPeter Dunlap 					    conn_queue_idm_aborting.mutex);
93530e7468fSPeter Dunlap 					iscsi_enqueue_idm_aborting_cmd(
93630e7468fSPeter Dunlap 					    t_icmdp->cmd_conn,  t_icmdp);
93730e7468fSPeter Dunlap 					mutex_exit(&icp->
93830e7468fSPeter Dunlap 					    conn_queue_idm_aborting.mutex);
93930e7468fSPeter Dunlap 					/*
94030e7468fSPeter Dunlap 					 * Complete abort processing after IDM
94130e7468fSPeter Dunlap 					 * calls us back.  Set the status to use
94230e7468fSPeter Dunlap 					 * when we complete the command.
94330e7468fSPeter Dunlap 					 */
94430e7468fSPeter Dunlap 					ISCSI_CMD_SET_REASON_STAT(t_icmdp,
94530e7468fSPeter Dunlap 					    CMD_TIMEOUT, STAT_TIMEOUT);
946*61dfa509SRick McNeal 					(void) idm_task_abort(icp->conn_ic,
94730e7468fSPeter Dunlap 					    t_icmdp->cmd_itp,
94830e7468fSPeter Dunlap 					    AT_TASK_MGMT_ABORT);
94930e7468fSPeter Dunlap 				} else {
95030e7468fSPeter Dunlap 					cv_broadcast(&t_icmdp->cmd_completion);
95130e7468fSPeter Dunlap 				}
95230e7468fSPeter Dunlap 				mutex_exit(&t_icmdp->cmd_mutex);
95330e7468fSPeter Dunlap 			} else {
95430e7468fSPeter Dunlap 				t_icmdp->cmd_un.scsi.abort_icmdp = NULL;
955fcf3ce44SJohn Forte 			}
956fcf3ce44SJohn Forte 			icmdp->cmd_un.abort.icmdp = NULL;
957d233de7eSJack Meng 			icmdp->cmd_misc_flags |=
958d233de7eSJack Meng 			    ISCSI_CMD_MISCFLAG_FREE;
959fcf3ce44SJohn Forte 			break;
960fcf3ce44SJohn Forte 
961fcf3ce44SJohn Forte 		case ISCSI_CMD_TYPE_RESET:
962fcf3ce44SJohn Forte 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
963fcf3ce44SJohn Forte 
964fcf3ce44SJohn Forte 			mutex_enter(&isp->sess_cmdsn_mutex);
965fcf3ce44SJohn Forte 			iscsi_sess_release_itt(isp, icmdp);
966fcf3ce44SJohn Forte 			iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
967fcf3ce44SJohn Forte 			mutex_exit(&isp->sess_cmdsn_mutex);