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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <sys/cpuvar.h> 26 #include <sys/types.h> 27 #include <sys/conf.h> 28 #include <sys/file.h> 29 #include <sys/ddi.h> 30 #include <sys/sunddi.h> 31 #include <sys/modctl.h> 32 #include <sys/sysmacros.h> 33 34 #include <sys/socket.h> 35 #include <sys/strsubr.h> 36 #include <sys/door.h> 37 #include <sys/note.h> 38 #include <sys/sdt.h> 39 40 #include <sys/stmf.h> 41 #include <sys/stmf_ioctl.h> 42 #include <sys/portif.h> 43 #define PPPT_TGT_SM_STRINGS 44 #include "pppt.h" 45 46 typedef struct { 47 list_node_t te_ctx_node; 48 pppt_tgt_event_t te_ctx_event; 49 } tgt_event_ctx_t; 50 51 static void 52 pppt_tgt_sm_event(pppt_tgt_t *tgt, pppt_tgt_event_t event); 53 54 static void 55 tgt_sm_event_locked(pppt_tgt_t *tgt, pppt_tgt_event_t event); 56 57 static void 58 tgt_sm_event_dispatch(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 59 60 static void 61 tgt_sm_created(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 62 63 static void 64 tgt_sm_onlining(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 65 66 static void 67 tgt_sm_online(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 68 69 static void 70 tgt_sm_stmf_online(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 71 72 static void 73 tgt_sm_deleting_need_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 74 75 static void 76 tgt_sm_offlining(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 77 78 static void 79 tgt_sm_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 80 81 static void 82 tgt_sm_stmf_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 83 84 static void 85 tgt_sm_deleting_stmf_dereg(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 86 87 static void 88 tgt_sm_deleting_stmf_dereg_fail(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 89 90 static void 91 tgt_sm_deleting(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 92 93 static void 94 pppt_tgt_offline_task(void *arg); 95 96 static void 97 pppt_tgt_dereg_retry(void *arg); 98 99 static void 100 pppt_tgt_dereg_task(void *arg); 101 102 static void 103 tgt_sm_new_state(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx, 104 pppt_tgt_state_t new_state); 105 106 /*ARGSUSED*/ 107 void 108 pppt_tgt_sm_ctl(stmf_local_port_t *lport, int cmd, void *arg) 109 { 110 pppt_tgt_t *pppt_tgt; 111 112 pppt_tgt = (pppt_tgt_t *)lport->lport_port_private; 113 114 switch (cmd) { 115 case STMF_CMD_LPORT_ONLINE: 116 pppt_tgt_sm_event(pppt_tgt, TE_STMF_ONLINE_REQ); 117 break; 118 case STMF_CMD_LPORT_OFFLINE: 119 pppt_tgt_sm_event(pppt_tgt, TE_STMF_OFFLINE_REQ); 120 break; 121 case STMF_ACK_LPORT_ONLINE_COMPLETE: 122 pppt_tgt_sm_event(pppt_tgt, TE_STMF_ONLINE_COMPLETE_ACK); 123 break; 124 case STMF_ACK_LPORT_OFFLINE_COMPLETE: 125 pppt_tgt_sm_event(pppt_tgt, TE_STMF_OFFLINE_COMPLETE_ACK); 126 break; 127 128 default: 129 ASSERT(0); 130 break; 131 } 132 } 133 134 pppt_tgt_t * 135 pppt_tgt_create(stmf_ic_reg_port_msg_t *reg_port, stmf_status_t *msg_errcode) 136 { 137 pppt_tgt_t *result; 138 stmf_local_port_t *lport; 139 int total_devid_len; 140 141 total_devid_len = sizeof (scsi_devid_desc_t) + 142 reg_port->icrp_port_id->ident_length - 1; 143 144 /* 145 * Each target is an STMF local port. Allocate an STMF local port 146 * including enough space to store a scsi_devid_desc_t for this target. 147 */ 148 lport = stmf_alloc(STMF_STRUCT_STMF_LOCAL_PORT, 149 sizeof (pppt_tgt_t) + total_devid_len, 0); 150 if (lport == NULL) { 151 *msg_errcode = STMF_ALLOC_FAILURE; 152 return (NULL); 153 } 154 155 result = lport->lport_port_private; 156 result->target_state = TS_CREATED; 157 /* Use pointer arithmetic to find scsi_devid_desc_t */ 158 result->target_devid = (scsi_devid_desc_t *)(result + 1); 159 bcopy(reg_port->icrp_port_id, result->target_devid, total_devid_len); 160 result->target_devid->piv = 1; 161 result->target_devid->code_set = CODE_SET_ASCII; 162 result->target_devid->association = ID_IS_TARGET_PORT; 163 164 mutex_init(&result->target_mutex, NULL, MUTEX_DEFAULT, NULL); 165 cv_init(&result->target_cv, NULL, CV_DEFAULT, NULL); 166 list_create(&result->target_events, sizeof (tgt_event_ctx_t), 167 offsetof(tgt_event_ctx_t, te_ctx_node)); 168 avl_create(&result->target_sess_list, pppt_sess_avl_compare_by_name, 169 sizeof (pppt_sess_t), offsetof(pppt_sess_t, ps_target_ln)); 170 171 lport->lport_abort_timeout = 120; /* seconds */ 172 lport->lport_id = result->target_devid; 173 lport->lport_pp = pppt_global.global_pp; 174 lport->lport_ds = pppt_global.global_dbuf_store; 175 lport->lport_xfer_data = &pppt_lport_xfer_data; 176 lport->lport_send_status = &pppt_lport_send_status; 177 lport->lport_task_free = &pppt_lport_task_free; 178 lport->lport_abort = &pppt_lport_abort; 179 lport->lport_ctl = &pppt_lport_ctl; 180 result->target_stmf_lport = lport; 181 182 /* 183 * Since this is a proxy port we need to do set the relative 184 * target port identifier before registering it with STMF. 185 */ 186 stmf_set_port_standby(lport, reg_port->icrp_relative_port_id); 187 188 /* 189 * Register the target with STMF. STMF may immediately ask us to go 190 * online so insure any additional config setup is complete. 191 */ 192 if (stmf_register_local_port(lport) != STMF_SUCCESS) { 193 *msg_errcode = STMF_FAILURE; 194 pppt_tgt_destroy(result); 195 return (NULL); 196 } 197 198 return (result); 199 200 } 201 202 void 203 pppt_tgt_destroy(pppt_tgt_t *tgt) 204 { 205 /* Destroy target */ 206 avl_destroy(&tgt->target_sess_list); 207 list_destroy(&tgt->target_events); 208 cv_destroy(&tgt->target_cv); 209 mutex_destroy(&tgt->target_mutex); 210 stmf_free(tgt->target_stmf_lport); /* Also frees "tgt' */ 211 } 212 213 pppt_tgt_t * 214 pppt_tgt_lookup(scsi_devid_desc_t *tgt_devid) 215 { 216 pppt_tgt_t *result; 217 PPPT_GLOBAL_LOCK(); 218 result = pppt_tgt_lookup_locked(tgt_devid); 219 PPPT_GLOBAL_UNLOCK(); 220 221 return (result); 222 } 223 224 pppt_tgt_t * 225 pppt_tgt_lookup_locked(scsi_devid_desc_t *tgt_devid) 226 { 227 pppt_tgt_t *result; 228 pppt_tgt_t tmptgt; 229 230 bzero(&tmptgt, sizeof (tmptgt)); 231 tmptgt.target_devid = tgt_devid; 232 233 result = avl_find(&pppt_global.global_target_list, &tmptgt, NULL); 234 235 return (result); 236 } 237 238 void 239 pppt_tgt_async_delete(pppt_tgt_t *tgt) 240 { 241 /* Generate TE_DELETE event to target state machine */ 242 pppt_tgt_sm_event(tgt, TE_DELETE); 243 } 244 245 int 246 pppt_tgt_avl_compare(const void *void_tgt1, const void *void_tgt2) 247 { 248 const pppt_tgt_t *ptgt1 = void_tgt1; 249 const pppt_tgt_t *ptgt2 = void_tgt2; 250 int result; 251 252 /* Sort by code set then ident */ 253 if (ptgt1->target_devid->code_set < 254 ptgt2->target_devid->code_set) { 255 return (-1); 256 } else if (ptgt1->target_devid->code_set > 257 ptgt2->target_devid->code_set) { 258 return (1); 259 } 260 261 /* Next by ident length */ 262 if (ptgt1->target_devid->ident_length < 263 ptgt2->target_devid->ident_length) { 264 return (-1); 265 } else if (ptgt1->target_devid->ident_length > 266 ptgt2->target_devid->ident_length) { 267 return (1); 268 } 269 270 /* Code set and ident length both match, now compare idents */ 271 result = memcmp(ptgt1->target_devid->ident, ptgt2->target_devid->ident, 272 ptgt1->target_devid->ident_length); 273 274 if (result < 0) { 275 return (-1); 276 } else if (result > 0) { 277 return (1); 278 } 279 280 return (0); 281 } 282 283 /* 284 * Target state machine 285 */ 286 287 static void 288 pppt_tgt_sm_event(pppt_tgt_t *tgt, pppt_tgt_event_t event) 289 { 290 mutex_enter(&tgt->target_mutex); 291 tgt_sm_event_locked(tgt, event); 292 mutex_exit(&tgt->target_mutex); 293 } 294 295 static void 296 tgt_sm_event_locked(pppt_tgt_t *tgt, pppt_tgt_event_t event) 297 { 298 tgt_event_ctx_t *ctx; 299 300 event = (event < TE_MAX_EVENT) ? event : TE_UNDEFINED; 301 DTRACE_PROBE2(pppt__tgt__event, pppt_tgt_t *, tgt, 302 pppt_tgt_event_t, event); 303 stmf_trace("pppt", "pppt_tgt_event: tgt %p event %s(%d)", 304 (void *)tgt, pppt_te_name[event], event); 305 306 tgt->target_refcount++; 307 308 ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP); 309 310 ctx->te_ctx_event = event; 311 312 list_insert_tail(&tgt->target_events, ctx); 313 314 /* 315 * Use the target_sm_busy flag to keep the state machine single 316 * threaded. This also serves as recursion avoidance since this 317 * flag will always be set if we call pppt_tgt_sm_event from 318 * within the state machine code. 319 */ 320 if (!tgt->target_sm_busy) { 321 tgt->target_sm_busy = B_TRUE; 322 while (!list_is_empty(&tgt->target_events)) { 323 ctx = list_head(&tgt->target_events); 324 list_remove(&tgt->target_events, ctx); 325 mutex_exit(&tgt->target_mutex); 326 tgt_sm_event_dispatch(tgt, ctx); 327 mutex_enter(&tgt->target_mutex); 328 } 329 tgt->target_sm_busy = B_FALSE; 330 331 } 332 333 tgt->target_refcount--; 334 cv_signal(&tgt->target_cv); 335 } 336 337 static void 338 tgt_sm_event_dispatch(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 339 { 340 stmf_trace("pppt", "pppt_tgt_event_dispatch: tgt %p event %s(%d)", 341 (void *)tgt, pppt_te_name[ctx->te_ctx_event], ctx->te_ctx_event); 342 343 /* State independent actions */ 344 switch (ctx->te_ctx_event) { 345 case TE_DELETE: 346 tgt->target_deleting = B_TRUE; 347 break; 348 } 349 350 /* State dependent actions */ 351 switch (tgt->target_state) { 352 case TS_CREATED: 353 tgt_sm_created(tgt, ctx); 354 break; 355 case TS_ONLINING: 356 tgt_sm_onlining(tgt, ctx); 357 break; 358 case TS_ONLINE: 359 tgt_sm_online(tgt, ctx); 360 break; 361 case TS_STMF_ONLINE: 362 tgt_sm_stmf_online(tgt, ctx); 363 break; 364 case TS_DELETING_NEED_OFFLINE: 365 tgt_sm_deleting_need_offline(tgt, ctx); 366 break; 367 case TS_OFFLINING: 368 tgt_sm_offlining(tgt, ctx); 369 break; 370 case TS_OFFLINE: 371 tgt_sm_offline(tgt, ctx); 372 break; 373 case TS_STMF_OFFLINE: 374 tgt_sm_stmf_offline(tgt, ctx); 375 break; 376 case TS_DELETING_STMF_DEREG: 377 tgt_sm_deleting_stmf_dereg(tgt, ctx); 378 break; 379 case TS_DELETING_STMF_DEREG_FAIL: 380 tgt_sm_deleting_stmf_dereg_fail(tgt, ctx); 381 break; 382 case TS_DELETING: 383 tgt_sm_deleting(tgt, ctx); 384 break; 385 default: 386 ASSERT(0); 387 } 388 389 kmem_free(ctx, sizeof (*ctx)); 390 } 391 392 static void 393 tgt_sm_created(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 394 { 395 stmf_change_status_t scs; 396 397 switch (ctx->te_ctx_event) { 398 case TE_STMF_ONLINE_REQ: 399 tgt_sm_new_state(tgt, ctx, TS_ONLINING); 400 break; 401 case TE_DELETE: 402 tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG); 403 break; 404 case TE_STMF_OFFLINE_REQ: 405 /* 406 * We're already offline but update to an equivelant 407 * state just to note that STMF talked to us. 408 */ 409 scs.st_completion_status = STMF_SUCCESS; 410 scs.st_additional_info = NULL; 411 tgt_sm_new_state(tgt, ctx, TS_OFFLINE); 412 (void) stmf_ctl(STMF_CMD_LPORT_OFFLINE_COMPLETE, 413 tgt->target_stmf_lport, &scs); 414 break; 415 case TE_STMF_ONLINE_COMPLETE_ACK: 416 case TE_STMF_OFFLINE_COMPLETE_ACK: 417 /* Ignore */ 418 break; 419 default: 420 ASSERT(0); 421 } 422 } 423 424 static void 425 tgt_sm_onlining(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 426 { 427 stmf_change_status_t scs; 428 429 switch (ctx->te_ctx_event) { 430 case TE_ONLINE_SUCCESS: 431 tgt_sm_new_state(tgt, ctx, TS_ONLINE); 432 break; 433 case TE_ONLINE_FAIL: 434 tgt_sm_new_state(tgt, ctx, TS_STMF_OFFLINE); 435 break; 436 case TE_DELETE: 437 /* TE_DELETE is handled in tgt_sm_event_dispatch() */ 438 break; 439 case TE_STMF_ONLINE_REQ: 440 case TE_STMF_OFFLINE_REQ: 441 /* 442 * We can't complete STMF's request since we are busy going 443 * online. 444 */ 445 scs.st_completion_status = STMF_INVALID_ARG; 446 scs.st_additional_info = NULL; 447 (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ? 448 STMF_CMD_LPORT_ONLINE_COMPLETE : 449 STMF_CMD_LPORT_OFFLINE_COMPLETE, 450 tgt->target_stmf_lport, &scs); 451 break; 452 case TE_STMF_ONLINE_COMPLETE_ACK: 453 case TE_STMF_OFFLINE_COMPLETE_ACK: 454 /* Ignore */ 455 break; 456 default: 457 ASSERT(0); 458 } 459 } 460 461 static void 462 tgt_sm_online(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 463 { 464 stmf_change_status_t scs; 465 466 switch (ctx->te_ctx_event) { 467 case TE_STMF_ONLINE_COMPLETE_ACK: 468 if (tgt->target_deleting) { 469 tgt_sm_new_state(tgt, ctx, TS_DELETING_NEED_OFFLINE); 470 } else { 471 tgt_sm_new_state(tgt, ctx, TS_STMF_ONLINE); 472 } 473 break; 474 case TE_DELETE: 475 /* TE_DELETE is handled in tgt_sm_event_dispatch() */ 476 break; 477 case TE_STMF_ONLINE_REQ: 478 case TE_STMF_OFFLINE_REQ: 479 /* 480 * We can't complete STMF's request since we are busy going 481 * online (waiting for acknowlegement from STMF) 482 */ 483 scs.st_completion_status = STMF_INVALID_ARG; 484 scs.st_additional_info = NULL; 485 (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ? 486 STMF_CMD_LPORT_ONLINE_COMPLETE : 487 STMF_CMD_LPORT_OFFLINE_COMPLETE, 488 tgt->target_stmf_lport, &scs); 489 break; 490 case TE_STMF_OFFLINE_COMPLETE_ACK: 491 /* Ignore */ 492 break; 493 default: 494 ASSERT(0); 495 } 496 } 497 498 499 static void 500 tgt_sm_stmf_online(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 501 { 502 stmf_change_status_t scs; 503 504 switch (ctx->te_ctx_event) { 505 case TE_DELETE: 506 tgt_sm_new_state(tgt, ctx, TS_DELETING_NEED_OFFLINE); 507 break; 508 case TE_STMF_OFFLINE_REQ: 509 tgt_sm_new_state(tgt, ctx, TS_OFFLINING); 510 break; 511 case TE_STMF_ONLINE_REQ: 512 /* Already online */ 513 scs.st_completion_status = STMF_ALREADY; 514 scs.st_additional_info = NULL; 515 (void) stmf_ctl(STMF_CMD_LPORT_ONLINE_COMPLETE, 516 tgt->target_stmf_lport, &scs); 517 break; 518 case TE_STMF_ONLINE_COMPLETE_ACK: 519 case TE_STMF_OFFLINE_COMPLETE_ACK: 520 /* Ignore */ 521 break; 522 default: 523 ASSERT(0); 524 } 525 } 526 527 528 static void 529 tgt_sm_deleting_need_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 530 { 531 stmf_change_status_t scs; 532 533 switch (ctx->te_ctx_event) { 534 case TE_STMF_OFFLINE_REQ: 535 tgt_sm_new_state(tgt, ctx, TS_OFFLINING); 536 break; 537 case TE_DELETE: 538 /* TE_DELETE is handled in tgt_sm_event_dispatch() */ 539 break; 540 case TE_STMF_ONLINE_REQ: 541 /* 542 * We can't complete STMF's request since we need to be offlined 543 */ 544 scs.st_completion_status = STMF_INVALID_ARG; 545 scs.st_additional_info = NULL; 546 (void) stmf_ctl(STMF_CMD_LPORT_ONLINE_COMPLETE, 547 tgt->target_stmf_lport, &scs); 548 break; 549 case TE_STMF_ONLINE_COMPLETE_ACK: 550 case TE_STMF_OFFLINE_COMPLETE_ACK: 551 /* Ignore */ 552 break; 553 default: 554 ASSERT(0); 555 } 556 } 557 558 559 static void 560 tgt_sm_offlining(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 561 { 562 stmf_change_status_t scs; 563 564 switch (ctx->te_ctx_event) { 565 case TE_OFFLINE_COMPLETE: 566 tgt_sm_new_state(tgt, ctx, TS_OFFLINE); 567 break; 568 case TE_DELETE: 569 /* TE_DELETE is handled in tgt_sm_event_dispatch() */ 570 break; 571 case TE_STMF_ONLINE_REQ: 572 case TE_STMF_OFFLINE_REQ: 573 /* 574 * We can't complete STMF's request since we are busy going 575 * offline. 576 */ 577 scs.st_completion_status = STMF_INVALID_ARG; 578 scs.st_additional_info = NULL; 579 (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ? 580 STMF_CMD_LPORT_ONLINE_COMPLETE : 581 STMF_CMD_LPORT_OFFLINE_COMPLETE, 582 tgt->target_stmf_lport, &scs); 583 break; 584 case TE_STMF_ONLINE_COMPLETE_ACK: 585 case TE_STMF_OFFLINE_COMPLETE_ACK: 586 /* Ignore */ 587 break; 588 default: 589 ASSERT(0); 590 } 591 } 592 593 594 static void 595 tgt_sm_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 596 { 597 stmf_change_status_t scs; 598 599 switch (ctx->te_ctx_event) { 600 case TE_STMF_OFFLINE_COMPLETE_ACK: 601 if (tgt->target_deleting) { 602 tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG); 603 } else { 604 tgt_sm_new_state(tgt, ctx, TS_STMF_OFFLINE); 605 } 606 break; 607 case TE_DELETE: 608 /* TE_DELETE is handled in tgt_sm_event_dispatch() */ 609 break; 610 case TE_STMF_ONLINE_REQ: 611 case TE_STMF_OFFLINE_REQ: 612 /* 613 * We can't complete STMF's request since we are busy going 614 * offline. 615 */ 616 scs.st_completion_status = STMF_INVALID_ARG; 617 scs.st_additional_info = NULL; 618 (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ? 619 STMF_CMD_LPORT_ONLINE_COMPLETE : 620 STMF_CMD_LPORT_OFFLINE_COMPLETE, 621 tgt->target_stmf_lport, &scs); 622 break; 623 case TE_STMF_ONLINE_COMPLETE_ACK: 624 /* Ignore */ 625 break; 626 default: 627 ASSERT(0); 628 } 629 } 630 631 632 static void 633 tgt_sm_stmf_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 634 { 635 stmf_change_status_t scs; 636 637 switch (ctx->te_ctx_event) { 638 case TE_STMF_ONLINE_REQ: 639 tgt_sm_new_state(tgt, ctx, TS_ONLINING); 640 break; 641 case TE_DELETE: 642 tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG); 643 break; 644 case TE_STMF_OFFLINE_REQ: 645 /* Already offline */ 646 scs.st_completion_status = STMF_ALREADY; 647 scs.st_additional_info = NULL; 648 (void) stmf_ctl(STMF_CMD_LPORT_OFFLINE_COMPLETE, 649 tgt->target_stmf_lport, &scs); 650 break; 651 case TE_STMF_ONLINE_COMPLETE_ACK: 652 case TE_STMF_OFFLINE_COMPLETE_ACK: 653 /* Ignore */ 654 break; 655 default: 656 ASSERT(0); 657 } 658 } 659 660 661 static void 662 tgt_sm_deleting_stmf_dereg(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 663 { 664 stmf_change_status_t scs; 665 666 /* Terminal state, no events */ 667 switch (ctx->te_ctx_event) { 668 case TE_STMF_ONLINE_REQ: 669 case TE_STMF_OFFLINE_REQ: 670 /* 671 * We can't complete STMF's request since we are being deleted 672 */ 673 scs.st_completion_status = STMF_INVALID_ARG; 674 scs.st_additional_info = NULL; 675 (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ? 676 STMF_CMD_LPORT_ONLINE_COMPLETE : 677 STMF_CMD_LPORT_OFFLINE_COMPLETE, 678 tgt->target_stmf_lport, &scs); 679 break; 680 case TE_STMF_ONLINE_COMPLETE_ACK: 681 case TE_STMF_OFFLINE_COMPLETE_ACK: 682 /* Ignore */ 683 break; 684 case TE_STMF_DEREG_SUCCESS: 685 tgt_sm_new_state(tgt, ctx, TS_DELETING); 686 break; 687 case TE_STMF_DEREG_FAIL: 688 tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG_FAIL); 689 break; 690 default: 691 ASSERT(0); 692 } 693 } 694 695 static void 696 tgt_sm_deleting_stmf_dereg_fail(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 697 { 698 stmf_change_status_t scs; 699 700 /* Terminal state, no events */ 701 switch (ctx->te_ctx_event) { 702 case TE_STMF_ONLINE_REQ: 703 case TE_STMF_OFFLINE_REQ: 704 /* 705 * We can't complete STMF's request since we are being deleted 706 */ 707 scs.st_completion_status = STMF_INVALID_ARG; 708 scs.st_additional_info = NULL; 709 (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ? 710 STMF_CMD_LPORT_ONLINE_COMPLETE : 711 STMF_CMD_LPORT_OFFLINE_COMPLETE, 712 tgt->target_stmf_lport, &scs); 713 break; 714 case TE_STMF_ONLINE_COMPLETE_ACK: 715 case TE_STMF_OFFLINE_COMPLETE_ACK: 716 /* Ignore */ 717 break; 718 case TE_STMF_DEREG_RETRY: 719 tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG); 720 break; 721 default: 722 ASSERT(0); 723 } 724 } 725 726 static void 727 tgt_sm_deleting(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 728 { 729 stmf_change_status_t scs; 730 731 /* Terminal state, no events */ 732 switch (ctx->te_ctx_event) { 733 case TE_STMF_ONLINE_REQ: 734 case TE_STMF_OFFLINE_REQ: 735 /* 736 * We can't complete STMF's request since we are being deleted 737 */ 738 scs.st_completion_status = STMF_INVALID_ARG; 739 scs.st_additional_info = NULL; 740 (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ? 741 STMF_CMD_LPORT_ONLINE_COMPLETE : 742 STMF_CMD_LPORT_OFFLINE_COMPLETE, 743 tgt->target_stmf_lport, &scs); 744 break; 745 case TE_STMF_ONLINE_COMPLETE_ACK: 746 case TE_STMF_OFFLINE_COMPLETE_ACK: 747 /* Ignore */ 748 break; 749 default: 750 ASSERT(0); 751 } 752 } 753 754 static void 755 pppt_tgt_offline(pppt_tgt_t *tgt) 756 { 757 (void) taskq_dispatch(pppt_global.global_dispatch_taskq, 758 pppt_tgt_offline_task, tgt, KM_SLEEP); 759 } 760 761 static void 762 pppt_tgt_offline_task(void *arg) 763 { 764 pppt_tgt_t *tgt = arg; 765 pppt_sess_t *ps, *next_ps; 766 stmf_change_status_t scs; 767 768 stmf_trace("pppt", "pppt_tgt_offline %p", (void *)tgt); 769 770 PPPT_GLOBAL_LOCK(); 771 mutex_enter(&tgt->target_mutex); 772 for (ps = avl_first(&tgt->target_sess_list); ps != NULL; ps = next_ps) { 773 next_ps = AVL_NEXT(&tgt->target_sess_list, ps); 774 mutex_enter(&ps->ps_mutex); 775 if (!ps->ps_closed) { 776 pppt_sess_close_locked(ps); 777 } 778 mutex_exit(&ps->ps_mutex); 779 } 780 mutex_exit(&tgt->target_mutex); 781 PPPT_GLOBAL_UNLOCK(); 782 783 pppt_tgt_sm_event(tgt, TE_OFFLINE_COMPLETE); 784 785 scs.st_completion_status = STMF_SUCCESS; 786 scs.st_additional_info = NULL; 787 (void) stmf_ctl(STMF_CMD_LPORT_OFFLINE_COMPLETE, 788 tgt->target_stmf_lport, &scs); 789 790 stmf_trace("pppt", "pppt_tgt_offline complete %p", (void *)tgt); 791 } 792 793 static void 794 pppt_tgt_dereg_retry(void *arg) 795 { 796 pppt_tgt_t *tgt = arg; 797 798 /* 799 * Rather than guaranteeing the target state machine code will not 800 * block for long periods of time (tying up this callout thread) 801 * we will queue a task on the taskq to send the retry event. 802 * If it fails we'll setup another timeout and try again later. 803 */ 804 if (taskq_dispatch(pppt_global.global_dispatch_taskq, 805 pppt_tgt_dereg_task, tgt, KM_NOSLEEP) == NULL) { 806 /* Dispatch failed, try again later */ 807 (void) timeout(pppt_tgt_dereg_retry, tgt, 808 drv_usectohz(TGT_DEREG_RETRY_SECONDS * 1000000)); 809 } 810 } 811 812 static void 813 pppt_tgt_dereg_task(void *arg) 814 { 815 pppt_tgt_t *tgt = arg; 816 817 pppt_tgt_sm_event(tgt, TE_STMF_DEREG_RETRY); 818 } 819 820 /*ARGSUSED*/ 821 static void 822 tgt_sm_new_state(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx, 823 pppt_tgt_state_t new_state) 824 { 825 stmf_local_port_t *lport = tgt->target_stmf_lport; 826 stmf_change_status_t scs; 827 stmf_state_change_info_t sci; 828 stmf_status_t stmfrc; 829 830 scs.st_completion_status = STMF_SUCCESS; 831 scs.st_additional_info = NULL; 832 833 /* 834 * Validate new state 835 */ 836 ASSERT(new_state != TS_UNDEFINED); 837 ASSERT3U(new_state, <, TS_MAX_STATE); 838 839 new_state = (new_state < TS_MAX_STATE) ? 840 new_state : TS_UNDEFINED; 841 842 stmf_trace("pppt", "pppt_target_state_change: " 843 "tgt %p, %s(%d) --> %s(%d)\n", 844 (void *) tgt, pppt_ts_name[tgt->target_state], tgt->target_state, 845 pppt_ts_name[new_state], new_state); 846 DTRACE_PROBE3(pppt__target__state__change, 847 pppt_tgt_t *, tgt, tgt_event_ctx_t *, ctx, 848 pppt_tgt_state_t, new_state); 849 850 mutex_enter(&tgt->target_mutex); 851 tgt->target_last_state = tgt->target_state; 852 tgt->target_state = new_state; 853 cv_signal(&tgt->target_cv); 854 mutex_exit(&tgt->target_mutex); 855 856 switch (tgt->target_state) { 857 case TS_ONLINING: 858 pppt_tgt_sm_event(tgt, TE_ONLINE_SUCCESS); 859 860 /* 861 * Let STMF know the how the online operation completed. 862 * STMF will respond with an acknowlege later 863 */ 864 (void) stmf_ctl(STMF_CMD_LPORT_ONLINE_COMPLETE, lport, &scs); 865 break; 866 case TS_ONLINE: 867 break; 868 case TS_STMF_ONLINE: 869 break; 870 case TS_DELETING_NEED_OFFLINE: 871 sci.st_rflags = STMF_RFLAG_STAY_OFFLINED; 872 sci.st_additional_info = "Offline for delete"; 873 (void) stmf_ctl(STMF_CMD_LPORT_OFFLINE, lport, &sci); 874 break; 875 case TS_OFFLINING: 876 /* Async callback generates completion event */ 877 pppt_tgt_offline(tgt); 878 break; 879 case TS_OFFLINE: 880 break; 881 case TS_STMF_OFFLINE: 882 break; 883 case TS_DELETING_STMF_DEREG: 884 stmfrc = stmf_deregister_local_port(tgt->target_stmf_lport); 885 if (stmfrc == STMF_SUCCESS) { 886 pppt_tgt_sm_event(tgt, TE_STMF_DEREG_SUCCESS); 887 } else { 888 pppt_tgt_sm_event(tgt, TE_STMF_DEREG_FAIL); 889 } 890 break; 891 case TS_DELETING_STMF_DEREG_FAIL: 892 /* Retry dereg in 1 second */ 893 (void) timeout(pppt_tgt_dereg_retry, tgt, 894 drv_usectohz(TGT_DEREG_RETRY_SECONDS * 1000000)); 895 break; 896 case TS_DELETING: 897 break; 898 default: 899 ASSERT(0); 900 } 901 } 902