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