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