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 CE_LOGOUT_OTHER_CONN_RCV:
944a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_SND:
945a6d42e7dSPeter Dunlap /* M2 */
946a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S10_IN_CLEANUP, event_ctx);
947a6d42e7dSPeter Dunlap break;
948a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND_DONE:
949a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND_DONE:
950a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info;
951a6d42e7dSPeter Dunlap /* restore client callback */
952a6d42e7dSPeter Dunlap pdu->isp_callback = ic->ic_client_callback;
953a6d42e7dSPeter Dunlap ic->ic_client_callback = NULL;
954a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, pdu->isp_status);
955a6d42e7dSPeter Dunlap break;
956a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_RCV:
957a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SND:
958a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR:
959a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR:
960a6d42e7dSPeter Dunlap case CE_MISC_TX:
961a6d42e7dSPeter Dunlap case CE_MISC_RX:
962a6d42e7dSPeter Dunlap case CE_TRANSPORT_FAIL:
96392adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_TIMEOUT:
964a6d42e7dSPeter Dunlap case CE_LOGOUT_TIMEOUT:
965a6d42e7dSPeter Dunlap /* Don't care */
966a6d42e7dSPeter Dunlap break;
967a6d42e7dSPeter Dunlap default:
968a6d42e7dSPeter Dunlap ASSERT(0);
969a6d42e7dSPeter Dunlap }
970a6d42e7dSPeter Dunlap }
971a6d42e7dSPeter Dunlap
972a6d42e7dSPeter Dunlap /* ARGSUSED */
973a6d42e7dSPeter Dunlap static void
idm_state_s9_init_error(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)974a6d42e7dSPeter Dunlap idm_state_s9_init_error(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
975a6d42e7dSPeter Dunlap {
976e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* All events ignored in this state */
977a6d42e7dSPeter Dunlap }
978a6d42e7dSPeter Dunlap
979e42a0851Speter dunlap /* ARGSUSED */
980e42a0851Speter dunlap static void
idm_state_s9a_rejected(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)981e42a0851Speter dunlap idm_state_s9a_rejected(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
982e42a0851Speter dunlap {
983e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* All events ignored in this state */
984e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States }
985e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States
986e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States
987e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States static void
idm_state_s9b_wait_snd_done_cb(idm_pdu_t * pdu,idm_status_t status)988e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done_cb(idm_pdu_t *pdu, idm_status_t status)
989e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States {
990e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_t *ic = pdu->isp_ic;
991e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States
992e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /*
993e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * This pdu callback can be invoked by the tx thread,
994e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * so run the disconnect code from another thread.
995e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States */
996e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States pdu->isp_status = status;
997e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_event(ic, CE_LOGIN_FAIL_SND_DONE, (uintptr_t)pdu);
998e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States }
999e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States
1000e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /*
1001e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * CS_S9B_WAIT_SND_DONE -- wait for callback completion.
1002e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States */
1003e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* ARGSUSED */
1004e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States static void
idm_state_s9b_wait_snd_done(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)1005e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
1006e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States {
1007e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_pdu_t *pdu;
1008e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /*
1009e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * Wait for completion of the login fail sequence and then
1010e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * go to state S9_INIT_ERROR to clean up the connection.
1011e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States */
1012e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States switch (event_ctx->iec_event) {
1013e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_FAIL_SND_DONE:
1014e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States pdu = (idm_pdu_t *)event_ctx->iec_info;
1015e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* restore client callback */
1016e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States pdu->isp_callback = ic->ic_client_callback;
1017e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States ic->ic_client_callback = NULL;
1018e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_pdu_complete(pdu, pdu->isp_status);
1019e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx);
1020e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States break;
1021e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States
1022e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* All other events ignored */
1023e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States }
1024e42a0851Speter dunlap }
1025e42a0851Speter dunlap
1026e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States
1027e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States
1028e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States
1029a6d42e7dSPeter Dunlap static void
idm_state_s10_in_cleanup(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)1030a6d42e7dSPeter Dunlap idm_state_s10_in_cleanup(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
1031a6d42e7dSPeter Dunlap {
1032a6d42e7dSPeter Dunlap idm_pdu_t *pdu;
1033a6d42e7dSPeter Dunlap
1034a6d42e7dSPeter Dunlap /*
1035a6d42e7dSPeter Dunlap * Need to cancel the cleanup timeout before leaving this state
1036a6d42e7dSPeter Dunlap * if it hasn't already fired.
1037a6d42e7dSPeter Dunlap */
1038a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) {
1039a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_RCV:
1040a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND:
1041a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S8_CLEANUP, event_ctx);
1042a6d42e7dSPeter Dunlap break;
1043a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND:
1044a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_RCV:
1045a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SUCCESS:
1046ff9de394SRick McNeal IDM_SM_TIMER_CLEAR(ic);
1047a6d42e7dSPeter Dunlap /*FALLTHROUGH*/
1048a6d42e7dSPeter Dunlap case CE_CLEANUP_TIMEOUT:
1049a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S11_COMPLETE, event_ctx);
1050a6d42e7dSPeter Dunlap break;
1051a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND_DONE:
1052a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND_DONE:
1053a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info;
1054a6d42e7dSPeter Dunlap /* restore client callback */
1055a6d42e7dSPeter Dunlap pdu->isp_callback = ic->ic_client_callback;
1056a6d42e7dSPeter Dunlap ic->ic_client_callback = NULL;
1057a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, pdu->isp_status);
1058a6d42e7dSPeter Dunlap break;
1059a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR:
1060a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR:
1061a6d42e7dSPeter Dunlap case CE_MISC_TX:
1062a6d42e7dSPeter Dunlap case CE_MISC_RX:
106392adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_TIMEOUT:
1064a6d42e7dSPeter Dunlap case CE_LOGOUT_TIMEOUT:
1065a6d42e7dSPeter Dunlap /* Don't care */
1066a6d42e7dSPeter Dunlap break;
1067a6d42e7dSPeter Dunlap default:
1068a6d42e7dSPeter Dunlap ASSERT(0);
1069a6d42e7dSPeter Dunlap }
1070a6d42e7dSPeter Dunlap }
1071a6d42e7dSPeter Dunlap
1072a6d42e7dSPeter Dunlap /* ARGSUSED */
1073a6d42e7dSPeter Dunlap static void
idm_state_s11_complete(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)1074a6d42e7dSPeter Dunlap idm_state_s11_complete(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
1075a6d42e7dSPeter Dunlap {
1076a6d42e7dSPeter Dunlap idm_pdu_t *pdu;
1077a6d42e7dSPeter Dunlap
1078a6d42e7dSPeter Dunlap /*
1079a6d42e7dSPeter Dunlap * Cleanup logout success/fail completion if it's been delayed
1080a6d42e7dSPeter Dunlap * until now.
1081e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States *
1082e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * All new events are filtered out before reaching this state, but
1083e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * there might already be events in the event queue, so handle the
1084e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * SND_DONE events here. Note that if either of the following
1085e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * SND_DONE events happens AFTER the change to state S11, then the
1086e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * event filter inside dm_conn_event_locked does enough cleanup.
1087a6d42e7dSPeter Dunlap */
1088a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) {
1089a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND_DONE:
1090a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND_DONE:
1091a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info;
1092a6d42e7dSPeter Dunlap /* restore client callback */
1093a6d42e7dSPeter Dunlap pdu->isp_callback = ic->ic_client_callback;
1094a6d42e7dSPeter Dunlap ic->ic_client_callback = NULL;
1095a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, pdu->isp_status);
1096a6d42e7dSPeter Dunlap break;
1097a6d42e7dSPeter Dunlap }
1098e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States
1099a6d42e7dSPeter Dunlap }
1100a6d42e7dSPeter Dunlap
1101a6d42e7dSPeter Dunlap static void
idm_state_s12_enable_dm(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)1102a6d42e7dSPeter Dunlap idm_state_s12_enable_dm(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
1103a6d42e7dSPeter Dunlap {
1104a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) {
1105a6d42e7dSPeter Dunlap case CE_ENABLE_DM_SUCCESS:
1106a6d42e7dSPeter Dunlap /* T20 */
1107a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S5_LOGGED_IN, event_ctx);
1108a6d42e7dSPeter Dunlap break;
1109a6d42e7dSPeter Dunlap case CE_ENABLE_DM_FAIL:
1110a6d42e7dSPeter Dunlap /* T21 */
1111a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx);
1112a6d42e7dSPeter Dunlap break;
1113a6d42e7dSPeter Dunlap case CE_TRANSPORT_FAIL:
1114a6d42e7dSPeter Dunlap /*
1115a6d42e7dSPeter Dunlap * We expect to always hear back from the transport layer
1116a6d42e7dSPeter Dunlap * once we have an "enable data-mover" request outstanding.
1117a6d42e7dSPeter Dunlap * Therefore we'll ignore other events that may occur even
1118a6d42e7dSPeter Dunlap * when they clearly indicate a problem and wait for
1119a6d42e7dSPeter Dunlap * CE_ENABLE_DM_FAIL. On a related note this means the
1120a6d42e7dSPeter Dunlap * transport must ensure that it eventually completes the
1121a6d42e7dSPeter Dunlap * "enable data-mover" operation with either success or
1122a6d42e7dSPeter Dunlap * failure -- otherwise we'll be stuck here.
1123a6d42e7dSPeter Dunlap */
1124a6d42e7dSPeter Dunlap break;
1125a6d42e7dSPeter Dunlap default:
1126a6d42e7dSPeter Dunlap ASSERT(0);
1127a6d42e7dSPeter Dunlap break;
1128a6d42e7dSPeter Dunlap }
1129a6d42e7dSPeter Dunlap }
1130a6d42e7dSPeter Dunlap
1131a6d42e7dSPeter Dunlap static void
idm_update_state(idm_conn_t * ic,idm_conn_state_t new_state,idm_conn_event_ctx_t * event_ctx)1132a6d42e7dSPeter Dunlap idm_update_state(idm_conn_t *ic, idm_conn_state_t new_state,
1133a6d42e7dSPeter Dunlap idm_conn_event_ctx_t *event_ctx)
1134a6d42e7dSPeter Dunlap {
1135a6d42e7dSPeter Dunlap int rc;
1136a6d42e7dSPeter Dunlap idm_status_t idm_status;
1137a6d42e7dSPeter Dunlap
1138a6d42e7dSPeter Dunlap /*
1139a6d42e7dSPeter Dunlap * Validate new state
1140a6d42e7dSPeter Dunlap */
1141a6d42e7dSPeter Dunlap ASSERT(new_state != CS_S0_UNDEFINED);
1142a6d42e7dSPeter Dunlap ASSERT3U(new_state, <, CS_MAX_STATE);
1143a6d42e7dSPeter Dunlap
1144a6d42e7dSPeter Dunlap /*
1145a6d42e7dSPeter Dunlap * Update state in context. We protect this with a mutex
1146a6d42e7dSPeter Dunlap * even though the state machine code is single threaded so that
1147a6d42e7dSPeter Dunlap * other threads can check the state value atomically.
1148a6d42e7dSPeter Dunlap */
1149a6d42e7dSPeter Dunlap new_state = (new_state < CS_MAX_STATE) ?
1150a6d42e7dSPeter Dunlap new_state : CS_S0_UNDEFINED;
1151a6d42e7dSPeter Dunlap
1152a6d42e7dSPeter Dunlap IDM_SM_LOG(CE_NOTE, "idm_update_state: conn %p, evt %s(%d), "
1153a6d42e7dSPeter Dunlap "%s(%d) --> %s(%d)", (void *)ic,
1154a6d42e7dSPeter Dunlap idm_ce_name[event_ctx->iec_event], event_ctx->iec_event,
1155a6d42e7dSPeter Dunlap idm_cs_name[ic->ic_state], ic->ic_state,
1156a6d42e7dSPeter Dunlap idm_cs_name[new_state], new_state);
1157a6d42e7dSPeter Dunlap
1158a6d42e7dSPeter Dunlap DTRACE_PROBE2(conn__state__change,
1159a6d42e7dSPeter Dunlap idm_conn_t *, ic, idm_conn_state_t, new_state);
1160a6d42e7dSPeter Dunlap
1161a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex);
1162a6d42e7dSPeter Dunlap idm_sm_audit_state_change(&ic->ic_state_audit, SAS_IDM_CONN,
1163a6d42e7dSPeter Dunlap (int)ic->ic_state, (int)new_state);
1164a6d42e7dSPeter Dunlap ic->ic_last_state = ic->ic_state;
1165a6d42e7dSPeter Dunlap ic->ic_state = new_state;
1166a6d42e7dSPeter Dunlap cv_signal(&ic->ic_state_cv);
1167a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex);
1168a6d42e7dSPeter Dunlap
1169a6d42e7dSPeter Dunlap switch (ic->ic_state) {
1170a6d42e7dSPeter Dunlap case CS_S1_FREE:
1171a6d42e7dSPeter Dunlap ASSERT(0); /* Initial state, can't return */
1172a6d42e7dSPeter Dunlap break;
1173a6d42e7dSPeter Dunlap case CS_S2_XPT_WAIT:
1174a6d42e7dSPeter Dunlap if ((rc = idm_ini_conn_finish(ic)) != 0) {
11758e718be9SToomas Soome idm_conn_event(ic, CE_CONNECT_FAIL, (uintptr_t)NULL);
1176a6d42e7dSPeter Dunlap } else {
11778e718be9SToomas Soome idm_conn_event(ic, CE_CONNECT_SUCCESS, (uintptr_t)NULL);
1178a6d42e7dSPeter Dunlap }
1179a6d42e7dSPeter Dunlap break;
1180a6d42e7dSPeter Dunlap case CS_S3_XPT_UP:
1181a6d42e7dSPeter Dunlap /*
1182a6d42e7dSPeter Dunlap * Finish any connection related setup including
1183a6d42e7dSPeter Dunlap * waking up the idm_tgt_conn_accept thread.
1184a6d42e7dSPeter Dunlap * and starting the login timer. If the function
1185a6d42e7dSPeter Dunlap * fails then we return to "free" state.
1186a6d42e7dSPeter Dunlap */
1187a6d42e7dSPeter Dunlap if ((rc = idm_tgt_conn_finish(ic)) != IDM_STATUS_SUCCESS) {
1188a6d42e7dSPeter Dunlap switch (rc) {
1189a6d42e7dSPeter Dunlap case IDM_STATUS_REJECT:
11908e718be9SToomas Soome idm_conn_event(ic, CE_CONNECT_REJECT,
11918e718be9SToomas Soome (uintptr_t)NULL);
1192a6d42e7dSPeter Dunlap break;
1193a6d42e7dSPeter Dunlap default:
11948e718be9SToomas Soome idm_conn_event(ic, CE_CONNECT_FAIL,
11958e718be9SToomas Soome (uintptr_t)NULL);
1196a6d42e7dSPeter Dunlap break;
1197a6d42e7dSPeter Dunlap }
1198a6d42e7dSPeter Dunlap }
1199a6d42e7dSPeter Dunlap
1200a6d42e7dSPeter Dunlap /*
1201a6d42e7dSPeter Dunlap * First login received will cause a transition to
1202a6d42e7dSPeter Dunlap * CS_S4_IN_LOGIN. Start login timer.
1203a6d42e7dSPeter Dunlap */
1204ff9de394SRick McNeal IDM_SM_TIMER_CHECK(ic);
1205a6d42e7dSPeter Dunlap ic->ic_state_timeout = timeout(idm_login_timeout, ic,
12068e718be9SToomas Soome drv_usectohz(IDM_LOGIN_SECONDS * 1000000));
1207a6d42e7dSPeter Dunlap break;
1208a6d42e7dSPeter Dunlap case CS_S4_IN_LOGIN:
1209a6d42e7dSPeter Dunlap if (ic->ic_conn_type == CONN_TYPE_INI) {
12108e718be9SToomas Soome (void) idm_notify_client(ic, CN_READY_FOR_LOGIN,
12118e718be9SToomas Soome (uintptr_t)NULL);
1212a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex);
1213a6d42e7dSPeter Dunlap ic->ic_state_flags |= CF_LOGIN_READY;
1214a6d42e7dSPeter Dunlap cv_signal(&ic->ic_state_cv);
1215a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex);
1216a6d42e7dSPeter Dunlap }
1217a6d42e7dSPeter Dunlap break;
1218a6d42e7dSPeter Dunlap case CS_S5_LOGGED_IN:
1219a6d42e7dSPeter Dunlap ASSERT(!ic->ic_ffp);
1220a6d42e7dSPeter Dunlap /*
1221a6d42e7dSPeter Dunlap * IDM can go to FFP before the initiator but it
1222a6d42e7dSPeter Dunlap * needs to go to FFP after the target (IDM target should
1223a6d42e7dSPeter Dunlap * go to FFP after notify_ack).
1224a6d42e7dSPeter Dunlap */
1225a6d42e7dSPeter Dunlap idm_status = idm_ffp_enable(ic);
1226a6d42e7dSPeter Dunlap if (idm_status != IDM_STATUS_SUCCESS) {
12278e718be9SToomas Soome idm_conn_event(ic, CE_TRANSPORT_FAIL, (uintptr_t)NULL);
1228a6d42e7dSPeter Dunlap }
1229a6d42e7dSPeter Dunlap
1230a6d42e7dSPeter Dunlap if (ic->ic_reinstate_conn) {
1231a6d42e7dSPeter Dunlap /* Connection reinstatement is complete */
123292adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_event(ic->ic_reinstate_conn,
12338e718be9SToomas Soome CE_CONN_REINSTATE_SUCCESS, (uintptr_t)NULL);
1234a6d42e7dSPeter Dunlap }
1235a6d42e7dSPeter Dunlap break;
1236a6d42e7dSPeter Dunlap case CS_S6_IN_LOGOUT:
1237a6d42e7dSPeter Dunlap break;
1238a6d42e7dSPeter Dunlap case CS_S7_LOGOUT_REQ:
1239a6d42e7dSPeter Dunlap /* Start logout timer for target connections */
1240a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) {
1241ff9de394SRick McNeal IDM_SM_TIMER_CHECK(ic);
1242a6d42e7dSPeter Dunlap ic->ic_state_timeout = timeout(idm_logout_req_timeout,
1243a6d42e7dSPeter Dunlap ic, drv_usectohz(IDM_LOGOUT_SECONDS*1000000));
1244a6d42e7dSPeter Dunlap }
1245a6d42e7dSPeter Dunlap break;
1246a6d42e7dSPeter Dunlap case CS_S8_CLEANUP:
1247a6d42e7dSPeter Dunlap /* Close connection (if it's not already closed) */
1248a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) {
1249a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_conn_disconnect(ic);
1250a6d42e7dSPeter Dunlap } else {
1251a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_ini_conn_disconnect(ic);
1252a6d42e7dSPeter Dunlap }
1253a6d42e7dSPeter Dunlap
1254a6d42e7dSPeter Dunlap /* Stop executing active tasks */
125561dfa509SRick McNeal (void) idm_task_abort(ic, NULL, AT_INTERNAL_SUSPEND);
1256a6d42e7dSPeter Dunlap
1257a6d42e7dSPeter Dunlap /* Start logout timer */
1258ff9de394SRick McNeal IDM_SM_TIMER_CHECK(ic);
1259a6d42e7dSPeter Dunlap ic->ic_state_timeout = timeout(idm_cleanup_timeout, ic,
1260a6d42e7dSPeter Dunlap drv_usectohz(IDM_CLEANUP_SECONDS*1000000));
1261a6d42e7dSPeter Dunlap break;
1262a6d42e7dSPeter Dunlap case CS_S10_IN_CLEANUP:
1263a6d42e7dSPeter Dunlap break;
1264e42a0851Speter dunlap case CS_S9A_REJECTED:
1265e42a0851Speter dunlap /*
1266e42a0851Speter dunlap * We never finished establishing the connection so no
1267e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * disconnect. No client notifications because the client
1268e42a0851Speter dunlap * rejected the connection.
1269e42a0851Speter dunlap */
1270e42a0851Speter dunlap idm_refcnt_async_wait_ref(&ic->ic_refcnt,
1271e42a0851Speter dunlap &idm_conn_reject_unref);
1272e42a0851Speter dunlap break;
1273e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CS_S9B_WAIT_SND_DONE:
1274e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States break;
1275a6d42e7dSPeter Dunlap case CS_S9_INIT_ERROR:
1276a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) {
1277a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_conn_disconnect(ic);
1278a6d42e7dSPeter Dunlap } else {
1279a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex);
1280a6d42e7dSPeter Dunlap ic->ic_state_flags |= CF_ERROR;
1281a6d42e7dSPeter Dunlap ic->ic_conn_sm_status = IDM_STATUS_FAIL;
1282a6d42e7dSPeter Dunlap cv_signal(&ic->ic_state_cv);
1283a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex);
128430e7468fSPeter Dunlap if (ic->ic_last_state != CS_S1_FREE &&
128530e7468fSPeter Dunlap ic->ic_last_state != CS_S2_XPT_WAIT) {
128630e7468fSPeter Dunlap ic->ic_transport_ops->it_ini_conn_disconnect(
128730e7468fSPeter Dunlap ic);
128830e7468fSPeter Dunlap } else {
128930e7468fSPeter Dunlap (void) idm_notify_client(ic, CN_CONNECT_FAIL,
12908e718be9SToomas Soome (uintptr_t)NULL);
129130e7468fSPeter Dunlap }
1292a6d42e7dSPeter Dunlap }
1293a6d42e7dSPeter Dunlap /*FALLTHROUGH*/
1294a6d42e7dSPeter Dunlap case CS_S11_COMPLETE:
129530e7468fSPeter Dunlap /*
129630e7468fSPeter Dunlap * No more traffic on this connection. If this is an
129730e7468fSPeter Dunlap * initiator connection and we weren't connected yet
129830e7468fSPeter Dunlap * then don't send the "connect lost" event.
129930e7468fSPeter Dunlap * It's useful to the initiator to know whether we were
130030e7468fSPeter Dunlap * logging in at the time so send that information in the
130130e7468fSPeter Dunlap * data field.
130230e7468fSPeter Dunlap */
130330e7468fSPeter Dunlap if (IDM_CONN_ISTGT(ic) ||
130430e7468fSPeter Dunlap ((ic->ic_last_state != CS_S1_FREE) &&
130530e7468fSPeter Dunlap (ic->ic_last_state != CS_S2_XPT_WAIT))) {
130630e7468fSPeter Dunlap (void) idm_notify_client(ic, CN_CONNECT_LOST,
130730e7468fSPeter Dunlap (uintptr_t)(ic->ic_last_state == CS_S4_IN_LOGIN));
130830e7468fSPeter Dunlap }
1309a6d42e7dSPeter Dunlap
1310a6d42e7dSPeter Dunlap /* Abort all tasks */
131161dfa509SRick McNeal (void) idm_task_abort(ic, NULL, AT_INTERNAL_ABORT);
1312a6d42e7dSPeter Dunlap
1313a6d42e7dSPeter Dunlap /*
1314a6d42e7dSPeter Dunlap * Handle terminal state actions on the global taskq so
1315a6d42e7dSPeter Dunlap * we can clean up all the connection resources from
1316a6d42e7dSPeter Dunlap * a separate thread context.
1317a6d42e7dSPeter Dunlap */
1318a6d42e7dSPeter Dunlap idm_refcnt_async_wait_ref(&ic->ic_refcnt, &idm_conn_unref);
1319a6d42e7dSPeter Dunlap break;
1320a6d42e7dSPeter Dunlap case CS_S12_ENABLE_DM:
1321a6d42e7dSPeter Dunlap
1322a6d42e7dSPeter Dunlap /*
1323a6d42e7dSPeter Dunlap * The Enable DM state indicates the initiator to initiate
1324a6d42e7dSPeter Dunlap * the hello sequence and the target to get ready to accept
1325a6d42e7dSPeter Dunlap * the iSER Hello Message.
1326a6d42e7dSPeter Dunlap */
1327a6d42e7dSPeter Dunlap idm_status = (IDM_CONN_ISINI(ic)) ?
1328a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_ini_enable_datamover(ic) :
1329a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_enable_datamover(ic);
1330a6d42e7dSPeter Dunlap
1331a6d42e7dSPeter Dunlap if (idm_status == IDM_STATUS_SUCCESS) {
13328e718be9SToomas Soome idm_conn_event(ic, CE_ENABLE_DM_SUCCESS,
13338e718be9SToomas Soome (uintptr_t)NULL);
1334a6d42e7dSPeter Dunlap } else {
13358e718be9SToomas Soome idm_conn_event(ic, CE_ENABLE_DM_FAIL, (uintptr_t)NULL);
1336a6d42e7dSPeter Dunlap }
1337a6d42e7dSPeter Dunlap
1338a6d42e7dSPeter Dunlap break;
1339e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States
1340e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States default:
1341e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(0);
1342e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States break;
1343e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States
1344a6d42e7dSPeter Dunlap }
1345a6d42e7dSPeter Dunlap }
1346a6d42e7dSPeter Dunlap
1347a6d42e7dSPeter Dunlap
1348a6d42e7dSPeter Dunlap static void
idm_conn_unref(void * ic_void)1349a6d42e7dSPeter Dunlap idm_conn_unref(void *ic_void)
1350a6d42e7dSPeter Dunlap {
1351a6d42e7dSPeter Dunlap idm_conn_t *ic = ic_void;
1352a6d42e7dSPeter Dunlap
1353a6d42e7dSPeter Dunlap /*
1354a6d42e7dSPeter Dunlap * Client should not be notified that the connection is destroyed
1355a6d42e7dSPeter Dunlap * until all references on the idm connection have been removed.
1356a6d42e7dSPeter Dunlap * Otherwise references on the associated client context would need
1357a6d42e7dSPeter Dunlap * to be tracked separately which seems like a waste (at least when
1358a6d42e7dSPeter Dunlap * there is a one for one correspondence with references on the
1359a6d42e7dSPeter Dunlap * IDM connection).
1360a6d42e7dSPeter Dunlap */
1361a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) {
13628e718be9SToomas Soome (void) idm_notify_client(ic, CN_CONNECT_DESTROY,
13638e718be9SToomas Soome (uintptr_t)NULL);
1364a6d42e7dSPeter Dunlap idm_svc_conn_destroy(ic);
1365a6d42e7dSPeter Dunlap } else {
1366a6d42e7dSPeter Dunlap /* Initiator may destroy connection during this call */
13678e718be9SToomas Soome (void) idm_notify_client(ic, CN_CONNECT_DESTROY,
13688e718be9SToomas Soome (uintptr_t)NULL);
1369a6d42e7dSPeter Dunlap }
1370a6d42e7dSPeter Dunlap }
1371a6d42e7dSPeter Dunlap
1372e42a0851Speter dunlap static void
idm_conn_reject_unref(void * ic_void)1373e42a0851Speter dunlap idm_conn_reject_unref(void *ic_void)
1374e42a0851Speter dunlap {
1375e42a0851Speter dunlap idm_conn_t *ic = ic_void;
1376e42a0851Speter dunlap
1377e42a0851Speter dunlap ASSERT(IDM_CONN_ISTGT(ic));
1378e42a0851Speter dunlap
1379e42a0851Speter dunlap /* Don't notify the client since it rejected the connection */
1380e42a0851Speter dunlap idm_svc_conn_destroy(ic);
1381e42a0851Speter dunlap }
1382e42a0851Speter dunlap
1383e42a0851Speter dunlap
1384a6d42e7dSPeter Dunlap
1385a6d42e7dSPeter Dunlap static idm_pdu_event_action_t
idm_conn_sm_validate_pdu(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx,idm_pdu_t * pdu)1386a6d42e7dSPeter Dunlap idm_conn_sm_validate_pdu(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx,
13878e718be9SToomas Soome idm_pdu_t *pdu)
1388a6d42e7dSPeter Dunlap {
1389a6d42e7dSPeter Dunlap char *reason_string;
1390a6d42e7dSPeter Dunlap idm_pdu_event_action_t action;
1391a6d42e7dSPeter Dunlap
1392a6d42e7dSPeter Dunlap ASSERT((event_ctx->iec_pdu_event_type == CT_RX_PDU) ||
1393a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_TX_PDU));
1394a6d42e7dSPeter Dunlap
1395a6d42e7dSPeter Dunlap /*
1396a6d42e7dSPeter Dunlap * Let's check the simple stuff first. Make sure if this is a
1397a6d42e7dSPeter Dunlap * target connection that the PDU is appropriate for a target
1398a6d42e7dSPeter Dunlap * and if this is an initiator connection that the PDU is
1399a6d42e7dSPeter Dunlap * appropriate for an initiator. This code is not in the data
1400a6d42e7dSPeter Dunlap * path so organization is more important than performance.
1401a6d42e7dSPeter Dunlap */
1402a6d42e7dSPeter Dunlap switch (IDM_PDU_OPCODE(pdu)) {
1403a6d42e7dSPeter Dunlap case ISCSI_OP_NOOP_OUT:
1404a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_CMD:
1405a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_TASK_MGT_MSG:
1406a6d42e7dSPeter Dunlap case ISCSI_OP_LOGIN_CMD:
1407a6d42e7dSPeter Dunlap case ISCSI_OP_TEXT_CMD:
1408a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_DATA:
1409a6d42e7dSPeter Dunlap case ISCSI_OP_LOGOUT_CMD:
1410a6d42e7dSPeter Dunlap case ISCSI_OP_SNACK_CMD:
1411a6d42e7dSPeter Dunlap /*
1412a6d42e7dSPeter Dunlap * Only the initiator should send these PDU's and
1413a6d42e7dSPeter Dunlap * only the target should receive them.
1414a6d42e7dSPeter Dunlap */
1415a6d42e7dSPeter Dunlap if (IDM_CONN_ISINI(ic) &&
1416a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_RX_PDU)) {
1417a6d42e7dSPeter Dunlap reason_string = "Invalid RX PDU for initiator";
1418a6d42e7dSPeter Dunlap action = CA_RX_PROTOCOL_ERROR;
1419a6d42e7dSPeter Dunlap goto validate_pdu_done;
1420a6d42e7dSPeter Dunlap }
1421a6d42e7dSPeter Dunlap
1422a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic) &&
1423a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_TX_PDU)) {
1424a6d42e7dSPeter Dunlap reason_string = "Invalid TX PDU for target";
1425a6d42e7dSPeter Dunlap action = CA_TX_PROTOCOL_ERROR;
1426a6d42e7dSPeter Dunlap goto validate_pdu_done;
1427a6d42e7dSPeter Dunlap }
1428a6d42e7dSPeter Dunlap break;
1429a6d42e7dSPeter Dunlap case ISCSI_OP_NOOP_IN:
1430a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_RSP:
1431a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_TASK_MGT_RSP:
1432a6d42e7dSPeter Dunlap case ISCSI_OP_LOGIN_RSP:
1433a6d42e7dSPeter Dunlap case ISCSI_OP_TEXT_RSP:
1434a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_DATA_RSP:
1435a6d42e7dSPeter Dunlap case ISCSI_OP_LOGOUT_RSP:
1436a6d42e7dSPeter Dunlap case ISCSI_OP_RTT_RSP:
1437a6d42e7dSPeter Dunlap case ISCSI_OP_ASYNC_EVENT:
1438a6d42e7dSPeter Dunlap case ISCSI_OP_REJECT_MSG:
1439a6d42e7dSPeter Dunlap /*
1440a6d42e7dSPeter Dunlap * Only the target should send these PDU's and
1441a6d42e7dSPeter Dunlap * only the initiator should receive them.
1442a6d42e7dSPeter Dunlap */
1443a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic) &&
1444a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_RX_PDU)) {
1445a6d42e7dSPeter Dunlap reason_string = "Invalid RX PDU for target";
1446a6d42e7dSPeter Dunlap action = CA_RX_PROTOCOL_ERROR;
1447a6d42e7dSPeter Dunlap goto validate_pdu_done;
1448a6d42e7dSPeter Dunlap }
1449a6d42e7dSPeter Dunlap
1450a6d42e7dSPeter Dunlap if (IDM_CONN_ISINI(ic) &&
1451a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_TX_PDU)) {
1452a6d42e7dSPeter Dunlap reason_string = "Invalid TX PDU for initiator";
1453a6d42e7dSPeter Dunlap action = CA_TX_PROTOCOL_ERROR;
1454a6d42e7dSPeter Dunlap goto validate_pdu_done;
1455a6d42e7dSPeter Dunlap }
1456a6d42e7dSPeter Dunlap break;
1457a6d42e7dSPeter Dunlap default:
1458a6d42e7dSPeter Dunlap reason_string = "Unknown PDU Type";
1459a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ?
1460a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR);
1461a6d42e7dSPeter Dunlap goto validate_pdu_done;
1462a6d42e7dSPeter Dunlap }
1463a6d42e7dSPeter Dunlap
1464a6d42e7dSPeter Dunlap /*
1465a6d42e7dSPeter Dunlap * Now validate the opcodes against the current state.
1466a6d42e7dSPeter Dunlap */
1467a6d42e7dSPeter Dunlap reason_string = "PDU not allowed in current state";
1468a6d42e7dSPeter Dunlap switch (IDM_PDU_OPCODE(pdu)) {
1469a6d42e7dSPeter Dunlap case ISCSI_OP_NOOP_OUT:
1470a6d42e7dSPeter Dunlap case ISCSI_OP_NOOP_IN:
1471a6d42e7dSPeter Dunlap /*
1472a6d42e7dSPeter Dunlap * Obviously S1-S3 are not allowed since login hasn't started.
1473a6d42e7dSPeter Dunlap * S8 is probably out as well since the connection has been
1474a6d42e7dSPeter Dunlap * dropped.
1475a6d42e7dSPeter Dunlap */
1476a6d42e7dSPeter Dunlap switch (ic->ic_state) {
1477a6d42e7dSPeter Dunlap case CS_S4_IN_LOGIN:
1478a6d42e7dSPeter Dunlap case CS_S5_LOGGED_IN:
1479a6d42e7dSPeter Dunlap case CS_S6_IN_LOGOUT:
1480a6d42e7dSPeter Dunlap case CS_S7_LOGOUT_REQ:
1481a6d42e7dSPeter Dunlap action = CA_FORWARD;
1482a6d42e7dSPeter Dunlap goto validate_pdu_done;
1483a6d42e7dSPeter Dunlap case CS_S8_CLEANUP:
1484a6d42e7dSPeter Dunlap case CS_S10_IN_CLEANUP:
1485a6d42e7dSPeter Dunlap action = CA_DROP;
1486327d9711SToomas Soome goto validate_pdu_done;
1487a6d42e7dSPeter Dunlap default:
1488a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ?
1489a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR);
1490a6d42e7dSPeter Dunlap goto validate_pdu_done;
1491a6d42e7dSPeter Dunlap }
1492a6d42e7dSPeter Dunlap /*NOTREACHED*/
1493a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_CMD:
1494a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_RSP:
1495a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_TASK_MGT_MSG:
1496a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_TASK_MGT_RSP:
1497a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_DATA:
1498a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_DATA_RSP:
1499a6d42e7dSPeter Dunlap case ISCSI_OP_RTT_RSP:
1500a6d42e7dSPeter Dunlap case ISCSI_OP_SNACK_CMD:
1501a6d42e7dSPeter Dunlap case ISCSI_OP_TEXT_CMD:
1502a6d42e7dSPeter Dunlap case ISCSI_OP_TEXT_RSP:
1503a6d42e7dSPeter Dunlap switch (ic->ic_state) {
1504a6d42e7dSPeter Dunlap case CS_S5_LOGGED_IN:
1505a6d42e7dSPeter Dunlap case CS_S6_IN_LOGOUT:
1506a6d42e7dSPeter Dunlap case CS_S7_LOGOUT_REQ:
1507a6d42e7dSPeter Dunlap action = CA_FORWARD;
1508a6d42e7dSPeter Dunlap goto validate_pdu_done;
1509a6d42e7dSPeter Dunlap case CS_S8_CLEANUP:
1510a6d42e7dSPeter Dunlap case CS_S10_IN_CLEANUP:
1511a6d42e7dSPeter Dunlap action = CA_DROP;
1512327d9711SToomas Soome goto validate_pdu_done;
1513a6d42e7dSPeter Dunlap default:
1514a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ?
1515a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR);
1516a6d42e7dSPeter Dunlap goto validate_pdu_done;
1517a6d42e7dSPeter Dunlap }
1518a6d42e7dSPeter Dunlap /*NOTREACHED*/
1519a6d42e7dSPeter Dunlap case ISCSI_OP_LOGOUT_CMD:
1520a6d42e7dSPeter Dunlap case ISCSI_OP_LOGOUT_RSP:
1521a6d42e7dSPeter Dunlap case ISCSI_OP_REJECT_MSG:
1522a6d42e7dSPeter Dunlap case ISCSI_OP_ASYNC_EVENT:
1523a6d42e7dSPeter Dunlap switch (ic->ic_state) {
1524a6d42e7dSPeter Dunlap case CS_S5_LOGGED_IN:
1525a6d42e7dSPeter Dunlap case CS_S6_IN_LOGOUT:
1526a6d42e7dSPeter Dunlap case CS_S7_LOGOUT_REQ:
1527a6d42e7dSPeter Dunlap action = CA_FORWARD;
1528a6d42e7dSPeter Dunlap goto validate_pdu_done;
1529a6d42e7dSPeter Dunlap case CS_S8_CLEANUP:
1530a6d42e7dSPeter Dunlap case CS_S10_IN_CLEANUP:
1531a6d42e7dSPeter Dunlap action = CA_DROP;
1532327d9711SToomas Soome goto validate_pdu_done;
1533a6d42e7dSPeter Dunlap default:
1534a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ?
1535a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR);
1536a6d42e7dSPeter Dunlap goto validate_pdu_done;
1537a6d42e7dSPeter Dunlap }
1538a6d42e7dSPeter Dunlap /*NOTREACHED*/
1539a6d42e7dSPeter Dunlap case ISCSI_OP_LOGIN_CMD:
1540a6d42e7dSPeter Dunlap case ISCSI_OP_LOGIN_RSP:
1541a6d42e7dSPeter Dunlap switch (ic->ic_state) {
1542a6d42e7dSPeter Dunlap case CS_S3_XPT_UP:
1543a6d42e7dSPeter Dunlap case CS_S4_IN_LOGIN:
1544a6d42e7dSPeter Dunlap action = CA_FORWARD;
1545a6d42e7dSPeter Dunlap goto validate_pdu_done;
1546a6d42e7dSPeter Dunlap default:
1547a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ?
1548a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR);
1549a6d42e7dSPeter Dunlap goto validate_pdu_done;
1550a6d42e7dSPeter Dunlap }
1551a6d42e7dSPeter Dunlap /*NOTREACHED*/
1552a6d42e7dSPeter Dunlap default:
1553a6d42e7dSPeter Dunlap /* This should never happen -- we already checked above */
1554a6d42e7dSPeter Dunlap ASSERT(0);
1555a6d42e7dSPeter Dunlap /*NOTREACHED*/
1556a6d42e7dSPeter Dunlap }
1557a6d42e7dSPeter Dunlap
1558a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ?
1559a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR);
1560a6d42e7dSPeter Dunlap
1561a6d42e7dSPeter Dunlap validate_pdu_done:
1562a6d42e7dSPeter Dunlap if (action != CA_FORWARD) {
1563a6d42e7dSPeter Dunlap DTRACE_PROBE2(idm__int__protocol__error,
1564a6d42e7dSPeter Dunlap idm_conn_event_ctx_t *, event_ctx,
1565a6d42e7dSPeter Dunlap char *, reason_string);
1566a6d42e7dSPeter Dunlap }
1567a6d42e7dSPeter Dunlap
1568a6d42e7dSPeter Dunlap return (action);
1569a6d42e7dSPeter Dunlap }
1570a6d42e7dSPeter Dunlap
1571a6d42e7dSPeter Dunlap /* ARGSUSED */
1572a6d42e7dSPeter Dunlap void
idm_pdu_tx_protocol_error(idm_conn_t * ic,idm_pdu_t * pdu)1573a6d42e7dSPeter Dunlap idm_pdu_tx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu)
1574a6d42e7dSPeter Dunlap {
1575a6d42e7dSPeter Dunlap /*
1576a6d42e7dSPeter Dunlap * Return the PDU to the caller indicating it was a protocol error.
1577a6d42e7dSPeter Dunlap * Caller can take appropriate action.
1578a6d42e7dSPeter Dunlap */
1579a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, IDM_STATUS_PROTOCOL_ERROR);
1580a6d42e7dSPeter Dunlap }
1581a6d42e7dSPeter Dunlap
1582a6d42e7dSPeter Dunlap void
idm_pdu_rx_protocol_error(idm_conn_t * ic,idm_pdu_t * pdu)1583a6d42e7dSPeter Dunlap idm_pdu_rx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu)
1584a6d42e7dSPeter Dunlap {
1585a6d42e7dSPeter Dunlap /*
1586a6d42e7dSPeter Dunlap * Forward PDU to caller indicating it is a protocol error.
1587a6d42e7dSPeter Dunlap * Caller should take appropriate action.
1588a6d42e7dSPeter Dunlap */
1589a6d42e7dSPeter Dunlap (*ic->ic_conn_ops.icb_rx_error)(ic, pdu, IDM_STATUS_PROTOCOL_ERROR);
1590a6d42e7dSPeter Dunlap }
1591a6d42e7dSPeter Dunlap
1592a6d42e7dSPeter Dunlap idm_status_t
idm_notify_client(idm_conn_t * ic,idm_client_notify_t cn,uintptr_t data)1593a6d42e7dSPeter Dunlap idm_notify_client(idm_conn_t *ic, idm_client_notify_t cn, uintptr_t data)
1594a6d42e7dSPeter Dunlap {
1595a6d42e7dSPeter Dunlap /*
1596a6d42e7dSPeter Dunlap * We may want to make this more complicated at some point but
1597a6d42e7dSPeter Dunlap * for now lets just call the client's notify function and return
1598a6d42e7dSPeter Dunlap * the status.
1599a6d42e7dSPeter Dunlap */
16005f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(!mutex_owned(&ic->ic_state_mutex));
160130e7468fSPeter Dunlap cn = (cn > CN_MAX) ? CN_MAX : cn;
160230e7468fSPeter Dunlap IDM_SM_LOG(CE_NOTE, "idm_notify_client: ic=%p %s(%d)\n",
160330e7468fSPeter Dunlap (void *)ic, idm_cn_strings[cn], cn);
1604a6d42e7dSPeter Dunlap return ((*ic->ic_conn_ops.icb_client_notify)(ic, cn, data));
1605a6d42e7dSPeter Dunlap }
1606a6d42e7dSPeter Dunlap
1607a6d42e7dSPeter Dunlap static idm_status_t
idm_ffp_enable(idm_conn_t * ic)1608a6d42e7dSPeter Dunlap idm_ffp_enable(idm_conn_t *ic)
1609a6d42e7dSPeter Dunlap {
1610a6d42e7dSPeter Dunlap idm_status_t rc;
1611a6d42e7dSPeter Dunlap
1612a6d42e7dSPeter Dunlap /*
1613a6d42e7dSPeter Dunlap * On the initiator side the client will see this notification
1614a6d42e7dSPeter Dunlap * before the actual login succes PDU. This shouldn't be a big
1615a6d42e7dSPeter Dunlap * deal since the initiator drives the connection. It can simply
1616a6d42e7dSPeter Dunlap * wait for the login response then start sending SCSI commands.
1617a6d42e7dSPeter Dunlap * Kind ugly though compared with the way things work on target
1618a6d42e7dSPeter Dunlap * connections.
1619a6d42e7dSPeter Dunlap */
1620a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex);
1621a6d42e7dSPeter Dunlap ic->ic_ffp = B_TRUE;
1622a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex);
1623a6d42e7dSPeter Dunlap
16248e718be9SToomas Soome rc = idm_notify_client(ic, CN_FFP_ENABLED, (uintptr_t)NULL);
1625a6d42e7dSPeter Dunlap if (rc != IDM_STATUS_SUCCESS) {
1626a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex);
1627a6d42e7dSPeter Dunlap ic->ic_ffp = B_FALSE;
1628a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex);
1629a6d42e7dSPeter Dunlap }
1630a6d42e7dSPeter Dunlap return (rc);
1631a6d42e7dSPeter Dunlap }
1632a6d42e7dSPeter Dunlap
1633a6d42e7dSPeter Dunlap static void
idm_ffp_disable(idm_conn_t * ic,idm_ffp_disable_t disable_type)1634a6d42e7dSPeter Dunlap idm_ffp_disable(idm_conn_t *ic, idm_ffp_disable_t disable_type)
1635a6d42e7dSPeter Dunlap {
1636a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex);
1637a6d42e7dSPeter Dunlap ic->ic_ffp = B_FALSE;
1638a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex);
1639a6d42e7dSPeter Dunlap
1640a6d42e7dSPeter Dunlap /* Client can't "fail" CN_FFP_DISABLED */
1641a6d42e7dSPeter Dunlap (void) idm_notify_client(ic, CN_FFP_DISABLED,
1642a6d42e7dSPeter Dunlap (uintptr_t)disable_type);
1643a6d42e7dSPeter Dunlap }
1644a6d42e7dSPeter Dunlap
1645a6d42e7dSPeter Dunlap static void
idm_initial_login_actions(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)1646a6d42e7dSPeter Dunlap idm_initial_login_actions(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
1647a6d42e7dSPeter Dunlap {
1648a6d42e7dSPeter Dunlap ASSERT((event_ctx->iec_event == CE_LOGIN_RCV) ||
1649a6d42e7dSPeter Dunlap (event_ctx->iec_event == CE_LOGIN_SND));
1650a6d42e7dSPeter Dunlap
1651a6d42e7dSPeter Dunlap /*
1652a6d42e7dSPeter Dunlap * Currently it's not clear what we would do here -- since
1653a6d42e7dSPeter Dunlap * we went to the trouble of coding an "initial login" hook
1654a6d42e7dSPeter Dunlap * we'll leave it in for now. Remove before integration if
1655a6d42e7dSPeter Dunlap * it's not used for anything.
1656a6d42e7dSPeter Dunlap */
1657a6d42e7dSPeter Dunlap ic->ic_state_flags |= CF_INITIAL_LOGIN;
1658a6d42e7dSPeter Dunlap }
1659a6d42e7dSPeter Dunlap
1660a6d42e7dSPeter Dunlap static void
idm_login_success_actions(idm_conn_t * ic,idm_conn_event_ctx_t * event_ctx)1661a6d42e7dSPeter Dunlap idm_login_success_actions(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx)
1662a6d42e7dSPeter Dunlap {
1663a6d42e7dSPeter Dunlap idm_pdu_t *pdu = (idm_pdu_t *)event_ctx->iec_info;
1664a6d42e7dSPeter Dunlap iscsi_login_hdr_t *login_req =
1665a6d42e7dSPeter Dunlap (iscsi_login_hdr_t *)pdu->isp_hdr;
1666a6d42e7dSPeter Dunlap
1667a6d42e7dSPeter Dunlap ASSERT((event_ctx->iec_event == CE_LOGIN_SUCCESS_RCV) ||
1668a6d42e7dSPeter Dunlap (event_ctx->iec_event == CE_LOGIN_SUCCESS_SND));
1669a6d42e7dSPeter Dunlap
1670a6d42e7dSPeter Dunlap /*
1671a6d42e7dSPeter Dunlap * Save off CID
1672a6d42e7dSPeter Dunlap */
1673a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex);
1674a6d42e7dSPeter Dunlap ic->ic_login_cid = ntohs(login_req->cid);
1675a6d42e7dSPeter Dunlap ic->ic_login_info_valid = B_TRUE;
1676a6d42e7dSPeter Dunlap
1677a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex);
1678a6d42e7dSPeter Dunlap }
1679