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 }