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. 24*57ff5e7eSJeff Biseda * Copyright (c) 2013 by Delphix. All rights reserved. 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 80e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States static void 81e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done_cb(idm_pdu_t *pdu, 82e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_status_t status); 83e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 84e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States static void 85e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done(idm_conn_t *ic, 86e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_event_ctx_t *event_ctx); 87e97fb153SPeter 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; 377e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CS_S9B_WAIT_SND_DONE: 378e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done(ic, event_ctx); 379e97fb153SPeter 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: 554e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(ic->ic_client_callback == NULL); 555e97fb153SPeter 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 574e97fb153SPeter 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 = 582e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done_cb; 583e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_update_state(ic, CS_S9B_WAIT_SND_DONE, 584e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States event_ctx); 585a6d42e7dSPeter Dunlap break; 586a6d42e7dSPeter Dunlap case CE_LOGIN_FAIL_RCV: 587e97fb153SPeter 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; 60547715e7fSPriya Krishnan case CE_LOGOUT_SESSION_SUCCESS: 60647715e7fSPriya Krishnan /* 60747715e7fSPriya Krishnan * T8 60847715e7fSPriya Krishnan * A session reinstatement request can be received while a 60947715e7fSPriya Krishnan * session is active and a login is in process. The iSCSI 61047715e7fSPriya Krishnan * connections are shut down by a CE_LOGOUT_SESSION_SUCCESS 61147715e7fSPriya Krishnan * event sent from the session to the IDM layer. 61247715e7fSPriya Krishnan */ 613*57ff5e7eSJeff Biseda (void) untimeout(ic->ic_state_timeout); 61447715e7fSPriya Krishnan if (IDM_CONN_ISTGT(ic)) { 61547715e7fSPriya Krishnan ic->ic_transport_ops->it_tgt_conn_disconnect(ic); 61647715e7fSPriya Krishnan } else { 61747715e7fSPriya Krishnan ic->ic_transport_ops->it_ini_conn_disconnect(ic); 61847715e7fSPriya Krishnan } 61947715e7fSPriya Krishnan idm_update_state(ic, CS_S11_COMPLETE, event_ctx); 62047715e7fSPriya Krishnan break; 62147715e7fSPriya Krishnan 622a6d42e7dSPeter Dunlap case CE_LOGIN_SND: 623e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(ic->ic_client_callback == NULL); 624a6d42e7dSPeter Dunlap /* 625a6d42e7dSPeter Dunlap * Initiator connections will see initial login PDU 626a6d42e7dSPeter Dunlap * in this state. Target connections see initial 627a6d42e7dSPeter Dunlap * login PDU in "xpt up" state. 628a6d42e7dSPeter Dunlap */ 629a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 630a6d42e7dSPeter Dunlap if (!(ic->ic_state_flags & CF_INITIAL_LOGIN)) { 631a6d42e7dSPeter Dunlap idm_initial_login_actions(ic, event_ctx); 632a6d42e7dSPeter Dunlap } 633a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 634a6d42e7dSPeter Dunlap break; 635a6d42e7dSPeter Dunlap case CE_MISC_TX: 636a6d42e7dSPeter Dunlap case CE_MISC_RX: 637a6d42e7dSPeter Dunlap case CE_LOGIN_RCV: 638a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 639a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 640a6d42e7dSPeter Dunlap /* Don't care */ 641a6d42e7dSPeter Dunlap break; 642a6d42e7dSPeter Dunlap default: 643a6d42e7dSPeter Dunlap ASSERT(0); 644a6d42e7dSPeter Dunlap /*NOTREACHED*/ 645a6d42e7dSPeter Dunlap } 646a6d42e7dSPeter Dunlap } 647a6d42e7dSPeter Dunlap 648a6d42e7dSPeter Dunlap 649a6d42e7dSPeter Dunlap static void 650a6d42e7dSPeter Dunlap idm_state_s5_logged_in(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 651a6d42e7dSPeter Dunlap { 652a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 653d618d68dSPriya Krishnan case CE_MISC_RX: 654d618d68dSPriya Krishnan /* MC/S: when removing the non-leading connection */ 655a6d42e7dSPeter Dunlap case CE_LOGOUT_THIS_CONN_RCV: 656a6d42e7dSPeter Dunlap case CE_LOGOUT_THIS_CONN_SND: 657a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_RCV: 658a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_SND: 659a6d42e7dSPeter Dunlap /* T9 */ 660a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_CONN_LOGOUT); /* Explicit logout */ 661a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S6_IN_LOGOUT, event_ctx); 662a6d42e7dSPeter Dunlap break; 663a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_RCV: 664a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SND: 665a6d42e7dSPeter Dunlap /* T9 */ 666a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_SESS_LOGOUT); /* Explicit logout */ 667a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S6_IN_LOGOUT, event_ctx); 668a6d42e7dSPeter Dunlap break; 669a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SUCCESS: 670a6d42e7dSPeter Dunlap /* T8 */ 671a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_SESS_LOGOUT); /* Explicit logout */ 672a6d42e7dSPeter Dunlap 673a6d42e7dSPeter Dunlap /* Close connection */ 674a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 675a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_conn_disconnect(ic); 676a6d42e7dSPeter Dunlap } else { 677a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_ini_conn_disconnect(ic); 678a6d42e7dSPeter Dunlap } 679a6d42e7dSPeter Dunlap 680a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S11_COMPLETE, event_ctx); 681a6d42e7dSPeter Dunlap break; 682a6d42e7dSPeter Dunlap case CE_ASYNC_LOGOUT_RCV: 683a6d42e7dSPeter Dunlap case CE_ASYNC_LOGOUT_SND: 684a6d42e7dSPeter Dunlap /* T11 */ 685a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S7_LOGOUT_REQ, event_ctx); 686a6d42e7dSPeter Dunlap break; 687a6d42e7dSPeter Dunlap case CE_TRANSPORT_FAIL: 688a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_CONN_RCV: 689a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_CONN_SND: 690a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_ALL_CONN_RCV: 691a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_ALL_CONN_SND: 692a6d42e7dSPeter Dunlap /* T15 */ 693a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_CONN_FAIL); /* Implicit logout */ 694a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S8_CLEANUP, event_ctx); 695a6d42e7dSPeter Dunlap break; 696a6d42e7dSPeter Dunlap case CE_MISC_TX: 697a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 698a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 69992adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_TIMEOUT: 700a6d42e7dSPeter Dunlap /* Don't care */ 701a6d42e7dSPeter Dunlap break; 702a6d42e7dSPeter Dunlap default: 703a6d42e7dSPeter Dunlap ASSERT(0); 704a6d42e7dSPeter Dunlap } 705a6d42e7dSPeter Dunlap } 706a6d42e7dSPeter Dunlap 707a6d42e7dSPeter Dunlap static void 708a6d42e7dSPeter Dunlap idm_state_s6_in_logout_success_snd_done(idm_pdu_t *pdu, idm_status_t status) 709a6d42e7dSPeter Dunlap { 710a6d42e7dSPeter Dunlap idm_conn_t *ic = pdu->isp_ic; 711a6d42e7dSPeter Dunlap 712a6d42e7dSPeter Dunlap /* 713a6d42e7dSPeter Dunlap * This pdu callback can be invoked by the tx thread, 714a6d42e7dSPeter Dunlap * so run the disconnect code from another thread. 715a6d42e7dSPeter Dunlap */ 716a6d42e7dSPeter Dunlap pdu->isp_status = status; 717a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_LOGOUT_SUCCESS_SND_DONE, (uintptr_t)pdu); 718a6d42e7dSPeter Dunlap } 719a6d42e7dSPeter Dunlap 720a6d42e7dSPeter Dunlap static void 721a6d42e7dSPeter Dunlap idm_state_s6_in_logout_fail_snd_done(idm_pdu_t *pdu, idm_status_t status) 722a6d42e7dSPeter Dunlap { 723a6d42e7dSPeter Dunlap idm_conn_t *ic = pdu->isp_ic; 724a6d42e7dSPeter Dunlap 725a6d42e7dSPeter Dunlap /* 726a6d42e7dSPeter Dunlap * This pdu callback can be invoked by the tx thread, 727a6d42e7dSPeter Dunlap * so run the disconnect code from another thread. 728a6d42e7dSPeter Dunlap */ 729a6d42e7dSPeter Dunlap pdu->isp_status = status; 730a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_LOGOUT_FAIL_SND_DONE, (uintptr_t)pdu); 731a6d42e7dSPeter Dunlap } 732a6d42e7dSPeter Dunlap 733a6d42e7dSPeter Dunlap static void 734a6d42e7dSPeter Dunlap idm_state_s6_in_logout(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 735a6d42e7dSPeter Dunlap { 736a6d42e7dSPeter Dunlap idm_pdu_t *pdu; 737a6d42e7dSPeter Dunlap 738a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 739a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND_DONE: 740a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 741a6d42e7dSPeter Dunlap 742a6d42e7dSPeter Dunlap /* Close connection (if it's not already closed) */ 743a6d42e7dSPeter Dunlap ASSERT(IDM_CONN_ISTGT(ic)); 744a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_conn_disconnect(ic); 745a6d42e7dSPeter Dunlap 746a6d42e7dSPeter Dunlap /* restore client callback */ 747a6d42e7dSPeter Dunlap pdu->isp_callback = ic->ic_client_callback; 748a6d42e7dSPeter Dunlap ic->ic_client_callback = NULL; 749a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, pdu->isp_status); 750a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S11_COMPLETE, event_ctx); 751a6d42e7dSPeter Dunlap break; 752a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND_DONE: 753a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 754a6d42e7dSPeter Dunlap /* restore client callback */ 755a6d42e7dSPeter Dunlap pdu->isp_callback = ic->ic_client_callback; 756a6d42e7dSPeter Dunlap ic->ic_client_callback = NULL; 757a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, pdu->isp_status); 758a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S8_CLEANUP, event_ctx); 759a6d42e7dSPeter Dunlap break; 760a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND: 761a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND: 762a6d42e7dSPeter Dunlap /* 763a6d42e7dSPeter Dunlap * Allow the logout response pdu to be sent and defer 764a6d42e7dSPeter Dunlap * the state machine update until the completion callback. 765a6d42e7dSPeter Dunlap * Only 1 level or callback interposition is allowed. 766a6d42e7dSPeter Dunlap */ 767a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 768a6d42e7dSPeter Dunlap ASSERT(ic->ic_client_callback == NULL); 769a6d42e7dSPeter Dunlap ic->ic_client_callback = pdu->isp_callback; 770a6d42e7dSPeter Dunlap if (event_ctx->iec_event == CE_LOGOUT_SUCCESS_SND) { 771a6d42e7dSPeter Dunlap pdu->isp_callback = 772a6d42e7dSPeter Dunlap idm_state_s6_in_logout_success_snd_done; 773a6d42e7dSPeter Dunlap } else { 774a6d42e7dSPeter Dunlap pdu->isp_callback = 775a6d42e7dSPeter Dunlap idm_state_s6_in_logout_fail_snd_done; 776a6d42e7dSPeter Dunlap } 777a6d42e7dSPeter Dunlap break; 778a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_RCV: 77930e7468fSPeter Dunlap /* 78030e7468fSPeter Dunlap * Need to deliver this PDU to the initiator now because after 78130e7468fSPeter Dunlap * we update the state to CS_S11_COMPLETE the initiator will 78230e7468fSPeter Dunlap * no longer be in an appropriate state. 78330e7468fSPeter Dunlap */ 78430e7468fSPeter Dunlap event_ctx->iec_pdu_forwarded = B_TRUE; 78530e7468fSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 78630e7468fSPeter Dunlap idm_pdu_rx_forward(ic, pdu); 78730e7468fSPeter Dunlap /* FALLTHROUGH */ 788a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SUCCESS: 789a6d42e7dSPeter Dunlap /* T13 */ 790a6d42e7dSPeter Dunlap 791a6d42e7dSPeter Dunlap /* Close connection (if it's not already closed) */ 792a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 793a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_conn_disconnect(ic); 794a6d42e7dSPeter Dunlap } else { 795a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_ini_conn_disconnect(ic); 796a6d42e7dSPeter Dunlap } 797a6d42e7dSPeter Dunlap 798a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S11_COMPLETE, event_ctx); 799a6d42e7dSPeter Dunlap break; 800a6d42e7dSPeter Dunlap case CE_ASYNC_LOGOUT_RCV: 801a6d42e7dSPeter Dunlap /* T14 Do nothing */ 802a6d42e7dSPeter Dunlap break; 803a6d42e7dSPeter Dunlap case CE_TRANSPORT_FAIL: 804a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_CONN_RCV: 805a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_CONN_SND: 806a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_ALL_CONN_RCV: 807a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_ALL_CONN_SND: 808a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_RCV: 809a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S8_CLEANUP, event_ctx); 810a6d42e7dSPeter Dunlap break; 811a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 812a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 813a6d42e7dSPeter Dunlap case CE_MISC_TX: 814a6d42e7dSPeter Dunlap case CE_MISC_RX: 81592adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_TIMEOUT: 816a6d42e7dSPeter Dunlap /* Don't care */ 817a6d42e7dSPeter Dunlap break; 818a6d42e7dSPeter Dunlap default: 819a6d42e7dSPeter Dunlap ASSERT(0); 820a6d42e7dSPeter Dunlap } 821a6d42e7dSPeter Dunlap } 822a6d42e7dSPeter Dunlap 823a6d42e7dSPeter Dunlap 824a6d42e7dSPeter Dunlap static void 825a6d42e7dSPeter Dunlap idm_logout_req_timeout(void *arg) 826a6d42e7dSPeter Dunlap { 827a6d42e7dSPeter Dunlap idm_conn_t *ic = arg; 828a6d42e7dSPeter Dunlap 829a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_LOGOUT_TIMEOUT, NULL); 830a6d42e7dSPeter Dunlap } 831a6d42e7dSPeter Dunlap 832a6d42e7dSPeter Dunlap static void 833a6d42e7dSPeter Dunlap idm_state_s7_logout_req(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 834a6d42e7dSPeter Dunlap { 835a6d42e7dSPeter Dunlap /* Must cancel logout timer before leaving this state */ 836a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 837a6d42e7dSPeter Dunlap case CE_LOGOUT_THIS_CONN_RCV: 838a6d42e7dSPeter Dunlap case CE_LOGOUT_THIS_CONN_SND: 839a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_RCV: 840a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_SND: 841a6d42e7dSPeter Dunlap /* T10 */ 842a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 843a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 844a6d42e7dSPeter Dunlap } 845a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_CONN_LOGOUT); /* Explicit logout */ 846a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S6_IN_LOGOUT, event_ctx); 847a6d42e7dSPeter Dunlap break; 848a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_RCV: 849a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SND: 850a6d42e7dSPeter Dunlap /* T10 */ 851a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 852a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 853a6d42e7dSPeter Dunlap } 854a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_SESS_LOGOUT); /* Explicit logout */ 855a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S6_IN_LOGOUT, event_ctx); 856a6d42e7dSPeter Dunlap break; 857a6d42e7dSPeter Dunlap case CE_ASYNC_LOGOUT_RCV: 858a6d42e7dSPeter Dunlap case CE_ASYNC_LOGOUT_SND: 859a6d42e7dSPeter Dunlap /* T12 Do nothing */ 860a6d42e7dSPeter Dunlap break; 861a6d42e7dSPeter Dunlap case CE_TRANSPORT_FAIL: 862a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_CONN_RCV: 863a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_CONN_SND: 864a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_ALL_CONN_RCV: 865a6d42e7dSPeter Dunlap case CE_ASYNC_DROP_ALL_CONN_SND: 866a6d42e7dSPeter Dunlap /* T16 */ 867a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 868a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 869a6d42e7dSPeter Dunlap } 870a6d42e7dSPeter Dunlap /* FALLTHROUGH */ 871a6d42e7dSPeter Dunlap case CE_LOGOUT_TIMEOUT: 872a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_CONN_FAIL); /* Implicit logout */ 873a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S8_CLEANUP, event_ctx); 874a6d42e7dSPeter Dunlap break; 875a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SUCCESS: 876a6d42e7dSPeter Dunlap /* T18 */ 877a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 878a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 879a6d42e7dSPeter Dunlap } 880a6d42e7dSPeter Dunlap idm_ffp_disable(ic, FD_SESS_LOGOUT); /* Explicit logout */ 881a6d42e7dSPeter Dunlap 882a6d42e7dSPeter Dunlap /* Close connection (if it's not already closed) */ 883a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 884a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_conn_disconnect(ic); 885a6d42e7dSPeter Dunlap } else { 886a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_ini_conn_disconnect(ic); 887a6d42e7dSPeter Dunlap } 888a6d42e7dSPeter Dunlap 889a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S11_COMPLETE, event_ctx); 890a6d42e7dSPeter Dunlap break; 891a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 892a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 893a6d42e7dSPeter Dunlap case CE_MISC_TX: 894a6d42e7dSPeter Dunlap case CE_MISC_RX: 89592adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_TIMEOUT: 896a6d42e7dSPeter Dunlap /* Don't care */ 897a6d42e7dSPeter Dunlap break; 898a6d42e7dSPeter Dunlap default: 899a6d42e7dSPeter Dunlap ASSERT(0); 900a6d42e7dSPeter Dunlap } 901a6d42e7dSPeter Dunlap } 902a6d42e7dSPeter Dunlap 903a6d42e7dSPeter Dunlap 904a6d42e7dSPeter Dunlap static void 905a6d42e7dSPeter Dunlap idm_cleanup_timeout(void *arg) 906a6d42e7dSPeter Dunlap { 907a6d42e7dSPeter Dunlap idm_conn_t *ic = arg; 908a6d42e7dSPeter Dunlap 909a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_CLEANUP_TIMEOUT, NULL); 910a6d42e7dSPeter Dunlap } 911a6d42e7dSPeter Dunlap 912a6d42e7dSPeter Dunlap static void 913a6d42e7dSPeter Dunlap idm_state_s8_cleanup(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 914a6d42e7dSPeter Dunlap { 915a6d42e7dSPeter Dunlap idm_pdu_t *pdu; 916a6d42e7dSPeter Dunlap 917a6d42e7dSPeter Dunlap /* 918a6d42e7dSPeter Dunlap * Need to cancel the cleanup timeout before leaving this state 919a6d42e7dSPeter Dunlap * if it hasn't already fired. 920a6d42e7dSPeter Dunlap */ 921a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 922a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_RCV: 923a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND: 924a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SUCCESS: 925a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 926a6d42e7dSPeter Dunlap /*FALLTHROUGH*/ 927a6d42e7dSPeter Dunlap case CE_CLEANUP_TIMEOUT: 928a6d42e7dSPeter Dunlap /* M1 */ 929a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S11_COMPLETE, event_ctx); 930a6d42e7dSPeter Dunlap break; 931a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_RCV: 932a6d42e7dSPeter Dunlap case CE_LOGOUT_OTHER_CONN_SND: 933a6d42e7dSPeter Dunlap /* M2 */ 934a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S10_IN_CLEANUP, event_ctx); 935a6d42e7dSPeter Dunlap break; 936a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND_DONE: 937a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND_DONE: 938a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 939a6d42e7dSPeter Dunlap /* restore client callback */ 940a6d42e7dSPeter Dunlap pdu->isp_callback = ic->ic_client_callback; 941a6d42e7dSPeter Dunlap ic->ic_client_callback = NULL; 942a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, pdu->isp_status); 943a6d42e7dSPeter Dunlap break; 944a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_RCV: 945a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SND: 946a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 947a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 948a6d42e7dSPeter Dunlap case CE_MISC_TX: 949a6d42e7dSPeter Dunlap case CE_MISC_RX: 950a6d42e7dSPeter Dunlap case CE_TRANSPORT_FAIL: 95192adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_TIMEOUT: 952a6d42e7dSPeter Dunlap case CE_LOGOUT_TIMEOUT: 953a6d42e7dSPeter Dunlap /* Don't care */ 954a6d42e7dSPeter Dunlap break; 955a6d42e7dSPeter Dunlap default: 956a6d42e7dSPeter Dunlap ASSERT(0); 957a6d42e7dSPeter Dunlap } 958a6d42e7dSPeter Dunlap } 959a6d42e7dSPeter Dunlap 960a6d42e7dSPeter Dunlap /* ARGSUSED */ 961a6d42e7dSPeter Dunlap static void 962a6d42e7dSPeter Dunlap idm_state_s9_init_error(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 963a6d42e7dSPeter Dunlap { 964e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* All events ignored in this state */ 965a6d42e7dSPeter Dunlap } 966a6d42e7dSPeter Dunlap 967e42a0851Speter dunlap /* ARGSUSED */ 968e42a0851Speter dunlap static void 969e42a0851Speter dunlap idm_state_s9a_rejected(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 970e42a0851Speter dunlap { 971e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* All events ignored in this state */ 972e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States } 973e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 974e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 975e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States static void 976e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done_cb(idm_pdu_t *pdu, idm_status_t status) 977e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States { 978e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_t *ic = pdu->isp_ic; 979e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 980e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* 981e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * This pdu callback can be invoked by the tx thread, 982e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * so run the disconnect code from another thread. 983e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States */ 984e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States pdu->isp_status = status; 985e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_event(ic, CE_LOGIN_FAIL_SND_DONE, (uintptr_t)pdu); 986e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States } 987e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 988e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* 989e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * CS_S9B_WAIT_SND_DONE -- wait for callback completion. 990e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States */ 991e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* ARGSUSED */ 992e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States static void 993e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_state_s9b_wait_snd_done(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 994e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States { 995e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_pdu_t *pdu; 996e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* 997e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * Wait for completion of the login fail sequence and then 998e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * go to state S9_INIT_ERROR to clean up the connection. 999e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States */ 1000e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States switch (event_ctx->iec_event) { 1001e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_FAIL_SND_DONE: 1002e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States pdu = (idm_pdu_t *)event_ctx->iec_info; 1003e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* restore client callback */ 1004e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States pdu->isp_callback = ic->ic_client_callback; 1005e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States ic->ic_client_callback = NULL; 1006e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_pdu_complete(pdu, pdu->isp_status); 1007e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx); 1008e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States break; 1009e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 1010e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* All other events ignored */ 1011e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States } 1012e42a0851Speter dunlap } 1013e42a0851Speter dunlap 1014e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 1015e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 1016e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 1017a6d42e7dSPeter Dunlap static void 1018a6d42e7dSPeter Dunlap idm_state_s10_in_cleanup(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 1019a6d42e7dSPeter Dunlap { 1020a6d42e7dSPeter Dunlap idm_pdu_t *pdu; 1021a6d42e7dSPeter Dunlap 1022a6d42e7dSPeter Dunlap /* 1023a6d42e7dSPeter Dunlap * Need to cancel the cleanup timeout before leaving this state 1024a6d42e7dSPeter Dunlap * if it hasn't already fired. 1025a6d42e7dSPeter Dunlap */ 1026a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 1027a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_RCV: 1028a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND: 1029a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S8_CLEANUP, event_ctx); 1030a6d42e7dSPeter Dunlap break; 1031a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND: 1032a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_RCV: 1033a6d42e7dSPeter Dunlap case CE_LOGOUT_SESSION_SUCCESS: 1034a6d42e7dSPeter Dunlap (void) untimeout(ic->ic_state_timeout); 1035a6d42e7dSPeter Dunlap /*FALLTHROUGH*/ 1036a6d42e7dSPeter Dunlap case CE_CLEANUP_TIMEOUT: 1037a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S11_COMPLETE, event_ctx); 1038a6d42e7dSPeter Dunlap break; 1039a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND_DONE: 1040a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND_DONE: 1041a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 1042a6d42e7dSPeter Dunlap /* restore client callback */ 1043a6d42e7dSPeter Dunlap pdu->isp_callback = ic->ic_client_callback; 1044a6d42e7dSPeter Dunlap ic->ic_client_callback = NULL; 1045a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, pdu->isp_status); 1046a6d42e7dSPeter Dunlap break; 1047a6d42e7dSPeter Dunlap case CE_TX_PROTOCOL_ERROR: 1048a6d42e7dSPeter Dunlap case CE_RX_PROTOCOL_ERROR: 1049a6d42e7dSPeter Dunlap case CE_MISC_TX: 1050a6d42e7dSPeter Dunlap case CE_MISC_RX: 105192adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CE_LOGIN_TIMEOUT: 1052a6d42e7dSPeter Dunlap case CE_LOGOUT_TIMEOUT: 1053a6d42e7dSPeter Dunlap /* Don't care */ 1054a6d42e7dSPeter Dunlap break; 1055a6d42e7dSPeter Dunlap default: 1056a6d42e7dSPeter Dunlap ASSERT(0); 1057a6d42e7dSPeter Dunlap } 1058a6d42e7dSPeter Dunlap } 1059a6d42e7dSPeter Dunlap 1060a6d42e7dSPeter Dunlap /* ARGSUSED */ 1061a6d42e7dSPeter Dunlap static void 1062a6d42e7dSPeter Dunlap idm_state_s11_complete(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 1063a6d42e7dSPeter Dunlap { 1064a6d42e7dSPeter Dunlap idm_pdu_t *pdu; 1065a6d42e7dSPeter Dunlap 1066a6d42e7dSPeter Dunlap /* 1067a6d42e7dSPeter Dunlap * Cleanup logout success/fail completion if it's been delayed 1068a6d42e7dSPeter Dunlap * until now. 1069e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * 1070e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * All new events are filtered out before reaching this state, but 1071e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * there might already be events in the event queue, so handle the 1072e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * SND_DONE events here. Note that if either of the following 1073e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * SND_DONE events happens AFTER the change to state S11, then the 1074e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * event filter inside dm_conn_event_locked does enough cleanup. 1075a6d42e7dSPeter Dunlap */ 1076a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 1077a6d42e7dSPeter Dunlap case CE_LOGOUT_SUCCESS_SND_DONE: 1078a6d42e7dSPeter Dunlap case CE_LOGOUT_FAIL_SND_DONE: 1079a6d42e7dSPeter Dunlap pdu = (idm_pdu_t *)event_ctx->iec_info; 1080a6d42e7dSPeter Dunlap /* restore client callback */ 1081a6d42e7dSPeter Dunlap pdu->isp_callback = ic->ic_client_callback; 1082a6d42e7dSPeter Dunlap ic->ic_client_callback = NULL; 1083a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, pdu->isp_status); 1084a6d42e7dSPeter Dunlap break; 1085a6d42e7dSPeter Dunlap } 1086e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 1087a6d42e7dSPeter Dunlap } 1088a6d42e7dSPeter Dunlap 1089a6d42e7dSPeter Dunlap static void 1090a6d42e7dSPeter Dunlap idm_state_s12_enable_dm(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 1091a6d42e7dSPeter Dunlap { 1092a6d42e7dSPeter Dunlap switch (event_ctx->iec_event) { 1093a6d42e7dSPeter Dunlap case CE_ENABLE_DM_SUCCESS: 1094a6d42e7dSPeter Dunlap /* T20 */ 1095a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S5_LOGGED_IN, event_ctx); 1096a6d42e7dSPeter Dunlap break; 1097a6d42e7dSPeter Dunlap case CE_ENABLE_DM_FAIL: 1098a6d42e7dSPeter Dunlap /* T21 */ 1099a6d42e7dSPeter Dunlap idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx); 1100a6d42e7dSPeter Dunlap break; 1101a6d42e7dSPeter Dunlap case CE_TRANSPORT_FAIL: 1102a6d42e7dSPeter Dunlap /* 1103a6d42e7dSPeter Dunlap * We expect to always hear back from the transport layer 1104a6d42e7dSPeter Dunlap * once we have an "enable data-mover" request outstanding. 1105a6d42e7dSPeter Dunlap * Therefore we'll ignore other events that may occur even 1106a6d42e7dSPeter Dunlap * when they clearly indicate a problem and wait for 1107a6d42e7dSPeter Dunlap * CE_ENABLE_DM_FAIL. On a related note this means the 1108a6d42e7dSPeter Dunlap * transport must ensure that it eventually completes the 1109a6d42e7dSPeter Dunlap * "enable data-mover" operation with either success or 1110a6d42e7dSPeter Dunlap * failure -- otherwise we'll be stuck here. 1111a6d42e7dSPeter Dunlap */ 1112a6d42e7dSPeter Dunlap break; 1113a6d42e7dSPeter Dunlap default: 1114a6d42e7dSPeter Dunlap ASSERT(0); 1115a6d42e7dSPeter Dunlap break; 1116a6d42e7dSPeter Dunlap } 1117a6d42e7dSPeter Dunlap } 1118a6d42e7dSPeter Dunlap 1119a6d42e7dSPeter Dunlap static void 1120a6d42e7dSPeter Dunlap idm_update_state(idm_conn_t *ic, idm_conn_state_t new_state, 1121a6d42e7dSPeter Dunlap idm_conn_event_ctx_t *event_ctx) 1122a6d42e7dSPeter Dunlap { 1123a6d42e7dSPeter Dunlap int rc; 1124a6d42e7dSPeter Dunlap idm_status_t idm_status; 1125a6d42e7dSPeter Dunlap 1126a6d42e7dSPeter Dunlap /* 1127a6d42e7dSPeter Dunlap * Validate new state 1128a6d42e7dSPeter Dunlap */ 1129a6d42e7dSPeter Dunlap ASSERT(new_state != CS_S0_UNDEFINED); 1130a6d42e7dSPeter Dunlap ASSERT3U(new_state, <, CS_MAX_STATE); 1131a6d42e7dSPeter Dunlap 1132a6d42e7dSPeter Dunlap /* 1133a6d42e7dSPeter Dunlap * Update state in context. We protect this with a mutex 1134a6d42e7dSPeter Dunlap * even though the state machine code is single threaded so that 1135a6d42e7dSPeter Dunlap * other threads can check the state value atomically. 1136a6d42e7dSPeter Dunlap */ 1137a6d42e7dSPeter Dunlap new_state = (new_state < CS_MAX_STATE) ? 1138a6d42e7dSPeter Dunlap new_state : CS_S0_UNDEFINED; 1139a6d42e7dSPeter Dunlap 1140a6d42e7dSPeter Dunlap IDM_SM_LOG(CE_NOTE, "idm_update_state: conn %p, evt %s(%d), " 1141a6d42e7dSPeter Dunlap "%s(%d) --> %s(%d)", (void *)ic, 1142a6d42e7dSPeter Dunlap idm_ce_name[event_ctx->iec_event], event_ctx->iec_event, 1143a6d42e7dSPeter Dunlap idm_cs_name[ic->ic_state], ic->ic_state, 1144a6d42e7dSPeter Dunlap idm_cs_name[new_state], new_state); 1145a6d42e7dSPeter Dunlap 1146a6d42e7dSPeter Dunlap DTRACE_PROBE2(conn__state__change, 1147a6d42e7dSPeter Dunlap idm_conn_t *, ic, idm_conn_state_t, new_state); 1148a6d42e7dSPeter Dunlap 1149a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 1150a6d42e7dSPeter Dunlap idm_sm_audit_state_change(&ic->ic_state_audit, SAS_IDM_CONN, 1151a6d42e7dSPeter Dunlap (int)ic->ic_state, (int)new_state); 1152a6d42e7dSPeter Dunlap ic->ic_last_state = ic->ic_state; 1153a6d42e7dSPeter Dunlap ic->ic_state = new_state; 1154a6d42e7dSPeter Dunlap cv_signal(&ic->ic_state_cv); 1155a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 1156a6d42e7dSPeter Dunlap 1157a6d42e7dSPeter Dunlap switch (ic->ic_state) { 1158a6d42e7dSPeter Dunlap case CS_S1_FREE: 1159a6d42e7dSPeter Dunlap ASSERT(0); /* Initial state, can't return */ 1160a6d42e7dSPeter Dunlap break; 1161a6d42e7dSPeter Dunlap case CS_S2_XPT_WAIT: 1162a6d42e7dSPeter Dunlap if ((rc = idm_ini_conn_finish(ic)) != 0) { 1163a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_CONNECT_FAIL, NULL); 1164a6d42e7dSPeter Dunlap } else { 1165a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_CONNECT_SUCCESS, NULL); 1166a6d42e7dSPeter Dunlap } 1167a6d42e7dSPeter Dunlap break; 1168a6d42e7dSPeter Dunlap case CS_S3_XPT_UP: 1169a6d42e7dSPeter Dunlap /* 1170a6d42e7dSPeter Dunlap * Finish any connection related setup including 1171a6d42e7dSPeter Dunlap * waking up the idm_tgt_conn_accept thread. 1172a6d42e7dSPeter Dunlap * and starting the login timer. If the function 1173a6d42e7dSPeter Dunlap * fails then we return to "free" state. 1174a6d42e7dSPeter Dunlap */ 1175a6d42e7dSPeter Dunlap if ((rc = idm_tgt_conn_finish(ic)) != IDM_STATUS_SUCCESS) { 1176a6d42e7dSPeter Dunlap switch (rc) { 1177a6d42e7dSPeter Dunlap case IDM_STATUS_REJECT: 1178a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_CONNECT_REJECT, NULL); 1179a6d42e7dSPeter Dunlap break; 1180a6d42e7dSPeter Dunlap default: 1181a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_CONNECT_FAIL, NULL); 1182a6d42e7dSPeter Dunlap break; 1183a6d42e7dSPeter Dunlap } 1184a6d42e7dSPeter Dunlap } 1185a6d42e7dSPeter Dunlap 1186a6d42e7dSPeter Dunlap /* 1187a6d42e7dSPeter Dunlap * First login received will cause a transition to 1188a6d42e7dSPeter Dunlap * CS_S4_IN_LOGIN. Start login timer. 1189a6d42e7dSPeter Dunlap */ 1190a6d42e7dSPeter Dunlap ic->ic_state_timeout = timeout(idm_login_timeout, ic, 1191a6d42e7dSPeter Dunlap drv_usectohz(IDM_LOGIN_SECONDS*1000000)); 1192a6d42e7dSPeter Dunlap break; 1193a6d42e7dSPeter Dunlap case CS_S4_IN_LOGIN: 1194a6d42e7dSPeter Dunlap if (ic->ic_conn_type == CONN_TYPE_INI) { 11955f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States (void) idm_notify_client(ic, CN_READY_FOR_LOGIN, NULL); 1196a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 1197a6d42e7dSPeter Dunlap ic->ic_state_flags |= CF_LOGIN_READY; 1198a6d42e7dSPeter Dunlap cv_signal(&ic->ic_state_cv); 1199a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 1200a6d42e7dSPeter Dunlap } 1201a6d42e7dSPeter Dunlap break; 1202a6d42e7dSPeter Dunlap case CS_S5_LOGGED_IN: 1203a6d42e7dSPeter Dunlap ASSERT(!ic->ic_ffp); 1204a6d42e7dSPeter Dunlap /* 1205a6d42e7dSPeter Dunlap * IDM can go to FFP before the initiator but it 1206a6d42e7dSPeter Dunlap * needs to go to FFP after the target (IDM target should 1207a6d42e7dSPeter Dunlap * go to FFP after notify_ack). 1208a6d42e7dSPeter Dunlap */ 1209a6d42e7dSPeter Dunlap idm_status = idm_ffp_enable(ic); 1210a6d42e7dSPeter Dunlap if (idm_status != IDM_STATUS_SUCCESS) { 1211a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_TRANSPORT_FAIL, NULL); 1212a6d42e7dSPeter Dunlap } 1213a6d42e7dSPeter Dunlap 1214a6d42e7dSPeter Dunlap if (ic->ic_reinstate_conn) { 1215a6d42e7dSPeter Dunlap /* Connection reinstatement is complete */ 121692adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_event(ic->ic_reinstate_conn, 121792adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States CE_CONN_REINSTATE_SUCCESS, NULL); 1218a6d42e7dSPeter Dunlap } 1219a6d42e7dSPeter Dunlap break; 1220a6d42e7dSPeter Dunlap case CS_S6_IN_LOGOUT: 1221a6d42e7dSPeter Dunlap break; 1222a6d42e7dSPeter Dunlap case CS_S7_LOGOUT_REQ: 1223a6d42e7dSPeter Dunlap /* Start logout timer for target connections */ 1224a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 1225a6d42e7dSPeter Dunlap ic->ic_state_timeout = timeout(idm_logout_req_timeout, 1226a6d42e7dSPeter Dunlap ic, drv_usectohz(IDM_LOGOUT_SECONDS*1000000)); 1227a6d42e7dSPeter Dunlap } 1228a6d42e7dSPeter Dunlap break; 1229a6d42e7dSPeter Dunlap case CS_S8_CLEANUP: 1230a6d42e7dSPeter Dunlap /* Close connection (if it's not already closed) */ 1231a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 1232a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_conn_disconnect(ic); 1233a6d42e7dSPeter Dunlap } else { 1234a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_ini_conn_disconnect(ic); 1235a6d42e7dSPeter Dunlap } 1236a6d42e7dSPeter Dunlap 1237a6d42e7dSPeter Dunlap /* Stop executing active tasks */ 1238a6d42e7dSPeter Dunlap idm_task_abort(ic, NULL, AT_INTERNAL_SUSPEND); 1239a6d42e7dSPeter Dunlap 1240a6d42e7dSPeter Dunlap /* Start logout timer */ 1241a6d42e7dSPeter Dunlap ic->ic_state_timeout = timeout(idm_cleanup_timeout, ic, 1242a6d42e7dSPeter Dunlap drv_usectohz(IDM_CLEANUP_SECONDS*1000000)); 1243a6d42e7dSPeter Dunlap break; 1244a6d42e7dSPeter Dunlap case CS_S10_IN_CLEANUP: 1245a6d42e7dSPeter Dunlap break; 1246e42a0851Speter dunlap case CS_S9A_REJECTED: 1247e42a0851Speter dunlap /* 1248e42a0851Speter dunlap * We never finished establishing the connection so no 1249e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States * disconnect. No client notifications because the client 1250e42a0851Speter dunlap * rejected the connection. 1251e42a0851Speter dunlap */ 1252e42a0851Speter dunlap idm_refcnt_async_wait_ref(&ic->ic_refcnt, 1253e42a0851Speter dunlap &idm_conn_reject_unref); 1254e42a0851Speter dunlap break; 1255e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States case CS_S9B_WAIT_SND_DONE: 1256e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States break; 1257a6d42e7dSPeter Dunlap case CS_S9_INIT_ERROR: 1258a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 1259a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_conn_disconnect(ic); 1260a6d42e7dSPeter Dunlap } else { 1261a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 1262a6d42e7dSPeter Dunlap ic->ic_state_flags |= CF_ERROR; 1263a6d42e7dSPeter Dunlap ic->ic_conn_sm_status = IDM_STATUS_FAIL; 1264a6d42e7dSPeter Dunlap cv_signal(&ic->ic_state_cv); 1265a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 126630e7468fSPeter Dunlap if (ic->ic_last_state != CS_S1_FREE && 126730e7468fSPeter Dunlap ic->ic_last_state != CS_S2_XPT_WAIT) { 126830e7468fSPeter Dunlap ic->ic_transport_ops->it_ini_conn_disconnect( 126930e7468fSPeter Dunlap ic); 127030e7468fSPeter Dunlap } else { 127130e7468fSPeter Dunlap (void) idm_notify_client(ic, CN_CONNECT_FAIL, 127230e7468fSPeter Dunlap NULL); 127330e7468fSPeter Dunlap } 1274a6d42e7dSPeter Dunlap } 1275a6d42e7dSPeter Dunlap /*FALLTHROUGH*/ 1276a6d42e7dSPeter Dunlap case CS_S11_COMPLETE: 127730e7468fSPeter Dunlap /* 127830e7468fSPeter Dunlap * No more traffic on this connection. If this is an 127930e7468fSPeter Dunlap * initiator connection and we weren't connected yet 128030e7468fSPeter Dunlap * then don't send the "connect lost" event. 128130e7468fSPeter Dunlap * It's useful to the initiator to know whether we were 128230e7468fSPeter Dunlap * logging in at the time so send that information in the 128330e7468fSPeter Dunlap * data field. 128430e7468fSPeter Dunlap */ 128530e7468fSPeter Dunlap if (IDM_CONN_ISTGT(ic) || 128630e7468fSPeter Dunlap ((ic->ic_last_state != CS_S1_FREE) && 128730e7468fSPeter Dunlap (ic->ic_last_state != CS_S2_XPT_WAIT))) { 128830e7468fSPeter Dunlap (void) idm_notify_client(ic, CN_CONNECT_LOST, 128930e7468fSPeter Dunlap (uintptr_t)(ic->ic_last_state == CS_S4_IN_LOGIN)); 129030e7468fSPeter Dunlap } 1291a6d42e7dSPeter Dunlap 1292a6d42e7dSPeter Dunlap /* Abort all tasks */ 1293a6d42e7dSPeter Dunlap idm_task_abort(ic, NULL, AT_INTERNAL_ABORT); 1294a6d42e7dSPeter Dunlap 1295a6d42e7dSPeter Dunlap /* 1296a6d42e7dSPeter Dunlap * Handle terminal state actions on the global taskq so 1297a6d42e7dSPeter Dunlap * we can clean up all the connection resources from 1298a6d42e7dSPeter Dunlap * a separate thread context. 1299a6d42e7dSPeter Dunlap */ 1300a6d42e7dSPeter Dunlap idm_refcnt_async_wait_ref(&ic->ic_refcnt, &idm_conn_unref); 1301a6d42e7dSPeter Dunlap break; 1302a6d42e7dSPeter Dunlap case CS_S12_ENABLE_DM: 1303a6d42e7dSPeter Dunlap 1304a6d42e7dSPeter Dunlap /* 1305a6d42e7dSPeter Dunlap * The Enable DM state indicates the initiator to initiate 1306a6d42e7dSPeter Dunlap * the hello sequence and the target to get ready to accept 1307a6d42e7dSPeter Dunlap * the iSER Hello Message. 1308a6d42e7dSPeter Dunlap */ 1309a6d42e7dSPeter Dunlap idm_status = (IDM_CONN_ISINI(ic)) ? 1310a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_ini_enable_datamover(ic) : 1311a6d42e7dSPeter Dunlap ic->ic_transport_ops->it_tgt_enable_datamover(ic); 1312a6d42e7dSPeter Dunlap 1313a6d42e7dSPeter Dunlap if (idm_status == IDM_STATUS_SUCCESS) { 1314a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_ENABLE_DM_SUCCESS, NULL); 1315a6d42e7dSPeter Dunlap } else { 1316a6d42e7dSPeter Dunlap idm_conn_event(ic, CE_ENABLE_DM_FAIL, NULL); 1317a6d42e7dSPeter Dunlap } 1318a6d42e7dSPeter Dunlap 1319a6d42e7dSPeter Dunlap break; 1320e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 1321e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States default: 1322e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(0); 1323e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States break; 1324e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States 1325a6d42e7dSPeter Dunlap } 1326a6d42e7dSPeter Dunlap } 1327a6d42e7dSPeter Dunlap 1328a6d42e7dSPeter Dunlap 1329a6d42e7dSPeter Dunlap static void 1330a6d42e7dSPeter Dunlap idm_conn_unref(void *ic_void) 1331a6d42e7dSPeter Dunlap { 1332a6d42e7dSPeter Dunlap idm_conn_t *ic = ic_void; 1333a6d42e7dSPeter Dunlap 1334a6d42e7dSPeter Dunlap /* 1335a6d42e7dSPeter Dunlap * Client should not be notified that the connection is destroyed 1336a6d42e7dSPeter Dunlap * until all references on the idm connection have been removed. 1337a6d42e7dSPeter Dunlap * Otherwise references on the associated client context would need 1338a6d42e7dSPeter Dunlap * to be tracked separately which seems like a waste (at least when 1339a6d42e7dSPeter Dunlap * there is a one for one correspondence with references on the 1340a6d42e7dSPeter Dunlap * IDM connection). 1341a6d42e7dSPeter Dunlap */ 1342a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic)) { 1343a6d42e7dSPeter Dunlap (void) idm_notify_client(ic, CN_CONNECT_DESTROY, NULL); 1344a6d42e7dSPeter Dunlap idm_svc_conn_destroy(ic); 1345a6d42e7dSPeter Dunlap } else { 1346a6d42e7dSPeter Dunlap /* Initiator may destroy connection during this call */ 1347a6d42e7dSPeter Dunlap (void) idm_notify_client(ic, CN_CONNECT_DESTROY, NULL); 1348a6d42e7dSPeter Dunlap } 1349a6d42e7dSPeter Dunlap } 1350a6d42e7dSPeter Dunlap 1351e42a0851Speter dunlap static void 1352e42a0851Speter dunlap idm_conn_reject_unref(void *ic_void) 1353e42a0851Speter dunlap { 1354e42a0851Speter dunlap idm_conn_t *ic = ic_void; 1355e42a0851Speter dunlap 1356e42a0851Speter dunlap ASSERT(IDM_CONN_ISTGT(ic)); 1357e42a0851Speter dunlap 1358e42a0851Speter dunlap /* Don't notify the client since it rejected the connection */ 1359e42a0851Speter dunlap idm_svc_conn_destroy(ic); 1360e42a0851Speter dunlap } 1361e42a0851Speter dunlap 1362e42a0851Speter dunlap 1363a6d42e7dSPeter Dunlap 1364a6d42e7dSPeter Dunlap static idm_pdu_event_action_t 1365a6d42e7dSPeter Dunlap idm_conn_sm_validate_pdu(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx, 1366a6d42e7dSPeter Dunlap idm_pdu_t *pdu) 1367a6d42e7dSPeter Dunlap { 1368a6d42e7dSPeter Dunlap char *reason_string; 1369a6d42e7dSPeter Dunlap idm_pdu_event_action_t action; 1370a6d42e7dSPeter Dunlap 1371a6d42e7dSPeter Dunlap ASSERT((event_ctx->iec_pdu_event_type == CT_RX_PDU) || 1372a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_TX_PDU)); 1373a6d42e7dSPeter Dunlap 1374a6d42e7dSPeter Dunlap /* 1375a6d42e7dSPeter Dunlap * Let's check the simple stuff first. Make sure if this is a 1376a6d42e7dSPeter Dunlap * target connection that the PDU is appropriate for a target 1377a6d42e7dSPeter Dunlap * and if this is an initiator connection that the PDU is 1378a6d42e7dSPeter Dunlap * appropriate for an initiator. This code is not in the data 1379a6d42e7dSPeter Dunlap * path so organization is more important than performance. 1380a6d42e7dSPeter Dunlap */ 1381a6d42e7dSPeter Dunlap switch (IDM_PDU_OPCODE(pdu)) { 1382a6d42e7dSPeter Dunlap case ISCSI_OP_NOOP_OUT: 1383a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_CMD: 1384a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_TASK_MGT_MSG: 1385a6d42e7dSPeter Dunlap case ISCSI_OP_LOGIN_CMD: 1386a6d42e7dSPeter Dunlap case ISCSI_OP_TEXT_CMD: 1387a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_DATA: 1388a6d42e7dSPeter Dunlap case ISCSI_OP_LOGOUT_CMD: 1389a6d42e7dSPeter Dunlap case ISCSI_OP_SNACK_CMD: 1390a6d42e7dSPeter Dunlap /* 1391a6d42e7dSPeter Dunlap * Only the initiator should send these PDU's and 1392a6d42e7dSPeter Dunlap * only the target should receive them. 1393a6d42e7dSPeter Dunlap */ 1394a6d42e7dSPeter Dunlap if (IDM_CONN_ISINI(ic) && 1395a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_RX_PDU)) { 1396a6d42e7dSPeter Dunlap reason_string = "Invalid RX PDU for initiator"; 1397a6d42e7dSPeter Dunlap action = CA_RX_PROTOCOL_ERROR; 1398a6d42e7dSPeter Dunlap goto validate_pdu_done; 1399a6d42e7dSPeter Dunlap } 1400a6d42e7dSPeter Dunlap 1401a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic) && 1402a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_TX_PDU)) { 1403a6d42e7dSPeter Dunlap reason_string = "Invalid TX PDU for target"; 1404a6d42e7dSPeter Dunlap action = CA_TX_PROTOCOL_ERROR; 1405a6d42e7dSPeter Dunlap goto validate_pdu_done; 1406a6d42e7dSPeter Dunlap } 1407a6d42e7dSPeter Dunlap break; 1408a6d42e7dSPeter Dunlap case ISCSI_OP_NOOP_IN: 1409a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_RSP: 1410a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_TASK_MGT_RSP: 1411a6d42e7dSPeter Dunlap case ISCSI_OP_LOGIN_RSP: 1412a6d42e7dSPeter Dunlap case ISCSI_OP_TEXT_RSP: 1413a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_DATA_RSP: 1414a6d42e7dSPeter Dunlap case ISCSI_OP_LOGOUT_RSP: 1415a6d42e7dSPeter Dunlap case ISCSI_OP_RTT_RSP: 1416a6d42e7dSPeter Dunlap case ISCSI_OP_ASYNC_EVENT: 1417a6d42e7dSPeter Dunlap case ISCSI_OP_REJECT_MSG: 1418a6d42e7dSPeter Dunlap /* 1419a6d42e7dSPeter Dunlap * Only the target should send these PDU's and 1420a6d42e7dSPeter Dunlap * only the initiator should receive them. 1421a6d42e7dSPeter Dunlap */ 1422a6d42e7dSPeter Dunlap if (IDM_CONN_ISTGT(ic) && 1423a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_RX_PDU)) { 1424a6d42e7dSPeter Dunlap reason_string = "Invalid RX PDU for target"; 1425a6d42e7dSPeter Dunlap action = CA_RX_PROTOCOL_ERROR; 1426a6d42e7dSPeter Dunlap goto validate_pdu_done; 1427a6d42e7dSPeter Dunlap } 1428a6d42e7dSPeter Dunlap 1429a6d42e7dSPeter Dunlap if (IDM_CONN_ISINI(ic) && 1430a6d42e7dSPeter Dunlap (event_ctx->iec_pdu_event_type == CT_TX_PDU)) { 1431a6d42e7dSPeter Dunlap reason_string = "Invalid TX PDU for initiator"; 1432a6d42e7dSPeter Dunlap action = CA_TX_PROTOCOL_ERROR; 1433a6d42e7dSPeter Dunlap goto validate_pdu_done; 1434a6d42e7dSPeter Dunlap } 1435a6d42e7dSPeter Dunlap break; 1436a6d42e7dSPeter Dunlap default: 1437a6d42e7dSPeter Dunlap reason_string = "Unknown PDU Type"; 1438a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ? 1439a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR); 1440a6d42e7dSPeter Dunlap goto validate_pdu_done; 1441a6d42e7dSPeter Dunlap } 1442a6d42e7dSPeter Dunlap 1443a6d42e7dSPeter Dunlap /* 1444a6d42e7dSPeter Dunlap * Now validate the opcodes against the current state. 1445a6d42e7dSPeter Dunlap */ 1446a6d42e7dSPeter Dunlap reason_string = "PDU not allowed in current state"; 1447a6d42e7dSPeter Dunlap switch (IDM_PDU_OPCODE(pdu)) { 1448a6d42e7dSPeter Dunlap case ISCSI_OP_NOOP_OUT: 1449a6d42e7dSPeter Dunlap case ISCSI_OP_NOOP_IN: 1450a6d42e7dSPeter Dunlap /* 1451a6d42e7dSPeter Dunlap * Obviously S1-S3 are not allowed since login hasn't started. 1452a6d42e7dSPeter Dunlap * S8 is probably out as well since the connection has been 1453a6d42e7dSPeter Dunlap * dropped. 1454a6d42e7dSPeter Dunlap */ 1455a6d42e7dSPeter Dunlap switch (ic->ic_state) { 1456a6d42e7dSPeter Dunlap case CS_S4_IN_LOGIN: 1457a6d42e7dSPeter Dunlap case CS_S5_LOGGED_IN: 1458a6d42e7dSPeter Dunlap case CS_S6_IN_LOGOUT: 1459a6d42e7dSPeter Dunlap case CS_S7_LOGOUT_REQ: 1460a6d42e7dSPeter Dunlap action = CA_FORWARD; 1461a6d42e7dSPeter Dunlap goto validate_pdu_done; 1462a6d42e7dSPeter Dunlap case CS_S8_CLEANUP: 1463a6d42e7dSPeter Dunlap case CS_S10_IN_CLEANUP: 1464a6d42e7dSPeter Dunlap action = CA_DROP; 1465a6d42e7dSPeter Dunlap break; 1466a6d42e7dSPeter Dunlap default: 1467a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ? 1468a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR); 1469a6d42e7dSPeter Dunlap goto validate_pdu_done; 1470a6d42e7dSPeter Dunlap } 1471a6d42e7dSPeter Dunlap /*NOTREACHED*/ 1472a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_CMD: 1473a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_RSP: 1474a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_TASK_MGT_MSG: 1475a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_TASK_MGT_RSP: 1476a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_DATA: 1477a6d42e7dSPeter Dunlap case ISCSI_OP_SCSI_DATA_RSP: 1478a6d42e7dSPeter Dunlap case ISCSI_OP_RTT_RSP: 1479a6d42e7dSPeter Dunlap case ISCSI_OP_SNACK_CMD: 1480a6d42e7dSPeter Dunlap case ISCSI_OP_TEXT_CMD: 1481a6d42e7dSPeter Dunlap case ISCSI_OP_TEXT_RSP: 1482a6d42e7dSPeter Dunlap switch (ic->ic_state) { 1483a6d42e7dSPeter Dunlap case CS_S5_LOGGED_IN: 1484a6d42e7dSPeter Dunlap case CS_S6_IN_LOGOUT: 1485a6d42e7dSPeter Dunlap case CS_S7_LOGOUT_REQ: 1486a6d42e7dSPeter Dunlap action = CA_FORWARD; 1487a6d42e7dSPeter Dunlap goto validate_pdu_done; 1488a6d42e7dSPeter Dunlap case CS_S8_CLEANUP: 1489a6d42e7dSPeter Dunlap case CS_S10_IN_CLEANUP: 1490a6d42e7dSPeter Dunlap action = CA_DROP; 1491a6d42e7dSPeter Dunlap break; 1492a6d42e7dSPeter Dunlap default: 1493a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ? 1494a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR); 1495a6d42e7dSPeter Dunlap goto validate_pdu_done; 1496a6d42e7dSPeter Dunlap } 1497a6d42e7dSPeter Dunlap /*NOTREACHED*/ 1498a6d42e7dSPeter Dunlap case ISCSI_OP_LOGOUT_CMD: 1499a6d42e7dSPeter Dunlap case ISCSI_OP_LOGOUT_RSP: 1500a6d42e7dSPeter Dunlap case ISCSI_OP_REJECT_MSG: 1501a6d42e7dSPeter Dunlap case ISCSI_OP_ASYNC_EVENT: 1502a6d42e7dSPeter Dunlap switch (ic->ic_state) { 1503a6d42e7dSPeter Dunlap case CS_S5_LOGGED_IN: 1504a6d42e7dSPeter Dunlap case CS_S6_IN_LOGOUT: 1505a6d42e7dSPeter Dunlap case CS_S7_LOGOUT_REQ: 1506a6d42e7dSPeter Dunlap action = CA_FORWARD; 1507a6d42e7dSPeter Dunlap goto validate_pdu_done; 1508a6d42e7dSPeter Dunlap case CS_S8_CLEANUP: 1509a6d42e7dSPeter Dunlap case CS_S10_IN_CLEANUP: 1510a6d42e7dSPeter Dunlap action = CA_DROP; 1511a6d42e7dSPeter Dunlap break; 1512a6d42e7dSPeter Dunlap default: 1513a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ? 1514a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR); 1515a6d42e7dSPeter Dunlap goto validate_pdu_done; 1516a6d42e7dSPeter Dunlap } 1517a6d42e7dSPeter Dunlap /*NOTREACHED*/ 1518a6d42e7dSPeter Dunlap case ISCSI_OP_LOGIN_CMD: 1519a6d42e7dSPeter Dunlap case ISCSI_OP_LOGIN_RSP: 1520a6d42e7dSPeter Dunlap switch (ic->ic_state) { 1521a6d42e7dSPeter Dunlap case CS_S3_XPT_UP: 1522a6d42e7dSPeter Dunlap case CS_S4_IN_LOGIN: 1523a6d42e7dSPeter Dunlap action = CA_FORWARD; 1524a6d42e7dSPeter Dunlap goto validate_pdu_done; 1525a6d42e7dSPeter Dunlap default: 1526a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ? 1527a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR); 1528a6d42e7dSPeter Dunlap goto validate_pdu_done; 1529a6d42e7dSPeter Dunlap } 1530a6d42e7dSPeter Dunlap /*NOTREACHED*/ 1531a6d42e7dSPeter Dunlap default: 1532a6d42e7dSPeter Dunlap /* This should never happen -- we already checked above */ 1533a6d42e7dSPeter Dunlap ASSERT(0); 1534a6d42e7dSPeter Dunlap /*NOTREACHED*/ 1535a6d42e7dSPeter Dunlap } 1536a6d42e7dSPeter Dunlap 1537a6d42e7dSPeter Dunlap action = ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ? 1538a6d42e7dSPeter Dunlap CA_TX_PROTOCOL_ERROR : CA_RX_PROTOCOL_ERROR); 1539a6d42e7dSPeter Dunlap 1540a6d42e7dSPeter Dunlap validate_pdu_done: 1541a6d42e7dSPeter Dunlap if (action != CA_FORWARD) { 1542a6d42e7dSPeter Dunlap DTRACE_PROBE2(idm__int__protocol__error, 1543a6d42e7dSPeter Dunlap idm_conn_event_ctx_t *, event_ctx, 1544a6d42e7dSPeter Dunlap char *, reason_string); 1545a6d42e7dSPeter Dunlap } 1546a6d42e7dSPeter Dunlap 1547a6d42e7dSPeter Dunlap return (action); 1548a6d42e7dSPeter Dunlap } 1549a6d42e7dSPeter Dunlap 1550a6d42e7dSPeter Dunlap /* ARGSUSED */ 1551a6d42e7dSPeter Dunlap void 1552a6d42e7dSPeter Dunlap idm_pdu_tx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu) 1553a6d42e7dSPeter Dunlap { 1554a6d42e7dSPeter Dunlap /* 1555a6d42e7dSPeter Dunlap * Return the PDU to the caller indicating it was a protocol error. 1556a6d42e7dSPeter Dunlap * Caller can take appropriate action. 1557a6d42e7dSPeter Dunlap */ 1558a6d42e7dSPeter Dunlap idm_pdu_complete(pdu, IDM_STATUS_PROTOCOL_ERROR); 1559a6d42e7dSPeter Dunlap } 1560a6d42e7dSPeter Dunlap 1561a6d42e7dSPeter Dunlap void 1562a6d42e7dSPeter Dunlap idm_pdu_rx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu) 1563a6d42e7dSPeter Dunlap { 1564a6d42e7dSPeter Dunlap /* 1565a6d42e7dSPeter Dunlap * Forward PDU to caller indicating it is a protocol error. 1566a6d42e7dSPeter Dunlap * Caller should take appropriate action. 1567a6d42e7dSPeter Dunlap */ 1568a6d42e7dSPeter Dunlap (*ic->ic_conn_ops.icb_rx_error)(ic, pdu, IDM_STATUS_PROTOCOL_ERROR); 1569a6d42e7dSPeter Dunlap } 1570a6d42e7dSPeter Dunlap 1571a6d42e7dSPeter Dunlap idm_status_t 1572a6d42e7dSPeter Dunlap idm_notify_client(idm_conn_t *ic, idm_client_notify_t cn, uintptr_t data) 1573a6d42e7dSPeter Dunlap { 1574a6d42e7dSPeter Dunlap /* 1575a6d42e7dSPeter Dunlap * We may want to make this more complicated at some point but 1576a6d42e7dSPeter Dunlap * for now lets just call the client's notify function and return 1577a6d42e7dSPeter Dunlap * the status. 1578a6d42e7dSPeter Dunlap */ 15795f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(!mutex_owned(&ic->ic_state_mutex)); 158030e7468fSPeter Dunlap cn = (cn > CN_MAX) ? CN_MAX : cn; 158130e7468fSPeter Dunlap IDM_SM_LOG(CE_NOTE, "idm_notify_client: ic=%p %s(%d)\n", 158230e7468fSPeter Dunlap (void *)ic, idm_cn_strings[cn], cn); 1583a6d42e7dSPeter Dunlap return ((*ic->ic_conn_ops.icb_client_notify)(ic, cn, data)); 1584a6d42e7dSPeter Dunlap } 1585a6d42e7dSPeter Dunlap 1586a6d42e7dSPeter Dunlap static idm_status_t 1587a6d42e7dSPeter Dunlap idm_ffp_enable(idm_conn_t *ic) 1588a6d42e7dSPeter Dunlap { 1589a6d42e7dSPeter Dunlap idm_status_t rc; 1590a6d42e7dSPeter Dunlap 1591a6d42e7dSPeter Dunlap /* 1592a6d42e7dSPeter Dunlap * On the initiator side the client will see this notification 1593a6d42e7dSPeter Dunlap * before the actual login succes PDU. This shouldn't be a big 1594a6d42e7dSPeter Dunlap * deal since the initiator drives the connection. It can simply 1595a6d42e7dSPeter Dunlap * wait for the login response then start sending SCSI commands. 1596a6d42e7dSPeter Dunlap * Kind ugly though compared with the way things work on target 1597a6d42e7dSPeter Dunlap * connections. 1598a6d42e7dSPeter Dunlap */ 1599a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 1600a6d42e7dSPeter Dunlap ic->ic_ffp = B_TRUE; 1601a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 1602a6d42e7dSPeter Dunlap 1603a6d42e7dSPeter Dunlap rc = idm_notify_client(ic, CN_FFP_ENABLED, NULL); 1604a6d42e7dSPeter Dunlap if (rc != IDM_STATUS_SUCCESS) { 1605a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 1606a6d42e7dSPeter Dunlap ic->ic_ffp = B_FALSE; 1607a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 1608a6d42e7dSPeter Dunlap } 1609a6d42e7dSPeter Dunlap return (rc); 1610a6d42e7dSPeter Dunlap } 1611a6d42e7dSPeter Dunlap 1612a6d42e7dSPeter Dunlap static void 1613a6d42e7dSPeter Dunlap idm_ffp_disable(idm_conn_t *ic, idm_ffp_disable_t disable_type) 1614a6d42e7dSPeter Dunlap { 1615a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 1616a6d42e7dSPeter Dunlap ic->ic_ffp = B_FALSE; 1617a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 1618a6d42e7dSPeter Dunlap 1619a6d42e7dSPeter Dunlap /* Client can't "fail" CN_FFP_DISABLED */ 1620a6d42e7dSPeter Dunlap (void) idm_notify_client(ic, CN_FFP_DISABLED, 1621a6d42e7dSPeter Dunlap (uintptr_t)disable_type); 1622a6d42e7dSPeter Dunlap } 1623a6d42e7dSPeter Dunlap 1624a6d42e7dSPeter Dunlap static void 1625a6d42e7dSPeter Dunlap idm_initial_login_actions(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 1626a6d42e7dSPeter Dunlap { 1627a6d42e7dSPeter Dunlap ASSERT((event_ctx->iec_event == CE_LOGIN_RCV) || 1628a6d42e7dSPeter Dunlap (event_ctx->iec_event == CE_LOGIN_SND)); 1629a6d42e7dSPeter Dunlap 1630a6d42e7dSPeter Dunlap /* 1631a6d42e7dSPeter Dunlap * Currently it's not clear what we would do here -- since 1632a6d42e7dSPeter Dunlap * we went to the trouble of coding an "initial login" hook 1633a6d42e7dSPeter Dunlap * we'll leave it in for now. Remove before integration if 1634a6d42e7dSPeter Dunlap * it's not used for anything. 1635a6d42e7dSPeter Dunlap */ 1636a6d42e7dSPeter Dunlap ic->ic_state_flags |= CF_INITIAL_LOGIN; 1637a6d42e7dSPeter Dunlap } 1638a6d42e7dSPeter Dunlap 1639a6d42e7dSPeter Dunlap static void 1640a6d42e7dSPeter Dunlap idm_login_success_actions(idm_conn_t *ic, idm_conn_event_ctx_t *event_ctx) 1641a6d42e7dSPeter Dunlap { 1642a6d42e7dSPeter Dunlap idm_pdu_t *pdu = (idm_pdu_t *)event_ctx->iec_info; 1643a6d42e7dSPeter Dunlap iscsi_login_hdr_t *login_req = 1644a6d42e7dSPeter Dunlap (iscsi_login_hdr_t *)pdu->isp_hdr; 1645a6d42e7dSPeter Dunlap 1646a6d42e7dSPeter Dunlap ASSERT((event_ctx->iec_event == CE_LOGIN_SUCCESS_RCV) || 1647a6d42e7dSPeter Dunlap (event_ctx->iec_event == CE_LOGIN_SUCCESS_SND)); 1648a6d42e7dSPeter Dunlap 1649a6d42e7dSPeter Dunlap /* 1650a6d42e7dSPeter Dunlap * Save off CID 1651a6d42e7dSPeter Dunlap */ 1652a6d42e7dSPeter Dunlap mutex_enter(&ic->ic_state_mutex); 1653a6d42e7dSPeter Dunlap ic->ic_login_cid = ntohs(login_req->cid); 1654a6d42e7dSPeter Dunlap ic->ic_login_info_valid = B_TRUE; 1655a6d42e7dSPeter Dunlap 1656a6d42e7dSPeter Dunlap mutex_exit(&ic->ic_state_mutex); 1657a6d42e7dSPeter Dunlap } 1658