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