Home | History | Annotate | Download | only in iscsi
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  *
     25  * iSCSI command interfaces
     26  */
     27 
     28 #include "iscsi.h"
     29 
     30 /* internal interfaces */
     31 static void iscsi_cmd_state_free(iscsi_cmd_t *icmdp,
     32     iscsi_cmd_event_t event, void *arg);
     33 static void iscsi_cmd_state_pending(iscsi_cmd_t *icmdp,
     34     iscsi_cmd_event_t event, void *arg);
     35 static void iscsi_cmd_state_active(iscsi_cmd_t *icmdp,
     36     iscsi_cmd_event_t event, void *arg);
     37 static void iscsi_cmd_state_aborting(iscsi_cmd_t *icmdp,
     38     iscsi_cmd_event_t event, void *arg);
     39 static void iscsi_cmd_state_idm_aborting(iscsi_cmd_t *icmdp,
     40     iscsi_cmd_event_t event, void *arg);
     41 static void iscsi_cmd_state_completed(iscsi_cmd_t *icmdp,
     42     iscsi_cmd_event_t event, void *arg);
     43 static char *iscsi_cmd_state_str(iscsi_cmd_state_t state);
     44 static char *iscsi_cmd_event_str(iscsi_cmd_event_t event);
     45 /* LINTED E_STATIC_UNUSED */
     46 static char *iscsi_cmd_type_str(iscsi_cmd_type_t type);
     47 
     48 #define	ISCSI_INTERNAL_CMD_TIMEOUT	60
     49 
     50 #define	ISCSI_CMD_ISSUE_CALLBACK(icmdp, status)	\
     51 	icmdp->cmd_completed = B_TRUE;		\
     52 	icmdp->cmd_result = status;		\
     53 	cv_broadcast(&icmdp->cmd_completion);
     54 
     55 #define	ISCSI_CMD_SET_REASON_STAT(icmdp, reason, stat)	\
     56 	icmdp->cmd_un.scsi.pkt->pkt_reason = reason;	\
     57 	icmdp->cmd_un.scsi.pkt->pkt_statistics = stat;
     58 
     59 /*
     60  * The following private tunable, settable via
     61  *	set iscsi:iscsi_cmd_timeout_factor = 2
     62  * in /etc/system, provides customer relief for configurations experiencing
     63  * SCSI command timeouts due to high-latency/high-loss network connections
     64  * or slow target response (possibly due to backing store issues). If frequent
     65  * use of this tunable is necessary, a beter mechanism must be provided.
     66  */
     67 int	iscsi_cmd_timeout_factor = 1;
     68 
     69 /*
     70  * +--------------------------------------------------------------------+
     71  * | External Command Interfaces					|
     72  * +--------------------------------------------------------------------+
     73  */
     74 
     75 /*
     76  * iscsi_cmd_state_machine - This function is used to drive the
     77  * state machine of the internal iscsi commands.  It takes in a command
     78  * and the associated event affecting the command.
     79  *
     80  * 7.1.3  Command State Diagram for an Initiator
     81  *      Symbolic Names for States:
     82  *      C1: FREE        - State on instantiation, or after successful
     83  *                        completion.
     84  *      C2: PENDING     - Command is in the session's pending queue awaiting
     85  *                        its turn to be sent on the wire.
     86  *      C3: ACTIVE      - Command has been sent on the wire and is
     87  *                        awaiting completion.
     88  *      C4: ABORTING    - Command which was sent on the wire has not timed
     89  *                        out or been requested to abort by an upper layer
     90  *                        driver.  At this point there is a task management
     91  *                        command in the active queue trying to abort the task.
     92  *	C4': IDM ABORTING - SCSI command is owned by IDM and idm_task_abort
     93  *                          has been called for this command.
     94  *      C5: COMPLETED	- Command which is ready to complete via pkt callback.
     95  *
     96  *      The state diagram is as follows:
     97  *               -------
     98  *              / C1    \
     99  *    I-------->\       /<------------
    100  *    N|         ---+---             |
    101  *    T|            |E1              |
    102  *    E|            V                |
    103  *    R|         -------             |
    104  *    N+--------/ C2    \            |
    105  *    A|  E4/6/7\       /--------    |
    106  *    L|         ---+---  E4/6/7|    |
    107  *     |            |E2    E10  |    |
    108  *    C|            V           | S  |
    109  *    M|         _______        | C  |
    110  *    D+--------/ C3    \       | S  |
    111  *    S E3/4/6/7\       /-------+ I  |
    112  *              /---+---E3/4/6/7|    |
    113  *             /    |      E9/10|    |
    114  *      ------/ E4/6|           | C  |
    115  *      |           V           | M  |
    116  *    E7|        -------        | D  |
    117  *  SCSI|    - >/ C4    \       | S  |
    118  *      |   /   \       /-------+    |
    119  *      |   |    ---+---E3/6/7/9|    |
    120  *      |   |  E4|  |           V   /E8
    121  *      |   ------  |        -------
    122  *      +-\         /       / C5    \
    123  *      V  \-------/  /---->\       /
    124  *   -------    E7   /       ---+---
    125  *  / C4'   \       /
    126  *  \       /------/ E9
    127  *   -------
    128  *
    129  * The state transition table is as follows:
    130  *
    131  *         +---------+---+---+-----+----+--------------+
    132  *         |C1       |C2 |C3 |C4   |C4' |C5            |
    133  *      ---+---------+---+---+-----+----+--------------+
    134  *       C1| -       |E1 | - | -   | -  |              |
    135  *      ---+---------+---+---+-----+----+--------------+
    136  *       C2|E4/6/7   |-  |E2 | -   | -  |E4/6/7/10     |
    137  *      ---+---------+---+---+-----+----+--------------+
    138  *       C3|E3/4/6/7 |-  |-  |E4/6 |E7  |E3/4/6/7/9/10 |
    139  *      ---+---------+---+---+-----+----+--------------+
    140  *       C4|         |-  |-  |E4   |E7  |E3/6/7/9      |
    141  *      ---+---------+---+---+-----+----+--------------+
    142  *      C4'|         |-  |-  |-    |-   |E9            |
    143  *      ---+---------+---+---+-----+----+--------------+
    144  *       C5|E8       |   |   |     |    |              |
    145  *      ---+---------+---+---+-----+----+--------------+
    146  *
    147  * Event definitions:
    148  *
    149  * -E1: Command was requested to be sent on wire
    150  * -E2: Command was submitted and now active on wire
    151  * -E3: Command was successfully completed
    152  *	- SCSI command is move to completion queue
    153  *	- ABORT/RESET/etc are completed.
    154  * -E4: Command has been requested to abort
    155  *	- SCSI command in pending queue will be returned
    156  *		to caller with aborted status.
    157  *	- SCSI command state updated and iscsi_handle_abort()
    158  *		will be called.
    159  *	- SCSI command with ABORTING state has already
    160  *		been requested to abort ignore request.
    161  *	- ABORT/RESET commands will be destroyed and the
    162  *		caller will be notify of the failure.
    163  *	- All other commands will just be destroyed.
    164  * -E6: Command has timed out
    165  *	- SCSI commands in pending queue will be returned up the
    166  *		stack with TIMEOUT errors.
    167  *	- SCSI commands in the active queue and timed out
    168  *		will be moved to the aborting queue.
    169  *	- SCSI commands in ABORTING state will be returned up
    170  *		up the stack with TIMEOUT errors.
    171  *	- ABORT/RESET commands will be destroyed and the caller
    172  *		notified of the failure.
    173  *	- All other commands will just be detroyed.
    174  * -E7: Connection has encountered a problem
    175  * -E8:	Command has completed
    176  *	- Only SCSI cmds should receive these events
    177  *		and reach the command state.
    178  * -E9: Callback received for previous idm_task_abort request
    179  * -E10: The command this abort was associated with has terminated on its own
    180  */
    181 void
    182 iscsi_cmd_state_machine(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
    183 {
    184 	boolean_t	release_lock = B_TRUE;
    185 
    186 	ASSERT(icmdp != NULL);
    187 	ASSERT(arg != NULL);
    188 
    189 	DTRACE_PROBE3(event, iscsi_cmd_t *, icmdp, char *,
    190 	    iscsi_cmd_state_str(icmdp->cmd_state),
    191 	    char *, iscsi_cmd_event_str(event));
    192 
    193 	mutex_enter(&icmdp->cmd_mutex);
    194 
    195 	/* Audit event */
    196 	idm_sm_audit_event(&icmdp->cmd_state_audit,
    197 	    SAS_ISCSI_CMD, icmdp->cmd_state, event, (uintptr_t)arg);
    198 
    199 	icmdp->cmd_prev_state = icmdp->cmd_state;
    200 	switch (icmdp->cmd_state) {
    201 	case ISCSI_CMD_STATE_FREE:
    202 		iscsi_cmd_state_free(icmdp, event, arg);
    203 		break;
    204 
    205 	case ISCSI_CMD_STATE_PENDING:
    206 		iscsi_cmd_state_pending(icmdp, event, arg);
    207 		break;
    208 
    209 	case ISCSI_CMD_STATE_ACTIVE:
    210 		iscsi_cmd_state_active(icmdp, event, arg);
    211 		break;
    212 
    213 	case ISCSI_CMD_STATE_ABORTING:
    214 		iscsi_cmd_state_aborting(icmdp, event, arg);
    215 		break;
    216 
    217 	case ISCSI_CMD_STATE_IDM_ABORTING:
    218 		iscsi_cmd_state_idm_aborting(icmdp, event, arg);
    219 		break;
    220 
    221 	case ISCSI_CMD_STATE_COMPLETED:
    222 		iscsi_cmd_state_completed(icmdp, event, arg);
    223 
    224 		/*
    225 		 * Once completed event is processed we DO NOT
    226 		 * want to touch it again because the caller
    227 		 * (sd, st, etc) may have freed the command.
    228 		 */
    229 		release_lock = B_FALSE;
    230 		break;
    231 
    232 	default:
    233 		ASSERT(FALSE);
    234 	}
    235 
    236 	if (release_lock == B_TRUE) {
    237 		/* Audit state if not completed */
    238 		idm_sm_audit_state_change(&icmdp->cmd_state_audit,
    239 		    SAS_ISCSI_CMD, icmdp->cmd_prev_state, icmdp->cmd_state);
    240 
    241 		if (!(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_FREE) ||
    242 		    !(icmdp->cmd_misc_flags &
    243 		    ISCSI_CMD_MISCFLAG_INTERNAL)) {
    244 			mutex_exit(&icmdp->cmd_mutex);
    245 			return;
    246 		}
    247 		mutex_exit(&icmdp->cmd_mutex);
    248 		iscsi_cmd_free(icmdp);
    249 	}
    250 }
    251 
    252 /*
    253  * iscsi_cmd_alloc -
    254  *
    255  */
    256 iscsi_cmd_t *
    257 iscsi_cmd_alloc(iscsi_conn_t *icp, int km_flags)
    258 {
    259 	iscsi_cmd_t	*icmdp;
    260 
    261 	icmdp = kmem_zalloc(sizeof (iscsi_cmd_t), km_flags);
    262 	if (icmdp) {
    263 		icmdp->cmd_sig		= ISCSI_SIG_CMD;
    264 		icmdp->cmd_state	= ISCSI_CMD_STATE_FREE;
    265 		icmdp->cmd_conn		= icp;
    266 		icmdp->cmd_misc_flags	|= ISCSI_CMD_MISCFLAG_INTERNAL;
    267 		idm_sm_audit_init(&icmdp->cmd_state_audit);
    268 		mutex_init(&icmdp->cmd_mutex, NULL, MUTEX_DRIVER, NULL);
    269 		cv_init(&icmdp->cmd_completion, NULL, CV_DRIVER, NULL);
    270 	}
    271 	return (icmdp);
    272 }
    273 
    274 /*
    275  * iscsi_cmd_free -
    276  *
    277  */
    278 void
    279 iscsi_cmd_free(iscsi_cmd_t *icmdp)
    280 {
    281 	ASSERT(icmdp != NULL);
    282 	ASSERT(icmdp->cmd_sig == ISCSI_SIG_CMD);
    283 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_FREE);
    284 	ASSERT(icmdp->cmd_next == NULL);
    285 	ASSERT(icmdp->cmd_prev == NULL);
    286 	ASSERT(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_INTERNAL);
    287 	if (icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT)
    288 		ASSERT(icmdp->cmd_un.abort.icmdp == NULL);
    289 	else if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
    290 		ASSERT(icmdp->cmd_un.scsi.r2t_icmdp == NULL);
    291 		ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
    292 	}
    293 	mutex_destroy(&icmdp->cmd_mutex);
    294 	cv_destroy(&icmdp->cmd_completion);
    295 	kmem_free(icmdp, sizeof (iscsi_cmd_t));
    296 }
    297 
    298 /*
    299  * +--------------------------------------------------------------------+
    300  * | Internal Command Interfaces					|
    301  * +--------------------------------------------------------------------+
    302  */
    303 /*
    304  * iscsi_cmd_state_free -
    305  *
    306  */
    307 static void
    308 iscsi_cmd_state_free(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
    309 {
    310 	iscsi_sess_t	*isp		= (iscsi_sess_t *)arg;
    311 
    312 	ASSERT(icmdp != NULL);
    313 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_FREE);
    314 	ASSERT(isp != NULL);
    315 
    316 	/* switch on event change */
    317 	switch (event) {
    318 	/* -E1: Command was requested to be sent on wire */
    319 	case ISCSI_CMD_EVENT_E1:
    320 
    321 		/* setup timestamps and timeouts for this command */
    322 		icmdp->cmd_lbolt_pending = ddi_get_lbolt();
    323 		if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
    324 			/*
    325 			 * Establish absolute time when command should timeout.
    326 			 * For commands that depend on cmdsn window to go
    327 			 * active, the timeout will be ignored while on
    328 			 * the pending queue and a new timeout will be
    329 			 * established when the command goes active.
    330 			 */
    331 			if (icmdp->cmd_un.scsi.pkt &&
    332 			    icmdp->cmd_un.scsi.pkt->pkt_time)
    333 				icmdp->cmd_lbolt_timeout =
    334 				    icmdp->cmd_lbolt_pending + SEC_TO_TICK(
    335 				    icmdp->cmd_un.scsi.pkt->pkt_time *
    336 				    iscsi_cmd_timeout_factor);
    337 			else
    338 				icmdp->cmd_lbolt_timeout = 0;
    339 
    340 			icmdp->cmd_un.scsi.pkt_stat &=
    341 			    ISCSI_CMD_PKT_STAT_INIT;
    342 		} else {
    343 			icmdp->cmd_lbolt_timeout = icmdp->cmd_lbolt_pending +
    344 			    SEC_TO_TICK(ISCSI_INTERNAL_CMD_TIMEOUT *
    345 			    iscsi_cmd_timeout_factor);
    346 		}
    347 
    348 		/* place into pending queue */
    349 		iscsi_enqueue_pending_cmd(isp, icmdp);
    350 
    351 		break;
    352 
    353 	/* All other events are invalid for this state */
    354 	default:
    355 		ASSERT(FALSE);
    356 	}
    357 }
    358 
    359 /*
    360  * iscsi_cmd_state_pending -
    361  *
    362  */
    363 static void
    364 iscsi_cmd_state_pending(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
    365 {
    366 	iscsi_status_t	status;
    367 	iscsi_sess_t	*isp		= (iscsi_sess_t *)arg;
    368 	boolean_t	free_icmdp	= B_FALSE;
    369 	int		rval;
    370 
    371 	ASSERT(icmdp != NULL);
    372 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_PENDING);
    373 	ASSERT(isp != NULL);
    374 
    375 	/* switch on event change */
    376 	switch (event) {
    377 	/* -E2: Command was submitted and now active on wire */
    378 	case ISCSI_CMD_EVENT_E2:
    379 
    380 		/* A connection should have already been assigned */
    381 		ASSERT(mutex_owned(&isp->sess_queue_pending.mutex));
    382 		ASSERT(icmdp->cmd_conn != NULL);
    383 
    384 		/*
    385 		 * RESERVE RESOURSES
    386 		 */
    387 		switch (icmdp->cmd_type) {
    388 		case ISCSI_CMD_TYPE_SCSI:
    389 			/* check cmdsn window */
    390 			mutex_enter(&isp->sess_cmdsn_mutex);
    391 			if (!iscsi_sna_lte(isp->sess_cmdsn,
    392 			    isp->sess_maxcmdsn)) {
    393 				/* cmdsn window closed */
    394 				mutex_exit(&isp->sess_cmdsn_mutex);
    395 				mutex_exit(&isp->sess_queue_pending.mutex);
    396 				isp->sess_window_open = B_FALSE;
    397 				icmdp->cmd_misc_flags |=
    398 				    ISCSI_CMD_MISCFLAG_STUCK;
    399 				return;
    400 			}
    401 
    402 			/* assign itt */
    403 			status = iscsi_sess_reserve_scsi_itt(icmdp);
    404 			if (!ISCSI_SUCCESS(status)) {
    405 				/* no available itt slots */
    406 				mutex_exit(&isp->sess_cmdsn_mutex);
    407 				mutex_exit(&isp->sess_queue_pending.mutex);
    408 				isp->sess_window_open = B_FALSE;
    409 				icmdp->cmd_misc_flags |=
    410 				    ISCSI_CMD_MISCFLAG_STUCK;
    411 				return;
    412 			}
    413 			mutex_exit(&isp->sess_cmdsn_mutex);
    414 			break;
    415 
    416 		case ISCSI_CMD_TYPE_ABORT:
    417 			/*
    418 			 * Verify ABORT's parent SCSI command is still
    419 			 * there.  If parent SCSI command is completed
    420 			 * then there is no longer any reason to abort
    421 			 * the parent command.  This could occur due
    422 			 * to a connection or target reset.
    423 			 */
    424 			ASSERT(icmdp->cmd_un.abort.icmdp != NULL);
    425 			if (icmdp->cmd_un.abort.icmdp->cmd_state ==
    426 			    ISCSI_CMD_STATE_COMPLETED) {
    427 				iscsi_dequeue_pending_cmd(isp, icmdp);
    428 				mutex_exit(&isp->sess_queue_pending.mutex);
    429 
    430 				mutex_enter(&icmdp->cmd_un.abort.icmdp->
    431 				    cmd_mutex);
    432 				icmdp->cmd_un.abort.icmdp->
    433 				    cmd_un.scsi.abort_icmdp = NULL;
    434 				cv_broadcast(&icmdp->cmd_un.abort.icmdp->
    435 				    cmd_completion);
    436 				mutex_exit(&icmdp->cmd_un.abort.icmdp->
    437 				    cmd_mutex);
    438 				icmdp->cmd_un.abort.icmdp = NULL;
    439 
    440 				icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    441 				icmdp->cmd_misc_flags |=
    442 				    ISCSI_CMD_MISCFLAG_FREE;
    443 				return;
    444 			}
    445 			/* FALLTHRU */
    446 		case ISCSI_CMD_TYPE_RESET:
    447 			/* FALLTHRU */
    448 		case ISCSI_CMD_TYPE_LOGOUT:
    449 			mutex_enter(&isp->sess_cmdsn_mutex);
    450 			/* assign itt */
    451 			status = iscsi_sess_reserve_itt(isp, icmdp);
    452 			if (!ISCSI_SUCCESS(status)) {
    453 				/* no available itt slots */
    454 				mutex_exit(&isp->sess_cmdsn_mutex);
    455 				mutex_exit(&isp->sess_queue_pending.mutex);
    456 				isp->sess_window_open = B_FALSE;
    457 				return;
    458 			}
    459 			mutex_exit(&isp->sess_cmdsn_mutex);
    460 			break;
    461 		case ISCSI_CMD_TYPE_NOP:
    462 			/* assign itt, if needed */
    463 			if (icmdp->cmd_itt == ISCSI_RSVD_TASK_TAG) {
    464 				/* not expecting a response */
    465 				free_icmdp = B_TRUE;
    466 			} else {
    467 				/* expecting response, assign an itt */
    468 				mutex_enter(&isp->sess_cmdsn_mutex);
    469 				/* assign itt */
    470 				status = iscsi_sess_reserve_itt(isp, icmdp);
    471 				if (!ISCSI_SUCCESS(status)) {
    472 					/* no available itt slots */
    473 					mutex_exit(&isp->sess_cmdsn_mutex);
    474 					mutex_exit(&isp->sess_queue_pending.
    475 					    mutex);
    476 					isp->sess_window_open = B_FALSE;
    477 					return;
    478 				}
    479 				mutex_exit(&isp->sess_cmdsn_mutex);
    480 			}
    481 			break;
    482 
    483 		case ISCSI_CMD_TYPE_TEXT:
    484 			mutex_enter(&isp->sess_cmdsn_mutex);
    485 			/* check cmdsn window */
    486 			if (!iscsi_sna_lte(isp->sess_cmdsn,
    487 			    isp->sess_maxcmdsn)) {
    488 				/* cmdsn window closed */
    489 				isp->sess_window_open = B_FALSE;
    490 				mutex_exit(&isp->sess_cmdsn_mutex);
    491 				mutex_exit(&isp->sess_queue_pending.mutex);
    492 				icmdp->cmd_misc_flags |=
    493 				    ISCSI_CMD_MISCFLAG_STUCK;
    494 				return;
    495 			}
    496 			if (icmdp->cmd_un.text.stage ==
    497 			    ISCSI_CMD_TEXT_INITIAL_REQ) {
    498 				/* assign itt */
    499 				status = iscsi_sess_reserve_itt(isp, icmdp);
    500 				if (!ISCSI_SUCCESS(status)) {
    501 					/* no available itt slots */
    502 					mutex_exit(&isp->sess_cmdsn_mutex);
    503 					mutex_exit(&isp->sess_queue_pending.
    504 					    mutex);
    505 					isp->sess_window_open = B_FALSE;
    506 					icmdp->cmd_misc_flags |=
    507 					    ISCSI_CMD_MISCFLAG_STUCK;
    508 					return;
    509 				}
    510 			}
    511 			mutex_exit(&isp->sess_cmdsn_mutex);
    512 			break;
    513 
    514 		default:
    515 			ASSERT(FALSE);
    516 		}
    517 
    518 		/*
    519 		 * RESOURCES RESERVED
    520 		 *
    521 		 * Now that we have the resources reserved, establish timeout
    522 		 * for cmd_type values that depend on having an open cmdsn
    523 		 * window (i.e. cmd_type that called iscsi_sna_lte() above).
    524 		 */
    525 		if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
    526 			if (icmdp->cmd_un.scsi.pkt &&
    527 			    icmdp->cmd_un.scsi.pkt->pkt_time)
    528 				icmdp->cmd_lbolt_timeout =
    529 				    ddi_get_lbolt() + SEC_TO_TICK(
    530 				    icmdp->cmd_un.scsi.pkt->pkt_time *
    531 				    iscsi_cmd_timeout_factor);
    532 			else
    533 				icmdp->cmd_lbolt_timeout = 0;
    534 		} else if (icmdp->cmd_type == ISCSI_CMD_TYPE_TEXT) {
    535 			icmdp->cmd_lbolt_timeout = ddi_get_lbolt() +
    536 			    SEC_TO_TICK(ISCSI_INTERNAL_CMD_TIMEOUT *
    537 			    iscsi_cmd_timeout_factor);
    538 		}
    539 
    540 		/* remove command from pending queue */
    541 		iscsi_dequeue_pending_cmd(isp, icmdp);
    542 		/* check if expecting a response */
    543 		if (free_icmdp == B_FALSE) {
    544 			/* response expected, move to active queue */
    545 			mutex_enter(&icmdp->cmd_conn->conn_queue_active.mutex);
    546 			iscsi_enqueue_active_cmd(icmdp->cmd_conn, icmdp);
    547 			mutex_exit(&icmdp->cmd_conn->conn_queue_active.mutex);
    548 		}
    549 
    550 		/*
    551 		 * TRANSFER COMMAND
    552 		 */
    553 		rval = iscsi_tx_cmd(isp, icmdp);
    554 
    555 		ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex));
    556 
    557 		/*
    558 		 * CHECK SUCCESS/FAILURE
    559 		 */
    560 		if (!ISCSI_SUCCESS(rval)) {
    561 			/*
    562 			 * iscsi_tx_cmd failed.  No cleanup is required
    563 			 * of commands that were put in the active queue.
    564 			 * If the tx failed then rx will also fail and cleanup
    565 			 * all items in the active/aborted queue in a common.
    566 			 */
    567 
    568 			/* EMPTY */
    569 		}
    570 
    571 		/* free temporary commands */
    572 		if (free_icmdp == B_TRUE) {
    573 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    574 			icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_FREE;
    575 		}
    576 		break;
    577 
    578 	/* -E10: Abort is no longer required for this command */
    579 	case ISCSI_CMD_EVENT_E10:
    580 		/*
    581 		 * Acquiring the sess_queue_pending lock while the
    582 		 * conn_queue_active lock is held conflicts with the
    583 		 * locking order in iscsi_cmd_state_pending where
    584 		 * conn_queue_active is acquired while sess_queue_pending
    585 		 * is held.  Normally this would be a dangerous lock
    586 		 * order conflict, except that we know that if we are
    587 		 * seeing ISCSI_CMD_EVENT_E10 then the command being
    588 		 * aborted is in "aborting" state and by extension
    589 		 * is not in "pending" state.  Therefore the code
    590 		 * path with that alternate lock order will not execute.
    591 		 * That's good because we can't drop the lock here without
    592 		 * risking a deadlock.
    593 		 */
    594 		ASSERT(mutex_owned(&icmdp->cmd_conn->conn_queue_active.mutex));
    595 		mutex_enter(&isp->sess_queue_pending.mutex);
    596 
    597 		icmdp->cmd_lbolt_aborting = ddi_get_lbolt();
    598 
    599 		iscsi_dequeue_pending_cmd(isp, icmdp);
    600 
    601 		icmdp->cmd_un.abort.icmdp->cmd_un.scsi.abort_icmdp = NULL;
    602 		icmdp->cmd_un.abort.icmdp = NULL;
    603 		icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_FREE;
    604 		icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    605 
    606 		mutex_exit(&isp->sess_queue_pending.mutex);
    607 		break;
    608 
    609 	/* -E4: Command has been requested to abort */
    610 	case ISCSI_CMD_EVENT_E4:
    611 		ASSERT(mutex_owned(&isp->sess_queue_pending.mutex));
    612 
    613 		icmdp->cmd_lbolt_aborting = ddi_get_lbolt();
    614 		ISCSI_CMD_SET_REASON_STAT(icmdp,
    615 		    CMD_ABORTED, STAT_ABORTED);
    616 
    617 		iscsi_dequeue_pending_cmd(isp, icmdp);
    618 		iscsi_enqueue_completed_cmd(isp, icmdp);
    619 
    620 		icmdp->cmd_lbolt_aborting = ddi_get_lbolt();
    621 
    622 		break;
    623 
    624 	/* -E7: Command has been reset */
    625 	case ISCSI_CMD_EVENT_E7:
    626 
    627 		/* FALLTHRU */
    628 
    629 	/* -E6: Command has timed out */
    630 	case ISCSI_CMD_EVENT_E6:
    631 		ASSERT(mutex_owned(&isp->sess_queue_pending.mutex));
    632 		iscsi_dequeue_pending_cmd(isp, icmdp);
    633 
    634 		switch (icmdp->cmd_type) {
    635 		case ISCSI_CMD_TYPE_SCSI:
    636 			/* Complete to caller as TIMEOUT */
    637 			if (event == ISCSI_CMD_EVENT_E6) {
    638 				ISCSI_CMD_SET_REASON_STAT(icmdp,
    639 				    CMD_TIMEOUT, STAT_TIMEOUT);
    640 			} else {
    641 				ISCSI_CMD_SET_REASON_STAT(icmdp,
    642 				    CMD_TRAN_ERR, icmdp->cmd_un.scsi.pkt_stat);
    643 			}
    644 			iscsi_enqueue_completed_cmd(isp, icmdp);
    645 			break;
    646 
    647 		case ISCSI_CMD_TYPE_NOP:
    648 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    649 			/*
    650 			 * Timeout occured.  Just free NOP.  Another
    651 			 * NOP request will be spawned to replace
    652 			 * this one.
    653 			 */
    654 			icmdp->cmd_misc_flags |=
    655 			    ISCSI_CMD_MISCFLAG_FREE;
    656 
    657 			break;
    658 
    659 		case ISCSI_CMD_TYPE_ABORT:
    660 			mutex_enter(&icmdp->cmd_un.abort.icmdp->cmd_mutex);
    661 			icmdp->cmd_un.abort.icmdp->
    662 			    cmd_un.scsi.abort_icmdp = NULL;
    663 			cv_broadcast(&icmdp->cmd_un.abort.icmdp->
    664 			    cmd_completion);
    665 			mutex_exit(&icmdp->cmd_un.abort.icmdp->cmd_mutex);
    666 			icmdp->cmd_un.abort.icmdp = NULL;
    667 
    668 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    669 			icmdp->cmd_misc_flags |=
    670 			    ISCSI_CMD_MISCFLAG_FREE;
    671 			break;
    672 
    673 		case ISCSI_CMD_TYPE_RESET:
    674 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    675 			/*
    676 			 * If we are failing a RESET we need
    677 			 * to notify the tran_reset caller.
    678 			 * with the cmd and notify caller.
    679 			 */
    680 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
    681 			    ISCSI_STATUS_CMD_FAILED);
    682 			break;
    683 
    684 		case ISCSI_CMD_TYPE_LOGOUT:
    685 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    686 			/* notify requester of failure */
    687 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
    688 			    ISCSI_STATUS_CMD_FAILED);
    689 			break;
    690 
    691 		case ISCSI_CMD_TYPE_TEXT:
    692 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    693 			icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
    694 			/*
    695 			 * If a TEXT command fails, notify the owner.
    696 			 */
    697 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
    698 			    ISCSI_STATUS_CMD_FAILED);
    699 			break;
    700 
    701 		default:
    702 			ASSERT(FALSE);
    703 			break;
    704 		}
    705 		break;
    706 
    707 	/* All other events are invalid for this state */
    708 	default:
    709 		ASSERT(FALSE);
    710 	}
    711 }
    712 
    713 
    714 /*
    715  * iscsi_cmd_state_active -
    716  *
    717  */
    718 static void
    719 iscsi_cmd_state_active(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
    720 {
    721 	iscsi_sess_t	*isp		= (iscsi_sess_t *)arg;
    722 	iscsi_hba_t	*ihp;
    723 	iscsi_cmd_t	*t_icmdp	= NULL;
    724 	iscsi_conn_t	*icp		= NULL;
    725 
    726 	ASSERT(icmdp != NULL);
    727 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_ACTIVE);
    728 	ASSERT(isp != NULL);
    729 
    730 	ihp = isp->sess_hba;
    731 	ASSERT(ihp != NULL);
    732 
    733 	icp = icmdp->cmd_conn;
    734 	ASSERT(icp != NULL);
    735 	ASSERT(mutex_owned(&icp->conn_queue_active.mutex));
    736 
    737 	/* switch on event change */
    738 	switch (event) {
    739 	/* -E3: Command was successfully completed */
    740 	case ISCSI_CMD_EVENT_E3:
    741 		/*
    742 		 * Remove command from the active list.  We need to protect
    743 		 * someone from looking up this command ITT until it's
    744 		 * freed of the command is moved to a new queue location.
    745 		 */
    746 		mutex_enter(&isp->sess_cmdsn_mutex);
    747 		iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
    748 
    749 		switch (icmdp->cmd_type) {
    750 		case ISCSI_CMD_TYPE_SCSI:
    751 			iscsi_sess_release_scsi_itt(icmdp);
    752 			mutex_exit(&isp->sess_cmdsn_mutex);
    753 			iscsi_enqueue_completed_cmd(isp, icmdp);
    754 			break;
    755 
    756 		case ISCSI_CMD_TYPE_NOP:
    757 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    758 			iscsi_sess_release_itt(isp, icmdp);
    759 			mutex_exit(&isp->sess_cmdsn_mutex);
    760 
    761 			/* free alloc */
    762 			icmdp->cmd_misc_flags |=
    763 			    ISCSI_CMD_MISCFLAG_FREE;
    764 
    765 			break;
    766 
    767 		case ISCSI_CMD_TYPE_ABORT:
    768 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    769 			iscsi_sess_release_itt(isp, icmdp);
    770 			mutex_exit(&isp->sess_cmdsn_mutex);
    771 
    772 			/*
    773 			 * Abort was completed successfully.  We should
    774 			 * complete the parent scsi command if it still
    775 			 * exists as timed out, and the state is not
    776 			 * COMPLETED
    777 			 */
    778 			t_icmdp = icmdp->cmd_un.abort.icmdp;
    779 			ASSERT(t_icmdp != NULL);
    780 			mutex_enter(&t_icmdp->cmd_mutex);
    781 			t_icmdp->cmd_un.scsi.abort_icmdp = NULL;
    782 			if (t_icmdp->cmd_state != ISCSI_CMD_STATE_COMPLETED) {
    783 				iscsi_dequeue_active_cmd(
    784 				    t_icmdp->cmd_conn, t_icmdp);
    785 				mutex_enter(
    786 				    &icp->conn_queue_idm_aborting.mutex);
    787 				iscsi_enqueue_idm_aborting_cmd(
    788 				    t_icmdp->cmd_conn,
    789 				    t_icmdp);
    790 				mutex_exit(&icp->conn_queue_idm_aborting.mutex);
    791 
    792 				/*
    793 				 * Complete abort processing after IDM
    794 				 * calls us back.  Set the status to use
    795 				 * when we complete the command.
    796 				 */
    797 				ISCSI_CMD_SET_REASON_STAT(
    798 				    t_icmdp, CMD_TIMEOUT, STAT_ABORTED);
    799 				idm_task_abort(icp->conn_ic, t_icmdp->cmd_itp,
    800 				    AT_TASK_MGMT_ABORT);
    801 			} else {
    802 				cv_broadcast(&t_icmdp->cmd_completion);
    803 			}
    804 			mutex_exit(&t_icmdp->cmd_mutex);
    805 			icmdp->cmd_un.abort.icmdp = NULL;
    806 
    807 			icmdp->cmd_misc_flags |=
    808 			    ISCSI_CMD_MISCFLAG_FREE;
    809 
    810 			break;
    811 		case ISCSI_CMD_TYPE_RESET:
    812 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    813 			iscsi_sess_release_itt(isp, icmdp);
    814 			mutex_exit(&isp->sess_cmdsn_mutex);
    815 
    816 			/*
    817 			 * Complete the abort/reset command.
    818 			 */
    819 			if (icmdp->cmd_un.reset.response !=
    820 			    SCSI_TCP_TM_RESP_COMPLETE) {
    821 				ISCSI_CMD_ISSUE_CALLBACK(icmdp,
    822 				    ISCSI_STATUS_CMD_FAILED);
    823 			} else {
    824 				ISCSI_CMD_ISSUE_CALLBACK(icmdp,
    825 				    ISCSI_STATUS_SUCCESS);
    826 			}
    827 
    828 			break;
    829 
    830 		case ISCSI_CMD_TYPE_LOGOUT:
    831 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    832 			iscsi_sess_release_itt(isp, icmdp);
    833 			mutex_exit(&isp->sess_cmdsn_mutex);
    834 
    835 			/*
    836 			 * Complete the logout successfully.
    837 			 */
    838 			ISCSI_CMD_ISSUE_CALLBACK(icmdp, ISCSI_STATUS_SUCCESS);
    839 			break;
    840 
    841 		case ISCSI_CMD_TYPE_TEXT:
    842 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    843 			if (icmdp->cmd_un.text.stage ==
    844 			    ISCSI_CMD_TEXT_FINAL_RSP) {
    845 				iscsi_sess_release_itt(isp, icmdp);
    846 			}
    847 			mutex_exit(&isp->sess_cmdsn_mutex);
    848 
    849 			/*
    850 			 * Complete the text command successfully.
    851 			 */
    852 			ISCSI_CMD_ISSUE_CALLBACK(icmdp, icmdp->cmd_result);
    853 			break;
    854 
    855 		default:
    856 			mutex_exit(&isp->sess_cmdsn_mutex);
    857 			ASSERT(FALSE);
    858 		}
    859 
    860 		ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex));
    861 		break;
    862 
    863 	/* -E10,E4: Command has been requested to abort */
    864 	case ISCSI_CMD_EVENT_E10:
    865 		/* FALLTHRU */
    866 	case ISCSI_CMD_EVENT_E4:
    867 
    868 		/* E4 is only for resets and aborts */
    869 		ASSERT((icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT) ||
    870 		    (icmdp->cmd_type == ISCSI_CMD_TYPE_RESET));
    871 		/* FALLTHRU */
    872 
    873 	/* -E6: Command has timed out */
    874 	case ISCSI_CMD_EVENT_E6:
    875 
    876 		switch (icmdp->cmd_type) {
    877 		case ISCSI_CMD_TYPE_SCSI:
    878 			icmdp->cmd_state = ISCSI_CMD_STATE_ABORTING;
    879 			iscsi_handle_abort(icmdp);
    880 			break;
    881 
    882 		case ISCSI_CMD_TYPE_NOP:
    883 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    884 
    885 			mutex_enter(&isp->sess_cmdsn_mutex);
    886 			iscsi_sess_release_itt(isp, icmdp);
    887 			iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
    888 			mutex_exit(&isp->sess_cmdsn_mutex);
    889 
    890 			icmdp->cmd_misc_flags |=
    891 			    ISCSI_CMD_MISCFLAG_FREE;
    892 
    893 			break;
    894 
    895 		case ISCSI_CMD_TYPE_ABORT:
    896 			icmdp->cmd_state =
    897 			    ISCSI_CMD_STATE_FREE;
    898 
    899 			mutex_enter(&isp->sess_cmdsn_mutex);
    900 			iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
    901 			iscsi_sess_release_itt(isp, icmdp);
    902 			mutex_exit(&isp->sess_cmdsn_mutex);
    903 
    904 			/*
    905 			 * If this is an E4 then we may need to deal with
    906 			 * the abort's associated SCSI command.  If this
    907 			 * is an E10 then IDM is already cleaning up the
    908 			 * SCSI command and all we need to do is break the
    909 			 * linkage between them and free the abort command.
    910 			 */
    911 			t_icmdp = icmdp->cmd_un.abort.icmdp;
    912 			ASSERT(t_icmdp != NULL);
    913 			if (event != ISCSI_CMD_EVENT_E10) {
    914 
    915 				mutex_enter(&t_icmdp->cmd_mutex);
    916 				t_icmdp->cmd_un.scsi.abort_icmdp = NULL;
    917 				/*
    918 				 * If abort command is aborted then we should
    919 				 * not act on the parent scsi command.  If the
    920 				 * abort command timed out then we need to
    921 				 * complete the parent command if it still
    922 				 * exists with a timeout failure.
    923 				 */
    924 				if ((event == ISCSI_CMD_EVENT_E6) &&
    925 				    (t_icmdp->cmd_state !=
    926 				    ISCSI_CMD_STATE_IDM_ABORTING) &&
    927 				    (t_icmdp->cmd_state !=
    928 				    ISCSI_CMD_STATE_COMPLETED)) {
    929 
    930 					iscsi_dequeue_active_cmd(
    931 					    t_icmdp->cmd_conn, t_icmdp);
    932 					mutex_enter(&icp->
    933 					    conn_queue_idm_aborting.mutex);
    934 					iscsi_enqueue_idm_aborting_cmd(
    935 					    t_icmdp->cmd_conn,  t_icmdp);
    936 					mutex_exit(&icp->
    937 					    conn_queue_idm_aborting.mutex);
    938 					/*
    939 					 * Complete abort processing after IDM
    940 					 * calls us back.  Set the status to use
    941 					 * when we complete the command.
    942 					 */
    943 					ISCSI_CMD_SET_REASON_STAT(t_icmdp,
    944 					    CMD_TIMEOUT, STAT_TIMEOUT);
    945 					idm_task_abort(icp->conn_ic,
    946 					    t_icmdp->cmd_itp,
    947 					    AT_TASK_MGMT_ABORT);
    948 				} else {
    949 					cv_broadcast(&t_icmdp->cmd_completion);
    950 				}
    951 				mutex_exit(&t_icmdp->cmd_mutex);
    952 			} else {
    953 				t_icmdp->cmd_un.scsi.abort_icmdp = NULL;
    954 			}
    955 			icmdp->cmd_un.abort.icmdp = NULL;
    956 			icmdp->cmd_misc_flags |=
    957 			    ISCSI_CMD_MISCFLAG_FREE;
    958 			break;
    959 
    960 		case ISCSI_CMD_TYPE_RESET:
    961 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    962 
    963 			mutex_enter(&isp->sess_cmdsn_mutex);
    964 			iscsi_sess_release_itt(isp, icmdp);
    965 			iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
    966 			mutex_exit(&isp->sess_cmdsn_mutex);
    967 
    968 			/*
    969 			 * If we are failing a RESET we need
    970 			 * to notify the tran_reset caller.
    971 			 * It will free the memory associated
    972 			 * with the cmd and notify caller.
    973 			 */
    974 
    975 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
    976 			    ISCSI_STATUS_CMD_FAILED);
    977 			break;
    978 
    979 		case ISCSI_CMD_TYPE_LOGOUT:
    980 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    981 
    982 			mutex_enter(&isp->sess_cmdsn_mutex);
    983 			iscsi_sess_release_itt(isp, icmdp);
    984 			iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
    985 			mutex_exit(&isp->sess_cmdsn_mutex);
    986 
    987 			/*
    988 			 * Notify caller of failure.
    989 			 */
    990 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
    991 			    ISCSI_STATUS_CMD_FAILED);
    992 			break;
    993 
    994 		case ISCSI_CMD_TYPE_TEXT:
    995 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
    996 			icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
    997 			mutex_enter(&isp->sess_cmdsn_mutex);
    998 			iscsi_sess_release_itt(isp, icmdp);
    999 			iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
   1000 			mutex_exit(&isp->sess_cmdsn_mutex);
   1001 
   1002 			/*
   1003 			 * If a TEXT command fails, notify caller so
   1004 			 * it can free assocated command
   1005 			 */
   1006 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
   1007 			    ISCSI_STATUS_CMD_FAILED);
   1008 			break;
   1009 
   1010 		default:
   1011 			ASSERT(FALSE);
   1012 		}
   1013 
   1014 		ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex));
   1015 		break;
   1016 
   1017 	/* -E7: Connection has encountered a problem */
   1018 	case ISCSI_CMD_EVENT_E7:
   1019 		mutex_enter(&isp->sess_cmdsn_mutex);
   1020 		iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
   1021 
   1022 		switch (icmdp->cmd_type) {
   1023 		case ISCSI_CMD_TYPE_SCSI:
   1024 			mutex_exit(&isp->sess_cmdsn_mutex);
   1025 			mutex_enter(&icp->conn_queue_idm_aborting.mutex);
   1026 			iscsi_enqueue_idm_aborting_cmd(icmdp->cmd_conn, icmdp);
   1027 			mutex_exit(&icp->conn_queue_idm_aborting.mutex);
   1028 			ISCSI_CMD_SET_REASON_STAT(icmdp,
   1029 			    CMD_TRAN_ERR, icmdp->cmd_un.scsi.pkt_stat);
   1030 			idm_task_abort(icp->conn_ic, icmdp->cmd_itp,
   1031 			    AT_TASK_MGMT_ABORT);
   1032 			break;
   1033 
   1034 		case ISCSI_CMD_TYPE_NOP:
   1035 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
   1036 			iscsi_sess_release_itt(isp, icmdp);
   1037 			mutex_exit(&isp->sess_cmdsn_mutex);
   1038 
   1039 			icmdp->cmd_misc_flags |=
   1040 			    ISCSI_CMD_MISCFLAG_FREE;
   1041 			break;
   1042 
   1043 		case ISCSI_CMD_TYPE_ABORT:
   1044 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
   1045 			iscsi_sess_release_itt(isp, icmdp);
   1046 			mutex_exit(&isp->sess_cmdsn_mutex);
   1047 
   1048 			mutex_enter(&icmdp->cmd_un.abort.icmdp->cmd_mutex);
   1049 			icmdp->cmd_un.abort.icmdp->
   1050 			    cmd_un.scsi.abort_icmdp = NULL;
   1051 			cv_broadcast(&icmdp->cmd_un.abort.icmdp->
   1052 			    cmd_completion);
   1053 			mutex_exit(&icmdp->cmd_un.abort.icmdp->cmd_mutex);
   1054 			/*
   1055 			 * Nullify the abort command's pointer to its
   1056 			 * parent command. It does not have to complete its
   1057 			 * parent command because the parent command will
   1058 			 * also get an E7.
   1059 			 */
   1060 			icmdp->cmd_un.abort.icmdp = NULL;
   1061 
   1062 			icmdp->cmd_misc_flags |=
   1063 			    ISCSI_CMD_MISCFLAG_FREE;
   1064 			break;
   1065 
   1066 		case ISCSI_CMD_TYPE_RESET:
   1067 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
   1068 			iscsi_sess_release_itt(isp, icmdp);
   1069 			mutex_exit(&isp->sess_cmdsn_mutex);
   1070 			/*
   1071 			 * If we are failing a ABORT we need
   1072 			 * to notify the tran_abort caller.
   1073 			 * It will free the memory associated
   1074 			 * with the cmd and notify caller.
   1075 			 */
   1076 
   1077 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
   1078 			    ISCSI_STATUS_CMD_FAILED);
   1079 			break;
   1080 
   1081 		case ISCSI_CMD_TYPE_LOGOUT:
   1082 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
   1083 			/*
   1084 			 * A connection problem and we attempted to
   1085 			 * logout?  I guess we can just free the
   1086 			 * request.  Someone has already pushed the
   1087 			 * connection state.
   1088 			 */
   1089 			iscsi_sess_release_itt(isp, icmdp);
   1090 			mutex_exit(&isp->sess_cmdsn_mutex);
   1091 
   1092 			ISCSI_CMD_ISSUE_CALLBACK(icmdp, ISCSI_STATUS_SUCCESS);
   1093 			break;
   1094 
   1095 		case ISCSI_CMD_TYPE_TEXT:
   1096 			icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
   1097 			icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
   1098 			iscsi_sess_release_itt(isp, icmdp);
   1099 			mutex_exit(&isp->sess_cmdsn_mutex);
   1100 
   1101 			/*
   1102 			 * If a TEXT command fails, notify caller so
   1103 			 * it can free assocated command
   1104 			 */
   1105 			ISCSI_CMD_ISSUE_CALLBACK(icmdp,
   1106 			    ISCSI_STATUS_CMD_FAILED);
   1107 			break;
   1108 
   1109 		default:
   1110 			mutex_exit(&isp->sess_cmdsn_mutex);
   1111 			ASSERT(FALSE);
   1112 			break;
   1113 		}
   1114 
   1115 		ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex));
   1116 		break;
   1117 
   1118 	/* -E9: IDM is no longer processing this command */
   1119 	case ISCSI_CMD_EVENT_E9:
   1120 		iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
   1121 
   1122 		iscsi_task_cleanup(ISCSI_OP_SCSI_RSP, icmdp);
   1123 		iscsi_sess_release_scsi_itt(icmdp);
   1124 
   1125 		ISCSI_CMD_SET_REASON_STAT(icmdp, CMD_TRAN_ERR,
   1126 		    icmdp->cmd_un.scsi.pkt_stat);
   1127 		iscsi_enqueue_completed_cmd(isp, icmdp);
   1128 		break;
   1129 
   1130 	/* All other events are invalid for this state */
   1131 	default:
   1132 		ASSERT(FALSE);
   1133 	}
   1134 }
   1135 
   1136 
   1137 /*
   1138  * iscsi_cmd_state_aborting -
   1139  *
   1140  */
   1141 static void
   1142 iscsi_cmd_state_aborting(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
   1143 {
   1144 	iscsi_sess_t	*isp	= (iscsi_sess_t *)arg;
   1145 	iscsi_cmd_t	*a_icmdp;
   1146 
   1147 	ASSERT(icmdp != NULL);
   1148 	ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI);
   1149 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_ABORTING);
   1150 	ASSERT(isp != NULL);
   1151 	ASSERT(mutex_owned(&icmdp->cmd_conn->conn_queue_active.mutex));
   1152 
   1153 	/* switch on event change */
   1154 	switch (event) {
   1155 	/* -E3: Command was successfully completed */
   1156 	case ISCSI_CMD_EVENT_E3:
   1157 		/*
   1158 		 * Remove command from the aborting list
   1159 		 */
   1160 		mutex_enter(&isp->sess_cmdsn_mutex);
   1161 		iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
   1162 		iscsi_sess_release_scsi_itt(icmdp);
   1163 		mutex_exit(&isp->sess_cmdsn_mutex);
   1164 
   1165 		iscsi_enqueue_completed_cmd(isp, icmdp);
   1166 		break;
   1167 
   1168 	/* -E4: Command has been requested to abort */
   1169 	case ISCSI_CMD_EVENT_E4:
   1170 		/*
   1171 		 * An upper level driver might attempt to
   1172 		 * abort a command that we are already
   1173 		 * aborting due to a nop.  Since we are
   1174 		 * already in the process of aborting
   1175 		 * ignore the request.
   1176 		 */
   1177 		break;
   1178 
   1179 	/* -E6: Command has timed out */
   1180 	case ISCSI_CMD_EVENT_E6:
   1181 		ASSERT(FALSE);
   1182 		/*
   1183 		 * Timeouts should not occur on command in abort queue
   1184 		 * they are already be processed due to a timeout.
   1185 		 */
   1186 		break;
   1187 
   1188 	/* -E7: Connection has encountered a problem */
   1189 	case ISCSI_CMD_EVENT_E7:
   1190 		iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
   1191 		mutex_enter(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex);
   1192 		iscsi_enqueue_idm_aborting_cmd(icmdp->cmd_conn, icmdp);
   1193 		mutex_exit(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex);
   1194 
   1195 		/*
   1196 		 * Since we are in "aborting" state there is another command
   1197 		 * representing the abort of this command.  This command
   1198 		 * will cleanup at some indeterminate time after the call
   1199 		 * to idm_task_abort so we can't leave the abort request
   1200 		 * active.  An E10 event to the abort command will cause
   1201 		 * it to complete immediately.
   1202 		 */
   1203 		if ((a_icmdp = icmdp->cmd_un.scsi.abort_icmdp) != NULL) {
   1204 			iscsi_cmd_state_machine(a_icmdp,
   1205 			    ISCSI_CMD_EVENT_E10, arg);
   1206 		}
   1207 
   1208 		ISCSI_CMD_SET_REASON_STAT(icmdp,
   1209 		    CMD_TRAN_ERR, icmdp->cmd_un.scsi.pkt_stat);
   1210 
   1211 		idm_task_abort(icmdp->cmd_conn->conn_ic, icmdp->cmd_itp,
   1212 		    AT_TASK_MGMT_ABORT);
   1213 		break;
   1214 
   1215 	/* -E9: IDM is no longer processing this command */
   1216 	case ISCSI_CMD_EVENT_E9:
   1217 		iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
   1218 
   1219 		iscsi_task_cleanup(ISCSI_OP_SCSI_RSP, icmdp);
   1220 		iscsi_sess_release_scsi_itt(icmdp);
   1221 
   1222 		ISCSI_CMD_SET_REASON_STAT(icmdp, CMD_TRAN_ERR,
   1223 		    icmdp->cmd_un.scsi.pkt_stat);
   1224 		iscsi_enqueue_completed_cmd(isp, icmdp);
   1225 		break;
   1226 
   1227 	/* All other events are invalid for this state */
   1228 	default:
   1229 		ASSERT(FALSE);
   1230 	}
   1231 }
   1232 
   1233 static void
   1234 iscsi_cmd_state_idm_aborting(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event,
   1235     void *arg)
   1236 {
   1237 	iscsi_sess_t	*isp	= (iscsi_sess_t *)arg;
   1238 
   1239 	ASSERT(icmdp != NULL);
   1240 	ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI);
   1241 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_IDM_ABORTING);
   1242 	ASSERT(isp != NULL);
   1243 
   1244 	/* switch on event change */
   1245 	switch (event) {
   1246 	/* -E3: Command was successfully completed */
   1247 	case ISCSI_CMD_EVENT_E3:
   1248 		/*
   1249 		 * iscsi_rx_process_cmd_rsp() and iscsi_rx_process_data_rsp()
   1250 		 * are supposed to confirm the cmd state is appropriate before
   1251 		 * generating an E3 event.  E3 is not allowed in this state.
   1252 		 */
   1253 		ASSERT(0);
   1254 		break;
   1255 
   1256 	/* -E4: Command has been requested to abort */
   1257 	case ISCSI_CMD_EVENT_E4:
   1258 		/*
   1259 		 * An upper level driver might attempt to
   1260 		 * abort a command that we are already
   1261 		 * aborting due to a nop.  Since we are
   1262 		 * already in the process of aborting
   1263 		 * ignore the request.
   1264 		 */
   1265 		break;
   1266 
   1267 	/* -E6: Command has timed out */
   1268 	case ISCSI_CMD_EVENT_E6:
   1269 		ASSERT(FALSE);
   1270 		/*
   1271 		 * Timeouts should not occur on aborting commands
   1272 		 */
   1273 		break;
   1274 
   1275 	/* -E7: Connection has encountered a problem */
   1276 	case ISCSI_CMD_EVENT_E7:
   1277 		/*
   1278 		 * We have already requested IDM to stop processing this
   1279 		 * command so just update the pkt_statistics.
   1280 		 */
   1281 		ISCSI_CMD_SET_REASON_STAT(icmdp,
   1282 		    CMD_TRAN_ERR, icmdp->cmd_un.scsi.pkt_stat);
   1283 		break;
   1284 
   1285 	/* -E9: IDM is no longer processing this command */
   1286 	case ISCSI_CMD_EVENT_E9:
   1287 		mutex_enter(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex);
   1288 		iscsi_dequeue_idm_aborting_cmd(icmdp->cmd_conn, icmdp);
   1289 		mutex_exit(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex);
   1290 
   1291 		/* This is always an error so make sure an error has been set */
   1292 		ASSERT(icmdp->cmd_un.scsi.pkt->pkt_reason != CMD_CMPLT);
   1293 		iscsi_task_cleanup(ISCSI_OP_SCSI_RSP, icmdp);
   1294 		iscsi_sess_release_scsi_itt(icmdp);
   1295 
   1296 		/*
   1297 		 * Whoever called idm_task_abort should have set the completion
   1298 		 * status beforehand.
   1299 		 */
   1300 		iscsi_enqueue_completed_cmd(isp, icmdp);
   1301 		cv_broadcast(&icmdp->cmd_completion);
   1302 		break;
   1303 
   1304 	/* All other events are invalid for this state */
   1305 	default:
   1306 		ASSERT(FALSE);
   1307 	}
   1308 }
   1309 
   1310 
   1311 /*
   1312  * iscsi_cmd_state_completed -
   1313  *
   1314  */
   1315 static void
   1316 iscsi_cmd_state_completed(iscsi_cmd_t *icmdp,
   1317     iscsi_cmd_event_t event, void *arg)
   1318 {
   1319 	iscsi_sess_t	*isp	= (iscsi_sess_t *)arg;
   1320 
   1321 	ASSERT(icmdp != NULL);
   1322 	ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI);
   1323 	ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_COMPLETED);
   1324 	ASSERT(isp != NULL);
   1325 
   1326 	/* switch on event change */
   1327 	switch (event) {
   1328 	/* -E8: */
   1329 	case ISCSI_CMD_EVENT_E8:
   1330 		icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
   1331 
   1332 		/* the caller has already remove cmd from queue */
   1333 
   1334 		icmdp->cmd_next = NULL;
   1335 		icmdp->cmd_prev = NULL;
   1336 		iscsi_iodone(isp, icmdp);
   1337 		break;
   1338 	/* All other events are invalid for this state */
   1339 	default:
   1340 		ASSERT(FALSE);
   1341 	}
   1342 }
   1343 
   1344 
   1345 /*
   1346  * iscsi_cmd_state_str -
   1347  *
   1348  */
   1349 static char *
   1350 iscsi_cmd_state_str(iscsi_cmd_state_t state)
   1351 {
   1352 	switch (state) {
   1353 	case ISCSI_CMD_STATE_FREE:
   1354 		return ("free");
   1355 	case ISCSI_CMD_STATE_PENDING:
   1356 		return ("pending");
   1357 	case ISCSI_CMD_STATE_ACTIVE:
   1358 		return ("active");
   1359 	case ISCSI_CMD_STATE_ABORTING:
   1360 		return ("aborting");
   1361 	case ISCSI_CMD_STATE_IDM_ABORTING:
   1362 		return ("idm-aborting");
   1363 	case ISCSI_CMD_STATE_COMPLETED:
   1364 		return ("completed");
   1365 	default:
   1366 		return ("unknown");
   1367 	}
   1368 }
   1369 
   1370 
   1371 /*
   1372  * iscsi_cmd_event_str -
   1373  *
   1374  */
   1375 static char *
   1376 iscsi_cmd_event_str(iscsi_cmd_event_t event)
   1377 {
   1378 	switch (event) {
   1379 	case ISCSI_CMD_EVENT_E1:
   1380 		return ("E1");
   1381 	case ISCSI_CMD_EVENT_E2:
   1382 		return ("E2");
   1383 	case ISCSI_CMD_EVENT_E3:
   1384 		return ("E3");
   1385 	case ISCSI_CMD_EVENT_E4:
   1386 		return ("E4");
   1387 	case ISCSI_CMD_EVENT_E6:
   1388 		return ("E6");
   1389 	case ISCSI_CMD_EVENT_E7:
   1390 		return ("E7");
   1391 	case ISCSI_CMD_EVENT_E8:
   1392 		return ("E8");
   1393 	case ISCSI_CMD_EVENT_E9:
   1394 		return ("E9");
   1395 	case ISCSI_CMD_EVENT_E10:
   1396 		return ("E10");
   1397 	default:
   1398 		return ("unknown");
   1399 	}
   1400 }
   1401 
   1402 
   1403 /*
   1404  * iscsi_cmd_event_str -
   1405  *
   1406  */
   1407 static char *
   1408 iscsi_cmd_type_str(iscsi_cmd_type_t type)
   1409 {
   1410 	switch (type) {
   1411 	case ISCSI_CMD_TYPE_SCSI:
   1412 		return ("scsi");
   1413 	case ISCSI_CMD_TYPE_NOP:
   1414 		return ("nop");
   1415 	case ISCSI_CMD_TYPE_ABORT:
   1416 		return ("abort");
   1417 	case ISCSI_CMD_TYPE_RESET:
   1418 		return ("reset");
   1419 	case ISCSI_CMD_TYPE_LOGOUT:
   1420 		return ("logout");
   1421 	default:
   1422 		return ("unknown");
   1423 	}
   1424 }
   1425