145039663SJohn Forte /* 245039663SJohn Forte * CDDL HEADER START 345039663SJohn Forte * 445039663SJohn Forte * The contents of this file are subject to the terms of the 545039663SJohn Forte * Common Development and Distribution License (the "License"). 645039663SJohn Forte * You may not use this file except in compliance with the License. 745039663SJohn Forte * 845039663SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 945039663SJohn Forte * or http://www.opensolaris.org/os/licensing. 1045039663SJohn Forte * See the License for the specific language governing permissions 1145039663SJohn Forte * and limitations under the License. 1245039663SJohn Forte * 1345039663SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 1445039663SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1545039663SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 1645039663SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 1745039663SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 1845039663SJohn Forte * 1945039663SJohn Forte * CDDL HEADER END 2045039663SJohn Forte */ 2145039663SJohn Forte /* 22*4558d122SViswanathan Kannappan * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 2345039663SJohn Forte */ 2445039663SJohn Forte 2545039663SJohn Forte #include <sys/cpuvar.h> 2645039663SJohn Forte #include <sys/types.h> 2745039663SJohn Forte #include <sys/conf.h> 2845039663SJohn Forte #include <sys/file.h> 2945039663SJohn Forte #include <sys/ddi.h> 3045039663SJohn Forte #include <sys/sunddi.h> 3145039663SJohn Forte #include <sys/modctl.h> 3245039663SJohn Forte #include <sys/sysmacros.h> 3345039663SJohn Forte 3445039663SJohn Forte #include <sys/socket.h> 3545039663SJohn Forte #include <sys/strsubr.h> 3645039663SJohn Forte #include <sys/door.h> 3745039663SJohn Forte #include <sys/note.h> 3845039663SJohn Forte #include <sys/sdt.h> 3945039663SJohn Forte 4045039663SJohn Forte #include <sys/stmf.h> 4145039663SJohn Forte #include <sys/stmf_ioctl.h> 4245039663SJohn Forte #include <sys/portif.h> 4345039663SJohn Forte #define PPPT_TGT_SM_STRINGS 44*4558d122SViswanathan Kannappan #include "pppt.h" 4545039663SJohn Forte 4645039663SJohn Forte typedef struct { 4745039663SJohn Forte list_node_t te_ctx_node; 4845039663SJohn Forte pppt_tgt_event_t te_ctx_event; 4945039663SJohn Forte } tgt_event_ctx_t; 5045039663SJohn Forte 5145039663SJohn Forte static void 5245039663SJohn Forte pppt_tgt_sm_event(pppt_tgt_t *tgt, pppt_tgt_event_t event); 5345039663SJohn Forte 5445039663SJohn Forte static void 5545039663SJohn Forte tgt_sm_event_locked(pppt_tgt_t *tgt, pppt_tgt_event_t event); 5645039663SJohn Forte 5745039663SJohn Forte static void 5845039663SJohn Forte tgt_sm_event_dispatch(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 5945039663SJohn Forte 6045039663SJohn Forte static void 6145039663SJohn Forte tgt_sm_created(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 6245039663SJohn Forte 6345039663SJohn Forte static void 6445039663SJohn Forte tgt_sm_onlining(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 6545039663SJohn Forte 6645039663SJohn Forte static void 6745039663SJohn Forte tgt_sm_online(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 6845039663SJohn Forte 6945039663SJohn Forte static void 7045039663SJohn Forte tgt_sm_stmf_online(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 7145039663SJohn Forte 7245039663SJohn Forte static void 7345039663SJohn Forte tgt_sm_deleting_need_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 7445039663SJohn Forte 7545039663SJohn Forte static void 7645039663SJohn Forte tgt_sm_offlining(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 7745039663SJohn Forte 7845039663SJohn Forte static void 7945039663SJohn Forte tgt_sm_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 8045039663SJohn Forte 8145039663SJohn Forte static void 8245039663SJohn Forte tgt_sm_stmf_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 8345039663SJohn Forte 8445039663SJohn Forte static void 8545039663SJohn Forte tgt_sm_deleting_stmf_dereg(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 8645039663SJohn Forte 8745039663SJohn Forte static void 8845039663SJohn Forte tgt_sm_deleting_stmf_dereg_fail(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 8945039663SJohn Forte 9045039663SJohn Forte static void 9145039663SJohn Forte tgt_sm_deleting(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx); 9245039663SJohn Forte 93e617f214Speter dunlap static void 94e617f214Speter dunlap pppt_tgt_offline_task(void *arg); 95e617f214Speter dunlap 9645039663SJohn Forte static void 9745039663SJohn Forte pppt_tgt_dereg_retry(void *arg); 9845039663SJohn Forte 9945039663SJohn Forte static void 10045039663SJohn Forte pppt_tgt_dereg_task(void *arg); 10145039663SJohn Forte 10245039663SJohn Forte static void 10345039663SJohn Forte tgt_sm_new_state(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx, 10445039663SJohn Forte pppt_tgt_state_t new_state); 10545039663SJohn Forte 10645039663SJohn Forte /*ARGSUSED*/ 10745039663SJohn Forte void 10845039663SJohn Forte pppt_tgt_sm_ctl(stmf_local_port_t *lport, int cmd, void *arg) 10945039663SJohn Forte { 11045039663SJohn Forte pppt_tgt_t *pppt_tgt; 11145039663SJohn Forte 11245039663SJohn Forte pppt_tgt = (pppt_tgt_t *)lport->lport_port_private; 11345039663SJohn Forte 11445039663SJohn Forte switch (cmd) { 11545039663SJohn Forte case STMF_CMD_LPORT_ONLINE: 11645039663SJohn Forte pppt_tgt_sm_event(pppt_tgt, TE_STMF_ONLINE_REQ); 11745039663SJohn Forte break; 11845039663SJohn Forte case STMF_CMD_LPORT_OFFLINE: 11945039663SJohn Forte pppt_tgt_sm_event(pppt_tgt, TE_STMF_OFFLINE_REQ); 12045039663SJohn Forte break; 12145039663SJohn Forte case STMF_ACK_LPORT_ONLINE_COMPLETE: 12245039663SJohn Forte pppt_tgt_sm_event(pppt_tgt, TE_STMF_ONLINE_COMPLETE_ACK); 12345039663SJohn Forte break; 12445039663SJohn Forte case STMF_ACK_LPORT_OFFLINE_COMPLETE: 12545039663SJohn Forte pppt_tgt_sm_event(pppt_tgt, TE_STMF_OFFLINE_COMPLETE_ACK); 12645039663SJohn Forte break; 12745039663SJohn Forte 12845039663SJohn Forte default: 12945039663SJohn Forte ASSERT(0); 13045039663SJohn Forte break; 13145039663SJohn Forte } 13245039663SJohn Forte } 13345039663SJohn Forte 13445039663SJohn Forte pppt_tgt_t * 13545039663SJohn Forte pppt_tgt_create(stmf_ic_reg_port_msg_t *reg_port, stmf_status_t *msg_errcode) 13645039663SJohn Forte { 13745039663SJohn Forte pppt_tgt_t *result; 13845039663SJohn Forte stmf_local_port_t *lport; 13945039663SJohn Forte int total_devid_len; 14045039663SJohn Forte 14145039663SJohn Forte total_devid_len = sizeof (scsi_devid_desc_t) + 14245039663SJohn Forte reg_port->icrp_port_id->ident_length - 1; 14345039663SJohn Forte 14445039663SJohn Forte /* 14545039663SJohn Forte * Each target is an STMF local port. Allocate an STMF local port 14645039663SJohn Forte * including enough space to store a scsi_devid_desc_t for this target. 14745039663SJohn Forte */ 14845039663SJohn Forte lport = stmf_alloc(STMF_STRUCT_STMF_LOCAL_PORT, 14945039663SJohn Forte sizeof (pppt_tgt_t) + total_devid_len, 0); 15045039663SJohn Forte if (lport == NULL) { 15145039663SJohn Forte *msg_errcode = STMF_ALLOC_FAILURE; 15245039663SJohn Forte return (NULL); 15345039663SJohn Forte } 15445039663SJohn Forte 15545039663SJohn Forte result = lport->lport_port_private; 15645039663SJohn Forte result->target_state = TS_CREATED; 15745039663SJohn Forte /* Use pointer arithmetic to find scsi_devid_desc_t */ 15845039663SJohn Forte result->target_devid = (scsi_devid_desc_t *)(result + 1); 15945039663SJohn Forte bcopy(reg_port->icrp_port_id, result->target_devid, total_devid_len); 16045039663SJohn Forte result->target_devid->piv = 1; 16145039663SJohn Forte result->target_devid->code_set = CODE_SET_ASCII; 16245039663SJohn Forte result->target_devid->association = ID_IS_TARGET_PORT; 16345039663SJohn Forte 16445039663SJohn Forte mutex_init(&result->target_mutex, NULL, MUTEX_DEFAULT, NULL); 16545039663SJohn Forte cv_init(&result->target_cv, NULL, CV_DEFAULT, NULL); 16645039663SJohn Forte list_create(&result->target_events, sizeof (tgt_event_ctx_t), 16745039663SJohn Forte offsetof(tgt_event_ctx_t, te_ctx_node)); 16845039663SJohn Forte avl_create(&result->target_sess_list, pppt_sess_avl_compare_by_name, 16945039663SJohn Forte sizeof (pppt_sess_t), offsetof(pppt_sess_t, ps_target_ln)); 17045039663SJohn Forte 17145039663SJohn Forte lport->lport_abort_timeout = 120; /* seconds */ 17245039663SJohn Forte lport->lport_id = result->target_devid; 17345039663SJohn Forte lport->lport_pp = pppt_global.global_pp; 17445039663SJohn Forte lport->lport_ds = pppt_global.global_dbuf_store; 17545039663SJohn Forte lport->lport_xfer_data = &pppt_lport_xfer_data; 17645039663SJohn Forte lport->lport_send_status = &pppt_lport_send_status; 17745039663SJohn Forte lport->lport_task_free = &pppt_lport_task_free; 17845039663SJohn Forte lport->lport_abort = &pppt_lport_abort; 17945039663SJohn Forte lport->lport_ctl = &pppt_lport_ctl; 18045039663SJohn Forte result->target_stmf_lport = lport; 18145039663SJohn Forte 18245039663SJohn Forte /* 18345039663SJohn Forte * Since this is a proxy port we need to do set the relative 18445039663SJohn Forte * target port identifier before registering it with STMF. 18545039663SJohn Forte */ 18645039663SJohn Forte stmf_set_port_standby(lport, reg_port->icrp_relative_port_id); 18745039663SJohn Forte 18845039663SJohn Forte /* 18945039663SJohn Forte * Register the target with STMF. STMF may immediately ask us to go 19045039663SJohn Forte * online so insure any additional config setup is complete. 19145039663SJohn Forte */ 19245039663SJohn Forte if (stmf_register_local_port(lport) != STMF_SUCCESS) { 19345039663SJohn Forte *msg_errcode = STMF_FAILURE; 19445039663SJohn Forte pppt_tgt_destroy(result); 19545039663SJohn Forte return (NULL); 19645039663SJohn Forte } 19745039663SJohn Forte 19845039663SJohn Forte return (result); 19945039663SJohn Forte 20045039663SJohn Forte } 20145039663SJohn Forte 20245039663SJohn Forte void 20345039663SJohn Forte pppt_tgt_destroy(pppt_tgt_t *tgt) 20445039663SJohn Forte { 20545039663SJohn Forte /* Destroy target */ 20645039663SJohn Forte avl_destroy(&tgt->target_sess_list); 20745039663SJohn Forte list_destroy(&tgt->target_events); 20845039663SJohn Forte cv_destroy(&tgt->target_cv); 20945039663SJohn Forte mutex_destroy(&tgt->target_mutex); 21045039663SJohn Forte stmf_free(tgt->target_stmf_lport); /* Also frees "tgt' */ 21145039663SJohn Forte } 21245039663SJohn Forte 21345039663SJohn Forte pppt_tgt_t * 21445039663SJohn Forte pppt_tgt_lookup(scsi_devid_desc_t *tgt_devid) 21545039663SJohn Forte { 21645039663SJohn Forte pppt_tgt_t *result; 21745039663SJohn Forte PPPT_GLOBAL_LOCK(); 21845039663SJohn Forte result = pppt_tgt_lookup_locked(tgt_devid); 21945039663SJohn Forte PPPT_GLOBAL_UNLOCK(); 22045039663SJohn Forte 22145039663SJohn Forte return (result); 22245039663SJohn Forte } 22345039663SJohn Forte 22445039663SJohn Forte pppt_tgt_t * 22545039663SJohn Forte pppt_tgt_lookup_locked(scsi_devid_desc_t *tgt_devid) 22645039663SJohn Forte { 22745039663SJohn Forte pppt_tgt_t *result; 22845039663SJohn Forte pppt_tgt_t tmptgt; 22945039663SJohn Forte 23045039663SJohn Forte bzero(&tmptgt, sizeof (tmptgt)); 23145039663SJohn Forte tmptgt.target_devid = tgt_devid; 23245039663SJohn Forte 23345039663SJohn Forte result = avl_find(&pppt_global.global_target_list, &tmptgt, NULL); 23445039663SJohn Forte 23545039663SJohn Forte return (result); 23645039663SJohn Forte } 23745039663SJohn Forte 23845039663SJohn Forte void 23945039663SJohn Forte pppt_tgt_async_delete(pppt_tgt_t *tgt) 24045039663SJohn Forte { 24145039663SJohn Forte /* Generate TE_DELETE event to target state machine */ 24245039663SJohn Forte pppt_tgt_sm_event(tgt, TE_DELETE); 24345039663SJohn Forte } 24445039663SJohn Forte 24545039663SJohn Forte int 24645039663SJohn Forte pppt_tgt_avl_compare(const void *void_tgt1, const void *void_tgt2) 24745039663SJohn Forte { 24845039663SJohn Forte const pppt_tgt_t *ptgt1 = void_tgt1; 24945039663SJohn Forte const pppt_tgt_t *ptgt2 = void_tgt2; 25045039663SJohn Forte int result; 25145039663SJohn Forte 25245039663SJohn Forte /* Sort by code set then ident */ 25345039663SJohn Forte if (ptgt1->target_devid->code_set < 25445039663SJohn Forte ptgt2->target_devid->code_set) { 25545039663SJohn Forte return (-1); 25645039663SJohn Forte } else if (ptgt1->target_devid->code_set > 25745039663SJohn Forte ptgt2->target_devid->code_set) { 25845039663SJohn Forte return (1); 25945039663SJohn Forte } 26045039663SJohn Forte 26145039663SJohn Forte /* Next by ident length */ 26245039663SJohn Forte if (ptgt1->target_devid->ident_length < 26345039663SJohn Forte ptgt2->target_devid->ident_length) { 26445039663SJohn Forte return (-1); 26545039663SJohn Forte } else if (ptgt1->target_devid->ident_length > 26645039663SJohn Forte ptgt2->target_devid->ident_length) { 26745039663SJohn Forte return (1); 26845039663SJohn Forte } 26945039663SJohn Forte 27045039663SJohn Forte /* Code set and ident length both match, now compare idents */ 27145039663SJohn Forte result = memcmp(ptgt1->target_devid->ident, ptgt2->target_devid->ident, 27245039663SJohn Forte ptgt1->target_devid->ident_length); 27345039663SJohn Forte 27445039663SJohn Forte if (result < 0) { 27545039663SJohn Forte return (-1); 27645039663SJohn Forte } else if (result > 0) { 27745039663SJohn Forte return (1); 27845039663SJohn Forte } 27945039663SJohn Forte 28045039663SJohn Forte return (0); 28145039663SJohn Forte } 28245039663SJohn Forte 28345039663SJohn Forte /* 28445039663SJohn Forte * Target state machine 28545039663SJohn Forte */ 28645039663SJohn Forte 28745039663SJohn Forte static void 28845039663SJohn Forte pppt_tgt_sm_event(pppt_tgt_t *tgt, pppt_tgt_event_t event) 28945039663SJohn Forte { 29045039663SJohn Forte mutex_enter(&tgt->target_mutex); 29145039663SJohn Forte tgt_sm_event_locked(tgt, event); 29245039663SJohn Forte mutex_exit(&tgt->target_mutex); 29345039663SJohn Forte } 29445039663SJohn Forte 29545039663SJohn Forte static void 29645039663SJohn Forte tgt_sm_event_locked(pppt_tgt_t *tgt, pppt_tgt_event_t event) 29745039663SJohn Forte { 29845039663SJohn Forte tgt_event_ctx_t *ctx; 29945039663SJohn Forte 300e617f214Speter dunlap event = (event < TE_MAX_EVENT) ? event : TE_UNDEFINED; 301e617f214Speter dunlap DTRACE_PROBE2(pppt__tgt__event, pppt_tgt_t *, tgt, 302e617f214Speter dunlap pppt_tgt_event_t, event); 303e617f214Speter dunlap stmf_trace("pppt", "pppt_tgt_event: tgt %p event %s(%d)", 304e617f214Speter dunlap (void *)tgt, pppt_te_name[event], event); 305e617f214Speter dunlap 30645039663SJohn Forte tgt->target_refcount++; 30745039663SJohn Forte 30845039663SJohn Forte ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP); 30945039663SJohn Forte 31045039663SJohn Forte ctx->te_ctx_event = event; 31145039663SJohn Forte 31245039663SJohn Forte list_insert_tail(&tgt->target_events, ctx); 31345039663SJohn Forte 31445039663SJohn Forte /* 31545039663SJohn Forte * Use the target_sm_busy flag to keep the state machine single 31645039663SJohn Forte * threaded. This also serves as recursion avoidance since this 31745039663SJohn Forte * flag will always be set if we call pppt_tgt_sm_event from 31845039663SJohn Forte * within the state machine code. 31945039663SJohn Forte */ 32045039663SJohn Forte if (!tgt->target_sm_busy) { 32145039663SJohn Forte tgt->target_sm_busy = B_TRUE; 32245039663SJohn Forte while (!list_is_empty(&tgt->target_events)) { 32345039663SJohn Forte ctx = list_head(&tgt->target_events); 32445039663SJohn Forte list_remove(&tgt->target_events, ctx); 32545039663SJohn Forte mutex_exit(&tgt->target_mutex); 32645039663SJohn Forte tgt_sm_event_dispatch(tgt, ctx); 32745039663SJohn Forte mutex_enter(&tgt->target_mutex); 32845039663SJohn Forte } 32945039663SJohn Forte tgt->target_sm_busy = B_FALSE; 33045039663SJohn Forte 33145039663SJohn Forte } 33245039663SJohn Forte 33345039663SJohn Forte tgt->target_refcount--; 33445039663SJohn Forte cv_signal(&tgt->target_cv); 33545039663SJohn Forte } 33645039663SJohn Forte 33745039663SJohn Forte static void 33845039663SJohn Forte tgt_sm_event_dispatch(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 33945039663SJohn Forte { 340e617f214Speter dunlap stmf_trace("pppt", "pppt_tgt_event_dispatch: tgt %p event %s(%d)", 34145039663SJohn Forte (void *)tgt, pppt_te_name[ctx->te_ctx_event], ctx->te_ctx_event); 34245039663SJohn Forte 34345039663SJohn Forte /* State independent actions */ 34445039663SJohn Forte switch (ctx->te_ctx_event) { 34545039663SJohn Forte case TE_DELETE: 34645039663SJohn Forte tgt->target_deleting = B_TRUE; 34745039663SJohn Forte break; 34845039663SJohn Forte } 34945039663SJohn Forte 35045039663SJohn Forte /* State dependent actions */ 35145039663SJohn Forte switch (tgt->target_state) { 35245039663SJohn Forte case TS_CREATED: 35345039663SJohn Forte tgt_sm_created(tgt, ctx); 35445039663SJohn Forte break; 35545039663SJohn Forte case TS_ONLINING: 35645039663SJohn Forte tgt_sm_onlining(tgt, ctx); 35745039663SJohn Forte break; 35845039663SJohn Forte case TS_ONLINE: 35945039663SJohn Forte tgt_sm_online(tgt, ctx); 36045039663SJohn Forte break; 36145039663SJohn Forte case TS_STMF_ONLINE: 36245039663SJohn Forte tgt_sm_stmf_online(tgt, ctx); 36345039663SJohn Forte break; 36445039663SJohn Forte case TS_DELETING_NEED_OFFLINE: 36545039663SJohn Forte tgt_sm_deleting_need_offline(tgt, ctx); 36645039663SJohn Forte break; 36745039663SJohn Forte case TS_OFFLINING: 36845039663SJohn Forte tgt_sm_offlining(tgt, ctx); 36945039663SJohn Forte break; 37045039663SJohn Forte case TS_OFFLINE: 37145039663SJohn Forte tgt_sm_offline(tgt, ctx); 37245039663SJohn Forte break; 37345039663SJohn Forte case TS_STMF_OFFLINE: 37445039663SJohn Forte tgt_sm_stmf_offline(tgt, ctx); 37545039663SJohn Forte break; 37645039663SJohn Forte case TS_DELETING_STMF_DEREG: 37745039663SJohn Forte tgt_sm_deleting_stmf_dereg(tgt, ctx); 37845039663SJohn Forte break; 37945039663SJohn Forte case TS_DELETING_STMF_DEREG_FAIL: 38045039663SJohn Forte tgt_sm_deleting_stmf_dereg_fail(tgt, ctx); 38145039663SJohn Forte break; 38245039663SJohn Forte case TS_DELETING: 38345039663SJohn Forte tgt_sm_deleting(tgt, ctx); 38445039663SJohn Forte break; 38545039663SJohn Forte default: 38645039663SJohn Forte ASSERT(0); 38745039663SJohn Forte } 38845039663SJohn Forte 38945039663SJohn Forte kmem_free(ctx, sizeof (*ctx)); 39045039663SJohn Forte } 39145039663SJohn Forte 39245039663SJohn Forte static void 39345039663SJohn Forte tgt_sm_created(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 39445039663SJohn Forte { 39545039663SJohn Forte stmf_change_status_t scs; 39645039663SJohn Forte 39745039663SJohn Forte switch (ctx->te_ctx_event) { 39845039663SJohn Forte case TE_STMF_ONLINE_REQ: 39945039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_ONLINING); 40045039663SJohn Forte break; 40145039663SJohn Forte case TE_DELETE: 40245039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG); 40345039663SJohn Forte break; 40445039663SJohn Forte case TE_STMF_OFFLINE_REQ: 40545039663SJohn Forte /* 40645039663SJohn Forte * We're already offline but update to an equivelant 40745039663SJohn Forte * state just to note that STMF talked to us. 40845039663SJohn Forte */ 40945039663SJohn Forte scs.st_completion_status = STMF_SUCCESS; 41045039663SJohn Forte scs.st_additional_info = NULL; 41145039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_OFFLINE); 41245039663SJohn Forte (void) stmf_ctl(STMF_CMD_LPORT_OFFLINE_COMPLETE, 41345039663SJohn Forte tgt->target_stmf_lport, &scs); 41445039663SJohn Forte break; 41545039663SJohn Forte case TE_STMF_ONLINE_COMPLETE_ACK: 41645039663SJohn Forte case TE_STMF_OFFLINE_COMPLETE_ACK: 41745039663SJohn Forte /* Ignore */ 41845039663SJohn Forte break; 41945039663SJohn Forte default: 42045039663SJohn Forte ASSERT(0); 42145039663SJohn Forte } 42245039663SJohn Forte } 42345039663SJohn Forte 42445039663SJohn Forte static void 42545039663SJohn Forte tgt_sm_onlining(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 42645039663SJohn Forte { 42745039663SJohn Forte stmf_change_status_t scs; 42845039663SJohn Forte 42945039663SJohn Forte switch (ctx->te_ctx_event) { 43045039663SJohn Forte case TE_ONLINE_SUCCESS: 43145039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_ONLINE); 43245039663SJohn Forte break; 43345039663SJohn Forte case TE_ONLINE_FAIL: 43445039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_STMF_OFFLINE); 43545039663SJohn Forte break; 43645039663SJohn Forte case TE_DELETE: 43745039663SJohn Forte /* TE_DELETE is handled in tgt_sm_event_dispatch() */ 43845039663SJohn Forte break; 43945039663SJohn Forte case TE_STMF_ONLINE_REQ: 44045039663SJohn Forte case TE_STMF_OFFLINE_REQ: 44145039663SJohn Forte /* 44245039663SJohn Forte * We can't complete STMF's request since we are busy going 44345039663SJohn Forte * online. 44445039663SJohn Forte */ 44545039663SJohn Forte scs.st_completion_status = STMF_INVALID_ARG; 44645039663SJohn Forte scs.st_additional_info = NULL; 44745039663SJohn Forte (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ? 44845039663SJohn Forte STMF_CMD_LPORT_ONLINE_COMPLETE : 44945039663SJohn Forte STMF_CMD_LPORT_OFFLINE_COMPLETE, 45045039663SJohn Forte tgt->target_stmf_lport, &scs); 45145039663SJohn Forte break; 45245039663SJohn Forte case TE_STMF_ONLINE_COMPLETE_ACK: 45345039663SJohn Forte case TE_STMF_OFFLINE_COMPLETE_ACK: 45445039663SJohn Forte /* Ignore */ 45545039663SJohn Forte break; 45645039663SJohn Forte default: 45745039663SJohn Forte ASSERT(0); 45845039663SJohn Forte } 45945039663SJohn Forte } 46045039663SJohn Forte 46145039663SJohn Forte static void 46245039663SJohn Forte tgt_sm_online(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 46345039663SJohn Forte { 46445039663SJohn Forte stmf_change_status_t scs; 46545039663SJohn Forte 46645039663SJohn Forte switch (ctx->te_ctx_event) { 46745039663SJohn Forte case TE_STMF_ONLINE_COMPLETE_ACK: 46845039663SJohn Forte if (tgt->target_deleting) { 46945039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_DELETING_NEED_OFFLINE); 47045039663SJohn Forte } else { 47145039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_STMF_ONLINE); 47245039663SJohn Forte } 47345039663SJohn Forte break; 47445039663SJohn Forte case TE_DELETE: 47545039663SJohn Forte /* TE_DELETE is handled in tgt_sm_event_dispatch() */ 47645039663SJohn Forte break; 47745039663SJohn Forte case TE_STMF_ONLINE_REQ: 47845039663SJohn Forte case TE_STMF_OFFLINE_REQ: 47945039663SJohn Forte /* 48045039663SJohn Forte * We can't complete STMF's request since we are busy going 48145039663SJohn Forte * online (waiting for acknowlegement from STMF) 48245039663SJohn Forte */ 48345039663SJohn Forte scs.st_completion_status = STMF_INVALID_ARG; 48445039663SJohn Forte scs.st_additional_info = NULL; 48545039663SJohn Forte (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ? 48645039663SJohn Forte STMF_CMD_LPORT_ONLINE_COMPLETE : 48745039663SJohn Forte STMF_CMD_LPORT_OFFLINE_COMPLETE, 48845039663SJohn Forte tgt->target_stmf_lport, &scs); 48945039663SJohn Forte break; 49045039663SJohn Forte case TE_STMF_OFFLINE_COMPLETE_ACK: 49145039663SJohn Forte /* Ignore */ 49245039663SJohn Forte break; 49345039663SJohn Forte default: 49445039663SJohn Forte ASSERT(0); 49545039663SJohn Forte } 49645039663SJohn Forte } 49745039663SJohn Forte 49845039663SJohn Forte 49945039663SJohn Forte static void 50045039663SJohn Forte tgt_sm_stmf_online(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 50145039663SJohn Forte { 50245039663SJohn Forte stmf_change_status_t scs; 50345039663SJohn Forte 50445039663SJohn Forte switch (ctx->te_ctx_event) { 50545039663SJohn Forte case TE_DELETE: 50645039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_DELETING_NEED_OFFLINE); 50745039663SJohn Forte break; 50845039663SJohn Forte case TE_STMF_OFFLINE_REQ: 50945039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_OFFLINING); 51045039663SJohn Forte break; 51145039663SJohn Forte case TE_STMF_ONLINE_REQ: 51245039663SJohn Forte /* Already online */ 51345039663SJohn Forte scs.st_completion_status = STMF_ALREADY; 51445039663SJohn Forte scs.st_additional_info = NULL; 51545039663SJohn Forte (void) stmf_ctl(STMF_CMD_LPORT_ONLINE_COMPLETE, 51645039663SJohn Forte tgt->target_stmf_lport, &scs); 51745039663SJohn Forte break; 51845039663SJohn Forte case TE_STMF_ONLINE_COMPLETE_ACK: 51945039663SJohn Forte case TE_STMF_OFFLINE_COMPLETE_ACK: 52045039663SJohn Forte /* Ignore */ 52145039663SJohn Forte break; 52245039663SJohn Forte default: 52345039663SJohn Forte ASSERT(0); 52445039663SJohn Forte } 52545039663SJohn Forte } 52645039663SJohn Forte 52745039663SJohn Forte 52845039663SJohn Forte static void 52945039663SJohn Forte tgt_sm_deleting_need_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 53045039663SJohn Forte { 53145039663SJohn Forte stmf_change_status_t scs; 53245039663SJohn Forte 53345039663SJohn Forte switch (ctx->te_ctx_event) { 53445039663SJohn Forte case TE_STMF_OFFLINE_REQ: 53545039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_OFFLINING); 53645039663SJohn Forte break; 53745039663SJohn Forte case TE_DELETE: 53845039663SJohn Forte /* TE_DELETE is handled in tgt_sm_event_dispatch() */ 53945039663SJohn Forte break; 54045039663SJohn Forte case TE_STMF_ONLINE_REQ: 54145039663SJohn Forte /* 54245039663SJohn Forte * We can't complete STMF's request since we need to be offlined 54345039663SJohn Forte */ 54445039663SJohn Forte scs.st_completion_status = STMF_INVALID_ARG; 54545039663SJohn Forte scs.st_additional_info = NULL; 54645039663SJohn Forte (void) stmf_ctl(STMF_CMD_LPORT_ONLINE_COMPLETE, 54745039663SJohn Forte tgt->target_stmf_lport, &scs); 54845039663SJohn Forte break; 54945039663SJohn Forte case TE_STMF_ONLINE_COMPLETE_ACK: 55045039663SJohn Forte case TE_STMF_OFFLINE_COMPLETE_ACK: 55145039663SJohn Forte /* Ignore */ 55245039663SJohn Forte break; 55345039663SJohn Forte default: 55445039663SJohn Forte ASSERT(0); 55545039663SJohn Forte } 55645039663SJohn Forte } 55745039663SJohn Forte 55845039663SJohn Forte 55945039663SJohn Forte static void 56045039663SJohn Forte tgt_sm_offlining(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 56145039663SJohn Forte { 56245039663SJohn Forte stmf_change_status_t scs; 56345039663SJohn Forte 56445039663SJohn Forte switch (ctx->te_ctx_event) { 56545039663SJohn Forte case TE_OFFLINE_COMPLETE: 56645039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_OFFLINE); 56745039663SJohn Forte break; 56845039663SJohn Forte case TE_DELETE: 56945039663SJohn Forte /* TE_DELETE is handled in tgt_sm_event_dispatch() */ 57045039663SJohn Forte break; 57145039663SJohn Forte case TE_STMF_ONLINE_REQ: 57245039663SJohn Forte case TE_STMF_OFFLINE_REQ: 57345039663SJohn Forte /* 57445039663SJohn Forte * We can't complete STMF's request since we are busy going 57545039663SJohn Forte * offline. 57645039663SJohn Forte */ 57745039663SJohn Forte scs.st_completion_status = STMF_INVALID_ARG; 57845039663SJohn Forte scs.st_additional_info = NULL; 57945039663SJohn Forte (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ? 58045039663SJohn Forte STMF_CMD_LPORT_ONLINE_COMPLETE : 58145039663SJohn Forte STMF_CMD_LPORT_OFFLINE_COMPLETE, 58245039663SJohn Forte tgt->target_stmf_lport, &scs); 58345039663SJohn Forte break; 58445039663SJohn Forte case TE_STMF_ONLINE_COMPLETE_ACK: 58545039663SJohn Forte case TE_STMF_OFFLINE_COMPLETE_ACK: 58645039663SJohn Forte /* Ignore */ 58745039663SJohn Forte break; 58845039663SJohn Forte default: 58945039663SJohn Forte ASSERT(0); 59045039663SJohn Forte } 59145039663SJohn Forte } 59245039663SJohn Forte 59345039663SJohn Forte 59445039663SJohn Forte static void 59545039663SJohn Forte tgt_sm_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 59645039663SJohn Forte { 59745039663SJohn Forte stmf_change_status_t scs; 59845039663SJohn Forte 59945039663SJohn Forte switch (ctx->te_ctx_event) { 60045039663SJohn Forte case TE_STMF_OFFLINE_COMPLETE_ACK: 60145039663SJohn Forte if (tgt->target_deleting) { 60245039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG); 60345039663SJohn Forte } else { 60445039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_STMF_OFFLINE); 60545039663SJohn Forte } 60645039663SJohn Forte break; 60745039663SJohn Forte case TE_DELETE: 60845039663SJohn Forte /* TE_DELETE is handled in tgt_sm_event_dispatch() */ 60945039663SJohn Forte break; 61045039663SJohn Forte case TE_STMF_ONLINE_REQ: 61145039663SJohn Forte case TE_STMF_OFFLINE_REQ: 61245039663SJohn Forte /* 61345039663SJohn Forte * We can't complete STMF's request since we are busy going 61445039663SJohn Forte * offline. 61545039663SJohn Forte */ 61645039663SJohn Forte scs.st_completion_status = STMF_INVALID_ARG; 61745039663SJohn Forte scs.st_additional_info = NULL; 61845039663SJohn Forte (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ? 61945039663SJohn Forte STMF_CMD_LPORT_ONLINE_COMPLETE : 62045039663SJohn Forte STMF_CMD_LPORT_OFFLINE_COMPLETE, 62145039663SJohn Forte tgt->target_stmf_lport, &scs); 62245039663SJohn Forte break; 62345039663SJohn Forte case TE_STMF_ONLINE_COMPLETE_ACK: 62445039663SJohn Forte /* Ignore */ 62545039663SJohn Forte break; 62645039663SJohn Forte default: 62745039663SJohn Forte ASSERT(0); 62845039663SJohn Forte } 62945039663SJohn Forte } 63045039663SJohn Forte 63145039663SJohn Forte 63245039663SJohn Forte static void 63345039663SJohn Forte tgt_sm_stmf_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 63445039663SJohn Forte { 63545039663SJohn Forte stmf_change_status_t scs; 63645039663SJohn Forte 63745039663SJohn Forte switch (ctx->te_ctx_event) { 63845039663SJohn Forte case TE_STMF_ONLINE_REQ: 63945039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_ONLINING); 64045039663SJohn Forte break; 64145039663SJohn Forte case TE_DELETE: 64245039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG); 64345039663SJohn Forte break; 64445039663SJohn Forte case TE_STMF_OFFLINE_REQ: 64545039663SJohn Forte /* Already offline */ 64645039663SJohn Forte scs.st_completion_status = STMF_ALREADY; 64745039663SJohn Forte scs.st_additional_info = NULL; 64845039663SJohn Forte (void) stmf_ctl(STMF_CMD_LPORT_OFFLINE_COMPLETE, 64945039663SJohn Forte tgt->target_stmf_lport, &scs); 65045039663SJohn Forte break; 65145039663SJohn Forte case TE_STMF_ONLINE_COMPLETE_ACK: 65245039663SJohn Forte case TE_STMF_OFFLINE_COMPLETE_ACK: 65345039663SJohn Forte /* Ignore */ 65445039663SJohn Forte break; 65545039663SJohn Forte default: 65645039663SJohn Forte ASSERT(0); 65745039663SJohn Forte } 65845039663SJohn Forte } 65945039663SJohn Forte 66045039663SJohn Forte 66145039663SJohn Forte static void 66245039663SJohn Forte tgt_sm_deleting_stmf_dereg(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 66345039663SJohn Forte { 66445039663SJohn Forte stmf_change_status_t scs; 66545039663SJohn Forte 66645039663SJohn Forte /* Terminal state, no events */ 66745039663SJohn Forte switch (ctx->te_ctx_event) { 66845039663SJohn Forte case TE_STMF_ONLINE_REQ: 66945039663SJohn Forte case TE_STMF_OFFLINE_REQ: 67045039663SJohn Forte /* 67145039663SJohn Forte * We can't complete STMF's request since we are being deleted 67245039663SJohn Forte */ 67345039663SJohn Forte scs.st_completion_status = STMF_INVALID_ARG; 67445039663SJohn Forte scs.st_additional_info = NULL; 67545039663SJohn Forte (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ? 67645039663SJohn Forte STMF_CMD_LPORT_ONLINE_COMPLETE : 67745039663SJohn Forte STMF_CMD_LPORT_OFFLINE_COMPLETE, 67845039663SJohn Forte tgt->target_stmf_lport, &scs); 67945039663SJohn Forte break; 68045039663SJohn Forte case TE_STMF_ONLINE_COMPLETE_ACK: 68145039663SJohn Forte case TE_STMF_OFFLINE_COMPLETE_ACK: 68245039663SJohn Forte /* Ignore */ 68345039663SJohn Forte break; 68445039663SJohn Forte case TE_STMF_DEREG_SUCCESS: 68545039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_DELETING); 68645039663SJohn Forte break; 68745039663SJohn Forte case TE_STMF_DEREG_FAIL: 68845039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG_FAIL); 68945039663SJohn Forte break; 69045039663SJohn Forte default: 69145039663SJohn Forte ASSERT(0); 69245039663SJohn Forte } 69345039663SJohn Forte } 69445039663SJohn Forte 69545039663SJohn Forte static void 69645039663SJohn Forte tgt_sm_deleting_stmf_dereg_fail(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 69745039663SJohn Forte { 69845039663SJohn Forte stmf_change_status_t scs; 69945039663SJohn Forte 70045039663SJohn Forte /* Terminal state, no events */ 70145039663SJohn Forte switch (ctx->te_ctx_event) { 70245039663SJohn Forte case TE_STMF_ONLINE_REQ: 70345039663SJohn Forte case TE_STMF_OFFLINE_REQ: 70445039663SJohn Forte /* 70545039663SJohn Forte * We can't complete STMF's request since we are being deleted 70645039663SJohn Forte */ 70745039663SJohn Forte scs.st_completion_status = STMF_INVALID_ARG; 70845039663SJohn Forte scs.st_additional_info = NULL; 70945039663SJohn Forte (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ? 71045039663SJohn Forte STMF_CMD_LPORT_ONLINE_COMPLETE : 71145039663SJohn Forte STMF_CMD_LPORT_OFFLINE_COMPLETE, 71245039663SJohn Forte tgt->target_stmf_lport, &scs); 71345039663SJohn Forte break; 71445039663SJohn Forte case TE_STMF_ONLINE_COMPLETE_ACK: 71545039663SJohn Forte case TE_STMF_OFFLINE_COMPLETE_ACK: 71645039663SJohn Forte /* Ignore */ 71745039663SJohn Forte break; 71845039663SJohn Forte case TE_STMF_DEREG_RETRY: 71945039663SJohn Forte tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG); 72045039663SJohn Forte break; 72145039663SJohn Forte default: 72245039663SJohn Forte ASSERT(0); 72345039663SJohn Forte } 72445039663SJohn Forte } 72545039663SJohn Forte 72645039663SJohn Forte static void 72745039663SJohn Forte tgt_sm_deleting(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx) 72845039663SJohn Forte { 72945039663SJohn Forte stmf_change_status_t scs; 73045039663SJohn Forte 73145039663SJohn Forte /* Terminal state, no events */ 73245039663SJohn Forte switch (ctx->te_ctx_event) { 73345039663SJohn Forte case TE_STMF_ONLINE_REQ: 73445039663SJohn Forte case TE_STMF_OFFLINE_REQ: 73545039663SJohn Forte /* 73645039663SJohn Forte * We can't complete STMF's request since we are being deleted 73745039663SJohn Forte */ 73845039663SJohn Forte scs.st_completion_status = STMF_INVALID_ARG; 73945039663SJohn Forte scs.st_additional_info = NULL; 74045039663SJohn Forte (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ? 74145039663SJohn Forte STMF_CMD_LPORT_ONLINE_COMPLETE : 74245039663SJohn Forte STMF_CMD_LPORT_OFFLINE_COMPLETE, 74345039663SJohn Forte tgt->target_stmf_lport, &scs); 74445039663SJohn Forte break; 74545039663SJohn Forte case TE_STMF_ONLINE_COMPLETE_ACK: 74645039663SJohn Forte case TE_STMF_OFFLINE_COMPLETE_ACK: 74745039663SJohn Forte /* Ignore */ 74845039663SJohn Forte break; 74945039663SJohn Forte default: 75045039663SJohn Forte ASSERT(0); 75145039663SJohn Forte } 75245039663SJohn Forte } 75345039663SJohn Forte 75445039663SJohn Forte static void 755e617f214Speter dunlap pppt_tgt_offline(pppt_tgt_t *tgt) 756e617f214Speter dunlap { 757e617f214Speter dunlap (void) taskq_dispatch(pppt_global.global_dispatch_taskq, 758e617f214Speter dunlap pppt_tgt_offline_task, tgt, KM_SLEEP); 759e617f214Speter dunlap } 760e617f214Speter dunlap 761e617f214Speter dunlap static void 762e617f214Speter dunlap pppt_tgt_offline_task(void *arg) 76345039663SJohn Forte { 76445039663SJohn Forte pppt_tgt_t *tgt = arg; 76545039663SJohn Forte pppt_sess_t *ps, *next_ps; 76645039663SJohn Forte stmf_change_status_t scs; 76745039663SJohn Forte 768e617f214Speter dunlap stmf_trace("pppt", "pppt_tgt_offline %p", (void *)tgt); 76945039663SJohn Forte 77045039663SJohn Forte PPPT_GLOBAL_LOCK(); 77145039663SJohn Forte mutex_enter(&tgt->target_mutex); 77245039663SJohn Forte for (ps = avl_first(&tgt->target_sess_list); ps != NULL; ps = next_ps) { 77345039663SJohn Forte next_ps = AVL_NEXT(&tgt->target_sess_list, ps); 77445039663SJohn Forte mutex_enter(&ps->ps_mutex); 77545039663SJohn Forte if (!ps->ps_closed) { 77645039663SJohn Forte pppt_sess_close_locked(ps); 77745039663SJohn Forte } 77845039663SJohn Forte mutex_exit(&ps->ps_mutex); 77945039663SJohn Forte } 78045039663SJohn Forte mutex_exit(&tgt->target_mutex); 78145039663SJohn Forte PPPT_GLOBAL_UNLOCK(); 78245039663SJohn Forte 78345039663SJohn Forte pppt_tgt_sm_event(tgt, TE_OFFLINE_COMPLETE); 78445039663SJohn Forte 78545039663SJohn Forte scs.st_completion_status = STMF_SUCCESS; 78645039663SJohn Forte scs.st_additional_info = NULL; 78745039663SJohn Forte (void) stmf_ctl(STMF_CMD_LPORT_OFFLINE_COMPLETE, 78845039663SJohn Forte tgt->target_stmf_lport, &scs); 78945039663SJohn Forte 790e617f214Speter dunlap stmf_trace("pppt", "pppt_tgt_offline complete %p", (void *)tgt); 79145039663SJohn Forte } 79245039663SJohn Forte 79345039663SJohn Forte static void 79445039663SJohn Forte pppt_tgt_dereg_retry(void *arg) 79545039663SJohn Forte { 79645039663SJohn Forte pppt_tgt_t *tgt = arg; 79745039663SJohn Forte 79845039663SJohn Forte /* 79945039663SJohn Forte * Rather than guaranteeing the target state machine code will not 80045039663SJohn Forte * block for long periods of time (tying up this callout thread) 80145039663SJohn Forte * we will queue a task on the taskq to send the retry event. 80245039663SJohn Forte * If it fails we'll setup another timeout and try again later. 80345039663SJohn Forte */ 80445039663SJohn Forte if (taskq_dispatch(pppt_global.global_dispatch_taskq, 80545039663SJohn Forte pppt_tgt_dereg_task, tgt, KM_NOSLEEP) == NULL) { 80645039663SJohn Forte /* Dispatch failed, try again later */ 80745039663SJohn Forte (void) timeout(pppt_tgt_dereg_retry, tgt, 80845039663SJohn Forte drv_usectohz(TGT_DEREG_RETRY_SECONDS * 1000000)); 80945039663SJohn Forte } 81045039663SJohn Forte } 81145039663SJohn Forte 81245039663SJohn Forte static void 81345039663SJohn Forte pppt_tgt_dereg_task(void *arg) 81445039663SJohn Forte { 81545039663SJohn Forte pppt_tgt_t *tgt = arg; 81645039663SJohn Forte 81745039663SJohn Forte pppt_tgt_sm_event(tgt, TE_STMF_DEREG_RETRY); 81845039663SJohn Forte } 81945039663SJohn Forte 82045039663SJohn Forte /*ARGSUSED*/ 82145039663SJohn Forte static void 82245039663SJohn Forte tgt_sm_new_state(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx, 82345039663SJohn Forte pppt_tgt_state_t new_state) 82445039663SJohn Forte { 82545039663SJohn Forte stmf_local_port_t *lport = tgt->target_stmf_lport; 82645039663SJohn Forte stmf_change_status_t scs; 82745039663SJohn Forte stmf_state_change_info_t sci; 82845039663SJohn Forte stmf_status_t stmfrc; 82945039663SJohn Forte 83045039663SJohn Forte scs.st_completion_status = STMF_SUCCESS; 83145039663SJohn Forte scs.st_additional_info = NULL; 83245039663SJohn Forte 83345039663SJohn Forte /* 83445039663SJohn Forte * Validate new state 83545039663SJohn Forte */ 83645039663SJohn Forte ASSERT(new_state != TS_UNDEFINED); 83745039663SJohn Forte ASSERT3U(new_state, <, TS_MAX_STATE); 83845039663SJohn Forte 83945039663SJohn Forte new_state = (new_state < TS_MAX_STATE) ? 84045039663SJohn Forte new_state : TS_UNDEFINED; 84145039663SJohn Forte 842e617f214Speter dunlap stmf_trace("pppt", "pppt_target_state_change: " 843e617f214Speter dunlap "tgt %p, %s(%d) --> %s(%d)\n", 84445039663SJohn Forte (void *) tgt, pppt_ts_name[tgt->target_state], tgt->target_state, 84545039663SJohn Forte pppt_ts_name[new_state], new_state); 84645039663SJohn Forte DTRACE_PROBE3(pppt__target__state__change, 84745039663SJohn Forte pppt_tgt_t *, tgt, tgt_event_ctx_t *, ctx, 84845039663SJohn Forte pppt_tgt_state_t, new_state); 84945039663SJohn Forte 85045039663SJohn Forte mutex_enter(&tgt->target_mutex); 85145039663SJohn Forte tgt->target_last_state = tgt->target_state; 85245039663SJohn Forte tgt->target_state = new_state; 85345039663SJohn Forte cv_signal(&tgt->target_cv); 85445039663SJohn Forte mutex_exit(&tgt->target_mutex); 85545039663SJohn Forte 85645039663SJohn Forte switch (tgt->target_state) { 85745039663SJohn Forte case TS_ONLINING: 85845039663SJohn Forte pppt_tgt_sm_event(tgt, TE_ONLINE_SUCCESS); 85945039663SJohn Forte 86045039663SJohn Forte /* 86145039663SJohn Forte * Let STMF know the how the online operation completed. 86245039663SJohn Forte * STMF will respond with an acknowlege later 86345039663SJohn Forte */ 86445039663SJohn Forte (void) stmf_ctl(STMF_CMD_LPORT_ONLINE_COMPLETE, lport, &scs); 86545039663SJohn Forte break; 86645039663SJohn Forte case TS_ONLINE: 86745039663SJohn Forte break; 86845039663SJohn Forte case TS_STMF_ONLINE: 86945039663SJohn Forte break; 87045039663SJohn Forte case TS_DELETING_NEED_OFFLINE: 87145039663SJohn Forte sci.st_rflags = STMF_RFLAG_STAY_OFFLINED; 87245039663SJohn Forte sci.st_additional_info = "Offline for delete"; 87345039663SJohn Forte (void) stmf_ctl(STMF_CMD_LPORT_OFFLINE, lport, &sci); 87445039663SJohn Forte break; 87545039663SJohn Forte case TS_OFFLINING: 87645039663SJohn Forte /* Async callback generates completion event */ 87745039663SJohn Forte pppt_tgt_offline(tgt); 87845039663SJohn Forte break; 87945039663SJohn Forte case TS_OFFLINE: 88045039663SJohn Forte break; 88145039663SJohn Forte case TS_STMF_OFFLINE: 88245039663SJohn Forte break; 88345039663SJohn Forte case TS_DELETING_STMF_DEREG: 88445039663SJohn Forte stmfrc = stmf_deregister_local_port(tgt->target_stmf_lport); 88545039663SJohn Forte if (stmfrc == STMF_SUCCESS) { 88645039663SJohn Forte pppt_tgt_sm_event(tgt, TE_STMF_DEREG_SUCCESS); 88745039663SJohn Forte } else { 88845039663SJohn Forte pppt_tgt_sm_event(tgt, TE_STMF_DEREG_FAIL); 88945039663SJohn Forte } 89045039663SJohn Forte break; 89145039663SJohn Forte case TS_DELETING_STMF_DEREG_FAIL: 89245039663SJohn Forte /* Retry dereg in 1 second */ 89345039663SJohn Forte (void) timeout(pppt_tgt_dereg_retry, tgt, 89445039663SJohn Forte drv_usectohz(TGT_DEREG_RETRY_SECONDS * 1000000)); 89545039663SJohn Forte break; 89645039663SJohn Forte case TS_DELETING: 89745039663SJohn Forte break; 89845039663SJohn Forte default: 89945039663SJohn Forte ASSERT(0); 90045039663SJohn Forte } 90145039663SJohn Forte } 902