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