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