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 /*
224558d122SViswanathan 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
444558d122SViswanathan 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
pppt_tgt_sm_ctl(stmf_local_port_t * lport,int cmd,void * arg)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 *
pppt_tgt_create(stmf_ic_reg_port_msg_t * reg_port,stmf_status_t * msg_errcode)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
pppt_tgt_destroy(pppt_tgt_t * tgt)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 *
pppt_tgt_lookup(scsi_devid_desc_t * tgt_devid)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 *
pppt_tgt_lookup_locked(scsi_devid_desc_t * tgt_devid)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
pppt_tgt_async_delete(pppt_tgt_t * tgt)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
pppt_tgt_avl_compare(const void * void_tgt1,const void * void_tgt2)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
pppt_tgt_sm_event(pppt_tgt_t * tgt,pppt_tgt_event_t event)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
tgt_sm_event_locked(pppt_tgt_t * tgt,pppt_tgt_event_t event)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
tgt_sm_event_dispatch(pppt_tgt_t * tgt,tgt_event_ctx_t * ctx)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
tgt_sm_created(pppt_tgt_t * tgt,tgt_event_ctx_t * ctx)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
tgt_sm_onlining(pppt_tgt_t * tgt,tgt_event_ctx_t * ctx)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
tgt_sm_online(pppt_tgt_t * tgt,tgt_event_ctx_t * ctx)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
tgt_sm_stmf_online(pppt_tgt_t * tgt,tgt_event_ctx_t * ctx)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
tgt_sm_deleting_need_offline(pppt_tgt_t * tgt,tgt_event_ctx_t * ctx)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
tgt_sm_offlining(pppt_tgt_t * tgt,tgt_event_ctx_t * ctx)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
tgt_sm_offline(pppt_tgt_t * tgt,tgt_event_ctx_t * ctx)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
tgt_sm_stmf_offline(pppt_tgt_t * tgt,tgt_event_ctx_t * ctx)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
tgt_sm_deleting_stmf_dereg(pppt_tgt_t * tgt,tgt_event_ctx_t * ctx)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
tgt_sm_deleting_stmf_dereg_fail(pppt_tgt_t * tgt,tgt_event_ctx_t * ctx)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
tgt_sm_deleting(pppt_tgt_t * tgt,tgt_event_ctx_t * ctx)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
pppt_tgt_offline(pppt_tgt_t * tgt)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
pppt_tgt_offline_task(void * arg)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
pppt_tgt_dereg_retry(void * arg)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,
805*fc8ae2ecSToomas Soome pppt_tgt_dereg_task, tgt, KM_NOSLEEP) == TASKQID_INVALID) {
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
pppt_tgt_dereg_task(void * arg)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
tgt_sm_new_state(pppt_tgt_t * tgt,tgt_event_ctx_t * ctx,pppt_tgt_state_t new_state)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