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 /* 23*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24a6d42e7dSPeter Dunlap * Use is subject to license terms. 25a6d42e7dSPeter Dunlap */ 26a6d42e7dSPeter Dunlap 27a6d42e7dSPeter Dunlap #include <sys/cpuvar.h> 28a6d42e7dSPeter Dunlap #include <sys/ddi.h> 29a6d42e7dSPeter Dunlap #include <sys/sunddi.h> 30a6d42e7dSPeter Dunlap #include <sys/modctl.h> 31a6d42e7dSPeter Dunlap #include <sys/socket.h> 32a6d42e7dSPeter Dunlap #include <sys/strsubr.h> 33a6d42e7dSPeter Dunlap #include <sys/note.h> 34a6d42e7dSPeter Dunlap #include <sys/sdt.h> 35a6d42e7dSPeter Dunlap 36a6d42e7dSPeter Dunlap #define IDM_CONN_SM_STRINGS 3730e7468fSPeter Dunlap #define IDM_CN_NOTIFY_STRINGS 38a6d42e7dSPeter Dunlap #include <sys/idm/idm.h> 39a6d42e7dSPeter Dunlap 40a6d42e7dSPeter Dunlap boolean_t idm_sm_logging = B_FALSE; 41a6d42e7dSPeter Dunlap 42a6d42e7dSPeter Dunlap extern idm_global_t idm; /* Global state */ 43a6d42e7dSPeter Dunlap 44a6d42e7dSPeter Dunlap static void 45a6d42e7dSPeter Dunlap idm_conn_event_handler(void *event_ctx_opaque); 46a6d42e7dSPeter Dunlap 47a6d42e7dSPeter Dunlap static void 48a6d42e7dSPeter Dunlap idm_state_s1_free(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 49a6d42e7dSPeter Dunlap 50a6d42e7dSPeter Dunlap static void 51a6d42e7dSPeter Dunlap idm_state_s2_xpt_wait(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 52a6d42e7dSPeter Dunlap 53a6d42e7dSPeter Dunlap static void 54a6d42e7dSPeter Dunlap idm_state_s3_xpt_up(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 55a6d42e7dSPeter Dunlap 56a6d42e7dSPeter Dunlap static void 57a6d42e7dSPeter Dunlap idm_state_s4_in_login(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 58a6d42e7dSPeter Dunlap 59a6d42e7dSPeter Dunlap static void 60a6d42e7dSPeter Dunlap idm_state_s5_logged_in(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 61a6d42e7dSPeter Dunlap 62a6d42e7dSPeter Dunlap static void 63a6d42e7dSPeter Dunlap idm_state_s6_in_logout(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 64a6d42e7dSPeter Dunlap 65a6d42e7dSPeter Dunlap static void 66a6d42e7dSPeter Dunlap idm_logout_req_timeout(void *arg); 67a6d42e7dSPeter Dunlap 68a6d42e7dSPeter Dunlap static void 69a6d42e7dSPeter Dunlap idm_state_s7_logout_req(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 70a6d42e7dSPeter Dunlap 71a6d42e7dSPeter Dunlap static void 72a6d42e7dSPeter Dunlap idm_state_s8_cleanup(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 73a6d42e7dSPeter Dunlap 74a6d42e7dSPeter Dunlap static void 75a6d42e7dSPeter Dunlap idm_state_s9_init_error(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 76a6d42e7dSPeter Dunlap 77e42a0851Speter dunlap static void 78e42a0851Speter dunlap idm_state_s9a_rejected(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 79e42a0851Speter dunlap 80*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States static void 81*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done_cb(idm_pdu_t *pdu, 82*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_status_t status); 83*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 84*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States static void 85*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done(idm_conn_t *ic, 86*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_event_ctx_t *event_ctx); 87*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 88a6d42e7dSPeter Dunlap static void 89a6d42e7dSPeter Dunlap idm_state_s10_in_cleanup(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 90a6d42e7dSPeter Dunlap 91a6d42e7dSPeter Dunlap static void 92a6d42e7dSPeter Dunlap idm_state_s11_complete(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 93a6d42e7dSPeter Dunlap 94a6d42e7dSPeter Dunlap static void 95a6d42e7dSPeter Dunlap idm_state_s12_enable_dm(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 96a6d42e7dSPeter Dunlap 97a6d42e7dSPeter Dunlap static void 98a6d42e7dSPeter Dunlap idm_update_state(idm_conn_t *ic, idm_conn_state_t new_state, 99a6d42e7dSPeter Dunlap idm_conn_event_ctx_t *event_ctx); 100a6d42e7dSPeter Dunlap 101a6d42e7dSPeter Dunlap static void 102a6d42e7dSPeter Dunlap idm_conn_unref(void *ic_void); 103a6d42e7dSPeter Dunlap 104e42a0851Speter dunlap static void 105e42a0851Speter dunlap idm_conn_reject_unref(void *ic_void); 106e42a0851Speter dunlap 107a6d42e7dSPeter Dunlap static idm_pdu_event_action_t 108a6d42e7dSPeter Dunlap idm_conn_sm_validate_pdu(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx, 109a6d42e7dSPeter Dunlap idm_pdu_t *pdu); 110a6d42e7dSPeter Dunlap 111a6d42e7dSPeter Dunlap static idm_status_t 112a6d42e7dSPeter Dunlap idm_ffp_enable(idm_conn_t *ic); 113a6d42e7dSPeter Dunlap 114a6d42e7dSPeter Dunlap static void 115a6d42e7dSPeter Dunlap idm_ffp_disable(idm_conn_t *ic, idm_ffp_disable_t disable_type); 116a6d42e7dSPeter Dunlap 117a6d42e7dSPeter Dunlap static void 118a6d42e7dSPeter Dunlap idm_initial_login_actions(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 119a6d42e7dSPeter Dunlap 120a6d42e7dSPeter Dunlap static void 121a6d42e7dSPeter Dunlap idm_login_success_actions(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx); 122a6d42e7dSPeter Dunlap 123a6d42e7dSPeter Dunlap idm_status_t 124a6d42e7dSPeter Dunlap idm_conn_sm_init(idm_conn_t *ic) 125a6d42e7dSPeter Dunlap { 126a6d42e7dSPeter Dunlap char taskq_name[32]; 127a6d42e7dSPeter Dunlap 128a6d42e7dSPeter Dunlap /* 129a6d42e7dSPeter Dunlap * Caller should have assigned a unique connection ID. Use this 130a6d42e7dSPeter Dunlap * connection ID to create a unique connection name string 131a6d42e7dSPeter Dunlap */ 132a6d42e7dSPeter Dunlap ASSERT(ic->ic_internal_cid != 0); 133a6d42e7dSPeter Dunlap (void) snprintf(taskq_name, sizeof (taskq_name) - 1, "conn_sm%08x", 134a6d42e7dSPeter Dunlap ic->ic_internal_cid); 135a6d42e7dSPeter Dunlap 13630e7468fSPeter Dunlap ic->ic_state_taskq = taskq_create(taskq_name, 1, minclsyspri, 4, 16384, 137a6d42e7dSPeter Dunlap TASKQ_PREPOPULATE); 138a6d42e7dSPeter Dunlap if (ic->ic_state_taskq == NULL) { 139a6d42e7dSPeter Dunlap return (IDM_STATUS_FAIL); 140a6d42e7dSPeter Dunlap } 141a6d42e7dSPeter Dunlap 142a6d42e7dSPeter Dunlap idm_sm_audit_init(&ic->ic_state_audit); 143a6d42e7dSPeter Dunlap mutex_init(&ic->ic_state_mutex, NULL, MUTEX_DEFAULT, NULL); 144a6d42e7dSPeter Dunlap cv_init(&ic->ic_state_cv, NULL, CV_DEFAULT, NULL); 145a6d42e7dSPeter Dunlap 146a6d42e7dSPeter Dunlap ic->ic_state = CS_S1_FREE; 147a6d42e7dSPeter Dunlap ic->ic_last_state = CS_S1_FREE; 148a6d42e7dSPeter Dunlap 149a6d42e7dSPeter Dunlap return (IDM_STATUS_SUCCESS); 150a6d42e7dSPeter Dunlap } 151a6d42e7dSPeter Dunlap 152a6d42e7dSPeter Dunlap void 153a6d42e7dSPeter Dunlap idm_conn_sm_fini(idm_conn_t *ic) 154a6d42e7dSPeter Dunlap { 1551050fd6dSJames Moore 1561050fd6dSJames Moore /* 1571050fd6dSJames Moore * The connection may only be partially created. If there 1581050fd6dSJames Moore * is no taskq, then the connection SM was not initialized. 1591050fd6dSJames Moore */ 1601050fd6dSJames Moore if (ic->ic_state_taskq == NULL) { 1611050fd6dSJames Moore return; 1621050fd6dSJames Moore } 1631050fd6dSJames Moore 164a6d42e7dSPeter Dunlap taskq_destroy(ic->ic_state_taskq); 165a6d42e7dSPeter Dunlap 166a6d42e7dSPeter Dunlap cv_destroy(&ic->ic_state_cv); 167a6d42e7dSPeter Dunlap /* 168a6d42e7dSPeter Dunlap * The thread that generated the event that got us here may still 169a6d42e7dSPeter Dunlap * hold the ic_state_mutex. Once it is released we can safely 170a6d42e7dSPeter Dunlap * destroy it since there is no way to locate the object now. 171a6d42e7dSPeter Dunlap */ 172a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 173a6d42e7dSPeter Dunlap mutex_destroy(&ic->ic_state_mutex); 174a6d42e7dSPeter Dunlap } 175a6d42e7dSPeter Dunlap 176a6d42e7dSPeter Dunlap void 177a6d42e7dSPeter Dunlap idm_conn_event(idm_conn_t *ic, idm_conn_event_t event, uintptr_t event_info) 178a6d42e7dSPeter Dunlap { 179a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 180a6d42e7dSPeter Dunlap idm_conn_event_locked(ic, event, event_info, CT_NONE); 181a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 182a6d42e7dSPeter Dunlap } 183a6d42e7dSPeter Dunlap 18430e7468fSPeter Dunlap 185a6d42e7dSPeter Dunlap idm_status_t 186a6d42e7dSPeter Dunlap idm_conn_reinstate_event(idm_conn_t *old_ic, idm_conn_t *new_ic) 187a6d42e7dSPeter Dunlap { 188a6d42e7dSPeter Dunlap int result; 189a6d42e7dSPeter Dunlap 190a6d42e7dSPeter Dunlap mutex_enter(&old_ic->ic_state_mutex); 191a6d42e7dSPeter Dunlap if (((old_ic->ic_conn_type == CONN_TYPE_INI) && 192a6d42e7dSPeter Dunlap (old_ic->ic_state != CS_S8_CLEANUP)) || 193a6d42e7dSPeter Dunlap ((old_ic->ic_conn_type == CONN_TYPE_TGT) && 194a6d42e7dSPeter Dunlap (old_ic->ic_state < CS_S5_LOGGED_IN))) { 195a6d42e7dSPeter Dunlap result = IDM_STATUS_FAIL; 196a6d42e7dSPeter Dunlap } else { 197a6d42e7dSPeter Dunlap result = IDM_STATUS_SUCCESS; 198a6d42e7dSPeter Dunlap new_ic->ic_reinstate_conn = old_ic; 199a6d42e7dSPeter Dunlap idm_conn_event_locked(new_ic->ic_reinstate_conn, 200a6d42e7dSPeter Dunlap CE_CONN_REINSTATE, (uintptr_t)new_ic, CT_NONE); 201a6d42e7dSPeter Dunlap } 202a6d42e7dSPeter Dunlap mutex_exit(&old_ic->ic_state_mutex); 203a6d42e7dSPeter Dunlap 204a6d42e7dSPeter Dunlap return (result); 205a6d42e7dSPeter Dunlap } 206a6d42e7dSPeter Dunlap 207a6d42e7dSPeter Dunlap void 208a6d42e7dSPeter Dunlap idm_conn_tx_pdu_event(idm_conn_t *ic, idm_conn_event_t event, 209a6d42e7dSPeter Dunlap uintptr_t event_info) 210a6d42e7dSPeter Dunlap { 211a6d42e7dSPeter Dunlap ASSERT(mutex_owned(&ic->ic_state_mutex)); 212a6d42e7dSPeter Dunlap ic->ic_pdu_events++; 213a6d42e7dSPeter Dunlap idm_conn_event_locked(ic, event, event_info, CT_TX_PDU); 214a6d42e7dSPeter Dunlap } 215a6d42e7dSPeter Dunlap 216a6d42e7dSPeter Dunlap void 217a6d42e7dSPeter Dunlap idm_conn_rx_pdu_event(idm_conn_t *ic, idm_conn_event_t event, 218a6d42e7dSPeter Dunlap uintptr_t event_info) 219a6d42e7dSPeter Dunlap { 220a6d42e7dSPeter Dunlap ASSERT(mutex_owned(&ic->ic_state_mutex)); 221a6d42e7dSPeter Dunlap ic->ic_pdu_events++; 222a6d42e7dSPeter Dunlap idm_conn_event_locked(ic, event, event_info, CT_RX_PDU); 223a6d42e7dSPeter Dunlap } 224a6d42e7dSPeter Dunlap 22530e7468fSPeter Dunlap void 226a6d42e7dSPeter Dunlap idm_conn_event_locked(idm_conn_t *ic, idm_conn_event_t event, 227a6d42e7dSPeter Dunlap uintptr_t event_info, idm_pdu_event_type_t pdu_event_type) 228a6d42e7dSPeter Dunlap { 229a6d42e7dSPeter Dunlap idm_conn_event_ctx_t *event_ctx; 230a6d42e7dSPeter Dunlap 23192adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(mutex_owned(&ic->ic_state_mutex)); 23292adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States 233a6d42e7dSPeter Dunlap idm_sm_audit_event(&ic->ic_state_audit, SAS_IDM_CONN, 234a6d42e7dSPeter Dunlap (int)ic->ic_state, (int)event, event_info); 235a6d42e7dSPeter Dunlap 236a6d42e7dSPeter Dunlap /* 237a6d42e7dSPeter Dunlap * It's very difficult to prevent a few straggling events 238a6d42e7dSPeter Dunlap * at the end. For example idm_sorx_thread will generate 239a6d42e7dSPeter Dunlap * a CE_TRANSPORT_FAIL event when it exits. Rather than 240a6d42e7dSPeter Dunlap * push complicated restrictions all over the code to 241a6d42e7dSPeter Dunlap * prevent this we will simply drop the events (and in 242a6d42e7dSPeter Dunlap * the case of PDU events release them appropriately) 243a6d42e7dSPeter Dunlap * since they are irrelevant once we are in a terminal state. 244a6d42e7dSPeter Dunlap * Of course those threads need to have appropriate holds on 245a6d42e7dSPeter Dunlap * the connection otherwise it might disappear. 246a6d42e7dSPeter Dunlap */ 247a6d42e7dSPeter Dunlap if ((ic->ic_state == CS_S9_INIT_ERROR) || 248e42a0851Speter dunlap (ic->ic_state == CS_S9A_REJECTED) || 249a6d42e7dSPeter Dunlap (ic->ic_state == CS_S11_COMPLETE)) { 250a6d42e7dSPeter Dunlap if ((pdu_event_type == CT_TX_PDU) || 251a6d42e7dSPeter Dunlap (pdu_event_type == CT_RX_PDU)) { 252a6d42e7dSPeter Dunlap ic->ic_pdu_events--; 253a6d42e7dSPeter Dunlap idm_pdu_complete((idm_pdu_t *)event_info, 254a6d42e7dSPeter Dunlap IDM_STATUS_SUCCESS); 255a6d42e7dSPeter Dunlap } 256a6d42e7dSPeter Dunlap IDM_SM_LOG(CE_NOTE, "*** Dropping event %s (%d) because of" 257a6d42e7dSPeter Dunlap "state %s (%d)", 258a6d42e7dSPeter Dunlap idm_ce_name[event], event, 259a6d42e7dSPeter Dunlap idm_cs_name[ic->ic_state], ic->ic_state); 260a6d42e7dSPeter Dunlap return; 261a6d42e7dSPeter Dunlap } 262a6d42e7dSPeter Dunlap 263a6d42e7dSPeter Dunlap /* 264a6d42e7dSPeter Dunlap * Normal event handling 265a6d42e7dSPeter Dunlap */ 266a6d42e7dSPeter Dunlap idm_conn_hold(ic); 267a6d42e7dSPeter Dunlap 268a6d42e7dSPeter Dunlap event_ctx = kmem_zalloc(sizeof (*event_ctx), KM_SLEEP); 269a6d42e7dSPeter Dunlap event_ctx->iec_ic = ic; 270a6d42e7dSPeter Dunlap event_ctx->iec_event = event; 271a6d42e7dSPeter Dunlap event_ctx->iec_info = event_info; 272a6d42e7dSPeter Dunlap event_ctx->iec_pdu_event_type = pdu_event_type; 273a6d42e7dSPeter Dunlap 274a6d42e7dSPeter Dunlap (void) taskq_dispatch(ic->ic_state_taskq, &idm_conn_event_handler, 275a6d42e7dSPeter Dunlap event_ctx, TQ_SLEEP); 276a6d42e7dSPeter Dunlap } 277a6d42e7dSPeter Dunlap 278a6d42e7dSPeter Dunlap static void 279a6d42e7dSPeter Dunlap idm_conn_event_handler(void *event_ctx_opaque) 280a6d42e7dSPeter Dunlap { 281a6d42e7dSPeter Dunlap idm_conn_event_ctx_t *event_ctx = event_ctx_opaque; 282a6d42e7dSPeter Dunlap idm_conn_t *ic = event_ctx->iec_ic; 283a6d42e7dSPeter Dunlap idm_pdu_t *pdu = (idm_pdu_t *)event_ctx->iec_info; 284a6d42e7dSPeter Dunlap idm_pdu_event_action_t action; 285a6d42e7dSPeter Dunlap 286a6d42e7dSPeter Dunlap IDM_SM_LOG(CE_NOTE, "idm_conn_event_handler: conn %p event %s(%d)", 287a6d42e7dSPeter Dunlap (void *)ic, idm_ce_name[event_ctx->iec_event], 288a6d42e7dSPeter Dunlap event_ctx->iec_event); 289a6d42e7dSPeter Dunlap DTRACE_PROBE2(conn__event, 29030e7468fSPeter Dunlap idm_conn_t *, ic, idm_conn_event_ctx_t *, event_ctx); 291a6d42e7dSPeter Dunlap 292a6d42e7dSPeter Dunlap /* 293a6d42e7dSPeter Dunlap * Validate event 294a6d42e7dSPeter Dunlap */ 295a6d42e7dSPeter Dunlap ASSERT(event_ctx->iec_event != CE_UNDEFINED); 296a6d42e7dSPeter Dunlap ASSERT3U(event_ctx->iec_event, <, CE_MAX_EVENT); 297a6d42e7dSPeter Dunlap 298a6d42e7dSPeter Dunlap /* 299a6d42e7dSPeter Dunlap * Validate current state 300a6d42e7dSPeter Dunlap */ 301a6d42e7dSPeter Dunlap ASSERT(ic->ic_state != CS_S0_UNDEFINED); 302a6d42e7dSPeter Dunlap ASSERT3U(ic->ic_state, <, CS_MAX_STATE); 303a6d42e7dSPeter Dunlap 304a6d42e7dSPeter Dunlap /* 305a6d42e7dSPeter Dunlap * Validate PDU-related events against the current state. If a PDU 306a6d42e7dSPeter Dunlap * is not allowed in the current state we change the event to a 307a6d42e7dSPeter Dunlap * protocol error. This simplifies the state-specific event handlers. 308a6d42e7dSPeter Dunlap * For example the CS_S2_XPT_WAIT state only needs to handle the 309a6d42e7dSPeter Dunlap * CE_TX_PROTOCOL_ERROR and CE_RX_PROTOCOL_ERROR events since 310a6d42e7dSPeter Dunlap * no PDU's can be transmitted or received in that state. 311a6d42e7dSPeter Dunlap */ 31230e7468fSPeter Dunlap event_ctx->iec_pdu_forwarded = B_FALSE; 313a6d42e7dSPeter Dunlap if (event_ctx->iec_pdu_event_type != CT_NONE) { 314a6d42e7dSPeter Dunlap ASSERT(pdu != NULL); 315a6d42e7dSPeter Dunlap action = idm_conn_sm_validate_pdu(ic, event_ctx, pdu); 316a6d42e7dSPeter Dunlap 317a6d42e7dSPeter Dunlap switch (action) { 318a6d42e7dSPeter Dunlap case CA_TX_PROTOCOL_ERROR: 319a6d42e7dSPeter Dunlap /* 320a6d42e7dSPeter Dunlap * Change event and forward the PDU 321a6d42e7dSPeter Dunlap */ 322a6d42e7dSPeter Dunlap event_ctx->iec_event = CE_TX_PROTOCOL_ERROR; 323a6d42e7dSPeter Dunlap break; 324a6d42e7dSPeter Dunlap case CA_RX_PROTOCOL_ERROR: 325a6d42e7dSPeter Dunlap /* 326a6d42e7dSPeter Dunlap * Change event and forward the PDU. 327a6d42e7dSPeter Dunlap */ 328a6d42e7dSPeter Dunlap event_ctx->iec_event = CE_RX_PROTOCOL_ERROR; 329a6d42e7dSPeter Dunlap break; 330a6d42e7dSPeter Dunlap case CA_FORWARD: 331a6d42e7dSPeter Dunlap /* 332a6d42e7dSPeter Dunlap * Let the state-specific event handlers take 333a6d42e7dSPeter Dunlap * care of it. 334a6d42e7dSPeter Dunlap */ 335a6d42e7dSPeter Dunlap break; 336a6d42e7dSPeter Dunlap case CA_DROP: 337a6d42e7dSPeter Dunlap /* 338a6d42e7dSPeter Dunlap * It never even happened 339a6d42e7dSPeter Dunlap */ 340a6d42e7dSPeter Dunlap IDM_SM_LOG(CE_NOTE, "*** drop PDU %p", (void *) pdu); 341a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, IDM_STATUS_FAIL); 342a6d42e7dSPeter Dunlap break; 343a6d42e7dSPeter Dunlap default: 344a6d42e7dSPeter Dunlap ASSERT(0); 345a6d42e7dSPeter Dunlap break; 346a6d42e7dSPeter Dunlap } 347a6d42e7dSPeter Dunlap } 348a6d42e7dSPeter Dunlap 349a6d42e7dSPeter Dunlap switch (ic->ic_state) { 350a6d42e7dSPeter Dunlap case CS_S1_FREE: 351a6d42e7dSPeter Dunlap idm_state_s1_free(ic, event_ctx); 352a6d42e7dSPeter Dunlap break; 353a6d42e7dSPeter Dunlap case CS_S2_XPT_WAIT: 354a6d42e7dSPeter Dunlap idm_state_s2_xpt_wait(ic, event_ctx); 355a6d42e7dSPeter Dunlap break; 356a6d42e7dSPeter Dunlap case CS_S3_XPT_UP: 357a6d42e7dSPeter Dunlap idm_state_s3_xpt_up(ic, event_ctx); 358a6d42e7dSPeter Dunlap break; 359a6d42e7dSPeter Dunlap case CS_S4_IN_LOGIN: 360a6d42e7dSPeter Dunlap idm_state_s4_in_login(ic, event_ctx); 361a6d42e7dSPeter Dunlap break; 362a6d42e7dSPeter Dunlap case CS_S5_LOGGED_IN: 363a6d42e7dSPeter Dunlap idm_state_s5_logged_in(ic, event_ctx); 364a6d42e7dSPeter Dunlap break; 365a6d42e7dSPeter Dunlap case CS_S6_IN_LOGOUT: 366a6d42e7dSPeter Dunlap idm_state_s6_in_logout(ic, event_ctx); 367a6d42e7dSPeter Dunlap break; 368a6d42e7dSPeter Dunlap case CS_S7_LOGOUT_REQ: 369a6d42e7dSPeter Dunlap idm_state_s7_logout_req(ic, event_ctx); 370a6d42e7dSPeter Dunlap break; 371a6d42e7dSPeter Dunlap case CS_S8_CLEANUP: 372a6d42e7dSPeter Dunlap idm_state_s8_cleanup(ic, event_ctx); 373a6d42e7dSPeter Dunlap break; 374e42a0851Speter dunlap case CS_S9A_REJECTED: 375e42a0851Speter dunlap idm_state_s9a_rejected(ic, event_ctx); 376e42a0851Speter dunlap break; 377*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CS_S9B_WAIT_SND_DONE: 378*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done(ic, event_ctx); 379*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States break; 380a6d42e7dSPeter Dunlap case CS_S9_INIT_ERROR: 381a6d42e7dSPeter Dunlap idm_state_s9_init_error(ic, event_ctx); 382a6d42e7dSPeter Dunlap break; 383a6d42e7dSPeter Dunlap case CS_S10_IN_CLEANUP: 384a6d42e7dSPeter Dunlap idm_state_s10_in_cleanup(ic, event_ctx); 385a6d42e7dSPeter Dunlap break; 386a6d42e7dSPeter Dunlap case CS_S11_COMPLETE: 387a6d42e7dSPeter Dunlap idm_state_s11_complete(ic, event_ctx); 388a6d42e7dSPeter Dunlap break; 389a6d42e7dSPeter Dunlap case CS_S12_ENABLE_DM: 390a6d42e7dSPeter Dunlap idm_state_s12_enable_dm(ic, event_ctx); 391a6d42e7dSPeter Dunlap break; 392a6d42e7dSPeter Dunlap default: 393a6d42e7dSPeter Dunlap ASSERT(0); 394a6d42e7dSPeter Dunlap break; 395a6d42e7dSPeter Dunlap } 396a6d42e7dSPeter Dunlap 397a6d42e7dSPeter Dunlap /* 398a6d42e7dSPeter Dunlap * Now that we've updated the state machine, if this was 399a6d42e7dSPeter Dunlap * a PDU-related event take the appropriate action on the PDU 400a6d42e7dSPeter Dunlap * (transmit it, forward it to the clients RX callback, drop 401a6d42e7dSPeter Dunlap * it, etc). 402a6d42e7dSPeter Dunlap */ 403a6d42e7dSPeter Dunlap if (event_ctx->iec_pdu_event_type != CT_NONE) { 404a6d42e7dSPeter Dunlap switch (action) { 405a6d42e7dSPeter Dunlap case CA_TX_PROTOCOL_ERROR: 406a6d42e7dSPeter Dunlap idm_pdu_tx_protocol_error(ic, pdu); 407a6d42e7dSPeter Dunlap break; 408a6d42e7dSPeter Dunlap case CA_RX_PROTOCOL_ERROR: 409a6d42e7dSPeter Dunlap idm_pdu_rx_protocol_error(ic, pdu); 410a6d42e7dSPeter Dunlap break; 411a6d42e7dSPeter Dunlap case CA_FORWARD: 41230e7468fSPeter Dunlap if (!event_ctx->iec_pdu_forwarded) { 41330e7468fSPeter Dunlap if (event_ctx->iec_pdu_event_type == 41430e7468fSPeter Dunlap CT_RX_PDU) { 41530e7468fSPeter Dunlap idm_pdu_rx_forward(ic, pdu); 41630e7468fSPeter Dunlap } else { 41730e7468fSPeter Dunlap idm_pdu_tx_forward(ic, pdu); 41830e7468fSPeter Dunlap } 419a6d42e7dSPeter Dunlap } 420a6d42e7dSPeter Dunlap break; 421a6d42e7dSPeter Dunlap default: 422a6d42e7dSPeter Dunlap ASSERT(0); 423a6d42e7dSPeter Dunlap break; 424a6d42e7dSPeter Dunlap } 425a6d42e7dSPeter Dunlap } 426a6d42e7dSPeter Dunlap 427a6d42e7dSPeter Dunlap /* 428a6d42e7dSPeter Dunlap * Update outstanding PDU event count (see idm_pdu_tx for 429a6d42e7dSPeter Dunlap * how this is used) 430a6d42e7dSPeter Dunlap */ 431a6d42e7dSPeter Dunlap if ((event_ctx->iec_pdu_event_type == CT_TX_PDU) || 432a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_RX_PDU)) { 433a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 434a6d42e7dSPeter Dunlap ic->ic_pdu_events--; 435a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 436a6d42e7dSPeter Dunlap } 437a6d42e7dSPeter Dunlap 438a6d42e7dSPeter Dunlap idm_conn_rele(ic); 439a6d42e7dSPeter Dunlap kmem_free(event_ctx, sizeof (*event_ctx)); 440a6d42e7dSPeter Dunlap } 441a6d42e7dSPeter Dunlap 442a6d42e7dSPeter Dunlap static void 443a6d42e7dSPeter Dunlap idm_state_s1_free(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 444a6d42e7dSPeter Dunlap { 445a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 446a6d42e7dSPeter Dunlap case CE_CONNECT_REQ: 447a6d42e7dSPeter Dunlap /* T1 */ 448a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S2_XPT_WAIT, event_ctx); 449a6d42e7dSPeter Dunlap break; 450a6d42e7dSPeter Dunlap case CE_CONNECT_ACCEPT: 451a6d42e7dSPeter Dunlap /* T3 */ 452a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S3_XPT_UP, event_ctx); 453a6d42e7dSPeter Dunlap break; 454a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 455a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 456a6d42e7dSPeter Dunlap /* This should never happen */ 457a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx); 458a6d42e7dSPeter Dunlap break; 459a6d42e7dSPeter Dunlap default: 460a6d42e7dSPeter Dunlap ASSERT(0); 461a6d42e7dSPeter Dunlap /*NOTREACHED*/ 462a6d42e7dSPeter Dunlap } 463a6d42e7dSPeter Dunlap } 464a6d42e7dSPeter Dunlap 465a6d42e7dSPeter Dunlap 466a6d42e7dSPeter Dunlap static void 467a6d42e7dSPeter Dunlap idm_state_s2_xpt_wait(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 468a6d42e7dSPeter Dunlap { 469a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 470a6d42e7dSPeter Dunlap case CE_CONNECT_SUCCESS: 471a6d42e7dSPeter Dunlap /* T4 */ 472a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S4_IN_LOGIN, event_ctx); 473a6d42e7dSPeter Dunlap break; 4745f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_TRANSPORT_FAIL: 475a6d42e7dSPeter Dunlap case CE_CONNECT_FAIL: 476a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_RCV: 477a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 478a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 479a6d42e7dSPeter Dunlap /* T2 */ 480a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx); 481a6d42e7dSPeter Dunlap break; 482a6d42e7dSPeter Dunlap default: 483a6d42e7dSPeter Dunlap ASSERT(0); 484a6d42e7dSPeter Dunlap /*NOTREACHED*/ 485a6d42e7dSPeter Dunlap } 486a6d42e7dSPeter Dunlap } 487a6d42e7dSPeter Dunlap 488a6d42e7dSPeter Dunlap 489a6d42e7dSPeter Dunlap static void 490a6d42e7dSPeter Dunlap idm_login_timeout(void *arg) 491a6d42e7dSPeter Dunlap { 492a6d42e7dSPeter Dunlap idm_conn_t *ic = arg; 493a6d42e7dSPeter Dunlap 494a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_LOGIN_TIMEOUT, NULL); 495a6d42e7dSPeter Dunlap } 496a6d42e7dSPeter Dunlap 497a6d42e7dSPeter Dunlap static void 498a6d42e7dSPeter Dunlap idm_state_s3_xpt_up(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 499a6d42e7dSPeter Dunlap { 500a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 501a6d42e7dSPeter Dunlap case CE_LOGIN_RCV: 502a6d42e7dSPeter Dunlap /* T4 */ 503a6d42e7dSPeter Dunlap idm_initial_login_actions(ic, event_ctx); 504a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S4_IN_LOGIN, event_ctx); 505a6d42e7dSPeter Dunlap break; 506a6d42e7dSPeter Dunlap case CE_LOGIN_TIMEOUT: 507a6d42e7dSPeter Dunlap /* 508a6d42e7dSPeter Dunlap * Don't need to cancel login timer since the timer is 509a6d42e7dSPeter Dunlap * presumed to be the source of this event. 510a6d42e7dSPeter Dunlap */ 511a6d42e7dSPeter Dunlap (void) idm_notify_client(ic, CN_LOGIN_FAIL, NULL); 512a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx); 513a6d42e7dSPeter Dunlap break; 514a6d42e7dSPeter Dunlap case CE_CONNECT_REJECT: 515e42a0851Speter dunlap /* 516e42a0851Speter dunlap * Iscsit doesn't want to hear from us again in this case. 517e42a0851Speter dunlap * Since it rejected the connection it doesn't have a 518e42a0851Speter dunlap * connection context to handle additional notifications. 519e42a0851Speter dunlap * IDM needs to just clean things up on its own. 520e42a0851Speter dunlap */ 521e42a0851Speter dunlap (void) untimeout(ic->ic_state_timeout); 522e42a0851Speter dunlap idm_update_state(ic, CS_S9A_REJECTED, event_ctx); 523e42a0851Speter dunlap break; 524a6d42e7dSPeter Dunlap case CE_CONNECT_FAIL: 525a6d42e7dSPeter Dunlap case CE_TRANSPORT_FAIL: 526a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_SND: 527a6d42e7dSPeter Dunlap /* T6 */ 528a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 529a6d42e7dSPeter Dunlap (void) idm_notify_client(ic, CN_LOGIN_FAIL, NULL); 530a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx); 531a6d42e7dSPeter Dunlap break; 532a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 533a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 534a6d42e7dSPeter Dunlap /* Don't care */ 535a6d42e7dSPeter Dunlap break; 536a6d42e7dSPeter Dunlap default: 537a6d42e7dSPeter Dunlap ASSERT(0); 538a6d42e7dSPeter Dunlap /*NOTREACHED*/ 539a6d42e7dSPeter Dunlap } 540a6d42e7dSPeter Dunlap } 541a6d42e7dSPeter Dunlap 542a6d42e7dSPeter Dunlap static void 543a6d42e7dSPeter Dunlap idm_state_s4_in_login(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 544a6d42e7dSPeter Dunlap { 545a6d42e7dSPeter Dunlap idm_pdu_t *pdu; 546a6d42e7dSPeter Dunlap 547a6d42e7dSPeter Dunlap /* 548a6d42e7dSPeter Dunlap * Login timer should no longer be active after leaving this 549a6d42e7dSPeter Dunlap * state. 550a6d42e7dSPeter Dunlap */ 551a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 552a6d42e7dSPeter Dunlap case CE_LOGIN_SUCCESS_RCV: 553a6d42e7dSPeter Dunlap case CE_LOGIN_SUCCESS_SND: 554*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(ic->ic_client_callback == NULL); 555*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 556a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 557a6d42e7dSPeter Dunlap idm_login_success_actions(ic, event_ctx); 558a6d42e7dSPeter Dunlap if (ic->ic_rdma_extensions) { 559a6d42e7dSPeter Dunlap /* T19 */ 560a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S12_ENABLE_DM, event_ctx); 561a6d42e7dSPeter Dunlap } else { 562a6d42e7dSPeter Dunlap /* T5 */ 563a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S5_LOGGED_IN, event_ctx); 564a6d42e7dSPeter Dunlap } 565a6d42e7dSPeter Dunlap break; 566a6d42e7dSPeter Dunlap case CE_LOGIN_TIMEOUT: 567a6d42e7dSPeter Dunlap /* T7 */ 568a6d42e7dSPeter Dunlap (void) idm_notify_client(ic, CN_LOGIN_FAIL, NULL); 569a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx); 570a6d42e7dSPeter Dunlap break; 571a6d42e7dSPeter Dunlap case CE_LOGIN_FAIL_SND: 572a6d42e7dSPeter Dunlap /* 573a6d42e7dSPeter Dunlap * Allow the logout response pdu to be sent and defer 574*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * the state machine cleanup until the completion callback. 575a6d42e7dSPeter Dunlap * Only 1 level or callback interposition is allowed. 576a6d42e7dSPeter Dunlap */ 577a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 578a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 579a6d42e7dSPeter Dunlap ASSERT(ic->ic_client_callback == NULL); 580a6d42e7dSPeter Dunlap ic->ic_client_callback = pdu->isp_callback; 581a6d42e7dSPeter Dunlap pdu->isp_callback = 582*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done_cb; 583*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_update_state(ic, CS_S9B_WAIT_SND_DONE, 584*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States event_ctx); 585a6d42e7dSPeter Dunlap break; 586a6d42e7dSPeter Dunlap case CE_LOGIN_FAIL_RCV: 587*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(ic->ic_client_callback == NULL); 58830e7468fSPeter Dunlap /* 58930e7468fSPeter Dunlap * Need to deliver this PDU to the initiator now because after 59030e7468fSPeter Dunlap * we update the state to CS_S9_INIT_ERROR the initiator will 59130e7468fSPeter Dunlap * no longer be in an appropriate state. 59230e7468fSPeter Dunlap */ 59330e7468fSPeter Dunlap event_ctx->iec_pdu_forwarded = B_TRUE; 59430e7468fSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 59530e7468fSPeter Dunlap idm_pdu_rx_forward(ic, pdu); 59630e7468fSPeter Dunlap /* FALLTHROUGH */ 597a6d42e7dSPeter Dunlap case CE_TRANSPORT_FAIL: 598a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_SND: 599a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_RCV: 600a6d42e7dSPeter Dunlap /* T7 */ 601a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 602a6d42e7dSPeter Dunlap (void) idm_notify_client(ic, CN_LOGIN_FAIL, NULL); 603a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx); 604a6d42e7dSPeter Dunlap break; 605a6d42e7dSPeter Dunlap case CE_LOGIN_SND: 606*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(ic->ic_client_callback == NULL); 607a6d42e7dSPeter Dunlap /* 608a6d42e7dSPeter Dunlap * Initiator connections will see initial login PDU 609a6d42e7dSPeter Dunlap * in this state. Target connections see initial 610a6d42e7dSPeter Dunlap * login PDU in "xpt up" state. 611a6d42e7dSPeter Dunlap */ 612a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 613a6d42e7dSPeter Dunlap if (!(ic->ic_state_flags & CF_INITIAL_LOGIN)) { 614a6d42e7dSPeter Dunlap idm_initial_login_actions(ic, event_ctx); 615a6d42e7dSPeter Dunlap } 616a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 617a6d42e7dSPeter Dunlap break; 618a6d42e7dSPeter Dunlap case CE_MISC_TX: 619a6d42e7dSPeter Dunlap case CE_MISC_RX: 620a6d42e7dSPeter Dunlap case CE_LOGIN_RCV: 621a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 622a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 623a6d42e7dSPeter Dunlap /* Don't care */ 624a6d42e7dSPeter Dunlap break; 625a6d42e7dSPeter Dunlap default: 626a6d42e7dSPeter Dunlap ASSERT(0); 627a6d42e7dSPeter Dunlap /*NOTREACHED*/ 628a6d42e7dSPeter Dunlap } 629a6d42e7dSPeter Dunlap } 630a6d42e7dSPeter Dunlap 631a6d42e7dSPeter Dunlap 632a6d42e7dSPeter Dunlap static void 633a6d42e7dSPeter Dunlap idm_state_s5_logged_in(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 634a6d42e7dSPeter Dunlap { 635a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 636a6d42e7dSPeter Dunlap case CE_LOGOUT_THIS_CONN_RCV: 637a6d42e7dSPeter Dunlap case CE_LOGOUT_THIS_CONN_SND: 638a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_RCV: 639a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_SND: 640a6d42e7dSPeter Dunlap /* T9 */ 641a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_CONN_LOGOUT); /* Explicit logout */ 642a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S6_IN_LOGOUT, event_ctx); 643a6d42e7dSPeter Dunlap break; 644a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_RCV: 645a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SND: 646a6d42e7dSPeter Dunlap /* T9 */ 647a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_SESS_LOGOUT); /* Explicit logout */ 648a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S6_IN_LOGOUT, event_ctx); 649a6d42e7dSPeter Dunlap break; 650a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SUCCESS: 651a6d42e7dSPeter Dunlap /* T8 */ 652a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_SESS_LOGOUT); /* Explicit logout */ 653a6d42e7dSPeter Dunlap 654a6d42e7dSPeter Dunlap /* Close connection */ 655a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 656a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_conn_disconnect(ic); 657a6d42e7dSPeter Dunlap } else { 658a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_ini_conn_disconnect(ic); 659a6d42e7dSPeter Dunlap } 660a6d42e7dSPeter Dunlap 661a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S11_COMPLETE, event_ctx); 662a6d42e7dSPeter Dunlap break; 663a6d42e7dSPeter Dunlap case CE_ASYNC_LOGOUT_RCV: 664a6d42e7dSPeter Dunlap case CE_ASYNC_LOGOUT_SND: 665a6d42e7dSPeter Dunlap /* T11 */ 666a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S7_LOGOUT_REQ, event_ctx); 667a6d42e7dSPeter Dunlap break; 668a6d42e7dSPeter Dunlap case CE_TRANSPORT_FAIL: 669a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_CONN_RCV: 670a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_CONN_SND: 671a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_ALL_CONN_RCV: 672a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_ALL_CONN_SND: 673a6d42e7dSPeter Dunlap /* T15 */ 674a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_CONN_FAIL); /* Implicit logout */ 675a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S8_CLEANUP, event_ctx); 676a6d42e7dSPeter Dunlap break; 677a6d42e7dSPeter Dunlap case CE_MISC_TX: 678a6d42e7dSPeter Dunlap case CE_MISC_RX: 679a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 680a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 68192adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_TIMEOUT: 682a6d42e7dSPeter Dunlap /* Don't care */ 683a6d42e7dSPeter Dunlap break; 684a6d42e7dSPeter Dunlap default: 685a6d42e7dSPeter Dunlap ASSERT(0); 686a6d42e7dSPeter Dunlap } 687a6d42e7dSPeter Dunlap } 688a6d42e7dSPeter Dunlap 689a6d42e7dSPeter Dunlap static void 690a6d42e7dSPeter Dunlap idm_state_s6_in_logout_success_snd_done(idm_pdu_t *pdu, idm_status_t status) 691a6d42e7dSPeter Dunlap { 692a6d42e7dSPeter Dunlap idm_conn_t *ic = pdu->isp_ic; 693a6d42e7dSPeter Dunlap 694a6d42e7dSPeter Dunlap /* 695a6d42e7dSPeter Dunlap * This pdu callback can be invoked by the tx thread, 696a6d42e7dSPeter Dunlap * so run the disconnect code from another thread. 697a6d42e7dSPeter Dunlap */ 698a6d42e7dSPeter Dunlap pdu->isp_status = status; 699a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_LOGOUT_SUCCESS_SND_DONE, (uintptr_t)pdu); 700a6d42e7dSPeter Dunlap } 701a6d42e7dSPeter Dunlap 702a6d42e7dSPeter Dunlap static void 703a6d42e7dSPeter Dunlap idm_state_s6_in_logout_fail_snd_done(idm_pdu_t *pdu, idm_status_t status) 704a6d42e7dSPeter Dunlap { 705a6d42e7dSPeter Dunlap idm_conn_t *ic = pdu->isp_ic; 706a6d42e7dSPeter Dunlap 707a6d42e7dSPeter Dunlap /* 708a6d42e7dSPeter Dunlap * This pdu callback can be invoked by the tx thread, 709a6d42e7dSPeter Dunlap * so run the disconnect code from another thread. 710a6d42e7dSPeter Dunlap */ 711a6d42e7dSPeter Dunlap pdu->isp_status = status; 712a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_LOGOUT_FAIL_SND_DONE, (uintptr_t)pdu); 713a6d42e7dSPeter Dunlap } 714a6d42e7dSPeter Dunlap 715a6d42e7dSPeter Dunlap static void 716a6d42e7dSPeter Dunlap idm_state_s6_in_logout(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 717a6d42e7dSPeter Dunlap { 718a6d42e7dSPeter Dunlap idm_pdu_t *pdu; 719a6d42e7dSPeter Dunlap 720a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 721a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND_DONE: 722a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 723a6d42e7dSPeter Dunlap 724a6d42e7dSPeter Dunlap /* Close connection (if it's not already closed) */ 725a6d42e7dSPeter Dunlap ASSERT(IDM_CONN_ISTGT(ic)); 726a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_conn_disconnect(ic); 727a6d42e7dSPeter Dunlap 728a6d42e7dSPeter Dunlap /* restore client callback */ 729a6d42e7dSPeter Dunlap pdu->isp_callback = ic->ic_client_callback; 730a6d42e7dSPeter Dunlap ic->ic_client_callback = NULL; 731a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, pdu->isp_status); 732a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S11_COMPLETE, event_ctx); 733a6d42e7dSPeter Dunlap break; 734a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND_DONE: 735a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 736a6d42e7dSPeter Dunlap /* restore client callback */ 737a6d42e7dSPeter Dunlap pdu->isp_callback = ic->ic_client_callback; 738a6d42e7dSPeter Dunlap ic->ic_client_callback = NULL; 739a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, pdu->isp_status); 740a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S8_CLEANUP, event_ctx); 741a6d42e7dSPeter Dunlap break; 742a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND: 743a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND: 744a6d42e7dSPeter Dunlap /* 745a6d42e7dSPeter Dunlap * Allow the logout response pdu to be sent and defer 746a6d42e7dSPeter Dunlap * the state machine update until the completion callback. 747a6d42e7dSPeter Dunlap * Only 1 level or callback interposition is allowed. 748a6d42e7dSPeter Dunlap */ 749a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 750a6d42e7dSPeter Dunlap ASSERT(ic->ic_client_callback == NULL); 751a6d42e7dSPeter Dunlap ic->ic_client_callback = pdu->isp_callback; 752a6d42e7dSPeter Dunlap if (event_ctx->iec_event == CE_LOGOUT_SUCCESS_SND) { 753a6d42e7dSPeter Dunlap pdu->isp_callback = 754a6d42e7dSPeter Dunlap idm_state_s6_in_logout_success_snd_done; 755a6d42e7dSPeter Dunlap } else { 756a6d42e7dSPeter Dunlap pdu->isp_callback = 757a6d42e7dSPeter Dunlap idm_state_s6_in_logout_fail_snd_done; 758a6d42e7dSPeter Dunlap } 759a6d42e7dSPeter Dunlap break; 760a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_RCV: 76130e7468fSPeter Dunlap /* 76230e7468fSPeter Dunlap * Need to deliver this PDU to the initiator now because after 76330e7468fSPeter Dunlap * we update the state to CS_S11_COMPLETE the initiator will 76430e7468fSPeter Dunlap * no longer be in an appropriate state. 76530e7468fSPeter Dunlap */ 76630e7468fSPeter Dunlap event_ctx->iec_pdu_forwarded = B_TRUE; 76730e7468fSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 76830e7468fSPeter Dunlap idm_pdu_rx_forward(ic, pdu); 76930e7468fSPeter Dunlap /* FALLTHROUGH */ 770a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SUCCESS: 771a6d42e7dSPeter Dunlap /* T13 */ 772a6d42e7dSPeter Dunlap 773a6d42e7dSPeter Dunlap /* Close connection (if it's not already closed) */ 774a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 775a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_conn_disconnect(ic); 776a6d42e7dSPeter Dunlap } else { 777a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_ini_conn_disconnect(ic); 778a6d42e7dSPeter Dunlap } 779a6d42e7dSPeter Dunlap 780a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S11_COMPLETE, event_ctx); 781a6d42e7dSPeter Dunlap break; 782a6d42e7dSPeter Dunlap case CE_ASYNC_LOGOUT_RCV: 783a6d42e7dSPeter Dunlap /* T14 Do nothing */ 784a6d42e7dSPeter Dunlap break; 785a6d42e7dSPeter Dunlap case CE_TRANSPORT_FAIL: 786a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_CONN_RCV: 787a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_CONN_SND: 788a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_ALL_CONN_RCV: 789a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_ALL_CONN_SND: 790a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_RCV: 791a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S8_CLEANUP, event_ctx); 792a6d42e7dSPeter Dunlap break; 793a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 794a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 795a6d42e7dSPeter Dunlap case CE_MISC_TX: 796a6d42e7dSPeter Dunlap case CE_MISC_RX: 79792adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_TIMEOUT: 798a6d42e7dSPeter Dunlap /* Don't care */ 799a6d42e7dSPeter Dunlap break; 800a6d42e7dSPeter Dunlap default: 801a6d42e7dSPeter Dunlap ASSERT(0); 802a6d42e7dSPeter Dunlap } 803a6d42e7dSPeter Dunlap } 804a6d42e7dSPeter Dunlap 805a6d42e7dSPeter Dunlap 806a6d42e7dSPeter Dunlap static void 807a6d42e7dSPeter Dunlap idm_logout_req_timeout(void *arg) 808a6d42e7dSPeter Dunlap { 809a6d42e7dSPeter Dunlap idm_conn_t *ic = arg; 810a6d42e7dSPeter Dunlap 811a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_LOGOUT_TIMEOUT, NULL); 812a6d42e7dSPeter Dunlap } 813a6d42e7dSPeter Dunlap 814a6d42e7dSPeter Dunlap static void 815a6d42e7dSPeter Dunlap idm_state_s7_logout_req(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 816a6d42e7dSPeter Dunlap { 817a6d42e7dSPeter Dunlap /* Must cancel logout timer before leaving this state */ 818a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 819a6d42e7dSPeter Dunlap case CE_LOGOUT_THIS_CONN_RCV: 820a6d42e7dSPeter Dunlap case CE_LOGOUT_THIS_CONN_SND: 821a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_RCV: 822a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_SND: 823a6d42e7dSPeter Dunlap /* T10 */ 824a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 825a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 826a6d42e7dSPeter Dunlap } 827a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_CONN_LOGOUT); /* Explicit logout */ 828a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S6_IN_LOGOUT, event_ctx); 829a6d42e7dSPeter Dunlap break; 830a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_RCV: 831a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SND: 832a6d42e7dSPeter Dunlap /* T10 */ 833a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 834a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 835a6d42e7dSPeter Dunlap } 836a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_SESS_LOGOUT); /* Explicit logout */ 837a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S6_IN_LOGOUT, event_ctx); 838a6d42e7dSPeter Dunlap break; 839a6d42e7dSPeter Dunlap case CE_ASYNC_LOGOUT_RCV: 840a6d42e7dSPeter Dunlap case CE_ASYNC_LOGOUT_SND: 841a6d42e7dSPeter Dunlap /* T12 Do nothing */ 842a6d42e7dSPeter Dunlap break; 843a6d42e7dSPeter Dunlap case CE_TRANSPORT_FAIL: 844a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_CONN_RCV: 845a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_CONN_SND: 846a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_ALL_CONN_RCV: 847a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_ALL_CONN_SND: 848a6d42e7dSPeter Dunlap /* T16 */ 849a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 850a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 851a6d42e7dSPeter Dunlap } 852a6d42e7dSPeter Dunlap /* FALLTHROUGH */ 853a6d42e7dSPeter Dunlap case CE_LOGOUT_TIMEOUT: 854a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_CONN_FAIL); /* Implicit logout */ 855a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S8_CLEANUP, event_ctx); 856a6d42e7dSPeter Dunlap break; 857a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SUCCESS: 858a6d42e7dSPeter Dunlap /* T18 */ 859a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 860a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 861a6d42e7dSPeter Dunlap } 862a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_SESS_LOGOUT); /* Explicit logout */ 863a6d42e7dSPeter Dunlap 864a6d42e7dSPeter Dunlap /* Close connection (if it's not already closed) */ 865a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 866a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_conn_disconnect(ic); 867a6d42e7dSPeter Dunlap } else { 868a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_ini_conn_disconnect(ic); 869a6d42e7dSPeter Dunlap } 870a6d42e7dSPeter Dunlap 871a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S11_COMPLETE, event_ctx); 872a6d42e7dSPeter Dunlap break; 873a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 874a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 875a6d42e7dSPeter Dunlap case CE_MISC_TX: 876a6d42e7dSPeter Dunlap case CE_MISC_RX: 87792adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_TIMEOUT: 878a6d42e7dSPeter Dunlap /* Don't care */ 879a6d42e7dSPeter Dunlap break; 880a6d42e7dSPeter Dunlap default: 881a6d42e7dSPeter Dunlap ASSERT(0); 882a6d42e7dSPeter Dunlap } 883a6d42e7dSPeter Dunlap } 884a6d42e7dSPeter Dunlap 885a6d42e7dSPeter Dunlap 886a6d42e7dSPeter Dunlap static void 887a6d42e7dSPeter Dunlap idm_cleanup_timeout(void *arg) 888a6d42e7dSPeter Dunlap { 889a6d42e7dSPeter Dunlap idm_conn_t *ic = arg; 890a6d42e7dSPeter Dunlap 891a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_CLEANUP_TIMEOUT, NULL); 892a6d42e7dSPeter Dunlap } 893a6d42e7dSPeter Dunlap 894a6d42e7dSPeter Dunlap static void 895a6d42e7dSPeter Dunlap idm_state_s8_cleanup(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 896a6d42e7dSPeter Dunlap { 897a6d42e7dSPeter Dunlap idm_pdu_t *pdu; 898a6d42e7dSPeter Dunlap 899a6d42e7dSPeter Dunlap /* 900a6d42e7dSPeter Dunlap * Need to cancel the cleanup timeout before leaving this state 901a6d42e7dSPeter Dunlap * if it hasn't already fired. 902a6d42e7dSPeter Dunlap */ 903a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 904a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_RCV: 905a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND: 906a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SUCCESS: 907a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 908a6d42e7dSPeter Dunlap /*FALLTHROUGH*/ 909a6d42e7dSPeter Dunlap case CE_CLEANUP_TIMEOUT: 910a6d42e7dSPeter Dunlap /* M1 */ 911a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S11_COMPLETE, event_ctx); 912a6d42e7dSPeter Dunlap break; 913a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_RCV: 914a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_SND: 915a6d42e7dSPeter Dunlap /* M2 */ 916a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S10_IN_CLEANUP, event_ctx); 917a6d42e7dSPeter Dunlap break; 918a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND_DONE: 919a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND_DONE: 920a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 921a6d42e7dSPeter Dunlap /* restore client callback */ 922a6d42e7dSPeter Dunlap pdu->isp_callback = ic->ic_client_callback; 923a6d42e7dSPeter Dunlap ic->ic_client_callback = NULL; 924a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, pdu->isp_status); 925a6d42e7dSPeter Dunlap break; 926a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_RCV: 927a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SND: 928a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 929a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 930a6d42e7dSPeter Dunlap case CE_MISC_TX: 931a6d42e7dSPeter Dunlap case CE_MISC_RX: 932a6d42e7dSPeter Dunlap case CE_TRANSPORT_FAIL: 93392adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_TIMEOUT: 934a6d42e7dSPeter Dunlap case CE_LOGOUT_TIMEOUT: 935a6d42e7dSPeter Dunlap /* Don't care */ 936a6d42e7dSPeter Dunlap break; 937a6d42e7dSPeter Dunlap default: 938a6d42e7dSPeter Dunlap ASSERT(0); 939a6d42e7dSPeter Dunlap } 940a6d42e7dSPeter Dunlap } 941a6d42e7dSPeter Dunlap 942a6d42e7dSPeter Dunlap /* ARGSUSED */ 943a6d42e7dSPeter Dunlap static void 944a6d42e7dSPeter Dunlap idm_state_s9_init_error(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 945a6d42e7dSPeter Dunlap { 946*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* All events ignored in this state */ 947a6d42e7dSPeter Dunlap } 948a6d42e7dSPeter Dunlap 949e42a0851Speter dunlap /* ARGSUSED */ 950e42a0851Speter dunlap static void 951e42a0851Speter dunlap idm_state_s9a_rejected(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 952e42a0851Speter dunlap { 953*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* All events ignored in this state */ 954*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States } 955*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 956*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 957*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States static void 958*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done_cb(idm_pdu_t *pdu, idm_status_t status) 959*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States { 960*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_t *ic = pdu->isp_ic; 961*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 962*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* 963*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * This pdu callback can be invoked by the tx thread, 964*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * so run the disconnect code from another thread. 965*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States */ 966*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States pdu->isp_status = status; 967*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_event(ic, CE_LOGIN_FAIL_SND_DONE, (uintptr_t)pdu); 968*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States } 969*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 970*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* 971*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * CS_S9B_WAIT_SND_DONE -- wait for callback completion. 972*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States */ 973*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* ARGSUSED */ 974*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States static void 975*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 976*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States { 977*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_pdu_t *pdu; 978*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* 979*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * Wait for completion of the login fail sequence and then 980*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * go to state S9_INIT_ERROR to clean up the connection. 981*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States */ 982*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States switch (event_ctx->iec_event) { 983*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_FAIL_SND_DONE: 984*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States pdu = (idm_pdu_t *)event_ctx->iec_info; 985*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* restore client callback */ 986*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States pdu->isp_callback = ic->ic_client_callback; 987*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States ic->ic_client_callback = NULL; 988*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_pdu_complete(pdu, pdu->isp_status); 989*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx); 990*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States break; 991*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 992*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* All other events ignored */ 993*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States } 994e42a0851Speter dunlap } 995e42a0851Speter dunlap 996*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 997*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 998*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 999a6d42e7dSPeter Dunlap static void 1000a6d42e7dSPeter Dunlap idm_state_s10_in_cleanup(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 1001a6d42e7dSPeter Dunlap { 1002a6d42e7dSPeter Dunlap idm_pdu_t *pdu; 1003a6d42e7dSPeter Dunlap 1004a6d42e7dSPeter Dunlap /* 1005a6d42e7dSPeter Dunlap * Need to cancel the cleanup timeout before leaving this state 1006a6d42e7dSPeter Dunlap * if it hasn't already fired. 1007a6d42e7dSPeter Dunlap */ 1008a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 1009a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_RCV: 1010a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND: 1011a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S8_CLEANUP, event_ctx); 1012a6d42e7dSPeter Dunlap break; 1013a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND: 1014a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_RCV: 1015a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SUCCESS: 1016a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 1017a6d42e7dSPeter Dunlap /*FALLTHROUGH*/ 1018a6d42e7dSPeter Dunlap case CE_CLEANUP_TIMEOUT: 1019a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S11_COMPLETE, event_ctx); 1020a6d42e7dSPeter Dunlap break; 1021a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND_DONE: 1022a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND_DONE: 1023a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 1024a6d42e7dSPeter Dunlap /* restore client callback */ 1025a6d42e7dSPeter Dunlap pdu->isp_callback = ic->ic_client_callback; 1026a6d42e7dSPeter Dunlap ic->ic_client_callback = NULL; 1027a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, pdu->isp_status); 1028a6d42e7dSPeter Dunlap break; 1029a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 1030a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 1031a6d42e7dSPeter Dunlap case CE_MISC_TX: 1032a6d42e7dSPeter Dunlap case CE_MISC_RX: 103392adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_TIMEOUT: 1034a6d42e7dSPeter Dunlap case CE_LOGOUT_TIMEOUT: 1035a6d42e7dSPeter Dunlap /* Don't care */ 1036a6d42e7dSPeter Dunlap break; 1037a6d42e7dSPeter Dunlap default: 1038a6d42e7dSPeter Dunlap ASSERT(0); 1039a6d42e7dSPeter Dunlap } 1040a6d42e7dSPeter Dunlap } 1041a6d42e7dSPeter Dunlap 1042a6d42e7dSPeter Dunlap /* ARGSUSED */ 1043a6d42e7dSPeter Dunlap static void 1044a6d42e7dSPeter Dunlap idm_state_s11_complete(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 1045a6d42e7dSPeter Dunlap { 1046a6d42e7dSPeter Dunlap idm_pdu_t *pdu; 1047a6d42e7dSPeter Dunlap 1048a6d42e7dSPeter Dunlap /* 1049a6d42e7dSPeter Dunlap * Cleanup logout success/fail completion if it's been delayed 1050a6d42e7dSPeter Dunlap * until now. 1051*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * 1052*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * All new events are filtered out before reaching this state, but 1053*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * there might already be events in the event queue, so handle the 1054*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * SND_DONE events here. Note that if either of the following 1055*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * SND_DONE events happens AFTER the change to state S11, then the 1056*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * event filter inside dm_conn_event_locked does enough cleanup. 1057a6d42e7dSPeter Dunlap */ 1058a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 1059a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND_DONE: 1060a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND_DONE: 1061a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 1062a6d42e7dSPeter Dunlap /* restore client callback */ 1063a6d42e7dSPeter Dunlap pdu->isp_callback = ic->ic_client_callback; 1064a6d42e7dSPeter Dunlap ic->ic_client_callback = NULL; 1065a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, pdu->isp_status); 1066a6d42e7dSPeter Dunlap break; 1067a6d42e7dSPeter Dunlap } 1068*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 1069a6d42e7dSPeter Dunlap } 1070a6d42e7dSPeter Dunlap 1071a6d42e7dSPeter Dunlap static void 1072a6d42e7dSPeter Dunlap idm_state_s12_enable_dm(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 1073a6d42e7dSPeter Dunlap { 1074a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 1075a6d42e7dSPeter Dunlap case CE_ENABLE_DM_SUCCESS: 1076a6d42e7dSPeter Dunlap /* T20 */ 1077a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S5_LOGGED_IN, event_ctx); 1078a6d42e7dSPeter Dunlap break; 1079a6d42e7dSPeter Dunlap case CE_ENABLE_DM_FAIL: 1080a6d42e7dSPeter Dunlap /* T21 */ 1081a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx); 1082a6d42e7dSPeter Dunlap break; 1083a6d42e7dSPeter Dunlap case CE_TRANSPORT_FAIL: 1084a6d42e7dSPeter Dunlap /* 1085a6d42e7dSPeter Dunlap * We expect to always hear back from the transport layer 1086a6d42e7dSPeter Dunlap * once we have an "enable data-mover" request outstanding. 1087a6d42e7dSPeter Dunlap * Therefore we'll ignore other events that may occur even 1088a6d42e7dSPeter Dunlap * when they clearly indicate a problem and wait for 1089a6d42e7dSPeter Dunlap * CE_ENABLE_DM_FAIL. On a related note this means the 1090a6d42e7dSPeter Dunlap * transport must ensure that it eventually completes the 1091a6d42e7dSPeter Dunlap * "enable data-mover" operation with either success or 1092a6d42e7dSPeter Dunlap * failure -- otherwise we'll be stuck here. 1093a6d42e7dSPeter Dunlap */ 1094a6d42e7dSPeter Dunlap break; 1095a6d42e7dSPeter Dunlap default: 1096a6d42e7dSPeter Dunlap ASSERT(0); 1097a6d42e7dSPeter Dunlap break; 1098a6d42e7dSPeter Dunlap } 1099a6d42e7dSPeter Dunlap } 1100a6d42e7dSPeter Dunlap 1101a6d42e7dSPeter Dunlap static void 1102a6d42e7dSPeter Dunlap idm_update_state(idm_conn_t *ic, idm_conn_state_t new_state, 1103a6d42e7dSPeter Dunlap idm_conn_event_ctx_t *event_ctx) 1104a6d42e7dSPeter Dunlap { 1105a6d42e7dSPeter Dunlap int rc; 1106a6d42e7dSPeter Dunlap idm_status_t idm_status; 1107a6d42e7dSPeter Dunlap 1108a6d42e7dSPeter Dunlap /* 1109a6d42e7dSPeter Dunlap * Validate new state 1110a6d42e7dSPeter Dunlap */ 1111a6d42e7dSPeter Dunlap ASSERT(new_state != CS_S0_UNDEFINED); 1112a6d42e7dSPeter Dunlap ASSERT3U(new_state, <, CS_MAX_STATE); 1113a6d42e7dSPeter Dunlap 1114a6d42e7dSPeter Dunlap /* 1115a6d42e7dSPeter Dunlap * Update state in context. We protect this with a mutex 1116a6d42e7dSPeter Dunlap * even though the state machine code is single threaded so that 1117a6d42e7dSPeter Dunlap * other threads can check the state value atomically. 1118a6d42e7dSPeter Dunlap */ 1119a6d42e7dSPeter Dunlap new_state = (new_state < CS_MAX_STATE) ? 1120a6d42e7dSPeter Dunlap new_state : CS_S0_UNDEFINED; 1121a6d42e7dSPeter Dunlap 1122a6d42e7dSPeter Dunlap IDM_SM_LOG(CE_NOTE, "idm_update_state: conn %p, evt %s(%d), " 1123a6d42e7dSPeter Dunlap "%s(%d) --> %s(%d)", (void *)ic, 1124a6d42e7dSPeter Dunlap idm_ce_name[event_ctx->iec_event], event_ctx->iec_event, 1125a6d42e7dSPeter Dunlap idm_cs_name[ic->ic_state], ic->ic_state, 1126a6d42e7dSPeter Dunlap idm_cs_name[new_state], new_state); 1127a6d42e7dSPeter Dunlap 1128a6d42e7dSPeter Dunlap DTRACE_PROBE2(conn__state__change, 1129a6d42e7dSPeter Dunlap idm_conn_t *, ic, idm_conn_state_t, new_state); 1130a6d42e7dSPeter Dunlap 1131a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 1132a6d42e7dSPeter Dunlap idm_sm_audit_state_change(&ic->ic_state_audit, SAS_IDM_CONN, 1133a6d42e7dSPeter Dunlap (int)ic->ic_state, (int)new_state); 1134a6d42e7dSPeter Dunlap ic->ic_last_state = ic->ic_state; 1135a6d42e7dSPeter Dunlap ic->ic_state = new_state; 1136a6d42e7dSPeter Dunlap cv_signal(&ic->ic_state_cv); 1137a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 1138a6d42e7dSPeter Dunlap 1139a6d42e7dSPeter Dunlap switch (ic->ic_state) { 1140a6d42e7dSPeter Dunlap case CS_S1_FREE: 1141a6d42e7dSPeter Dunlap ASSERT(0); /* Initial state, can't return */ 1142a6d42e7dSPeter Dunlap break; 1143a6d42e7dSPeter Dunlap case CS_S2_XPT_WAIT: 1144a6d42e7dSPeter Dunlap if ((rc = idm_ini_conn_finish(ic)) != 0) { 1145a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_CONNECT_FAIL, NULL); 1146a6d42e7dSPeter Dunlap } else { 1147a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_CONNECT_SUCCESS, NULL); 1148a6d42e7dSPeter Dunlap } 1149a6d42e7dSPeter Dunlap break; 1150a6d42e7dSPeter Dunlap case CS_S3_XPT_UP: 1151a6d42e7dSPeter Dunlap /* 1152a6d42e7dSPeter Dunlap * Finish any connection related setup including 1153a6d42e7dSPeter Dunlap * waking up the idm_tgt_conn_accept thread. 1154a6d42e7dSPeter Dunlap * and starting the login timer. If the function 1155a6d42e7dSPeter Dunlap * fails then we return to "free" state. 1156a6d42e7dSPeter Dunlap */ 1157a6d42e7dSPeter Dunlap if ((rc = idm_tgt_conn_finish(ic)) != IDM_STATUS_SUCCESS) { 1158a6d42e7dSPeter Dunlap switch (rc) { 1159a6d42e7dSPeter Dunlap case IDM_STATUS_REJECT: 1160a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_CONNECT_REJECT, NULL); 1161a6d42e7dSPeter Dunlap break; 1162a6d42e7dSPeter Dunlap default: 1163a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_CONNECT_FAIL, NULL); 1164a6d42e7dSPeter Dunlap break; 1165a6d42e7dSPeter Dunlap } 1166a6d42e7dSPeter Dunlap } 1167a6d42e7dSPeter Dunlap 1168a6d42e7dSPeter Dunlap /* 1169a6d42e7dSPeter Dunlap * First login received will cause a transition to 1170a6d42e7dSPeter Dunlap * CS_S4_IN_LOGIN. Start login timer. 1171a6d42e7dSPeter Dunlap */ 1172a6d42e7dSPeter Dunlap ic->ic_state_timeout = timeout(idm_login_timeout, ic, 1173a6d42e7dSPeter Dunlap drv_usectohz(IDM_LOGIN_SECONDS*1000000)); 1174a6d42e7dSPeter Dunlap break; 1175a6d42e7dSPeter Dunlap case CS_S4_IN_LOGIN: 1176a6d42e7dSPeter Dunlap if (ic->ic_conn_type == CONN_TYPE_INI) { 11775f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States (void) idm_notify_client(ic, CN_READY_FOR_LOGIN, NULL); 1178a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 1179a6d42e7dSPeter Dunlap ic->ic_state_flags |= CF_LOGIN_READY; 1180a6d42e7dSPeter Dunlap cv_signal(&ic->ic_state_cv); 1181a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 1182a6d42e7dSPeter Dunlap } 1183a6d42e7dSPeter Dunlap break; 1184a6d42e7dSPeter Dunlap case CS_S5_LOGGED_IN: 1185a6d42e7dSPeter Dunlap ASSERT(!ic->ic_ffp); 1186a6d42e7dSPeter Dunlap /* 1187a6d42e7dSPeter Dunlap * IDM can go to FFP before the initiator but it 1188a6d42e7dSPeter Dunlap * needs to go to FFP after the target (IDM target should 1189a6d42e7dSPeter Dunlap * go to FFP after notify_ack). 1190a6d42e7dSPeter Dunlap */ 1191a6d42e7dSPeter Dunlap idm_status = idm_ffp_enable(ic); 1192a6d42e7dSPeter Dunlap if (idm_status != IDM_STATUS_SUCCESS) { 1193a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_TRANSPORT_FAIL, NULL); 1194a6d42e7dSPeter Dunlap } 1195a6d42e7dSPeter Dunlap 1196a6d42e7dSPeter Dunlap if (ic->ic_reinstate_conn) { 1197a6d42e7dSPeter Dunlap /* Connection reinstatement is complete */ 119892adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_event(ic->ic_reinstate_conn, 119992adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States CE_CONN_REINSTATE_SUCCESS, NULL); 1200a6d42e7dSPeter Dunlap } 1201a6d42e7dSPeter Dunlap break; 1202a6d42e7dSPeter Dunlap case CS_S6_IN_LOGOUT: 1203a6d42e7dSPeter Dunlap break; 1204a6d42e7dSPeter Dunlap case CS_S7_LOGOUT_REQ: 1205a6d42e7dSPeter Dunlap /* Start logout timer for target connections */ 1206a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 1207a6d42e7dSPeter Dunlap ic->ic_state_timeout = timeout(idm_logout_req_timeout, 1208a6d42e7dSPeter Dunlap ic, drv_usectohz(IDM_LOGOUT_SECONDS*1000000)); 1209a6d42e7dSPeter Dunlap } 1210a6d42e7dSPeter Dunlap break; 1211a6d42e7dSPeter Dunlap case CS_S8_CLEANUP: 1212a6d42e7dSPeter Dunlap /* Close connection (if it's not already closed) */ 1213a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 1214a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_conn_disconnect(ic); 1215a6d42e7dSPeter Dunlap } else { 1216a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_ini_conn_disconnect(ic); 1217a6d42e7dSPeter Dunlap } 1218a6d42e7dSPeter Dunlap 1219a6d42e7dSPeter Dunlap /* Stop executing active tasks */ 1220a6d42e7dSPeter Dunlap idm_task_abort(ic, NULL, AT_INTERNAL_SUSPEND); 1221a6d42e7dSPeter Dunlap 1222a6d42e7dSPeter Dunlap /* Start logout timer */ 1223a6d42e7dSPeter Dunlap ic->ic_state_timeout = timeout(idm_cleanup_timeout, ic, 1224a6d42e7dSPeter Dunlap drv_usectohz(IDM_CLEANUP_SECONDS*1000000)); 1225a6d42e7dSPeter Dunlap break; 1226a6d42e7dSPeter Dunlap case CS_S10_IN_CLEANUP: 1227a6d42e7dSPeter Dunlap break; 1228e42a0851Speter dunlap case CS_S9A_REJECTED: 1229e42a0851Speter dunlap /* 1230e42a0851Speter dunlap * We never finished establishing the connection so no 1231*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * disconnect. No client notifications because the client 1232e42a0851Speter dunlap * rejected the connection. 1233e42a0851Speter dunlap */ 1234e42a0851Speter dunlap idm_refcnt_async_wait_ref(&ic->ic_refcnt, 1235e42a0851Speter dunlap &idm_conn_reject_unref); 1236e42a0851Speter dunlap break; 1237*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CS_S9B_WAIT_SND_DONE: 1238*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States break; 1239a6d42e7dSPeter Dunlap case CS_S9_INIT_ERROR: 1240a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 1241a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_conn_disconnect(ic); 1242a6d42e7dSPeter Dunlap } else { 1243a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 1244a6d42e7dSPeter Dunlap ic->ic_state_flags |= CF_ERROR; 1245a6d42e7dSPeter Dunlap ic->ic_conn_sm_status = IDM_STATUS_FAIL; 1246a6d42e7dSPeter Dunlap cv_signal(&ic->ic_state_cv); 1247a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 124830e7468fSPeter Dunlap if (ic->ic_last_state != CS_S1_FREE && 124930e7468fSPeter Dunlap ic->ic_last_state != CS_S2_XPT_WAIT) { 125030e7468fSPeter Dunlap ic->ic_transport_ops->it_ini_conn_disconnect( 125130e7468fSPeter Dunlap ic); 125230e7468fSPeter Dunlap } else { 125330e7468fSPeter Dunlap (void) idm_notify_client(ic, CN_CONNECT_FAIL, 125430e7468fSPeter Dunlap NULL); 125530e7468fSPeter Dunlap } 1256a6d42e7dSPeter Dunlap } 1257a6d42e7dSPeter Dunlap /*FALLTHROUGH*/ 1258a6d42e7dSPeter Dunlap case CS_S11_COMPLETE: 125930e7468fSPeter Dunlap /* 126030e7468fSPeter Dunlap * No more traffic on this connection. If this is an 126130e7468fSPeter Dunlap * initiator connection and we weren't connected yet 126230e7468fSPeter Dunlap * then don't send the "connect lost" event. 126330e7468fSPeter Dunlap * It's useful to the initiator to know whether we were 126430e7468fSPeter Dunlap * logging in at the time so send that information in the 126530e7468fSPeter Dunlap * data field. 126630e7468fSPeter Dunlap */ 126730e7468fSPeter Dunlap if (IDM_CONN_ISTGT(ic) || 126830e7468fSPeter Dunlap ((ic->ic_last_state != CS_S1_FREE) && 126930e7468fSPeter Dunlap (ic->ic_last_state != CS_S2_XPT_WAIT))) { 127030e7468fSPeter Dunlap (void) idm_notify_client(ic, CN_CONNECT_LOST, 127130e7468fSPeter Dunlap (uintptr_t)(ic->ic_last_state == CS_S4_IN_LOGIN)); 127230e7468fSPeter Dunlap } 1273a6d42e7dSPeter Dunlap 1274a6d42e7dSPeter Dunlap /* Abort all tasks */ 1275a6d42e7dSPeter Dunlap idm_task_abort(ic, NULL, AT_INTERNAL_ABORT); 1276a6d42e7dSPeter Dunlap 1277a6d42e7dSPeter Dunlap /* 1278a6d42e7dSPeter Dunlap * Handle terminal state actions on the global taskq so 1279a6d42e7dSPeter Dunlap * we can clean up all the connection resources from 1280a6d42e7dSPeter Dunlap * a separate thread context. 1281a6d42e7dSPeter Dunlap */ 1282a6d42e7dSPeter Dunlap idm_refcnt_async_wait_ref(&ic->ic_refcnt, &idm_conn_unref); 1283a6d42e7dSPeter Dunlap break; 1284a6d42e7dSPeter Dunlap case CS_S12_ENABLE_DM: 1285a6d42e7dSPeter Dunlap 1286a6d42e7dSPeter Dunlap /* 1287a6d42e7dSPeter Dunlap * The Enable DM state indicates the initiator to initiate 1288a6d42e7dSPeter Dunlap * the hello sequence and the target to get ready to accept 1289a6d42e7dSPeter Dunlap * the iSER Hello Message. 1290a6d42e7dSPeter Dunlap */ 1291a6d42e7dSPeter Dunlap idm_status = (IDM_CONN_ISINI(ic)) ? 1292a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_ini_enable_datamover(ic) : 1293a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_enable_datamover(ic); 1294a6d42e7dSPeter Dunlap 1295a6d42e7dSPeter Dunlap if (idm_status == IDM_STATUS_SUCCESS) { 1296a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_ENABLE_DM_SUCCESS, NULL); 1297a6d42e7dSPeter Dunlap } else { 1298a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_ENABLE_DM_FAIL, NULL); 1299a6d42e7dSPeter Dunlap } 1300a6d42e7dSPeter Dunlap 1301a6d42e7dSPeter Dunlap break; 1302*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 1303*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States default: 1304*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(0); 1305*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States break; 1306*e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 1307a6d42e7dSPeter Dunlap } 1308a6d42e7dSPeter Dunlap } 1309a6d42e7dSPeter Dunlap 1310a6d42e7dSPeter Dunlap 1311a6d42e7dSPeter Dunlap static void 1312a6d42e7dSPeter Dunlap idm_conn_unref(void *ic_void) 1313a6d42e7dSPeter Dunlap { 1314a6d42e7dSPeter Dunlap idm_conn_t *ic = ic_void; 1315a6d42e7dSPeter Dunlap 1316a6d42e7dSPeter Dunlap /* 1317a6d42e7dSPeter Dunlap * Client should not be notified that the connection is destroyed 1318a6d42e7dSPeter Dunlap * until all references on the idm connection have been removed. 1319a6d42e7dSPeter Dunlap * Otherwise references on the associated client context would need 1320a6d42e7dSPeter Dunlap * to be tracked separately which seems like a waste (at least when 1321a6d42e7dSPeter Dunlap * there is a one for one correspondence with references on the 1322a6d42e7dSPeter Dunlap * IDM connection). 1323a6d42e7dSPeter Dunlap */ 1324a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 1325a6d42e7dSPeter Dunlap (void) idm_notify_client(ic, CN_CONNECT_DESTROY, NULL); 1326a6d42e7dSPeter Dunlap idm_svc_conn_destroy(ic); 1327a6d42e7dSPeter Dunlap } else { 1328a6d42e7dSPeter Dunlap /* Initiator may destroy connection during this call */ 1329a6d42e7dSPeter Dunlap (void) idm_notify_client(ic, CN_CONNECT_DESTROY, NULL); 1330a6d42e7dSPeter Dunlap } 1331a6d42e7dSPeter Dunlap } 1332a6d42e7dSPeter Dunlap 1333e42a0851Speter dunlap static void 1334e42a0851Speter dunlap idm_conn_reject_unref(void *ic_void) 1335e42a0851Speter dunlap { 1336e42a0851Speter dunlap idm_conn_t *ic = ic_void; 1337e42a0851Speter dunlap 1338e42a0851Speter dunlap ASSERT(IDM_CONN_ISTGT(ic)); 1339e42a0851Speter dunlap 1340e42a0851Speter dunlap /* Don't notify the client since it rejected the connection */ 1341e42a0851Speter dunlap idm_svc_conn_destroy(ic); 1342e42a0851Speter dunlap } 1343e42a0851Speter dunlap 1344e42a0851Speter dunlap 1345a6d42e7dSPeter Dunlap 1346a6d42e7dSPeter Dunlap static idm_pdu_event_action_t 1347a6d42e7dSPeter Dunlap idm_conn_sm_validate_pdu(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx, 1348a6d42e7dSPeter Dunlap idm_pdu_t *pdu) 1349a6d42e7dSPeter Dunlap { 1350a6d42e7dSPeter Dunlap char *reason_string; 1351a6d42e7dSPeter Dunlap idm_pdu_event_action_t action; 1352a6d42e7dSPeter Dunlap 1353a6d42e7dSPeter Dunlap ASSERT((event_ctx->iec_pdu_event_type == CT_RX_PDU) || 1354a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_TX_PDU)); 1355a6d42e7dSPeter Dunlap 1356a6d42e7dSPeter Dunlap /* 1357a6d42e7dSPeter Dunlap * Let's check the simple stuff first. Make sure if this is a 1358a6d42e7dSPeter Dunlap * target connection that the PDU is appropriate for a target 1359a6d42e7dSPeter Dunlap * and if this is an initiator connection that the PDU is 1360a6d42e7dSPeter Dunlap * appropriate for an initiator. This code is not in the data 1361a6d42e7dSPeter Dunlap * path so organization is more important than performance. 1362a6d42e7dSPeter Dunlap */ 1363a6d42e7dSPeter Dunlap switch (IDM_PDU_OPCODE(pdu)) { 1364a6d42e7dSPeter Dunlap case ISCSI_OP_NOOP_OUT: 1365a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_CMD: 1366a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_TASK_MGT_MSG: 1367a6d42e7dSPeter Dunlap case ISCSI_OP_LOGIN_CMD: 1368a6d42e7dSPeter Dunlap case ISCSI_OP_TEXT_CMD: 1369a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_DATA: 1370a6d42e7dSPeter Dunlap case ISCSI_OP_LOGOUT_CMD: 1371a6d42e7dSPeter Dunlap case ISCSI_OP_SNACK_CMD: 1372a6d42e7dSPeter Dunlap /* 1373a6d42e7dSPeter Dunlap * Only the initiator should send these PDU's and 1374a6d42e7dSPeter Dunlap * only the target should receive them. 1375a6d42e7dSPeter Dunlap */ 1376a6d42e7dSPeter Dunlap if (IDM_CONN_ISINI(ic) && 1377a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_RX_PDU)) { 1378a6d42e7dSPeter Dunlap reason_string = "Invalid RX PDU for initiator"; 1379a6d42e7dSPeter Dunlap action = CA_RX_PROTOCOL_ERROR; 1380a6d42e7dSPeter Dunlap goto validate_pdu_done; 1381a6d42e7dSPeter Dunlap } 1382a6d42e7dSPeter Dunlap 1383a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic) && 1384a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_TX_PDU)) { 1385a6d42e7dSPeter Dunlap reason_string = "Invalid TX PDU for target"; 1386a6d42e7dSPeter Dunlap action = CA_TX_PROTOCOL_ERROR; 1387a6d42e7dSPeter Dunlap goto validate_pdu_done; 1388a6d42e7dSPeter Dunlap } 1389a6d42e7dSPeter Dunlap break; 1390a6d42e7dSPeter Dunlap case ISCSI_OP_NOOP_IN: 1391a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_RSP: 1392a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_TASK_MGT_RSP: 1393a6d42e7dSPeter Dunlap case ISCSI_OP_LOGIN_RSP: 1394a6d42e7dSPeter Dunlap case ISCSI_OP_TEXT_RSP: 1395a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_DATA_RSP: 1396a6d42e7dSPeter Dunlap case ISCSI_OP_LOGOUT_RSP: 1397a6d42e7dSPeter Dunlap case ISCSI_OP_RTT_RSP: 1398a6d42e7dSPeter Dunlap case ISCSI_OP_ASYNC_EVENT: 1399a6d42e7dSPeter Dunlap case ISCSI_OP_REJECT_MSG: 1400a6d42e7dSPeter Dunlap /* 1401a6d42e7dSPeter Dunlap * Only the target should send these PDU's and 1402a6d42e7dSPeter Dunlap * only the initiator should receive them. 1403a6d42e7dSPeter Dunlap */ 1404a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic) && 1405a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_RX_PDU)) { 1406a6d42e7dSPeter Dunlap reason_string = "Invalid RX PDU for target"; 1407a6d42e7dSPeter Dunlap action = CA_RX_PROTOCOL_ERROR; 1408a6d42e7dSPeter Dunlap goto validate_pdu_done; 1409a6d42e7dSPeter Dunlap } 1410a6d42e7dSPeter Dunlap 1411a6d42e7dSPeter Dunlap if (IDM_CONN_ISINI(ic) && 1412a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_TX_PDU)) { 1413a6d42e7dSPeter Dunlap reason_string = "Invalid TX PDU for initiator"; 1414a6d42e7dSPeter Dunlap action = CA_TX_PROTOCOL_ERROR; 1415a6d42e7dSPeter Dunlap goto validate_pdu_done; 1416a6d42e7dSPeter Dunlap } 1417a6d42e7dSPeter Dunlap break; 1418a6d42e7dSPeter Dunlap default: 1419a6d42e7dSPeter Dunlap reason_string = "Unknown PDU Type"; 1420a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ? 1421a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR); 1422a6d42e7dSPeter Dunlap goto validate_pdu_done; 1423a6d42e7dSPeter Dunlap } 1424a6d42e7dSPeter Dunlap 1425a6d42e7dSPeter Dunlap /* 1426a6d42e7dSPeter Dunlap * Now validate the opcodes against the current state. 1427a6d42e7dSPeter Dunlap */ 1428a6d42e7dSPeter Dunlap reason_string = "PDU not allowed in current state"; 1429a6d42e7dSPeter Dunlap switch (IDM_PDU_OPCODE(pdu)) { 1430a6d42e7dSPeter Dunlap case ISCSI_OP_NOOP_OUT: 1431a6d42e7dSPeter Dunlap case ISCSI_OP_NOOP_IN: 1432a6d42e7dSPeter Dunlap /* 1433a6d42e7dSPeter Dunlap * Obviously S1-S3 are not allowed since login hasn't started. 1434a6d42e7dSPeter Dunlap * S8 is probably out as well since the connection has been 1435a6d42e7dSPeter Dunlap * dropped. 1436a6d42e7dSPeter Dunlap */ 1437a6d42e7dSPeter Dunlap switch (ic->ic_state) { 1438a6d42e7dSPeter Dunlap case CS_S4_IN_LOGIN: 1439a6d42e7dSPeter Dunlap case CS_S5_LOGGED_IN: 1440a6d42e7dSPeter Dunlap case CS_S6_IN_LOGOUT: 1441a6d42e7dSPeter Dunlap case CS_S7_LOGOUT_REQ: 1442a6d42e7dSPeter Dunlap action = CA_FORWARD; 1443a6d42e7dSPeter Dunlap goto validate_pdu_done; 1444a6d42e7dSPeter Dunlap case CS_S8_CLEANUP: 1445a6d42e7dSPeter Dunlap case CS_S10_IN_CLEANUP: 1446a6d42e7dSPeter Dunlap action = CA_DROP; 1447a6d42e7dSPeter Dunlap break; 1448a6d42e7dSPeter Dunlap default: 1449a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ? 1450a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR); 1451a6d42e7dSPeter Dunlap goto validate_pdu_done; 1452a6d42e7dSPeter Dunlap } 1453a6d42e7dSPeter Dunlap /*NOTREACHED*/ 1454a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_CMD: 1455a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_RSP: 1456a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_TASK_MGT_MSG: 1457a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_TASK_MGT_RSP: 1458a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_DATA: 1459a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_DATA_RSP: 1460a6d42e7dSPeter Dunlap case ISCSI_OP_RTT_RSP: 1461a6d42e7dSPeter Dunlap case ISCSI_OP_SNACK_CMD: 1462a6d42e7dSPeter Dunlap case ISCSI_OP_TEXT_CMD: 1463a6d42e7dSPeter Dunlap case ISCSI_OP_TEXT_RSP: 1464a6d42e7dSPeter Dunlap switch (ic->ic_state) { 1465a6d42e7dSPeter Dunlap case CS_S5_LOGGED_IN: 1466a6d42e7dSPeter Dunlap case CS_S6_IN_LOGOUT: 1467a6d42e7dSPeter Dunlap case CS_S7_LOGOUT_REQ: 1468a6d42e7dSPeter Dunlap action = CA_FORWARD; 1469a6d42e7dSPeter Dunlap goto validate_pdu_done; 1470a6d42e7dSPeter Dunlap case CS_S8_CLEANUP: 1471a6d42e7dSPeter Dunlap case CS_S10_IN_CLEANUP: 1472a6d42e7dSPeter Dunlap action = CA_DROP; 1473a6d42e7dSPeter Dunlap break; 1474a6d42e7dSPeter Dunlap default: 1475a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ? 1476a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR); 1477a6d42e7dSPeter Dunlap goto validate_pdu_done; 1478a6d42e7dSPeter Dunlap } 1479a6d42e7dSPeter Dunlap /*NOTREACHED*/ 1480a6d42e7dSPeter Dunlap case ISCSI_OP_LOGOUT_CMD: 1481a6d42e7dSPeter Dunlap case ISCSI_OP_LOGOUT_RSP: 1482a6d42e7dSPeter Dunlap case ISCSI_OP_REJECT_MSG: 1483a6d42e7dSPeter Dunlap case ISCSI_OP_ASYNC_EVENT: 1484a6d42e7dSPeter Dunlap switch (ic->ic_state) { 1485a6d42e7dSPeter Dunlap case CS_S5_LOGGED_IN: 1486a6d42e7dSPeter Dunlap case CS_S6_IN_LOGOUT: 1487a6d42e7dSPeter Dunlap case CS_S7_LOGOUT_REQ: 1488a6d42e7dSPeter Dunlap action = CA_FORWARD; 1489a6d42e7dSPeter Dunlap goto validate_pdu_done; 1490a6d42e7dSPeter Dunlap case CS_S8_CLEANUP: 1491a6d42e7dSPeter Dunlap case CS_S10_IN_CLEANUP: 1492a6d42e7dSPeter Dunlap action = CA_DROP; 1493a6d42e7dSPeter Dunlap break; 1494a6d42e7dSPeter Dunlap default: 1495a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ? 1496a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR); 1497a6d42e7dSPeter Dunlap goto validate_pdu_done; 1498a6d42e7dSPeter Dunlap } 1499a6d42e7dSPeter Dunlap /*NOTREACHED*/ 1500a6d42e7dSPeter Dunlap case ISCSI_OP_LOGIN_CMD: 1501a6d42e7dSPeter Dunlap case ISCSI_OP_LOGIN_RSP: 1502a6d42e7dSPeter Dunlap switch (ic->ic_state) { 1503a6d42e7dSPeter Dunlap case CS_S3_XPT_UP: 1504a6d42e7dSPeter Dunlap case CS_S4_IN_LOGIN: 1505a6d42e7dSPeter Dunlap action = CA_FORWARD; 1506a6d42e7dSPeter Dunlap goto validate_pdu_done; 1507a6d42e7dSPeter Dunlap default: 1508a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ? 1509a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR); 1510a6d42e7dSPeter Dunlap goto validate_pdu_done; 1511a6d42e7dSPeter Dunlap } 1512a6d42e7dSPeter Dunlap /*NOTREACHED*/ 1513a6d42e7dSPeter Dunlap default: 1514a6d42e7dSPeter Dunlap /* This should never happen -- we already checked above */ 1515a6d42e7dSPeter Dunlap ASSERT(0); 1516a6d42e7dSPeter Dunlap /*NOTREACHED*/ 1517a6d42e7dSPeter Dunlap } 1518a6d42e7dSPeter Dunlap 1519a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ? 1520a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR); 1521a6d42e7dSPeter Dunlap 1522a6d42e7dSPeter Dunlap validate_pdu_done: 1523a6d42e7dSPeter Dunlap if (action != CA_FORWARD) { 1524a6d42e7dSPeter Dunlap DTRACE_PROBE2(idm__int__protocol__error, 1525a6d42e7dSPeter Dunlap idm_conn_event_ctx_t *, event_ctx, 1526a6d42e7dSPeter Dunlap char *, reason_string); 1527a6d42e7dSPeter Dunlap } 1528a6d42e7dSPeter Dunlap 1529a6d42e7dSPeter Dunlap return (action); 1530a6d42e7dSPeter Dunlap } 1531a6d42e7dSPeter Dunlap 1532a6d42e7dSPeter Dunlap /* ARGSUSED */ 1533a6d42e7dSPeter Dunlap void 1534a6d42e7dSPeter Dunlap idm_pdu_tx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu) 1535a6d42e7dSPeter Dunlap { 1536a6d42e7dSPeter Dunlap /* 1537a6d42e7dSPeter Dunlap * Return the PDU to the caller indicating it was a protocol error. 1538a6d42e7dSPeter Dunlap * Caller can take appropriate action. 1539a6d42e7dSPeter Dunlap */ 1540a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, IDM_STATUS_PROTOCOL_ERROR); 1541a6d42e7dSPeter Dunlap } 1542a6d42e7dSPeter Dunlap 1543a6d42e7dSPeter Dunlap void 1544a6d42e7dSPeter Dunlap idm_pdu_rx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu) 1545a6d42e7dSPeter Dunlap { 1546a6d42e7dSPeter Dunlap /* 1547a6d42e7dSPeter Dunlap * Forward PDU to caller indicating it is a protocol error. 1548a6d42e7dSPeter Dunlap * Caller should take appropriate action. 1549a6d42e7dSPeter Dunlap */ 1550a6d42e7dSPeter Dunlap (*ic->ic_conn_ops.icb_rx_error)(ic, pdu, IDM_STATUS_PROTOCOL_ERROR); 1551a6d42e7dSPeter Dunlap } 1552a6d42e7dSPeter Dunlap 1553a6d42e7dSPeter Dunlap idm_status_t 1554a6d42e7dSPeter Dunlap idm_notify_client(idm_conn_t *ic, idm_client_notify_t cn, uintptr_t data) 1555a6d42e7dSPeter Dunlap { 1556a6d42e7dSPeter Dunlap /* 1557a6d42e7dSPeter Dunlap * We may want to make this more complicated at some point but 1558a6d42e7dSPeter Dunlap * for now lets just call the client's notify function and return 1559a6d42e7dSPeter Dunlap * the status. 1560a6d42e7dSPeter Dunlap */ 15615f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(!mutex_owned(&ic->ic_state_mutex)); 156230e7468fSPeter Dunlap cn = (cn > CN_MAX) ? CN_MAX : cn; 156330e7468fSPeter Dunlap IDM_SM_LOG(CE_NOTE, "idm_notify_client: ic=%p %s(%d)\n", 156430e7468fSPeter Dunlap (void *)ic, idm_cn_strings[cn], cn); 1565a6d42e7dSPeter Dunlap return ((*ic->ic_conn_ops.icb_client_notify)(ic, cn, data)); 1566a6d42e7dSPeter Dunlap } 1567a6d42e7dSPeter Dunlap 1568a6d42e7dSPeter Dunlap static idm_status_t 1569a6d42e7dSPeter Dunlap idm_ffp_enable(idm_conn_t *ic) 1570a6d42e7dSPeter Dunlap { 1571a6d42e7dSPeter Dunlap idm_status_t rc; 1572a6d42e7dSPeter Dunlap 1573a6d42e7dSPeter Dunlap /* 1574a6d42e7dSPeter Dunlap * On the initiator side the client will see this notification 1575a6d42e7dSPeter Dunlap * before the actual login succes PDU. This shouldn't be a big 1576a6d42e7dSPeter Dunlap * deal since the initiator drives the connection. It can simply 1577a6d42e7dSPeter Dunlap * wait for the login response then start sending SCSI commands. 1578a6d42e7dSPeter Dunlap * Kind ugly though compared with the way things work on target 1579a6d42e7dSPeter Dunlap * connections. 1580a6d42e7dSPeter Dunlap */ 1581a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 1582a6d42e7dSPeter Dunlap ic->ic_ffp = B_TRUE; 1583a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 1584a6d42e7dSPeter Dunlap 1585a6d42e7dSPeter Dunlap rc = idm_notify_client(ic, CN_FFP_ENABLED, NULL); 1586a6d42e7dSPeter Dunlap if (rc != IDM_STATUS_SUCCESS) { 1587a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 1588a6d42e7dSPeter Dunlap ic->ic_ffp = B_FALSE; 1589a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 1590a6d42e7dSPeter Dunlap } 1591a6d42e7dSPeter Dunlap return (rc); 1592a6d42e7dSPeter Dunlap } 1593a6d42e7dSPeter Dunlap 1594a6d42e7dSPeter Dunlap static void 1595a6d42e7dSPeter Dunlap idm_ffp_disable(idm_conn_t *ic, idm_ffp_disable_t disable_type) 1596a6d42e7dSPeter Dunlap { 1597a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 1598a6d42e7dSPeter Dunlap ic->ic_ffp = B_FALSE; 1599a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 1600a6d42e7dSPeter Dunlap 1601a6d42e7dSPeter Dunlap /* Client can't "fail" CN_FFP_DISABLED */ 1602a6d42e7dSPeter Dunlap (void) idm_notify_client(ic, CN_FFP_DISABLED, 1603a6d42e7dSPeter Dunlap (uintptr_t)disable_type); 1604a6d42e7dSPeter Dunlap } 1605a6d42e7dSPeter Dunlap 1606a6d42e7dSPeter Dunlap static void 1607a6d42e7dSPeter Dunlap idm_initial_login_actions(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 1608a6d42e7dSPeter Dunlap { 1609a6d42e7dSPeter Dunlap ASSERT((event_ctx->iec_event == CE_LOGIN_RCV) || 1610a6d42e7dSPeter Dunlap (event_ctx->iec_event == CE_LOGIN_SND)); 1611a6d42e7dSPeter Dunlap 1612a6d42e7dSPeter Dunlap /* 1613a6d42e7dSPeter Dunlap * Currently it's not clear what we would do here -- since 1614a6d42e7dSPeter Dunlap * we went to the trouble of coding an "initial login" hook 1615a6d42e7dSPeter Dunlap * we'll leave it in for now. Remove before integration if 1616a6d42e7dSPeter Dunlap * it's not used for anything. 1617a6d42e7dSPeter Dunlap */ 1618a6d42e7dSPeter Dunlap ic->ic_state_flags |= CF_INITIAL_LOGIN; 1619a6d42e7dSPeter Dunlap } 1620a6d42e7dSPeter Dunlap 1621a6d42e7dSPeter Dunlap static void 1622a6d42e7dSPeter Dunlap idm_login_success_actions(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 1623a6d42e7dSPeter Dunlap { 1624a6d42e7dSPeter Dunlap idm_pdu_t *pdu = (idm_pdu_t *)event_ctx->iec_info; 1625a6d42e7dSPeter Dunlap iscsi_login_hdr_t *login_req = 1626a6d42e7dSPeter Dunlap (iscsi_login_hdr_t *)pdu->isp_hdr; 1627a6d42e7dSPeter Dunlap 1628a6d42e7dSPeter Dunlap ASSERT((event_ctx->iec_event == CE_LOGIN_SUCCESS_RCV) || 1629a6d42e7dSPeter Dunlap (event_ctx->iec_event == CE_LOGIN_SUCCESS_SND)); 1630a6d42e7dSPeter Dunlap 1631a6d42e7dSPeter Dunlap /* 1632a6d42e7dSPeter Dunlap * Save off CID 1633a6d42e7dSPeter Dunlap */ 1634a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 1635a6d42e7dSPeter Dunlap ic->ic_login_cid = ntohs(login_req->cid); 1636a6d42e7dSPeter Dunlap ic->ic_login_info_valid = B_TRUE; 1637a6d42e7dSPeter Dunlap 1638a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 1639a6d42e7dSPeter Dunlap } 1640