1a6d42e7dSPeter Dunlap /*
2a6d42e7dSPeter Dunlap  * CDDL HEADER START
3a6d42e7dSPeter Dunlap  *
4a6d42e7dSPeter Dunlap  * The contents of this file are subject to the terms of the
5a6d42e7dSPeter Dunlap  * Common Development and Distribution License (the "License").
6a6d42e7dSPeter Dunlap  * You may not use this file except in compliance with the License.
7a6d42e7dSPeter Dunlap  *
8a6d42e7dSPeter Dunlap  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9a6d42e7dSPeter Dunlap  * or http://www.opensolaris.org/os/licensing.
10a6d42e7dSPeter Dunlap  * See the License for the specific language governing permissions
11a6d42e7dSPeter Dunlap  * and limitations under the License.
12a6d42e7dSPeter Dunlap  *
13a6d42e7dSPeter Dunlap  * When distributing Covered Code, include this CDDL HEADER in each
14a6d42e7dSPeter Dunlap  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15a6d42e7dSPeter Dunlap  * If applicable, add the following below this CDDL HEADER, with the
16a6d42e7dSPeter Dunlap  * fields enclosed by brackets "[]" replaced with your own identifying
17a6d42e7dSPeter Dunlap  * information: Portions Copyright [yyyy] [name of copyright owner]
18a6d42e7dSPeter Dunlap  *
19a6d42e7dSPeter Dunlap  * CDDL HEADER END
20a6d42e7dSPeter Dunlap  */
21a6d42e7dSPeter Dunlap 
22a6d42e7dSPeter Dunlap /*
23d618d68dSPriya Krishnan  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
2457ff5e7eSJeff Biseda  * Copyright (c) 2013 by Delphix. All rights reserved.
2561dfa509SRick McNeal  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
26*5fe3b092SMike Gerdts  * Copyright 2020 Joyent, Inc.
27a6d42e7dSPeter Dunlap  */
28a6d42e7dSPeter Dunlap 
29a6d42e7dSPeter Dunlap #include <sys/cpuvar.h>
30a6d42e7dSPeter Dunlap #include <sys/ddi.h>
31a6d42e7dSPeter Dunlap #include <sys/sunddi.h>
32a6d42e7dSPeter Dunlap #include <sys/modctl.h>
33a6d42e7dSPeter Dunlap #include <sys/socket.h>
34a6d42e7dSPeter Dunlap #include <sys/strsubr.h>
35a6d42e7dSPeter Dunlap #include <sys/note.h>
36a6d42e7dSPeter Dunlap #include <sys/sdt.h>
37a6d42e7dSPeter Dunlap 
38a6d42e7dSPeter Dunlap #define	IDM_CONN_SM_STRINGS
3930e7468fSPeter Dunlap #define	IDM_CN_NOTIFY_STRINGS
40a6d42e7dSPeter Dunlap #include <sys/idm/idm.h>
41a6d42e7dSPeter Dunlap 
42a6d42e7dSPeter Dunlap boolean_t	idm_sm_logging = B_FALSE;
43a6d42e7dSPeter Dunlap 
44a6d42e7dSPeter Dunlap extern idm_global_t	idm; /* Global state */
45a6d42e7dSPeter Dunlap 
46a6d42e7dSPeter Dunlap static void
47a6d42e7dSPeter Dunlap idm_conn_event_handler(void *event_ctx_opaque);
48a6d42e7dSPeter Dunlap 
49a6d42e7dSPeter Dunlap static void
50a6d42e7dSPeter Dunlap idm_state_s1_free(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
51a6d42e7dSPeter Dunlap 
52a6d42e7dSPeter Dunlap static void
53a6d42e7dSPeter Dunlap idm_state_s2_xpt_wait(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
54a6d42e7dSPeter Dunlap 
55a6d42e7dSPeter Dunlap static void
56a6d42e7dSPeter Dunlap idm_state_s3_xpt_up(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
57a6d42e7dSPeter Dunlap 
58a6d42e7dSPeter Dunlap static void
59a6d42e7dSPeter Dunlap idm_state_s4_in_login(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
60a6d42e7dSPeter Dunlap 
61a6d42e7dSPeter Dunlap static void
62a6d42e7dSPeter Dunlap idm_state_s5_logged_in(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
63a6d42e7dSPeter Dunlap 
64a6d42e7dSPeter Dunlap static void
65a6d42e7dSPeter Dunlap idm_state_s6_in_logout(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
66a6d42e7dSPeter Dunlap 
67a6d42e7dSPeter Dunlap static void
68a6d42e7dSPeter Dunlap idm_logout_req_timeout(void *arg);
69a6d42e7dSPeter Dunlap 
70a6d42e7dSPeter Dunlap static void
71a6d42e7dSPeter Dunlap idm_state_s7_logout_req(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
72a6d42e7dSPeter Dunlap 
73a6d42e7dSPeter Dunlap static void
74a6d42e7dSPeter Dunlap idm_state_s8_cleanup(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
75a6d42e7dSPeter Dunlap 
76a6d42e7dSPeter Dunlap static void
77a6d42e7dSPeter Dunlap idm_state_s9_init_error(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
78a6d42e7dSPeter Dunlap 
79e42a0851Speter dunlap static void
80e42a0851Speter dunlap idm_state_s9a_rejected(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
81e42a0851Speter dunlap 
82e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States static void
83e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done_cb(idm_pdu_t *pdu,
84e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States     idm_status_t status);
85e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 
86e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States static void
87e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done(idm_conn_t *ic,
88e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States     idm_conn_event_ctx_t *event_ctx);
89e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 
90a6d42e7dSPeter Dunlap static void
91a6d42e7dSPeter Dunlap idm_state_s10_in_cleanup(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
92a6d42e7dSPeter Dunlap 
93a6d42e7dSPeter Dunlap static void
94a6d42e7dSPeter Dunlap idm_state_s11_complete(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
95a6d42e7dSPeter Dunlap 
96a6d42e7dSPeter Dunlap static void
97a6d42e7dSPeter Dunlap idm_state_s12_enable_dm(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
98a6d42e7dSPeter Dunlap 
99a6d42e7dSPeter Dunlap static void
100a6d42e7dSPeter Dunlap idm_update_state(idm_conn_t *ic, idm_conn_state_t new_state,
101a6d42e7dSPeter Dunlap     idm_conn_event_ctx_t *event_ctx);
102a6d42e7dSPeter Dunlap 
103a6d42e7dSPeter Dunlap static void
104a6d42e7dSPeter Dunlap idm_conn_unref(void *ic_void);
105a6d42e7dSPeter Dunlap 
106e42a0851Speter dunlap static void
107e42a0851Speter dunlap idm_conn_reject_unref(void *ic_void);
108e42a0851Speter dunlap 
109a6d42e7dSPeter Dunlap static idm_pdu_event_action_t
110a6d42e7dSPeter Dunlap idm_conn_sm_validate_pdu(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx,
111a6d42e7dSPeter Dunlap     idm_pdu_t *pdu);
112a6d42e7dSPeter Dunlap 
113a6d42e7dSPeter Dunlap static idm_status_t
114a6d42e7dSPeter Dunlap idm_ffp_enable(idm_conn_t *ic);
115a6d42e7dSPeter Dunlap 
116a6d42e7dSPeter Dunlap static void
117a6d42e7dSPeter Dunlap idm_ffp_disable(idm_conn_t *ic, idm_ffp_disable_t disable_type);
118a6d42e7dSPeter Dunlap 
119a6d42e7dSPeter Dunlap static void
120a6d42e7dSPeter Dunlap idm_initial_login_actions(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
121a6d42e7dSPeter Dunlap 
122a6d42e7dSPeter Dunlap static void
123a6d42e7dSPeter Dunlap idm_login_success_actions(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx);
124a6d42e7dSPeter Dunlap 
125a6d42e7dSPeter Dunlap idm_status_t
idm_conn_sm_init(idm_conn_t * ic)126a6d42e7dSPeter Dunlap idm_conn_sm_init(idm_conn_t *ic)
127a6d42e7dSPeter Dunlap {
128a6d42e7dSPeter Dunlap 	char taskq_name[32];
129a6d42e7dSPeter Dunlap 
130a6d42e7dSPeter Dunlap 	/*
131a6d42e7dSPeter Dunlap 	 * Caller should have assigned a unique connection ID.  Use this
132a6d42e7dSPeter Dunlap 	 * connection ID to create a unique connection name string
133a6d42e7dSPeter Dunlap 	 */
134a6d42e7dSPeter Dunlap 	ASSERT(ic->ic_internal_cid != 0);
135a6d42e7dSPeter Dunlap 	(void) snprintf(taskq_name, sizeof (taskq_name) - 1, "conn_sm%08x",
136a6d42e7dSPeter Dunlap 	    ic->ic_internal_cid);
137a6d42e7dSPeter Dunlap 
13830e7468fSPeter Dunlap 	ic->ic_state_taskq = taskq_create(taskq_name, 1, minclsyspri, 4, 16384,
139a6d42e7dSPeter Dunlap 	    TASKQ_PREPOPULATE);
140a6d42e7dSPeter Dunlap 	if (ic->ic_state_taskq == NULL) {
141a6d42e7dSPeter Dunlap 		return (IDM_STATUS_FAIL);
142a6d42e7dSPeter Dunlap 	}
143a6d42e7dSPeter Dunlap 
144a6d42e7dSPeter Dunlap 	idm_sm_audit_init(&ic->ic_state_audit);
145a6d42e7dSPeter Dunlap 	mutex_init(&ic->ic_state_mutex, NULL, MUTEX_DEFAULT, NULL);
146a6d42e7dSPeter Dunlap 	cv_init(&ic->ic_state_cv, NULL, CV_DEFAULT, NULL);
147a6d42e7dSPeter Dunlap 
148a6d42e7dSPeter Dunlap 	ic->ic_state = CS_S1_FREE;
149a6d42e7dSPeter Dunlap 	ic->ic_last_state = CS_S1_FREE;
150a6d42e7dSPeter Dunlap 
151a6d42e7dSPeter Dunlap 	return (IDM_STATUS_SUCCESS);
152a6d42e7dSPeter Dunlap }
153a6d42e7dSPeter Dunlap 
154a6d42e7dSPeter Dunlap void
idm_conn_sm_fini(idm_conn_t * ic)155a6d42e7dSPeter Dunlap idm_conn_sm_fini(idm_conn_t *ic)
156a6d42e7dSPeter Dunlap {
1571050fd6dSJames Moore 
1581050fd6dSJames Moore 	/*
1591050fd6dSJames Moore 	 * The connection may only be partially created. If there
1601050fd6dSJames Moore 	 * is no taskq, then the connection SM was not initialized.
1611050fd6dSJames Moore 	 */
1621050fd6dSJames Moore 	if (ic->ic_state_taskq == NULL) {
1631050fd6dSJames Moore 		return;
1641050fd6dSJames Moore 	}
1651050fd6dSJames Moore 
166a6d42e7dSPeter Dunlap 	taskq_destroy(ic->ic_state_taskq);
167a6d42e7dSPeter Dunlap 
168a6d42e7dSPeter Dunlap 	cv_destroy(&ic->ic_state_cv);
169a6d42e7dSPeter Dunlap 	/*
170a6d42e7dSPeter Dunlap 	 * The thread that generated the event that got us here may still
171a6d42e7dSPeter Dunlap 	 * hold the ic_state_mutex. Once it is released we can safely
172a6d42e7dSPeter Dunlap 	 * destroy it since there is no way to locate the object now.
173a6d42e7dSPeter Dunlap 	 */
174a6d42e7dSPeter Dunlap 	mutex_enter(&ic->ic_state_mutex);
175ff9de394SRick McNeal 	IDM_SM_TIMER_CLEAR(ic);
176a6d42e7dSPeter Dunlap 	mutex_destroy(&ic->ic_state_mutex);
177a6d42e7dSPeter Dunlap }
178a6d42e7dSPeter Dunlap 
179a6d42e7dSPeter Dunlap void
idm_conn_event(idm_conn_t * ic,idm_conn_event_t event,uintptr_t event_info)180a6d42e7dSPeter Dunlap idm_conn_event(idm_conn_t *ic, idm_conn_event_t event, uintptr_t event_info)
181a6d42e7dSPeter Dunlap {
182a6d42e7dSPeter Dunlap 	mutex_enter(&ic->ic_state_mutex);
183a6d42e7dSPeter Dunlap 	idm_conn_event_locked(ic, event, event_info, CT_NONE);
184a6d42e7dSPeter Dunlap 	mutex_exit(&ic->ic_state_mutex);
185a6d42e7dSPeter Dunlap }
186a6d42e7dSPeter Dunlap 
18730e7468fSPeter Dunlap 
188a6d42e7dSPeter Dunlap idm_status_t
idm_conn_reinstate_event(idm_conn_t * old_ic,idm_conn_t * new_ic)189a6d42e7dSPeter Dunlap idm_conn_reinstate_event(idm_conn_t *old_ic, idm_conn_t *new_ic)
190a6d42e7dSPeter Dunlap {
191a6d42e7dSPeter Dunlap 	int result;
192a6d42e7dSPeter Dunlap 
193a6d42e7dSPeter Dunlap 	mutex_enter(&old_ic->ic_state_mutex);
194a6d42e7dSPeter Dunlap 	if (((old_ic->ic_conn_type == CONN_TYPE_INI) &&
195a6d42e7dSPeter Dunlap 	    (old_ic->ic_state != CS_S8_CLEANUP)) ||
196a6d42e7dSPeter Dunlap 	    ((old_ic->ic_conn_type == CONN_TYPE_TGT) &&
197a6d42e7dSPeter Dunlap 	    (old_ic->ic_state < CS_S5_LOGGED_IN))) {
198a6d42e7dSPeter Dunlap 		result = IDM_STATUS_FAIL;
199a6d42e7dSPeter Dunlap 	} else {
200a6d42e7dSPeter Dunlap 		result = IDM_STATUS_SUCCESS;
201a6d42e7dSPeter Dunlap 		new_ic->ic_reinstate_conn = old_ic;
202a6d42e7dSPeter Dunlap 		idm_conn_event_locked(new_ic->ic_reinstate_conn,
203a6d42e7dSPeter Dunlap 		    CE_CONN_REINSTATE, (uintptr_t)new_ic, CT_NONE);
204a6d42e7dSPeter Dunlap 	}
205a6d42e7dSPeter Dunlap 	mutex_exit(&old_ic->ic_state_mutex);
206a6d42e7dSPeter Dunlap 
207a6d42e7dSPeter Dunlap 	return (result);
208a6d42e7dSPeter Dunlap }
209a6d42e7dSPeter Dunlap 
210a6d42e7dSPeter Dunlap void
idm_conn_tx_pdu_event(idm_conn_t * ic,idm_conn_event_t event,uintptr_t event_info)211a6d42e7dSPeter Dunlap idm_conn_tx_pdu_event(idm_conn_t *ic, idm_conn_event_t event,
212a6d42e7dSPeter Dunlap     uintptr_t event_info)
213a6d42e7dSPeter Dunlap {
214a6d42e7dSPeter Dunlap 	ASSERT(mutex_owned(&ic->ic_state_mutex));
215a6d42e7dSPeter Dunlap 	ic->ic_pdu_events++;
216a6d42e7dSPeter Dunlap 	idm_conn_event_locked(ic, event, event_info, CT_TX_PDU);
217a6d42e7dSPeter Dunlap }
218a6d42e7dSPeter Dunlap 
219a6d42e7dSPeter Dunlap void
idm_conn_rx_pdu_event(idm_conn_t * ic,idm_conn_event_t event,uintptr_t event_info)220a6d42e7dSPeter Dunlap idm_conn_rx_pdu_event(idm_conn_t *ic, idm_conn_event_t event,
221a6d42e7dSPeter Dunlap     uintptr_t event_info)
222a6d42e7dSPeter Dunlap {
223a6d42e7dSPeter Dunlap 	ASSERT(mutex_owned(&ic->ic_state_mutex));
224a6d42e7dSPeter Dunlap 	ic->ic_pdu_events++;
225a6d42e7dSPeter Dunlap 	idm_conn_event_locked(ic, event, event_info, CT_RX_PDU);
226a6d42e7dSPeter Dunlap }
227a6d42e7dSPeter Dunlap 
22830e7468fSPeter Dunlap void
idm_conn_event_locked(idm_conn_t * ic,idm_conn_event_t event,uintptr_t event_info,idm_pdu_event_type_t pdu_event_type)229a6d42e7dSPeter Dunlap idm_conn_event_locked(idm_conn_t *ic, idm_conn_event_t event,
230a6d42e7dSPeter Dunlap     uintptr_t event_info, idm_pdu_event_type_t pdu_event_type)
231a6d42e7dSPeter Dunlap {
232a6d42e7dSPeter Dunlap 	idm_conn_event_ctx_t	*event_ctx;
233a6d42e7dSPeter Dunlap 
23492adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	ASSERT(mutex_owned(&ic->ic_state_mutex));
23592adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States 
236a6d42e7dSPeter Dunlap 	idm_sm_audit_event(&ic->ic_state_audit, SAS_IDM_CONN,
237a6d42e7dSPeter Dunlap 	    (int)ic->ic_state, (int)event, event_info);
238a6d42e7dSPeter Dunlap 
239a6d42e7dSPeter Dunlap 	/*
240a6d42e7dSPeter Dunlap 	 * It's very difficult to prevent a few straggling events
241a6d42e7dSPeter Dunlap 	 * at the end.  For example idm_sorx_thread will generate
242a6d42e7dSPeter Dunlap 	 * a CE_TRANSPORT_FAIL event when it exits.  Rather than
243a6d42e7dSPeter Dunlap 	 * push complicated restrictions all over the code to
244a6d42e7dSPeter Dunlap 	 * prevent this we will simply drop the events (and in
245a6d42e7dSPeter Dunlap 	 * the case of PDU events release them appropriately)
246a6d42e7dSPeter Dunlap 	 * since they are irrelevant once we are in a terminal state.
247a6d42e7dSPeter Dunlap 	 * Of course those threads need to have appropriate holds on
248a6d42e7dSPeter Dunlap 	 * the connection otherwise it might disappear.
249a6d42e7dSPeter Dunlap 	 */
250a6d42e7dSPeter Dunlap 	if ((ic->ic_state == CS_S9_INIT_ERROR) ||
251e42a0851Speter dunlap 	    (ic->ic_state == CS_S9A_REJECTED) ||
252a6d42e7dSPeter Dunlap 	    (ic->ic_state == CS_S11_COMPLETE)) {
253a6d42e7dSPeter Dunlap 		if ((pdu_event_type == CT_TX_PDU) ||
254a6d42e7dSPeter Dunlap 		    (pdu_event_type == CT_RX_PDU)) {
255a6d42e7dSPeter Dunlap 			ic->ic_pdu_events--;
256a6d42e7dSPeter Dunlap 			idm_pdu_complete((idm_pdu_t *)event_info,
257a6d42e7dSPeter Dunlap 			    IDM_STATUS_SUCCESS);
258a6d42e7dSPeter Dunlap 		}
259a6d42e7dSPeter Dunlap 		IDM_SM_LOG(CE_NOTE, "*** Dropping event %s (%d) because of"
260a6d42e7dSPeter Dunlap 		    "state %s (%d)",
261a6d42e7dSPeter Dunlap 		    idm_ce_name[event], event,
262a6d42e7dSPeter Dunlap 		    idm_cs_name[ic->ic_state], ic->ic_state);
263a6d42e7dSPeter Dunlap 		return;
264a6d42e7dSPeter Dunlap 	}
265a6d42e7dSPeter Dunlap 
266a6d42e7dSPeter Dunlap 	/*
267a6d42e7dSPeter Dunlap 	 * Normal event handling
268a6d42e7dSPeter Dunlap 	 */
269a6d42e7dSPeter Dunlap 	idm_conn_hold(ic);
270a6d42e7dSPeter Dunlap 
271a6d42e7dSPeter Dunlap 	event_ctx = kmem_zalloc(sizeof (*event_ctx), KM_SLEEP);
272a6d42e7dSPeter Dunlap 	event_ctx->iec_ic = ic;
273a6d42e7dSPeter Dunlap 	event_ctx->iec_event = event;
274a6d42e7dSPeter Dunlap 	event_ctx->iec_info = event_info;
275a6d42e7dSPeter Dunlap 	event_ctx->iec_pdu_event_type = pdu_event_type;
276a6d42e7dSPeter Dunlap 
277a6d42e7dSPeter Dunlap 	(void) taskq_dispatch(ic->ic_state_taskq, &idm_conn_event_handler,
278a6d42e7dSPeter Dunlap 	    event_ctx, TQ_SLEEP);
279a6d42e7dSPeter Dunlap }
280a6d42e7dSPeter Dunlap 
281a6d42e7dSPeter Dunlap static void
idm_conn_event_handler(void * event_ctx_opaque)282a6d42e7dSPeter Dunlap idm_conn_event_handler(void *event_ctx_opaque)
283a6d42e7dSPeter Dunlap {
284a6d42e7dSPeter Dunlap 	idm_conn_event_ctx_t *event_ctx = event_ctx_opaque;
285a6d42e7dSPeter Dunlap 	idm_conn_t *ic = event_ctx->iec_ic;
286a6d42e7dSPeter Dunlap 	idm_pdu_t *pdu = (idm_pdu_t *)event_ctx->iec_info;
287a6d42e7dSPeter Dunlap 	idm_pdu_event_action_t action;
288a6d42e7dSPeter Dunlap 
289a6d42e7dSPeter Dunlap 	IDM_SM_LOG(CE_NOTE, "idm_conn_event_handler: conn %p event %s(%d)",
290a6d42e7dSPeter Dunlap 	    (void *)ic, idm_ce_name[event_ctx->iec_event],
291a6d42e7dSPeter Dunlap 	    event_ctx->iec_event);
292a6d42e7dSPeter Dunlap 	DTRACE_PROBE2(conn__event,
29330e7468fSPeter Dunlap 	    idm_conn_t *, ic, idm_conn_event_ctx_t *, event_ctx);
294a6d42e7dSPeter Dunlap 
295a6d42e7dSPeter Dunlap 	/*
296a6d42e7dSPeter Dunlap 	 * Validate event
297a6d42e7dSPeter Dunlap 	 */
298a6d42e7dSPeter Dunlap 	ASSERT(event_ctx->iec_event != CE_UNDEFINED);
299a6d42e7dSPeter Dunlap 	ASSERT3U(event_ctx->iec_event, <, CE_MAX_EVENT);
300a6d42e7dSPeter Dunlap 
301a6d42e7dSPeter Dunlap 	/*
302a6d42e7dSPeter Dunlap 	 * Validate current state
303a6d42e7dSPeter Dunlap 	 */
304a6d42e7dSPeter Dunlap 	ASSERT(ic->ic_state != CS_S0_UNDEFINED);
305a6d42e7dSPeter Dunlap 	ASSERT3U(ic->ic_state, <, CS_MAX_STATE);
306a6d42e7dSPeter Dunlap 
307a6d42e7dSPeter Dunlap 	/*
308a6d42e7dSPeter Dunlap 	 * Validate PDU-related events against the current state.  If a PDU
309a6d42e7dSPeter Dunlap 	 * is not allowed in the current state we change the event to a
310a6d42e7dSPeter Dunlap 	 * protocol error.  This simplifies the state-specific event handlers.
311a6d42e7dSPeter Dunlap 	 * For example the CS_S2_XPT_WAIT state only needs to handle the
312a6d42e7dSPeter Dunlap 	 * CE_TX_PROTOCOL_ERROR and CE_RX_PROTOCOL_ERROR events since
313a6d42e7dSPeter Dunlap 	 * no PDU's can be transmitted or received in that state.
314a6d42e7dSPeter Dunlap 	 */
31530e7468fSPeter Dunlap 	event_ctx->iec_pdu_forwarded = B_FALSE;
316a6d42e7dSPeter Dunlap 	if (event_ctx->iec_pdu_event_type != CT_NONE) {
317a6d42e7dSPeter Dunlap 		ASSERT(pdu != NULL);
318a6d42e7dSPeter Dunlap 		action = idm_conn_sm_validate_pdu(ic, event_ctx, pdu);
319a6d42e7dSPeter Dunlap 
320a6d42e7dSPeter Dunlap 		switch (action) {
321a6d42e7dSPeter Dunlap 		case CA_TX_PROTOCOL_ERROR:
322a6d42e7dSPeter Dunlap 			/*
323a6d42e7dSPeter Dunlap 			 * Change event and forward the PDU
324a6d42e7dSPeter Dunlap 			 */
325a6d42e7dSPeter Dunlap 			event_ctx->iec_event = CE_TX_PROTOCOL_ERROR;
326a6d42e7dSPeter Dunlap 			break;
327a6d42e7dSPeter Dunlap 		case CA_RX_PROTOCOL_ERROR:
328a6d42e7dSPeter Dunlap 			/*
329a6d42e7dSPeter Dunlap 			 * Change event and forward the PDU.
330a6d42e7dSPeter Dunlap 			 */
331a6d42e7dSPeter Dunlap 			event_ctx->iec_event = CE_RX_PROTOCOL_ERROR;
332a6d42e7dSPeter Dunlap 			break;
333a6d42e7dSPeter Dunlap 		case CA_FORWARD:
334a6d42e7dSPeter Dunlap 			/*
335a6d42e7dSPeter Dunlap 			 * Let the state-specific event handlers take
336a6d42e7dSPeter Dunlap 			 * care of it.
337a6d42e7dSPeter Dunlap 			 */
338a6d42e7dSPeter Dunlap 			break;
339a6d42e7dSPeter Dunlap 		case CA_DROP:
340a6d42e7dSPeter Dunlap 			/*
341a6d42e7dSPeter Dunlap 			 * It never even happened
342a6d42e7dSPeter Dunlap 			 */
343a6d42e7dSPeter Dunlap 			IDM_SM_LOG(CE_NOTE, "*** drop PDU %p", (void *) pdu);
344a6d42e7dSPeter Dunlap 			idm_pdu_complete(pdu, IDM_STATUS_FAIL);
345*5fe3b092SMike Gerdts 			event_ctx->iec_info = (uintptr_t)NULL;
346a6d42e7dSPeter Dunlap 			break;
347a6d42e7dSPeter Dunlap 		default:
348a6d42e7dSPeter Dunlap 			ASSERT(0);
349a6d42e7dSPeter Dunlap 			break;
350a6d42e7dSPeter Dunlap 		}
351a6d42e7dSPeter Dunlap 	}
352a6d42e7dSPeter Dunlap 
353a6d42e7dSPeter Dunlap 	switch (ic->ic_state) {
354a6d42e7dSPeter Dunlap 	case CS_S1_FREE:
355a6d42e7dSPeter Dunlap 		idm_state_s1_free(ic, event_ctx);
356a6d42e7dSPeter Dunlap 		break;
357a6d42e7dSPeter Dunlap 	case CS_S2_XPT_WAIT:
358a6d42e7dSPeter Dunlap 		idm_state_s2_xpt_wait(ic, event_ctx);
359a6d42e7dSPeter Dunlap 		break;
360a6d42e7dSPeter Dunlap 	case CS_S3_XPT_UP:
361a6d42e7dSPeter Dunlap 		idm_state_s3_xpt_up(ic, event_ctx);
362a6d42e7dSPeter Dunlap 		break;
363a6d42e7dSPeter Dunlap 	case CS_S4_IN_LOGIN:
364a6d42e7dSPeter Dunlap 		idm_state_s4_in_login(ic, event_ctx);
365a6d42e7dSPeter Dunlap 		break;
366a6d42e7dSPeter Dunlap 	case CS_S5_LOGGED_IN:
367a6d42e7dSPeter Dunlap 		idm_state_s5_logged_in(ic, event_ctx);
368a6d42e7dSPeter Dunlap 		break;
369a6d42e7dSPeter Dunlap 	case CS_S6_IN_LOGOUT:
370a6d42e7dSPeter Dunlap 		idm_state_s6_in_logout(ic, event_ctx);
371a6d42e7dSPeter Dunlap 		break;
372a6d42e7dSPeter Dunlap 	case CS_S7_LOGOUT_REQ:
373a6d42e7dSPeter Dunlap 		idm_state_s7_logout_req(ic, event_ctx);
374a6d42e7dSPeter Dunlap 		break;
375a6d42e7dSPeter Dunlap 	case CS_S8_CLEANUP:
376a6d42e7dSPeter Dunlap 		idm_state_s8_cleanup(ic, event_ctx);
377a6d42e7dSPeter Dunlap 		break;
378e42a0851Speter dunlap 	case CS_S9A_REJECTED:
379e42a0851Speter dunlap 		idm_state_s9a_rejected(ic, event_ctx);
380e42a0851Speter dunlap 		break;
381e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	case CS_S9B_WAIT_SND_DONE:
382e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		idm_state_s9b_wait_snd_done(ic, event_ctx);
383e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		break;
384a6d42e7dSPeter Dunlap 	case CS_S9_INIT_ERROR:
385a6d42e7dSPeter Dunlap 		idm_state_s9_init_error(ic, event_ctx);
386a6d42e7dSPeter Dunlap 		break;
387a6d42e7dSPeter Dunlap 	case CS_S10_IN_CLEANUP:
388a6d42e7dSPeter Dunlap 		idm_state_s10_in_cleanup(ic, event_ctx);
389a6d42e7dSPeter Dunlap 		break;
390a6d42e7dSPeter Dunlap 	case CS_S11_COMPLETE:
391a6d42e7dSPeter Dunlap 		idm_state_s11_complete(ic, event_ctx);
392a6d42e7dSPeter Dunlap 		break;
393a6d42e7dSPeter Dunlap 	case CS_S12_ENABLE_DM:
394a6d42e7dSPeter Dunlap 		idm_state_s12_enable_dm(ic, event_ctx);
395a6d42e7dSPeter Dunlap 		break;
396a6d42e7dSPeter Dunlap 	default:
397a6d42e7dSPeter Dunlap 		ASSERT(0);
398a6d42e7dSPeter Dunlap 		break;
399a6d42e7dSPeter Dunlap 	}
400a6d42e7dSPeter Dunlap 
401a6d42e7dSPeter Dunlap 	/*
402a6d42e7dSPeter Dunlap 	 * Now that we've updated the state machine, if this was
403a6d42e7dSPeter Dunlap 	 * a PDU-related event take the appropriate action on the PDU
404a6d42e7dSPeter Dunlap 	 * (transmit it, forward it to the clients RX callback, drop
405a6d42e7dSPeter Dunlap 	 * it, etc).
406a6d42e7dSPeter Dunlap 	 */
407a6d42e7dSPeter Dunlap 	if (event_ctx->iec_pdu_event_type != CT_NONE) {
408a6d42e7dSPeter Dunlap 		switch (action) {
409a6d42e7dSPeter Dunlap 		case CA_TX_PROTOCOL_ERROR:
410a6d42e7dSPeter Dunlap 			idm_pdu_tx_protocol_error(ic, pdu);
411a6d42e7dSPeter Dunlap 			break;
412a6d42e7dSPeter Dunlap 		case CA_RX_PROTOCOL_ERROR:
413a6d42e7dSPeter Dunlap 			idm_pdu_rx_protocol_error(ic, pdu);
414a6d42e7dSPeter Dunlap 			break;
415a6d42e7dSPeter Dunlap 		case CA_FORWARD:
41630e7468fSPeter Dunlap 			if (!event_ctx->iec_pdu_forwarded) {
41730e7468fSPeter Dunlap 				if (event_ctx->iec_pdu_event_type ==
41830e7468fSPeter Dunlap 				    CT_RX_PDU) {
41930e7468fSPeter Dunlap 					idm_pdu_rx_forward(ic, pdu);
42030e7468fSPeter Dunlap 				} else {
42130e7468fSPeter Dunlap 					idm_pdu_tx_forward(ic, pdu);
42230e7468fSPeter Dunlap 				}
423a6d42e7dSPeter Dunlap 			}
424a6d42e7dSPeter Dunlap 			break;
425*5fe3b092SMike Gerdts 		case CA_DROP:
426*5fe3b092SMike Gerdts 			/* Already completed above. */
427*5fe3b092SMike Gerdts 			ASSERT3P(event_ctx->iec_info, ==, NULL);
428*5fe3b092SMike Gerdts 			break;
429a6d42e7dSPeter Dunlap 		default:
430a6d42e7dSPeter Dunlap 			ASSERT(0);
431a6d42e7dSPeter Dunlap 			break;
432a6d42e7dSPeter Dunlap 		}
433a6d42e7dSPeter Dunlap 	}
434a6d42e7dSPeter Dunlap 
435a6d42e7dSPeter Dunlap 	/*
436a6d42e7dSPeter Dunlap 	 * Update outstanding PDU event count (see idm_pdu_tx for
437a6d42e7dSPeter Dunlap 	 * how this is used)
438a6d42e7dSPeter Dunlap 	 */
439a6d42e7dSPeter Dunlap 	if ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ||
440a6d42e7dSPeter Dunlap 	    (event_ctx->iec_pdu_event_type == CT_RX_PDU)) {
441a6d42e7dSPeter Dunlap 		mutex_enter(&ic->ic_state_mutex);
442a6d42e7dSPeter Dunlap 		ic->ic_pdu_events--;
443a6d42e7dSPeter Dunlap 		mutex_exit(&ic->ic_state_mutex);
444a6d42e7dSPeter Dunlap 	}
445a6d42e7dSPeter Dunlap 
446a6d42e7dSPeter Dunlap 	idm_conn_rele(ic);
447a6d42e7dSPeter Dunlap 	kmem_free(event_ctx, sizeof (*event_ctx));
448a6d42e7dSPeter Dunlap }
449a6d42e7dSPeter Dunlap 
450a6d42e7dSPeter Dunlap static void
idm_state_s1_free(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)451a6d42e7dSPeter Dunlap idm_state_s1_free(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
452a6d42e7dSPeter Dunlap {
453a6d42e7dSPeter Dunlap 	switch (event_ctx->iec_event) {
454a6d42e7dSPeter Dunlap 	case CE_CONNECT_REQ:
455a6d42e7dSPeter Dunlap 		/* T1 */
456a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S2_XPT_WAIT, event_ctx);
457a6d42e7dSPeter Dunlap 		break;
458a6d42e7dSPeter Dunlap 	case CE_CONNECT_ACCEPT:
459a6d42e7dSPeter Dunlap 		/* T3 */
460a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S3_XPT_UP, event_ctx);
461a6d42e7dSPeter Dunlap 		break;
462a6d42e7dSPeter Dunlap 	case CE_TX_PROTOCOL_ERROR:
463a6d42e7dSPeter Dunlap 	case CE_RX_PROTOCOL_ERROR:
464a6d42e7dSPeter Dunlap 		/* This should never happen */
465a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx);
466a6d42e7dSPeter Dunlap 		break;
467a6d42e7dSPeter Dunlap 	default:
468a6d42e7dSPeter Dunlap 		ASSERT(0);
469a6d42e7dSPeter Dunlap 		/*NOTREACHED*/
470a6d42e7dSPeter Dunlap 	}
471a6d42e7dSPeter Dunlap }
472a6d42e7dSPeter Dunlap 
473a6d42e7dSPeter Dunlap 
474a6d42e7dSPeter Dunlap static void
idm_state_s2_xpt_wait(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)475a6d42e7dSPeter Dunlap idm_state_s2_xpt_wait(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
476a6d42e7dSPeter Dunlap {
477a6d42e7dSPeter Dunlap 	switch (event_ctx->iec_event) {
478a6d42e7dSPeter Dunlap 	case CE_CONNECT_SUCCESS:
479a6d42e7dSPeter Dunlap 		/* T4 */
480a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S4_IN_LOGIN, event_ctx);
481a6d42e7dSPeter Dunlap 		break;
4825f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	case CE_TRANSPORT_FAIL:
483a6d42e7dSPeter Dunlap 	case CE_CONNECT_FAIL:
484a6d42e7dSPeter Dunlap 	case CE_LOGOUT_OTHER_CONN_RCV:
485a6d42e7dSPeter Dunlap 	case CE_TX_PROTOCOL_ERROR:
486a6d42e7dSPeter Dunlap 	case CE_RX_PROTOCOL_ERROR:
487a6d42e7dSPeter Dunlap 		/* T2 */
488a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx);
489a6d42e7dSPeter Dunlap 		break;
490a6d42e7dSPeter Dunlap 	default:
491a6d42e7dSPeter Dunlap 		ASSERT(0);
492a6d42e7dSPeter Dunlap 		/*NOTREACHED*/
493a6d42e7dSPeter Dunlap 	}
494a6d42e7dSPeter Dunlap }
495a6d42e7dSPeter Dunlap 
496a6d42e7dSPeter Dunlap 
497a6d42e7dSPeter Dunlap static void
idm_login_timeout(void * arg)498a6d42e7dSPeter Dunlap idm_login_timeout(void *arg)
499a6d42e7dSPeter Dunlap {
500a6d42e7dSPeter Dunlap 	idm_conn_t *ic = arg;
501a6d42e7dSPeter Dunlap 
502ff9de394SRick McNeal 	ic->ic_state_timeout = 0;
5038e718be9SToomas Soome 	idm_conn_event(ic, CE_LOGIN_TIMEOUT, (uintptr_t)NULL);
504a6d42e7dSPeter Dunlap }
505a6d42e7dSPeter Dunlap 
506a6d42e7dSPeter Dunlap static void
idm_state_s3_xpt_up(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)507a6d42e7dSPeter Dunlap idm_state_s3_xpt_up(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
508a6d42e7dSPeter Dunlap {
509a6d42e7dSPeter Dunlap 	switch (event_ctx->iec_event) {
510a6d42e7dSPeter Dunlap 	case CE_LOGIN_RCV:
511a6d42e7dSPeter Dunlap 		/* T4 */
512ff9de394SRick McNeal 		/* Keep login timeout active through S3 and into S4 */
513a6d42e7dSPeter Dunlap 		idm_initial_login_actions(ic, event_ctx);
514a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S4_IN_LOGIN, event_ctx);
515a6d42e7dSPeter Dunlap 		break;
516a6d42e7dSPeter Dunlap 	case CE_LOGIN_TIMEOUT:
517a6d42e7dSPeter Dunlap 		/*
518a6d42e7dSPeter Dunlap 		 * Don't need to cancel login timer since the timer is
519a6d42e7dSPeter Dunlap 		 * presumed to be the source of this event.
520a6d42e7dSPeter Dunlap 		 */
5218e718be9SToomas Soome 		(void) idm_notify_client(ic, CN_LOGIN_FAIL, (uintptr_t)NULL);
522a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx);
523a6d42e7dSPeter Dunlap 		break;
524a6d42e7dSPeter Dunlap 	case CE_CONNECT_REJECT:
525e42a0851Speter dunlap 		/*
526e42a0851Speter dunlap 		 * Iscsit doesn't want to hear from us again in this case.
527e42a0851Speter dunlap 		 * Since it rejected the connection it doesn't have a
528e42a0851Speter dunlap 		 * connection context to handle additional notifications.
529e42a0851Speter dunlap 		 * IDM needs to just clean things up on its own.
530e42a0851Speter dunlap 		 */
531ff9de394SRick McNeal 		IDM_SM_TIMER_CLEAR(ic);
532e42a0851Speter dunlap 		idm_update_state(ic, CS_S9A_REJECTED, event_ctx);
533e42a0851Speter dunlap 		break;
534a6d42e7dSPeter Dunlap 	case CE_CONNECT_FAIL:
535a6d42e7dSPeter Dunlap 	case CE_TRANSPORT_FAIL:
536a6d42e7dSPeter Dunlap 	case CE_LOGOUT_OTHER_CONN_SND:
537a6d42e7dSPeter Dunlap 		/* T6 */
538ff9de394SRick McNeal 		IDM_SM_TIMER_CLEAR(ic);
5398e718be9SToomas Soome 		(void) idm_notify_client(ic, CN_LOGIN_FAIL, (uintptr_t)NULL);
540a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx);
541a6d42e7dSPeter Dunlap 		break;
542a6d42e7dSPeter Dunlap 	case CE_TX_PROTOCOL_ERROR:
543a6d42e7dSPeter Dunlap 	case CE_RX_PROTOCOL_ERROR:
544a6d42e7dSPeter Dunlap 		/* Don't care */
545a6d42e7dSPeter Dunlap 		break;
546a6d42e7dSPeter Dunlap 	default:
547a6d42e7dSPeter Dunlap 		ASSERT(0);
548a6d42e7dSPeter Dunlap 		/*NOTREACHED*/
549a6d42e7dSPeter Dunlap 	}
550a6d42e7dSPeter Dunlap }
551a6d42e7dSPeter Dunlap 
552a6d42e7dSPeter Dunlap static void
idm_state_s4_in_login(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)553a6d42e7dSPeter Dunlap idm_state_s4_in_login(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
554a6d42e7dSPeter Dunlap {
555a6d42e7dSPeter Dunlap 	idm_pdu_t *pdu;
556a6d42e7dSPeter Dunlap 
557a6d42e7dSPeter Dunlap 	/*
558a6d42e7dSPeter Dunlap 	 * Login timer should no longer be active after leaving this
559a6d42e7dSPeter Dunlap 	 * state.
560a6d42e7dSPeter Dunlap 	 */
561a6d42e7dSPeter Dunlap 	switch (event_ctx->iec_event) {
562a6d42e7dSPeter Dunlap 	case CE_LOGIN_SUCCESS_RCV:
563a6d42e7dSPeter Dunlap 	case CE_LOGIN_SUCCESS_SND:
564e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		ASSERT(ic->ic_client_callback == NULL);
565e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 
566ff9de394SRick McNeal 		IDM_SM_TIMER_CLEAR(ic);
567a6d42e7dSPeter Dunlap 		idm_login_success_actions(ic, event_ctx);
568a6d42e7dSPeter Dunlap 		if (ic->ic_rdma_extensions) {
569a6d42e7dSPeter Dunlap 			/* T19 */
570a6d42e7dSPeter Dunlap 			idm_update_state(ic, CS_S12_ENABLE_DM, event_ctx);
571a6d42e7dSPeter Dunlap 		} else {
572a6d42e7dSPeter Dunlap 			/* T5 */
573a6d42e7dSPeter Dunlap 			idm_update_state(ic, CS_S5_LOGGED_IN, event_ctx);
574a6d42e7dSPeter Dunlap 		}
575a6d42e7dSPeter Dunlap 		break;
576a6d42e7dSPeter Dunlap 	case CE_LOGIN_TIMEOUT:
577a6d42e7dSPeter Dunlap 		/* T7 */
5788e718be9SToomas Soome 		(void) idm_notify_client(ic, CN_LOGIN_FAIL, (uintptr_t)NULL);
579a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx);
580a6d42e7dSPeter Dunlap 		break;
581a6d42e7dSPeter Dunlap 	case CE_LOGIN_FAIL_SND:
582a6d42e7dSPeter Dunlap 		/*
583a6d42e7dSPeter Dunlap 		 * Allow the logout response pdu to be sent and defer
584e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		 * the state machine cleanup until the completion callback.
585a6d42e7dSPeter Dunlap 		 * Only 1 level or callback interposition is allowed.
586a6d42e7dSPeter Dunlap 		 */
587ff9de394SRick McNeal 		IDM_SM_TIMER_CLEAR(ic);
588a6d42e7dSPeter Dunlap 		pdu = (idm_pdu_t *)event_ctx->iec_info;
589a6d42e7dSPeter Dunlap 		ASSERT(ic->ic_client_callback == NULL);
590a6d42e7dSPeter Dunlap 		ic->ic_client_callback = pdu->isp_callback;
591a6d42e7dSPeter Dunlap 		pdu->isp_callback =
592e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		    idm_state_s9b_wait_snd_done_cb;
593e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		idm_update_state(ic, CS_S9B_WAIT_SND_DONE,
594e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		    event_ctx);
595a6d42e7dSPeter Dunlap 		break;
596a6d42e7dSPeter Dunlap 	case CE_LOGIN_FAIL_RCV:
597e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		ASSERT(ic->ic_client_callback == NULL);
59830e7468fSPeter Dunlap 		/*
59930e7468fSPeter Dunlap 		 * Need to deliver this PDU to the initiator now because after
60030e7468fSPeter Dunlap 		 * we update the state to CS_S9_INIT_ERROR the initiator will
60130e7468fSPeter Dunlap 		 * no longer be in an appropriate state.
60230e7468fSPeter Dunlap 		 */
60330e7468fSPeter Dunlap 		event_ctx->iec_pdu_forwarded = B_TRUE;
60430e7468fSPeter Dunlap 		pdu = (idm_pdu_t *)event_ctx->iec_info;
60530e7468fSPeter Dunlap 		idm_pdu_rx_forward(ic, pdu);
60630e7468fSPeter Dunlap 		/* FALLTHROUGH */
607a6d42e7dSPeter Dunlap 	case CE_TRANSPORT_FAIL:
608a6d42e7dSPeter Dunlap 	case CE_LOGOUT_OTHER_CONN_SND:
609a6d42e7dSPeter Dunlap 	case CE_LOGOUT_OTHER_CONN_RCV:
610a6d42e7dSPeter Dunlap 		/* T7 */
611ff9de394SRick McNeal 		IDM_SM_TIMER_CLEAR(ic);
6128e718be9SToomas Soome 		(void) idm_notify_client(ic, CN_LOGIN_FAIL, (uintptr_t)NULL);
613a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx);
614a6d42e7dSPeter Dunlap 		break;
61547715e7fSPriya Krishnan 	case CE_LOGOUT_SESSION_SUCCESS:
61647715e7fSPriya Krishnan 		/*
61747715e7fSPriya Krishnan 		 * T8
61847715e7fSPriya Krishnan 		 * A session reinstatement request can be received while a
61947715e7fSPriya Krishnan 		 * session is active and a login is in process. The iSCSI
62047715e7fSPriya Krishnan 		 * connections are shut down by a CE_LOGOUT_SESSION_SUCCESS
62147715e7fSPriya Krishnan 		 * event sent from the session to the IDM layer.
62247715e7fSPriya Krishnan 		 */
623ff9de394SRick McNeal 		IDM_SM_TIMER_CLEAR(ic);
62447715e7fSPriya Krishnan 		if (IDM_CONN_ISTGT(ic)) {
62547715e7fSPriya Krishnan 			ic->ic_transport_ops->it_tgt_conn_disconnect(ic);
62647715e7fSPriya Krishnan 		} else {
62747715e7fSPriya Krishnan 			ic->ic_transport_ops->it_ini_conn_disconnect(ic);
62847715e7fSPriya Krishnan 		}
62947715e7fSPriya Krishnan 		idm_update_state(ic, CS_S11_COMPLETE, event_ctx);
63047715e7fSPriya Krishnan 		break;
63147715e7fSPriya Krishnan 
632a6d42e7dSPeter Dunlap 	case CE_LOGIN_SND:
633e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		ASSERT(ic->ic_client_callback == NULL);
634a6d42e7dSPeter Dunlap 		/*
635a6d42e7dSPeter Dunlap 		 * Initiator connections will see initial login PDU
636a6d42e7dSPeter Dunlap 		 * in this state.  Target connections see initial
637a6d42e7dSPeter Dunlap 		 * login PDU in "xpt up" state.
638a6d42e7dSPeter Dunlap 		 */
639a6d42e7dSPeter Dunlap 		mutex_enter(&ic->ic_state_mutex);
640a6d42e7dSPeter Dunlap 		if (!(ic->ic_state_flags & CF_INITIAL_LOGIN)) {
641a6d42e7dSPeter Dunlap 			idm_initial_login_actions(ic, event_ctx);
642a6d42e7dSPeter Dunlap 		}
643a6d42e7dSPeter Dunlap 		mutex_exit(&ic->ic_state_mutex);
644a6d42e7dSPeter Dunlap 		break;
645a6d42e7dSPeter Dunlap 	case CE_MISC_TX:
646a6d42e7dSPeter Dunlap 	case CE_MISC_RX:
647a6d42e7dSPeter Dunlap 	case CE_LOGIN_RCV:
648a6d42e7dSPeter Dunlap 	case CE_TX_PROTOCOL_ERROR:
649a6d42e7dSPeter Dunlap 	case CE_RX_PROTOCOL_ERROR:
650a6d42e7dSPeter Dunlap 		/* Don't care */
651a6d42e7dSPeter Dunlap 		break;
652a6d42e7dSPeter Dunlap 	default:
653a6d42e7dSPeter Dunlap 		ASSERT(0);
654a6d42e7dSPeter Dunlap 		/*NOTREACHED*/
655a6d42e7dSPeter Dunlap 	}
656a6d42e7dSPeter Dunlap }
657a6d42e7dSPeter Dunlap 
658a6d42e7dSPeter Dunlap 
659a6d42e7dSPeter Dunlap static void
idm_state_s5_logged_in(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)660a6d42e7dSPeter Dunlap idm_state_s5_logged_in(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
661a6d42e7dSPeter Dunlap {
662a6d42e7dSPeter Dunlap 	switch (event_ctx->iec_event) {
663d618d68dSPriya Krishnan 	case CE_MISC_RX:
664d618d68dSPriya Krishnan 		/* MC/S: when removing the non-leading connection */
665a6d42e7dSPeter Dunlap 	case CE_LOGOUT_THIS_CONN_RCV:
666a6d42e7dSPeter Dunlap 	case CE_LOGOUT_THIS_CONN_SND:
667a6d42e7dSPeter Dunlap 	case CE_LOGOUT_OTHER_CONN_RCV:
668a6d42e7dSPeter Dunlap 	case CE_LOGOUT_OTHER_CONN_SND:
669a6d42e7dSPeter Dunlap 		/* T9 */
670a6d42e7dSPeter Dunlap 		idm_ffp_disable(ic, FD_CONN_LOGOUT); /* Explicit logout */
671a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S6_IN_LOGOUT, event_ctx);
672a6d42e7dSPeter Dunlap 		break;
673a6d42e7dSPeter Dunlap 	case CE_LOGOUT_SESSION_RCV:
674a6d42e7dSPeter Dunlap 	case CE_LOGOUT_SESSION_SND:
675a6d42e7dSPeter Dunlap 		/* T9 */
676a6d42e7dSPeter Dunlap 		idm_ffp_disable(ic, FD_SESS_LOGOUT); /* Explicit logout */
677a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S6_IN_LOGOUT, event_ctx);
678a6d42e7dSPeter Dunlap 		break;
679a6d42e7dSPeter Dunlap 	case CE_LOGOUT_SESSION_SUCCESS:
680a6d42e7dSPeter Dunlap 		/* T8 */
681a6d42e7dSPeter Dunlap 		idm_ffp_disable(ic, FD_SESS_LOGOUT); /* Explicit logout */
682a6d42e7dSPeter Dunlap 
683a6d42e7dSPeter Dunlap 		/* Close connection */
684a6d42e7dSPeter Dunlap 		if (IDM_CONN_ISTGT(ic)) {
685a6d42e7dSPeter Dunlap 			ic->ic_transport_ops->it_tgt_conn_disconnect(ic);
686a6d42e7dSPeter Dunlap 		} else {
687a6d42e7dSPeter Dunlap 			ic->ic_transport_ops->it_ini_conn_disconnect(ic);
688a6d42e7dSPeter Dunlap 		}
689a6d42e7dSPeter Dunlap 
690a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S11_COMPLETE, event_ctx);
691a6d42e7dSPeter Dunlap 		break;
692a6d42e7dSPeter Dunlap 	case CE_ASYNC_LOGOUT_RCV:
693a6d42e7dSPeter Dunlap 	case CE_ASYNC_LOGOUT_SND:
694a6d42e7dSPeter Dunlap 		/* T11 */
695a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S7_LOGOUT_REQ, event_ctx);
696a6d42e7dSPeter Dunlap 		break;
697a6d42e7dSPeter Dunlap 	case CE_TRANSPORT_FAIL:
698a6d42e7dSPeter Dunlap 	case CE_ASYNC_DROP_CONN_RCV:
699a6d42e7dSPeter Dunlap 	case CE_ASYNC_DROP_CONN_SND:
700a6d42e7dSPeter Dunlap 	case CE_ASYNC_DROP_ALL_CONN_RCV:
701a6d42e7dSPeter Dunlap 	case CE_ASYNC_DROP_ALL_CONN_SND:
702a6d42e7dSPeter Dunlap 		/* T15 */
703a6d42e7dSPeter Dunlap 		idm_ffp_disable(ic, FD_CONN_FAIL); /* Implicit logout */
704a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S8_CLEANUP, event_ctx);
705a6d42e7dSPeter Dunlap 		break;
706a6d42e7dSPeter Dunlap 	case CE_MISC_TX:
707a6d42e7dSPeter Dunlap 	case CE_TX_PROTOCOL_ERROR:
708a6d42e7dSPeter Dunlap 	case CE_RX_PROTOCOL_ERROR:
70992adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	case CE_LOGIN_TIMEOUT:
710a6d42e7dSPeter Dunlap 		/* Don't care */
711a6d42e7dSPeter Dunlap 		break;
712a6d42e7dSPeter Dunlap 	default:
713a6d42e7dSPeter Dunlap 		ASSERT(0);
714a6d42e7dSPeter Dunlap 	}
715a6d42e7dSPeter Dunlap }
716a6d42e7dSPeter Dunlap 
717a6d42e7dSPeter Dunlap static void
idm_state_s6_in_logout_success_snd_done(idm_pdu_t * pdu,idm_status_t status)718a6d42e7dSPeter Dunlap idm_state_s6_in_logout_success_snd_done(idm_pdu_t *pdu, idm_status_t status)
719a6d42e7dSPeter Dunlap {
720a6d42e7dSPeter Dunlap 	idm_conn_t		*ic = pdu->isp_ic;
721a6d42e7dSPeter Dunlap 
722a6d42e7dSPeter Dunlap 	/*
723a6d42e7dSPeter Dunlap 	 * This pdu callback can be invoked by the tx thread,
724a6d42e7dSPeter Dunlap 	 * so run the disconnect code from another thread.
725a6d42e7dSPeter Dunlap 	 */
726a6d42e7dSPeter Dunlap 	pdu->isp_status = status;
727a6d42e7dSPeter Dunlap 	idm_conn_event(ic, CE_LOGOUT_SUCCESS_SND_DONE, (uintptr_t)pdu);
728a6d42e7dSPeter Dunlap }
729a6d42e7dSPeter Dunlap 
730a6d42e7dSPeter Dunlap static void
idm_state_s6_in_logout_fail_snd_done(idm_pdu_t * pdu,idm_status_t status)731a6d42e7dSPeter Dunlap idm_state_s6_in_logout_fail_snd_done(idm_pdu_t *pdu, idm_status_t status)
732a6d42e7dSPeter Dunlap {
733a6d42e7dSPeter Dunlap 	idm_conn_t		*ic = pdu->isp_ic;
734a6d42e7dSPeter Dunlap 
735a6d42e7dSPeter Dunlap 	/*
736a6d42e7dSPeter Dunlap 	 * This pdu callback can be invoked by the tx thread,
737a6d42e7dSPeter Dunlap 	 * so run the disconnect code from another thread.
738a6d42e7dSPeter Dunlap 	 */
739a6d42e7dSPeter Dunlap 	pdu->isp_status = status;
740a6d42e7dSPeter Dunlap 	idm_conn_event(ic, CE_LOGOUT_FAIL_SND_DONE, (uintptr_t)pdu);
741a6d42e7dSPeter Dunlap }
742a6d42e7dSPeter Dunlap 
743a6d42e7dSPeter Dunlap static void
idm_state_s6_in_logout(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)744a6d42e7dSPeter Dunlap idm_state_s6_in_logout(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
745a6d42e7dSPeter Dunlap {
746a6d42e7dSPeter Dunlap 	idm_pdu_t *pdu;
747a6d42e7dSPeter Dunlap 
748a6d42e7dSPeter Dunlap 	switch (event_ctx->iec_event) {
749a6d42e7dSPeter Dunlap 	case CE_LOGOUT_SUCCESS_SND_DONE:
750a6d42e7dSPeter Dunlap 		pdu = (idm_pdu_t *)event_ctx->iec_info;
751a6d42e7dSPeter Dunlap 
752a6d42e7dSPeter Dunlap 		/* Close connection (if it's not already closed) */
753a6d42e7dSPeter Dunlap 		ASSERT(IDM_CONN_ISTGT(ic));
754a6d42e7dSPeter Dunlap 		ic->ic_transport_ops->it_tgt_conn_disconnect(ic);
755a6d42e7dSPeter Dunlap 
756a6d42e7dSPeter Dunlap 		/* restore client callback */
757a6d42e7dSPeter Dunlap 		pdu->isp_callback =  ic->ic_client_callback;
758a6d42e7dSPeter Dunlap 		ic->ic_client_callback = NULL;
759a6d42e7dSPeter Dunlap 		idm_pdu_complete(pdu, pdu->isp_status);
760a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S11_COMPLETE, event_ctx);
761a6d42e7dSPeter Dunlap 		break;
762a6d42e7dSPeter Dunlap 	case CE_LOGOUT_FAIL_SND_DONE:
763a6d42e7dSPeter Dunlap 		pdu = (idm_pdu_t *)event_ctx->iec_info;
764a6d42e7dSPeter Dunlap 		/* restore client callback */
765a6d42e7dSPeter Dunlap 		pdu->isp_callback =  ic->ic_client_callback;
766a6d42e7dSPeter Dunlap 		ic->ic_client_callback = NULL;
767a6d42e7dSPeter Dunlap 		idm_pdu_complete(pdu, pdu->isp_status);
768a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S8_CLEANUP, event_ctx);
769a6d42e7dSPeter Dunlap 		break;
770a6d42e7dSPeter Dunlap 	case CE_LOGOUT_SUCCESS_SND:
771a6d42e7dSPeter Dunlap 	case CE_LOGOUT_FAIL_SND:
772a6d42e7dSPeter Dunlap 		/*
773a6d42e7dSPeter Dunlap 		 * Allow the logout response pdu to be sent and defer
774a6d42e7dSPeter Dunlap 		 * the state machine update until the completion callback.
775a6d42e7dSPeter Dunlap 		 * Only 1 level or callback interposition is allowed.
776a6d42e7dSPeter Dunlap 		 */
777a6d42e7dSPeter Dunlap 		pdu = (idm_pdu_t *)event_ctx->iec_info;
778a6d42e7dSPeter Dunlap 		ASSERT(ic->ic_client_callback == NULL);
779a6d42e7dSPeter Dunlap 		ic->ic_client_callback = pdu->isp_callback;
780a6d42e7dSPeter Dunlap 		if (event_ctx->iec_event == CE_LOGOUT_SUCCESS_SND) {
781a6d42e7dSPeter Dunlap 			pdu->isp_callback =
782a6d42e7dSPeter Dunlap 			    idm_state_s6_in_logout_success_snd_done;
783a6d42e7dSPeter Dunlap 		} else {
784a6d42e7dSPeter Dunlap 			pdu->isp_callback =
785a6d42e7dSPeter Dunlap 			    idm_state_s6_in_logout_fail_snd_done;
786a6d42e7dSPeter Dunlap 		}
787a6d42e7dSPeter Dunlap 		break;
788a6d42e7dSPeter Dunlap 	case CE_LOGOUT_SUCCESS_RCV:
78930e7468fSPeter Dunlap 		/*
79030e7468fSPeter Dunlap 		 * Need to deliver this PDU to the initiator now because after
79130e7468fSPeter Dunlap 		 * we update the state to CS_S11_COMPLETE the initiator will
79230e7468fSPeter Dunlap 		 * no longer be in an appropriate state.
79330e7468fSPeter Dunlap 		 */
79430e7468fSPeter Dunlap 		event_ctx->iec_pdu_forwarded = B_TRUE;
79530e7468fSPeter Dunlap 		pdu = (idm_pdu_t *)event_ctx->iec_info;
79630e7468fSPeter Dunlap 		idm_pdu_rx_forward(ic, pdu);
79730e7468fSPeter Dunlap 		/* FALLTHROUGH */
798a6d42e7dSPeter Dunlap 	case CE_LOGOUT_SESSION_SUCCESS:
799a6d42e7dSPeter Dunlap 		/* T13 */
800a6d42e7dSPeter Dunlap 
801a6d42e7dSPeter Dunlap 		/* Close connection (if it's not already closed) */
802a6d42e7dSPeter Dunlap 		if (IDM_CONN_ISTGT(ic)) {
803a6d42e7dSPeter Dunlap 			ic->ic_transport_ops->it_tgt_conn_disconnect(ic);
804a6d42e7dSPeter Dunlap 		} else {
805a6d42e7dSPeter Dunlap 			ic->ic_transport_ops->it_ini_conn_disconnect(ic);
806a6d42e7dSPeter Dunlap 		}
807a6d42e7dSPeter Dunlap 
808a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S11_COMPLETE, event_ctx);
809a6d42e7dSPeter Dunlap 		break;
810a6d42e7dSPeter Dunlap 	case CE_ASYNC_LOGOUT_RCV:
811a6d42e7dSPeter Dunlap 		/* T14 Do nothing */
812a6d42e7dSPeter Dunlap 		break;
813a6d42e7dSPeter Dunlap 	case CE_TRANSPORT_FAIL:
814a6d42e7dSPeter Dunlap 	case CE_ASYNC_DROP_CONN_RCV:
815a6d42e7dSPeter Dunlap 	case CE_ASYNC_DROP_CONN_SND:
816a6d42e7dSPeter Dunlap 	case CE_ASYNC_DROP_ALL_CONN_RCV:
817a6d42e7dSPeter Dunlap 	case CE_ASYNC_DROP_ALL_CONN_SND:
818a6d42e7dSPeter Dunlap 	case CE_LOGOUT_FAIL_RCV:
819a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S8_CLEANUP, event_ctx);
820a6d42e7dSPeter Dunlap 		break;
821a6d42e7dSPeter Dunlap 	case CE_TX_PROTOCOL_ERROR:
822a6d42e7dSPeter Dunlap 	case CE_RX_PROTOCOL_ERROR:
823a6d42e7dSPeter Dunlap 	case CE_MISC_TX:
824a6d42e7dSPeter Dunlap 	case CE_MISC_RX:
82592adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	case CE_LOGIN_TIMEOUT:
826a6d42e7dSPeter Dunlap 		/* Don't care */
827a6d42e7dSPeter Dunlap 		break;
828a6d42e7dSPeter Dunlap 	default:
829a6d42e7dSPeter Dunlap 		ASSERT(0);
830a6d42e7dSPeter Dunlap 	}
831a6d42e7dSPeter Dunlap }
832a6d42e7dSPeter Dunlap 
833a6d42e7dSPeter Dunlap 
834a6d42e7dSPeter Dunlap static void
idm_logout_req_timeout(void * arg)835a6d42e7dSPeter Dunlap idm_logout_req_timeout(void *arg)
836a6d42e7dSPeter Dunlap {
837a6d42e7dSPeter Dunlap 	idm_conn_t *ic = arg;
838a6d42e7dSPeter Dunlap 
839ff9de394SRick McNeal 	ic->ic_state_timeout = 0;
8408e718be9SToomas Soome 	idm_conn_event(ic, CE_LOGOUT_TIMEOUT, (uintptr_t)NULL);
841a6d42e7dSPeter Dunlap }
842a6d42e7dSPeter Dunlap 
843a6d42e7dSPeter Dunlap static void
idm_state_s7_logout_req(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)844a6d42e7dSPeter Dunlap idm_state_s7_logout_req(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
845a6d42e7dSPeter Dunlap {
846a6d42e7dSPeter Dunlap 	/* Must cancel logout timer before leaving this state */
847a6d42e7dSPeter Dunlap 	switch (event_ctx->iec_event) {
848a6d42e7dSPeter Dunlap 	case CE_LOGOUT_THIS_CONN_RCV:
849a6d42e7dSPeter Dunlap 	case CE_LOGOUT_THIS_CONN_SND:
850a6d42e7dSPeter Dunlap 	case CE_LOGOUT_OTHER_CONN_RCV:
851a6d42e7dSPeter Dunlap 	case CE_LOGOUT_OTHER_CONN_SND:
852a6d42e7dSPeter Dunlap 		/* T10 */
853a6d42e7dSPeter Dunlap 		if (IDM_CONN_ISTGT(ic)) {
854ff9de394SRick McNeal 			IDM_SM_TIMER_CLEAR(ic);
855a6d42e7dSPeter Dunlap 		}
856a6d42e7dSPeter Dunlap 		idm_ffp_disable(ic, FD_CONN_LOGOUT); /* Explicit logout */
857a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S6_IN_LOGOUT, event_ctx);
858a6d42e7dSPeter Dunlap 		break;
859a6d42e7dSPeter Dunlap 	case CE_LOGOUT_SESSION_RCV:
860a6d42e7dSPeter Dunlap 	case CE_LOGOUT_SESSION_SND:
861a6d42e7dSPeter Dunlap 		/* T10 */
862a6d42e7dSPeter Dunlap 		if (IDM_CONN_ISTGT(ic)) {
863ff9de394SRick McNeal 			IDM_SM_TIMER_CLEAR(ic);
864a6d42e7dSPeter Dunlap 		}
865a6d42e7dSPeter Dunlap 		idm_ffp_disable(ic, FD_SESS_LOGOUT); /* Explicit logout */
866a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S6_IN_LOGOUT, event_ctx);
867a6d42e7dSPeter Dunlap 		break;
868a6d42e7dSPeter Dunlap 	case CE_ASYNC_LOGOUT_RCV:
869a6d42e7dSPeter Dunlap 	case CE_ASYNC_LOGOUT_SND:
870a6d42e7dSPeter Dunlap 		/* T12 Do nothing */
871a6d42e7dSPeter Dunlap 		break;
872a6d42e7dSPeter Dunlap 	case CE_TRANSPORT_FAIL:
873a6d42e7dSPeter Dunlap 	case CE_ASYNC_DROP_CONN_RCV:
874a6d42e7dSPeter Dunlap 	case CE_ASYNC_DROP_CONN_SND:
875a6d42e7dSPeter Dunlap 	case CE_ASYNC_DROP_ALL_CONN_RCV:
876a6d42e7dSPeter Dunlap 	case CE_ASYNC_DROP_ALL_CONN_SND:
877a6d42e7dSPeter Dunlap 		/* T16 */
878a6d42e7dSPeter Dunlap 		if (IDM_CONN_ISTGT(ic)) {
879ff9de394SRick McNeal 			IDM_SM_TIMER_CLEAR(ic);
880a6d42e7dSPeter Dunlap 		}
881a6d42e7dSPeter Dunlap 		/* FALLTHROUGH */
882a6d42e7dSPeter Dunlap 	case CE_LOGOUT_TIMEOUT:
883a6d42e7dSPeter Dunlap 		idm_ffp_disable(ic, FD_CONN_FAIL); /* Implicit logout */
884a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S8_CLEANUP, event_ctx);
885a6d42e7dSPeter Dunlap 		break;
886a6d42e7dSPeter Dunlap 	case CE_LOGOUT_SESSION_SUCCESS:
887a6d42e7dSPeter Dunlap 		/* T18 */
888a6d42e7dSPeter Dunlap 		if (IDM_CONN_ISTGT(ic)) {
889ff9de394SRick McNeal 			IDM_SM_TIMER_CLEAR(ic);
890a6d42e7dSPeter Dunlap 		}
891a6d42e7dSPeter Dunlap 		idm_ffp_disable(ic, FD_SESS_LOGOUT); /* Explicit logout */
892a6d42e7dSPeter Dunlap 
893a6d42e7dSPeter Dunlap 		/* Close connection (if it's not already closed) */
894a6d42e7dSPeter Dunlap 		if (IDM_CONN_ISTGT(ic)) {
895a6d42e7dSPeter Dunlap 			ic->ic_transport_ops->it_tgt_conn_disconnect(ic);
896a6d42e7dSPeter Dunlap 		} else {
897a6d42e7dSPeter Dunlap 			ic->ic_transport_ops->it_ini_conn_disconnect(ic);
898a6d42e7dSPeter Dunlap 		}
899a6d42e7dSPeter Dunlap 
900a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S11_COMPLETE, event_ctx);
901a6d42e7dSPeter Dunlap 		break;
902a6d42e7dSPeter Dunlap 	case CE_TX_PROTOCOL_ERROR:
903a6d42e7dSPeter Dunlap 	case CE_RX_PROTOCOL_ERROR:
904a6d42e7dSPeter Dunlap 	case CE_MISC_TX:
905a6d42e7dSPeter Dunlap 	case CE_MISC_RX:
90692adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	case CE_LOGIN_TIMEOUT:
907a6d42e7dSPeter Dunlap 		/* Don't care */
908a6d42e7dSPeter Dunlap 		break;
909a6d42e7dSPeter Dunlap 	default:
910a6d42e7dSPeter Dunlap 		ASSERT(0);
911a6d42e7dSPeter Dunlap 	}
912a6d42e7dSPeter Dunlap }
913a6d42e7dSPeter Dunlap 
914a6d42e7dSPeter Dunlap 
915a6d42e7dSPeter Dunlap static void
idm_cleanup_timeout(void * arg)916a6d42e7dSPeter Dunlap idm_cleanup_timeout(void *arg)
917a6d42e7dSPeter Dunlap {
918a6d42e7dSPeter Dunlap 	idm_conn_t *ic = arg;
919a6d42e7dSPeter Dunlap 
920ff9de394SRick McNeal 	ic->ic_state_timeout = 0;
9218e718be9SToomas Soome 	idm_conn_event(ic, CE_CLEANUP_TIMEOUT, (uintptr_t)NULL);
922a6d42e7dSPeter Dunlap }
923a6d42e7dSPeter Dunlap 
924a6d42e7dSPeter Dunlap static void
idm_state_s8_cleanup(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)925a6d42e7dSPeter Dunlap idm_state_s8_cleanup(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
926a6d42e7dSPeter Dunlap {
927a6d42e7dSPeter Dunlap 	idm_pdu_t *pdu;
928a6d42e7dSPeter Dunlap 
929a6d42e7dSPeter Dunlap 	/*
930a6d42e7dSPeter Dunlap 	 * Need to cancel the cleanup timeout before leaving this state
931a6d42e7dSPeter Dunlap 	 * if it hasn't already fired.
932a6d42e7dSPeter Dunlap 	 */
933a6d42e7dSPeter Dunlap 	switch (event_ctx->iec_event) {
934a6d42e7dSPeter Dunlap 	case CE_LOGOUT_SUCCESS_RCV:
935a6d42e7dSPeter Dunlap 	case CE_LOGOUT_SUCCESS_SND:
936a6d42e7dSPeter Dunlap 	case CE_LOGOUT_SESSION_SUCCESS:
937ff9de394SRick McNeal 		IDM_SM_TIMER_CLEAR(ic);
938a6d42e7dSPeter Dunlap 		/*FALLTHROUGH*/
939a6d42e7dSPeter Dunlap 	case CE_CLEANUP_TIMEOUT:
940a6d42e7dSPeter Dunlap 		/* M1 */
941a6d42e7dSPeter Dunlap 		idm_update_state(ic, CS_S11_COMPLETE, event_ctx);
942a6d42e7dSPeter Dunlap 		break;
943a6d42e7dSPeter Dunlap 	case