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