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 } else { 340 icmdp->cmd_lbolt_timeout = icmdp->cmd_lbolt_pending + 341 SEC_TO_TICK(ISCSI_INTERNAL_CMD_TIMEOUT * 342 iscsi_cmd_timeout_factor); 343 } 344 345 /* place into pending queue */ 346 iscsi_enqueue_pending_cmd(isp, icmdp); 347 348 break; 349 350 /* All other events are invalid for this state */ 351 default: 352 ASSERT(FALSE); 353 } 354 } 355 356 /* 357 * iscsi_cmd_state_pending - 358 * 359 */ 360 static void 361 iscsi_cmd_state_pending(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg) 362 { 363 iscsi_status_t status; 364 iscsi_sess_t *isp = (iscsi_sess_t *)arg; 365 boolean_t free_icmdp = B_FALSE; 366 int rval; 367 368 ASSERT(icmdp != NULL); 369 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_PENDING); 370 ASSERT(isp != NULL); 371 372 /* switch on event change */ 373 switch (event) { 374 /* -E2: Command was submitted and now active on wire */ 375 case ISCSI_CMD_EVENT_E2: 376 377 /* A connection should have already been assigned */ 378 ASSERT(mutex_owned(&isp->sess_queue_pending.mutex)); 379 ASSERT(icmdp->cmd_conn != NULL); 380 381 /* 382 * RESERVE RESOURSES 383 */ 384 switch (icmdp->cmd_type) { 385 case ISCSI_CMD_TYPE_SCSI: 386 /* check cmdsn window */ 387 mutex_enter(&isp->sess_cmdsn_mutex); 388 if (!iscsi_sna_lte(isp->sess_cmdsn, 389 isp->sess_maxcmdsn)) { 390 /* cmdsn window closed */ 391 mutex_exit(&isp->sess_cmdsn_mutex); 392 mutex_exit(&isp->sess_queue_pending.mutex); 393 isp->sess_window_open = B_FALSE; 394 icmdp->cmd_misc_flags |= 395 ISCSI_CMD_MISCFLAG_STUCK; 396 return; 397 } 398 399 /* assign itt */ 400 status = iscsi_sess_reserve_scsi_itt(icmdp); 401 if (!ISCSI_SUCCESS(status)) { 402 /* no available itt slots */ 403 mutex_exit(&isp->sess_cmdsn_mutex); 404 mutex_exit(&isp->sess_queue_pending.mutex); 405 isp->sess_window_open = B_FALSE; 406 icmdp->cmd_misc_flags |= 407 ISCSI_CMD_MISCFLAG_STUCK; 408 return; 409 } 410 mutex_exit(&isp->sess_cmdsn_mutex); 411 break; 412 413 case ISCSI_CMD_TYPE_ABORT: 414 /* 415 * Verify ABORT's parent SCSI command is still 416 * there. If parent SCSI command is completed 417 * then there is no longer any reason to abort 418 * the parent command. This could occur due 419 * to a connection or target reset. 420 */ 421 ASSERT(icmdp->cmd_un.abort.icmdp != NULL); 422 if (icmdp->cmd_un.abort.icmdp->cmd_state == 423 ISCSI_CMD_STATE_COMPLETED) { 424 iscsi_dequeue_pending_cmd(isp, icmdp); 425 mutex_exit(&isp->sess_queue_pending.mutex); 426 427 mutex_enter(&icmdp->cmd_un.abort.icmdp-> 428 cmd_mutex); 429 icmdp->cmd_un.abort.icmdp-> 430 cmd_un.scsi.abort_icmdp = NULL; 431 cv_broadcast(&icmdp->cmd_un.abort.icmdp-> 432 cmd_completion); 433 mutex_exit(&icmdp->cmd_un.abort.icmdp-> 434 cmd_mutex); 435 icmdp->cmd_un.abort.icmdp = NULL; 436 437 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 438 icmdp->cmd_misc_flags |= 439 ISCSI_CMD_MISCFLAG_FREE; 440 return; 441 } 442 /* FALLTHRU */ 443 case ISCSI_CMD_TYPE_RESET: 444 /* FALLTHRU */ 445 case ISCSI_CMD_TYPE_LOGOUT: 446 mutex_enter(&isp->sess_cmdsn_mutex); 447 /* assign itt */ 448 status = iscsi_sess_reserve_itt(isp, icmdp); 449 if (!ISCSI_SUCCESS(status)) { 450 /* no available itt slots */ 451 mutex_exit(&isp->sess_cmdsn_mutex); 452 mutex_exit(&isp->sess_queue_pending.mutex); 453 isp->sess_window_open = B_FALSE; 454 return; 455 } 456 mutex_exit(&isp->sess_cmdsn_mutex); 457 break; 458 case ISCSI_CMD_TYPE_NOP: 459 /* assign itt, if needed */ 460 if (icmdp->cmd_itt == ISCSI_RSVD_TASK_TAG) { 461 /* not expecting a response */ 462 free_icmdp = B_TRUE; 463 } else { 464 /* expecting response, assign an itt */ 465 mutex_enter(&isp->sess_cmdsn_mutex); 466 /* assign itt */ 467 status = iscsi_sess_reserve_itt(isp, icmdp); 468 if (!ISCSI_SUCCESS(status)) { 469 /* no available itt slots */ 470 mutex_exit(&isp->sess_cmdsn_mutex); 471 mutex_exit(&isp->sess_queue_pending. 472 mutex); 473 isp->sess_window_open = B_FALSE; 474 return; 475 } 476 mutex_exit(&isp->sess_cmdsn_mutex); 477 } 478 break; 479 480 case ISCSI_CMD_TYPE_TEXT: 481 mutex_enter(&isp->sess_cmdsn_mutex); 482 /* check cmdsn window */ 483 if (!iscsi_sna_lte(isp->sess_cmdsn, 484 isp->sess_maxcmdsn)) { 485 /* cmdsn window closed */ 486 isp->sess_window_open = B_FALSE; 487 mutex_exit(&isp->sess_cmdsn_mutex); 488 mutex_exit(&isp->sess_queue_pending.mutex); 489 icmdp->cmd_misc_flags |= 490 ISCSI_CMD_MISCFLAG_STUCK; 491 return; 492 } 493 if (icmdp->cmd_un.text.stage == 494 ISCSI_CMD_TEXT_INITIAL_REQ) { 495 /* assign itt */ 496 status = iscsi_sess_reserve_itt(isp, icmdp); 497 if (!ISCSI_SUCCESS(status)) { 498 /* no available itt slots */ 499 mutex_exit(&isp->sess_cmdsn_mutex); 500 mutex_exit(&isp->sess_queue_pending. 501 mutex); 502 isp->sess_window_open = B_FALSE; 503 icmdp->cmd_misc_flags |= 504 ISCSI_CMD_MISCFLAG_STUCK; 505 return; 506 } 507 } 508 mutex_exit(&isp->sess_cmdsn_mutex); 509 break; 510 511 default: 512 ASSERT(FALSE); 513 } 514 515 /* 516 * RESOURCES RESERVED 517 * 518 * Now that we have the resources reserved, establish timeout 519 * for cmd_type values that depend on having an open cmdsn 520 * window (i.e. cmd_type that called iscsi_sna_lte() above). 521 */ 522 if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) { 523 if (icmdp->cmd_un.scsi.pkt && 524 icmdp->cmd_un.scsi.pkt->pkt_time) 525 icmdp->cmd_lbolt_timeout = 526 ddi_get_lbolt() + SEC_TO_TICK( 527 icmdp->cmd_un.scsi.pkt->pkt_time * 528 iscsi_cmd_timeout_factor); 529 else 530 icmdp->cmd_lbolt_timeout = 0; 531 } else if (icmdp->cmd_type == ISCSI_CMD_TYPE_TEXT) { 532 icmdp->cmd_lbolt_timeout = ddi_get_lbolt() + 533 SEC_TO_TICK(ISCSI_INTERNAL_CMD_TIMEOUT * 534 iscsi_cmd_timeout_factor); 535 } 536 537 /* remove command from pending queue */ 538 iscsi_dequeue_pending_cmd(isp, icmdp); 539 /* check if expecting a response */ 540 if (free_icmdp == B_FALSE) { 541 /* response expected, move to active queue */ 542 mutex_enter(&icmdp->cmd_conn->conn_queue_active.mutex); 543 iscsi_enqueue_active_cmd(icmdp->cmd_conn, icmdp); 544 mutex_exit(&icmdp->cmd_conn->conn_queue_active.mutex); 545 } 546 547 /* 548 * TRANSFER COMMAND 549 */ 550 rval = iscsi_tx_cmd(isp, icmdp); 551 552 ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex)); 553 554 /* 555 * CHECK SUCCESS/FAILURE 556 */ 557 if (!ISCSI_SUCCESS(rval)) { 558 /* 559 * iscsi_tx_cmd failed. No cleanup is required 560 * of commands that were put in the active queue. 561 * If the tx failed then rx will also fail and cleanup 562 * all items in the active/aborted queue in a common. 563 */ 564 565 /* EMPTY */ 566 } 567 568 /* free temporary commands */ 569 if (free_icmdp == B_TRUE) { 570 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 571 icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_FREE; 572 } 573 break; 574 575 /* -E10: Abort is no longer required for this command */ 576 case ISCSI_CMD_EVENT_E10: 577 /* 578 * Acquiring the sess_queue_pending lock while the 579 * conn_queue_active lock is held conflicts with the 580 * locking order in iscsi_cmd_state_pending where 581 * conn_queue_active is acquired while sess_queue_pending 582 * is held. Normally this would be a dangerous lock 583 * order conflict, except that we know that if we are 584 * seeing ISCSI_CMD_EVENT_E10 then the command being 585 * aborted is in "aborting" state and by extension 586 * is not in "pending" state. Therefore the code 587 * path with that alternate lock order will not execute. 588 * That's good because we can't drop the lock here without 589 * risking a deadlock. 590 */ 591 ASSERT(mutex_owned(&icmdp->cmd_conn->conn_queue_active.mutex)); 592 mutex_enter(&isp->sess_queue_pending.mutex); 593 594 icmdp->cmd_lbolt_aborting = ddi_get_lbolt(); 595 596 iscsi_dequeue_pending_cmd(isp, icmdp); 597 598 icmdp->cmd_un.abort.icmdp->cmd_un.scsi.abort_icmdp = NULL; 599 icmdp->cmd_un.abort.icmdp = NULL; 600 icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_FREE; 601 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 602 603 mutex_exit(&isp->sess_queue_pending.mutex); 604 break; 605 606 /* -E4: Command has been requested to abort */ 607 case ISCSI_CMD_EVENT_E4: 608 ASSERT(mutex_owned(&isp->sess_queue_pending.mutex)); 609 610 icmdp->cmd_lbolt_aborting = ddi_get_lbolt(); 611 ISCSI_CMD_SET_REASON_STAT(icmdp, 612 CMD_ABORTED, STAT_ABORTED); 613 614 iscsi_dequeue_pending_cmd(isp, icmdp); 615 iscsi_enqueue_completed_cmd(isp, icmdp); 616 617 icmdp->cmd_lbolt_aborting = ddi_get_lbolt(); 618 619 break; 620 621 /* -E7: Command has been reset */ 622 case ISCSI_CMD_EVENT_E7: 623 624 /* FALLTHRU */ 625 626 /* -E6: Command has timed out */ 627 case ISCSI_CMD_EVENT_E6: 628 ASSERT(mutex_owned(&isp->sess_queue_pending.mutex)); 629 iscsi_dequeue_pending_cmd(isp, icmdp); 630 631 switch (icmdp->cmd_type) { 632 case ISCSI_CMD_TYPE_SCSI: 633 /* Complete to caller as TIMEOUT */ 634 if (event == ISCSI_CMD_EVENT_E6) { 635 ISCSI_CMD_SET_REASON_STAT(icmdp, 636 CMD_TIMEOUT, STAT_TIMEOUT); 637 } else { 638 ISCSI_CMD_SET_REASON_STAT(icmdp, 639 CMD_TRAN_ERR, 0); 640 } 641 iscsi_enqueue_completed_cmd(isp, icmdp); 642 break; 643 644 case ISCSI_CMD_TYPE_NOP: 645 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 646 /* 647 * Timeout occured. Just free NOP. Another 648 * NOP request will be spawned to replace 649 * this one. 650 */ 651 icmdp->cmd_misc_flags |= 652 ISCSI_CMD_MISCFLAG_FREE; 653 654 break; 655 656 case ISCSI_CMD_TYPE_ABORT: 657 mutex_enter(&icmdp->cmd_un.abort.icmdp->cmd_mutex); 658 icmdp->cmd_un.abort.icmdp-> 659 cmd_un.scsi.abort_icmdp = NULL; 660 cv_broadcast(&icmdp->cmd_un.abort.icmdp-> 661 cmd_completion); 662 mutex_exit(&icmdp->cmd_un.abort.icmdp->cmd_mutex); 663 icmdp->cmd_un.abort.icmdp = NULL; 664 665 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 666 icmdp->cmd_misc_flags |= 667 ISCSI_CMD_MISCFLAG_FREE; 668 break; 669 670 case ISCSI_CMD_TYPE_RESET: 671 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 672 /* 673 * If we are failing a RESET we need 674 * to notify the tran_reset caller. 675 * with the cmd and notify caller. 676 */ 677 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 678 ISCSI_STATUS_CMD_FAILED); 679 break; 680 681 case ISCSI_CMD_TYPE_LOGOUT: 682 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 683 /* notify requester of failure */ 684 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 685 ISCSI_STATUS_CMD_FAILED); 686 break; 687 688 case ISCSI_CMD_TYPE_TEXT: 689 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 690 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP; 691 /* 692 * If a TEXT command fails, notify the owner. 693 */ 694 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 695 ISCSI_STATUS_CMD_FAILED); 696 break; 697 698 default: 699 ASSERT(FALSE); 700 break; 701 } 702 break; 703 704 /* All other events are invalid for this state */ 705 default: 706 ASSERT(FALSE); 707 } 708 } 709 710 711 /* 712 * iscsi_cmd_state_active - 713 * 714 */ 715 static void 716 iscsi_cmd_state_active(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg) 717 { 718 iscsi_sess_t *isp = (iscsi_sess_t *)arg; 719 iscsi_hba_t *ihp; 720 iscsi_cmd_t *t_icmdp = NULL; 721 iscsi_conn_t *icp = NULL; 722 723 ASSERT(icmdp != NULL); 724 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_ACTIVE); 725 ASSERT(isp != NULL); 726 727 ihp = isp->sess_hba; 728 ASSERT(ihp != NULL); 729 730 icp = icmdp->cmd_conn; 731 ASSERT(icp != NULL); 732 ASSERT(mutex_owned(&icp->conn_queue_active.mutex)); 733 734 /* switch on event change */ 735 switch (event) { 736 /* -E3: Command was successfully completed */ 737 case ISCSI_CMD_EVENT_E3: 738 /* 739 * Remove command from the active list. We need to protect 740 * someone from looking up this command ITT until it's 741 * freed of the command is moved to a new queue location. 742 */ 743 mutex_enter(&isp->sess_cmdsn_mutex); 744 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 745 746 switch (icmdp->cmd_type) { 747 case ISCSI_CMD_TYPE_SCSI: 748 iscsi_sess_release_scsi_itt(icmdp); 749 mutex_exit(&isp->sess_cmdsn_mutex); 750 iscsi_enqueue_completed_cmd(isp, icmdp); 751 break; 752 753 case ISCSI_CMD_TYPE_NOP: 754 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 755 iscsi_sess_release_itt(isp, icmdp); 756 mutex_exit(&isp->sess_cmdsn_mutex); 757 758 /* free alloc */ 759 icmdp->cmd_misc_flags |= 760 ISCSI_CMD_MISCFLAG_FREE; 761 762 break; 763 764 case ISCSI_CMD_TYPE_ABORT: 765 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 766 iscsi_sess_release_itt(isp, icmdp); 767 mutex_exit(&isp->sess_cmdsn_mutex); 768 769 /* 770 * Abort was completed successfully. We should 771 * complete the parent scsi command if it still 772 * exists as timed out, and the state is not 773 * COMPLETED 774 */ 775 t_icmdp = icmdp->cmd_un.abort.icmdp; 776 ASSERT(t_icmdp != NULL); 777 mutex_enter(&t_icmdp->cmd_mutex); 778 t_icmdp->cmd_un.scsi.abort_icmdp = NULL; 779 if (t_icmdp->cmd_state != ISCSI_CMD_STATE_COMPLETED) { 780 iscsi_dequeue_active_cmd( 781 t_icmdp->cmd_conn, t_icmdp); 782 mutex_enter( 783 &icp->conn_queue_idm_aborting.mutex); 784 iscsi_enqueue_idm_aborting_cmd( 785 t_icmdp->cmd_conn, 786 t_icmdp); 787 mutex_exit(&icp->conn_queue_idm_aborting.mutex); 788 789 /* 790 * Complete abort processing after IDM 791 * calls us back. Set the status to use 792 * when we complete the command. 793 */ 794 ISCSI_CMD_SET_REASON_STAT( 795 t_icmdp, CMD_TIMEOUT, STAT_TIMEOUT); 796 idm_task_abort(icp->conn_ic, t_icmdp->cmd_itp, 797 AT_TASK_MGMT_ABORT); 798 } else { 799 cv_broadcast(&t_icmdp->cmd_completion); 800 } 801 mutex_exit(&t_icmdp->cmd_mutex); 802 icmdp->cmd_un.abort.icmdp = NULL; 803 804 icmdp->cmd_misc_flags |= 805 ISCSI_CMD_MISCFLAG_FREE; 806 807 break; 808 case ISCSI_CMD_TYPE_RESET: 809 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 810 iscsi_sess_release_itt(isp, icmdp); 811 mutex_exit(&isp->sess_cmdsn_mutex); 812 813 /* 814 * Complete the abort/reset successfully. 815 */ 816 ISCSI_CMD_ISSUE_CALLBACK(icmdp, ISCSI_STATUS_SUCCESS); 817 break; 818 819 case ISCSI_CMD_TYPE_LOGOUT: 820 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 821 iscsi_sess_release_itt(isp, icmdp); 822 mutex_exit(&isp->sess_cmdsn_mutex); 823 824 /* 825 * Complete the logout successfully. 826 */ 827 ISCSI_CMD_ISSUE_CALLBACK(icmdp, ISCSI_STATUS_SUCCESS); 828 break; 829 830 case ISCSI_CMD_TYPE_TEXT: 831 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 832 if (icmdp->cmd_un.text.stage == 833 ISCSI_CMD_TEXT_FINAL_RSP) { 834 iscsi_sess_release_itt(isp, icmdp); 835 } 836 mutex_exit(&isp->sess_cmdsn_mutex); 837 838 /* 839 * Complete the text command successfully. 840 */ 841 ISCSI_CMD_ISSUE_CALLBACK(icmdp, icmdp->cmd_result); 842 break; 843 844 default: 845 mutex_exit(&isp->sess_cmdsn_mutex); 846 ASSERT(FALSE); 847 } 848 849 ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex)); 850 break; 851 852 /* -E10,E4: Command has been requested to abort */ 853 case ISCSI_CMD_EVENT_E10: 854 /* FALLTHRU */ 855 case ISCSI_CMD_EVENT_E4: 856 857 /* E4 is only for resets and aborts */ 858 ASSERT((icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT) || 859 (icmdp->cmd_type == ISCSI_CMD_TYPE_RESET)); 860 /* FALLTHRU */ 861 862 /* -E6: Command has timed out */ 863 case ISCSI_CMD_EVENT_E6: 864 865 switch (icmdp->cmd_type) { 866 case ISCSI_CMD_TYPE_SCSI: 867 icmdp->cmd_state = ISCSI_CMD_STATE_ABORTING; 868 iscsi_handle_abort(icmdp); 869 break; 870 871 case ISCSI_CMD_TYPE_NOP: 872 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 873 874 mutex_enter(&isp->sess_cmdsn_mutex); 875 iscsi_sess_release_itt(isp, icmdp); 876 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 877 mutex_exit(&isp->sess_cmdsn_mutex); 878 879 icmdp->cmd_misc_flags |= 880 ISCSI_CMD_MISCFLAG_FREE; 881 882 break; 883 884 case ISCSI_CMD_TYPE_ABORT: 885 icmdp->cmd_state = 886 ISCSI_CMD_STATE_FREE; 887 888 mutex_enter(&isp->sess_cmdsn_mutex); 889 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 890 iscsi_sess_release_itt(isp, icmdp); 891 mutex_exit(&isp->sess_cmdsn_mutex); 892 893 /* 894 * If this is an E4 then we may need to deal with 895 * the abort's associated SCSI command. If this 896 * is an E10 then IDM is already cleaning up the 897 * SCSI command and all we need to do is break the 898 * linkage between them and free the abort command. 899 */ 900 t_icmdp = icmdp->cmd_un.abort.icmdp; 901 ASSERT(t_icmdp != NULL); 902 if (event != ISCSI_CMD_EVENT_E10) { 903 904 mutex_enter(&t_icmdp->cmd_mutex); 905 t_icmdp->cmd_un.scsi.abort_icmdp = NULL; 906 /* 907 * If abort command is aborted then we should 908 * not act on the parent scsi command. If the 909 * abort command timed out then we need to 910 * complete the parent command if it still 911 * exists with a timeout failure. 912 */ 913 if ((event == ISCSI_CMD_EVENT_E6) && 914 (t_icmdp->cmd_state != 915 ISCSI_CMD_STATE_IDM_ABORTING) && 916 (t_icmdp->cmd_state != 917 ISCSI_CMD_STATE_COMPLETED)) { 918 919 iscsi_dequeue_active_cmd( 920 t_icmdp->cmd_conn, t_icmdp); 921 mutex_enter(&icp-> 922 conn_queue_idm_aborting.mutex); 923 iscsi_enqueue_idm_aborting_cmd( 924 t_icmdp->cmd_conn, t_icmdp); 925 mutex_exit(&icp-> 926 conn_queue_idm_aborting.mutex); 927 /* 928 * Complete abort processing after IDM 929 * calls us back. Set the status to use 930 * when we complete the command. 931 */ 932 ISCSI_CMD_SET_REASON_STAT(t_icmdp, 933 CMD_TIMEOUT, STAT_TIMEOUT); 934 idm_task_abort(icp->conn_ic, 935 t_icmdp->cmd_itp, 936 AT_TASK_MGMT_ABORT); 937 } else { 938 cv_broadcast(&t_icmdp->cmd_completion); 939 } 940 mutex_exit(&t_icmdp->cmd_mutex); 941 } else { 942 t_icmdp->cmd_un.scsi.abort_icmdp = NULL; 943 } 944 icmdp->cmd_un.abort.icmdp = NULL; 945 icmdp->cmd_misc_flags |= 946 ISCSI_CMD_MISCFLAG_FREE; 947 break; 948 949 case ISCSI_CMD_TYPE_RESET: 950 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 951 952 mutex_enter(&isp->sess_cmdsn_mutex); 953 iscsi_sess_release_itt(isp, icmdp); 954 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 955 mutex_exit(&isp->sess_cmdsn_mutex); 956 957 /* 958 * If we are failing a RESET we need 959 * to notify the tran_reset caller. 960 * It will free the memory associated 961 * with the cmd and notify caller. 962 */ 963 964 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 965 ISCSI_STATUS_CMD_FAILED); 966 break; 967 968 case ISCSI_CMD_TYPE_LOGOUT: 969 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 970 971 mutex_enter(&isp->sess_cmdsn_mutex); 972 iscsi_sess_release_itt(isp, icmdp); 973 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 974 mutex_exit(&isp->sess_cmdsn_mutex); 975 976 /* 977 * Notify caller of failure. 978 */ 979 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 980 ISCSI_STATUS_CMD_FAILED); 981 break; 982 983 case ISCSI_CMD_TYPE_TEXT: 984 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 985 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP; 986 mutex_enter(&isp->sess_cmdsn_mutex); 987 iscsi_sess_release_itt(isp, icmdp); 988 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 989 mutex_exit(&isp->sess_cmdsn_mutex); 990 991 /* 992 * If a TEXT command fails, notify caller so 993 * it can free assocated command 994 */ 995 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 996 ISCSI_STATUS_CMD_FAILED); 997 break; 998 999 default: 1000 ASSERT(FALSE); 1001 } 1002 1003 ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex)); 1004 break; 1005 1006 /* -E7: Connection has encountered a problem */ 1007 case ISCSI_CMD_EVENT_E7: 1008 mutex_enter(&isp->sess_cmdsn_mutex); 1009 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 1010 1011 switch (icmdp->cmd_type) { 1012 case ISCSI_CMD_TYPE_SCSI: 1013 mutex_exit(&isp->sess_cmdsn_mutex); 1014 mutex_enter(&icp->conn_queue_idm_aborting.mutex); 1015 iscsi_enqueue_idm_aborting_cmd(icmdp->cmd_conn, icmdp); 1016 mutex_exit(&icp->conn_queue_idm_aborting.mutex); 1017 1018 ISCSI_CMD_SET_REASON_STAT(icmdp, CMD_TRAN_ERR, 0); 1019 idm_task_abort(icp->conn_ic, icmdp->cmd_itp, 1020 AT_TASK_MGMT_ABORT); 1021 break; 1022 1023 case ISCSI_CMD_TYPE_NOP: 1024 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 1025 iscsi_sess_release_itt(isp, icmdp); 1026 mutex_exit(&isp->sess_cmdsn_mutex); 1027 1028 icmdp->cmd_misc_flags |= 1029 ISCSI_CMD_MISCFLAG_FREE; 1030 break; 1031 1032 case ISCSI_CMD_TYPE_ABORT: 1033 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 1034 iscsi_sess_release_itt(isp, icmdp); 1035 mutex_exit(&isp->sess_cmdsn_mutex); 1036 1037 mutex_enter(&icmdp->cmd_un.abort.icmdp->cmd_mutex); 1038 icmdp->cmd_un.abort.icmdp-> 1039 cmd_un.scsi.abort_icmdp = NULL; 1040 cv_broadcast(&icmdp->cmd_un.abort.icmdp-> 1041 cmd_completion); 1042 mutex_exit(&icmdp->cmd_un.abort.icmdp->cmd_mutex); 1043 /* 1044 * Nullify the abort command's pointer to its 1045 * parent command. It does not have to complete its 1046 * parent command because the parent command will 1047 * also get an E7. 1048 */ 1049 icmdp->cmd_un.abort.icmdp = NULL; 1050 1051 icmdp->cmd_misc_flags |= 1052 ISCSI_CMD_MISCFLAG_FREE; 1053 break; 1054 1055 case ISCSI_CMD_TYPE_RESET: 1056 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 1057 iscsi_sess_release_itt(isp, icmdp); 1058 mutex_exit(&isp->sess_cmdsn_mutex); 1059 /* 1060 * If we are failing a ABORT we need 1061 * to notify the tran_abort caller. 1062 * It will free the memory associated 1063 * with the cmd and notify caller. 1064 */ 1065 1066 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 1067 ISCSI_STATUS_CMD_FAILED); 1068 break; 1069 1070 case ISCSI_CMD_TYPE_LOGOUT: 1071 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 1072 /* 1073 * A connection problem and we attempted to 1074 * logout? I guess we can just free the 1075 * request. Someone has already pushed the 1076 * connection state. 1077 */ 1078 iscsi_sess_release_itt(isp, icmdp); 1079 mutex_exit(&isp->sess_cmdsn_mutex); 1080 1081 ISCSI_CMD_ISSUE_CALLBACK(icmdp, ISCSI_STATUS_SUCCESS); 1082 break; 1083 1084 case ISCSI_CMD_TYPE_TEXT: 1085 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 1086 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP; 1087 iscsi_sess_release_itt(isp, icmdp); 1088 mutex_exit(&isp->sess_cmdsn_mutex); 1089 1090 /* 1091 * If a TEXT command fails, notify caller so 1092 * it can free assocated command 1093 */ 1094 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 1095 ISCSI_STATUS_CMD_FAILED); 1096 break; 1097 1098 default: 1099 mutex_exit(&isp->sess_cmdsn_mutex); 1100 ASSERT(FALSE); 1101 break; 1102 } 1103 1104 ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex)); 1105 break; 1106 1107 /* -E9: IDM is no longer processing this command */ 1108 case ISCSI_CMD_EVENT_E9: 1109 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 1110 1111 iscsi_task_cleanup(ISCSI_OP_SCSI_RSP, icmdp); 1112 iscsi_sess_release_scsi_itt(icmdp); 1113 1114 ISCSI_CMD_SET_REASON_STAT(icmdp, CMD_TRAN_ERR, 0); 1115 iscsi_enqueue_completed_cmd(isp, icmdp); 1116 break; 1117 1118 /* All other events are invalid for this state */ 1119 default: 1120 ASSERT(FALSE); 1121 } 1122 } 1123 1124 1125 /* 1126 * iscsi_cmd_state_aborting - 1127 * 1128 */ 1129 static void 1130 iscsi_cmd_state_aborting(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg) 1131 { 1132 iscsi_sess_t *isp = (iscsi_sess_t *)arg; 1133 iscsi_cmd_t *a_icmdp; 1134 1135 ASSERT(icmdp != NULL); 1136 ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI); 1137 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_ABORTING); 1138 ASSERT(isp != NULL); 1139 ASSERT(mutex_owned(&icmdp->cmd_conn->conn_queue_active.mutex)); 1140 1141 /* switch on event change */ 1142 switch (event) { 1143 /* -E3: Command was successfully completed */ 1144 case ISCSI_CMD_EVENT_E3: 1145 /* 1146 * Remove command from the aborting list 1147 */ 1148 mutex_enter(&isp->sess_cmdsn_mutex); 1149 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 1150 iscsi_sess_release_scsi_itt(icmdp); 1151 mutex_exit(&isp->sess_cmdsn_mutex); 1152 1153 iscsi_enqueue_completed_cmd(isp, icmdp); 1154 break; 1155 1156 /* -E4: Command has been requested to abort */ 1157 case ISCSI_CMD_EVENT_E4: 1158 /* 1159 * An upper level driver might attempt to 1160 * abort a command that we are already 1161 * aborting due to a nop. Since we are 1162 * already in the process of aborting 1163 * ignore the request. 1164 */ 1165 break; 1166 1167 /* -E6: Command has timed out */ 1168 case ISCSI_CMD_EVENT_E6: 1169 ASSERT(FALSE); 1170 /* 1171 * Timeouts should not occur on command in abort queue 1172 * they are already be processed due to a timeout. 1173 */ 1174 break; 1175 1176 /* -E7: Connection has encountered a problem */ 1177 case ISCSI_CMD_EVENT_E7: 1178 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 1179 mutex_enter(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex); 1180 iscsi_enqueue_idm_aborting_cmd(icmdp->cmd_conn, icmdp); 1181 mutex_exit(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex); 1182 1183 /* 1184 * Since we are in "aborting" state there is another command 1185 * representing the abort of this command. This command 1186 * will cleanup at some indeterminate time after the call 1187 * to idm_task_abort so we can't leave the abort request 1188 * active. An E10 event to the abort command will cause 1189 * it to complete immediately. 1190 */ 1191 if ((a_icmdp = icmdp->cmd_un.scsi.abort_icmdp) != NULL) { 1192 iscsi_cmd_state_machine(a_icmdp, 1193 ISCSI_CMD_EVENT_E10, arg); 1194 } 1195 1196 ISCSI_CMD_SET_REASON_STAT(icmdp, CMD_TRAN_ERR, 0); 1197 idm_task_abort(icmdp->cmd_conn->conn_ic, icmdp->cmd_itp, 1198 AT_TASK_MGMT_ABORT); 1199 break; 1200 1201 /* -E9: IDM is no longer processing this command */ 1202 case ISCSI_CMD_EVENT_E9: 1203 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 1204 1205 iscsi_task_cleanup(ISCSI_OP_SCSI_RSP, icmdp); 1206 iscsi_sess_release_scsi_itt(icmdp); 1207 1208 ISCSI_CMD_SET_REASON_STAT(icmdp, CMD_TRAN_ERR, 0); 1209 iscsi_enqueue_completed_cmd(isp, icmdp); 1210 break; 1211 1212 /* All other events are invalid for this state */ 1213 default: 1214 ASSERT(FALSE); 1215 } 1216 } 1217 1218 static void 1219 iscsi_cmd_state_idm_aborting(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, 1220 void *arg) 1221 { 1222 iscsi_sess_t *isp = (iscsi_sess_t *)arg; 1223 1224 ASSERT(icmdp != NULL); 1225 ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI); 1226 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_IDM_ABORTING); 1227 ASSERT(isp != NULL); 1228 1229 /* switch on event change */ 1230 switch (event) { 1231 /* -E3: Command was successfully completed */ 1232 case ISCSI_CMD_EVENT_E3: 1233 /* 1234 * iscsi_rx_process_cmd_rsp() and iscsi_rx_process_data_rsp() 1235 * are supposed to confirm the cmd state is appropriate before 1236 * generating an E3 event. E3 is not allowed in this state. 1237 */ 1238 ASSERT(0); 1239 break; 1240 1241 /* -E4: Command has been requested to abort */ 1242 case ISCSI_CMD_EVENT_E4: 1243 /* 1244 * An upper level driver might attempt to 1245 * abort a command that we are already 1246 * aborting due to a nop. Since we are 1247 * already in the process of aborting 1248 * ignore the request. 1249 */ 1250 break; 1251 1252 /* -E6: Command has timed out */ 1253 case ISCSI_CMD_EVENT_E6: 1254 ASSERT(FALSE); 1255 /* 1256 * Timeouts should not occur on aborting commands 1257 */ 1258 break; 1259 1260 /* -E7: Connection has encountered a problem */ 1261 case ISCSI_CMD_EVENT_E7: 1262 /* 1263 * We have already requested IDM to stop processing this 1264 * command so ignore this request. 1265 */ 1266 break; 1267 1268 /* -E9: IDM is no longer processing this command */ 1269 case ISCSI_CMD_EVENT_E9: 1270 mutex_enter(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex); 1271 iscsi_dequeue_idm_aborting_cmd(icmdp->cmd_conn, icmdp); 1272 mutex_exit(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex); 1273 1274 /* This is always an error so make sure an error has been set */ 1275 ASSERT(icmdp->cmd_un.scsi.pkt->pkt_reason != CMD_CMPLT); 1276 iscsi_task_cleanup(ISCSI_OP_SCSI_RSP, icmdp); 1277 iscsi_sess_release_scsi_itt(icmdp); 1278 1279 /* 1280 * Whoever called idm_task_abort should have set the completion 1281 * status beforehand. 1282 */ 1283 iscsi_enqueue_completed_cmd(isp, icmdp); 1284 cv_broadcast(&icmdp->cmd_completion); 1285 break; 1286 1287 /* All other events are invalid for this state */ 1288 default: 1289 ASSERT(FALSE); 1290 } 1291 } 1292 1293 1294 /* 1295 * iscsi_cmd_state_completed - 1296 * 1297 */ 1298 static void 1299 iscsi_cmd_state_completed(iscsi_cmd_t *icmdp, 1300 iscsi_cmd_event_t event, void *arg) 1301 { 1302 iscsi_sess_t *isp = (iscsi_sess_t *)arg; 1303 1304 ASSERT(icmdp != NULL); 1305 ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI); 1306 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_COMPLETED); 1307 ASSERT(isp != NULL); 1308 1309 /* switch on event change */ 1310 switch (event) { 1311 /* -E8: */ 1312 case ISCSI_CMD_EVENT_E8: 1313 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 1314 1315 /* the caller has already remove cmd from queue */ 1316 1317 icmdp->cmd_next = NULL; 1318 icmdp->cmd_prev = NULL; 1319 iscsi_iodone(isp, icmdp); 1320 break; 1321 /* All other events are invalid for this state */ 1322 default: 1323 ASSERT(FALSE); 1324 } 1325 } 1326 1327 1328 /* 1329 * iscsi_cmd_state_str - 1330 * 1331 */ 1332 static char * 1333 iscsi_cmd_state_str(iscsi_cmd_state_t state) 1334 { 1335 switch (state) { 1336 case ISCSI_CMD_STATE_FREE: 1337 return ("free"); 1338 case ISCSI_CMD_STATE_PENDING: 1339 return ("pending"); 1340 case ISCSI_CMD_STATE_ACTIVE: 1341 return ("active"); 1342 case ISCSI_CMD_STATE_ABORTING: 1343 return ("aborting"); 1344 case ISCSI_CMD_STATE_IDM_ABORTING: 1345 return ("idm-aborting"); 1346 case ISCSI_CMD_STATE_COMPLETED: 1347 return ("completed"); 1348 default: 1349 return ("unknown"); 1350 } 1351 } 1352 1353 1354 /* 1355 * iscsi_cmd_event_str - 1356 * 1357 */ 1358 static char * 1359 iscsi_cmd_event_str(iscsi_cmd_event_t event) 1360 { 1361 switch (event) { 1362 case ISCSI_CMD_EVENT_E1: 1363 return ("E1"); 1364 case ISCSI_CMD_EVENT_E2: 1365 return ("E2"); 1366 case ISCSI_CMD_EVENT_E3: 1367 return ("E3"); 1368 case ISCSI_CMD_EVENT_E4: 1369 return ("E4"); 1370 case ISCSI_CMD_EVENT_E6: 1371 return ("E6"); 1372 case ISCSI_CMD_EVENT_E7: 1373 return ("E7"); 1374 case ISCSI_CMD_EVENT_E8: 1375 return ("E8"); 1376 case ISCSI_CMD_EVENT_E9: 1377 return ("E9"); 1378 case ISCSI_CMD_EVENT_E10: 1379 return ("E10"); 1380 default: 1381 return ("unknown"); 1382 } 1383 } 1384 1385 1386 /* 1387 * iscsi_cmd_event_str - 1388 * 1389 */ 1390 static char * 1391 iscsi_cmd_type_str(iscsi_cmd_type_t type) 1392 { 1393 switch (type) { 1394 case ISCSI_CMD_TYPE_SCSI: 1395 return ("scsi"); 1396 case ISCSI_CMD_TYPE_NOP: 1397 return ("nop"); 1398 case ISCSI_CMD_TYPE_ABORT: 1399 return ("abort"); 1400 case ISCSI_CMD_TYPE_RESET: 1401 return ("reset"); 1402 case ISCSI_CMD_TYPE_LOGOUT: 1403 return ("logout"); 1404 default: 1405 return ("unknown"); 1406 } 1407 } 1408