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