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