1fcf3ce44SJohn Forte /* 2fcf3ce44SJohn Forte * CDDL HEADER START 3fcf3ce44SJohn Forte * 4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7fcf3ce44SJohn Forte * 8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11fcf3ce44SJohn Forte * and limitations under the License. 12fcf3ce44SJohn Forte * 13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18fcf3ce44SJohn Forte * 19fcf3ce44SJohn Forte * CDDL HEADER END 20fcf3ce44SJohn Forte */ 21fcf3ce44SJohn Forte /* 22*cc7ef495Syi zhang - Sun Microsystems - Beijing China * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23fcf3ce44SJohn Forte * Use is subject to license terms. 24fcf3ce44SJohn Forte * 25fcf3ce44SJohn Forte * iSCSI connection interfaces 26fcf3ce44SJohn Forte */ 27fcf3ce44SJohn Forte 2830e7468fSPeter Dunlap #define ISCSI_ICS_NAMES 29fcf3ce44SJohn Forte #include "iscsi.h" 30fcf3ce44SJohn Forte #include "persistent.h" 316cefaae1SJack Meng #include <sys/bootprops.h> 326cefaae1SJack Meng 336cefaae1SJack Meng extern ib_boot_prop_t *iscsiboot_prop; 34fcf3ce44SJohn Forte 3530e7468fSPeter Dunlap static void iscsi_client_notify_task(void *cn_task_void); 36fcf3ce44SJohn Forte 3730e7468fSPeter Dunlap static void iscsi_conn_flush_active_cmds(iscsi_conn_t *icp); 38fcf3ce44SJohn Forte 39fcf3ce44SJohn Forte #define SHUTDOWN_TIMEOUT 180 /* seconds */ 40fcf3ce44SJohn Forte 416cefaae1SJack Meng extern int modrootloaded; 4230e7468fSPeter Dunlap 4330e7468fSPeter Dunlap boolean_t iscsi_conn_logging = B_FALSE; 4430e7468fSPeter Dunlap 45*cc7ef495Syi zhang - Sun Microsystems - Beijing China #define ISCSI_LOGIN_TPGT_NEGO_ERROR(icp) \ 46*cc7ef495Syi zhang - Sun Microsystems - Beijing China (((icp)->conn_login_state == LOGIN_ERROR) && \ 47*cc7ef495Syi zhang - Sun Microsystems - Beijing China ((icp)->conn_login_status == ISCSI_STATUS_LOGIN_TPGT_NEGO_FAIL)) 48*cc7ef495Syi zhang - Sun Microsystems - Beijing China 49fcf3ce44SJohn Forte /* 50fcf3ce44SJohn Forte * +--------------------------------------------------------------------+ 51fcf3ce44SJohn Forte * | External Connection Interfaces | 52fcf3ce44SJohn Forte * +--------------------------------------------------------------------+ 53fcf3ce44SJohn Forte */ 54fcf3ce44SJohn Forte 55fcf3ce44SJohn Forte /* 56fcf3ce44SJohn Forte * iscsi_conn_create - This creates an iscsi connection structure and 57fcf3ce44SJohn Forte * associates it with a session structure. The session's sess_conn_list_rwlock 58fcf3ce44SJohn Forte * should be held as a writer before calling this function. 59fcf3ce44SJohn Forte */ 60fcf3ce44SJohn Forte iscsi_status_t 61fcf3ce44SJohn Forte iscsi_conn_create(struct sockaddr *addr, iscsi_sess_t *isp, iscsi_conn_t **icpp) 62fcf3ce44SJohn Forte { 63fcf3ce44SJohn Forte iscsi_conn_t *icp = NULL; 64fcf3ce44SJohn Forte char th_name[ISCSI_TH_MAX_NAME_LEN]; 65fcf3ce44SJohn Forte 66fcf3ce44SJohn Forte /* See if this connection already exists */ 67fcf3ce44SJohn Forte for (icp = isp->sess_conn_list; icp; icp = icp->conn_next) { 68fcf3ce44SJohn Forte 69fcf3ce44SJohn Forte /* 70fcf3ce44SJohn Forte * Compare the ioctl information to see if 71fcf3ce44SJohn Forte * its a match for this connection. (This 72fcf3ce44SJohn Forte * is done by making sure the IPs are of 73fcf3ce44SJohn Forte * the same size and then they are the 74fcf3ce44SJohn Forte * same value. 75fcf3ce44SJohn Forte */ 76fcf3ce44SJohn Forte if (bcmp(&icp->conn_base_addr, addr, 77fcf3ce44SJohn Forte SIZEOF_SOCKADDR(addr)) == 0) { 78fcf3ce44SJohn Forte /* It's a match, record this connection */ 79fcf3ce44SJohn Forte break; 80fcf3ce44SJohn Forte } 81fcf3ce44SJohn Forte } 82fcf3ce44SJohn Forte 83fcf3ce44SJohn Forte /* If icp is found return it */ 84fcf3ce44SJohn Forte if (icp != NULL) { 85fcf3ce44SJohn Forte *icpp = icp; 86fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 87fcf3ce44SJohn Forte } 88fcf3ce44SJohn Forte 89fcf3ce44SJohn Forte /* We are creating the connection, allocate, and setup */ 90fcf3ce44SJohn Forte icp = (iscsi_conn_t *)kmem_zalloc(sizeof (iscsi_conn_t), KM_SLEEP); 91fcf3ce44SJohn Forte 92fcf3ce44SJohn Forte /* 93fcf3ce44SJohn Forte * Setup connection 94fcf3ce44SJohn Forte */ 95fcf3ce44SJohn Forte icp->conn_sig = ISCSI_SIG_CONN; 96fcf3ce44SJohn Forte icp->conn_state = ISCSI_CONN_STATE_FREE; 97fcf3ce44SJohn Forte mutex_init(&icp->conn_state_mutex, NULL, MUTEX_DRIVER, NULL); 98fcf3ce44SJohn Forte cv_init(&icp->conn_state_change, NULL, CV_DRIVER, NULL); 9930e7468fSPeter Dunlap mutex_init(&icp->conn_login_mutex, NULL, MUTEX_DRIVER, NULL); 10030e7468fSPeter Dunlap cv_init(&icp->conn_login_cv, NULL, CV_DRIVER, NULL); 101fcf3ce44SJohn Forte icp->conn_state_destroy = B_FALSE; 10230e7468fSPeter Dunlap idm_sm_audit_init(&icp->conn_state_audit); 103fcf3ce44SJohn Forte icp->conn_sess = isp; 104fcf3ce44SJohn Forte 105fcf3ce44SJohn Forte mutex_enter(&iscsi_oid_mutex); 106fcf3ce44SJohn Forte icp->conn_oid = iscsi_oid++; 107fcf3ce44SJohn Forte mutex_exit(&iscsi_oid_mutex); 108fcf3ce44SJohn Forte 10930e7468fSPeter Dunlap /* 11030e7468fSPeter Dunlap * IDM CN taskq 11130e7468fSPeter Dunlap */ 11230e7468fSPeter Dunlap 11330e7468fSPeter Dunlap if (snprintf(th_name, sizeof (th_name) - 1, 11430e7468fSPeter Dunlap ISCSI_CONN_CN_TASKQ_NAME_FORMAT, 115fcf3ce44SJohn Forte icp->conn_sess->sess_hba->hba_oid, icp->conn_sess->sess_oid, 116fcf3ce44SJohn Forte icp->conn_oid) >= sizeof (th_name)) { 117fcf3ce44SJohn Forte cv_destroy(&icp->conn_state_change); 118fcf3ce44SJohn Forte mutex_destroy(&icp->conn_state_mutex); 119fcf3ce44SJohn Forte kmem_free(icp, sizeof (iscsi_conn_t)); 120fcf3ce44SJohn Forte *icpp = NULL; 121fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 122fcf3ce44SJohn Forte } 123fcf3ce44SJohn Forte 12430e7468fSPeter Dunlap icp->conn_cn_taskq = 12530e7468fSPeter Dunlap ddi_taskq_create(icp->conn_sess->sess_hba->hba_dip, th_name, 1, 12630e7468fSPeter Dunlap TASKQ_DEFAULTPRI, 0); 12730e7468fSPeter Dunlap if (icp->conn_cn_taskq == NULL) { 12830e7468fSPeter Dunlap cv_destroy(&icp->conn_state_change); 12930e7468fSPeter Dunlap mutex_destroy(&icp->conn_state_mutex); 13030e7468fSPeter Dunlap kmem_free(icp, sizeof (iscsi_conn_t)); 13130e7468fSPeter Dunlap *icpp = NULL; 13230e7468fSPeter Dunlap return (ISCSI_STATUS_INTERNAL_ERROR); 13330e7468fSPeter Dunlap } 134fcf3ce44SJohn Forte 135fcf3ce44SJohn Forte /* Creation of the transfer thread */ 136fcf3ce44SJohn Forte if (snprintf(th_name, sizeof (th_name) - 1, ISCSI_CONN_TXTH_NAME_FORMAT, 137fcf3ce44SJohn Forte icp->conn_sess->sess_hba->hba_oid, icp->conn_sess->sess_oid, 138fcf3ce44SJohn Forte icp->conn_oid) >= sizeof (th_name)) { 139fcf3ce44SJohn Forte cv_destroy(&icp->conn_state_change); 140fcf3ce44SJohn Forte mutex_destroy(&icp->conn_state_mutex); 141fcf3ce44SJohn Forte kmem_free(icp, sizeof (iscsi_conn_t)); 14230e7468fSPeter Dunlap ddi_taskq_destroy(icp->conn_cn_taskq); 143fcf3ce44SJohn Forte *icpp = NULL; 144fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 145fcf3ce44SJohn Forte } 146fcf3ce44SJohn Forte 147fcf3ce44SJohn Forte icp->conn_tx_thread = iscsi_thread_create(isp->sess_hba->hba_dip, 148fcf3ce44SJohn Forte th_name, iscsi_tx_thread, icp); 149fcf3ce44SJohn Forte 150fcf3ce44SJohn Forte /* setup connection queues */ 151fcf3ce44SJohn Forte iscsi_init_queue(&icp->conn_queue_active); 15230e7468fSPeter Dunlap iscsi_init_queue(&icp->conn_queue_idm_aborting); 153fcf3ce44SJohn Forte 154fcf3ce44SJohn Forte bcopy(addr, &icp->conn_base_addr, sizeof (icp->conn_base_addr)); 155fcf3ce44SJohn Forte 156fcf3ce44SJohn Forte /* Add new connection to the session connection list */ 157fcf3ce44SJohn Forte icp->conn_cid = isp->sess_conn_next_cid++; 158fcf3ce44SJohn Forte if (isp->sess_conn_list == NULL) { 159fcf3ce44SJohn Forte isp->sess_conn_list = isp->sess_conn_list_last_ptr = icp; 160fcf3ce44SJohn Forte } else { 161fcf3ce44SJohn Forte isp->sess_conn_list_last_ptr->conn_next = icp; 162fcf3ce44SJohn Forte isp->sess_conn_list_last_ptr = icp; 163fcf3ce44SJohn Forte } 164fcf3ce44SJohn Forte 165fcf3ce44SJohn Forte KSTAT_INC_SESS_CNTR_CONN(isp); 166fcf3ce44SJohn Forte (void) iscsi_conn_kstat_init(icp); 167fcf3ce44SJohn Forte 168fcf3ce44SJohn Forte *icpp = icp; 169fcf3ce44SJohn Forte 170fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 171fcf3ce44SJohn Forte } 172fcf3ce44SJohn Forte 17330e7468fSPeter Dunlap /* 17430e7468fSPeter Dunlap * iscsi_conn_online - This attempts to take a connection from 17530e7468fSPeter Dunlap * ISCSI_CONN_STATE_FREE to ISCSI_CONN_STATE_LOGGED_IN. 17630e7468fSPeter Dunlap */ 17730e7468fSPeter Dunlap iscsi_status_t 17830e7468fSPeter Dunlap iscsi_conn_online(iscsi_conn_t *icp) 17930e7468fSPeter Dunlap { 18030e7468fSPeter Dunlap iscsi_task_t *itp; 18130e7468fSPeter Dunlap iscsi_status_t rval; 18230e7468fSPeter Dunlap 18330e7468fSPeter Dunlap ASSERT(icp != NULL); 18430e7468fSPeter Dunlap ASSERT(mutex_owned(&icp->conn_state_mutex)); 18530e7468fSPeter Dunlap ASSERT(icp->conn_state == ISCSI_CONN_STATE_FREE); 18630e7468fSPeter Dunlap 18730e7468fSPeter Dunlap /* 18830e7468fSPeter Dunlap * If we are attempting to connect then for the purposes of the 18930e7468fSPeter Dunlap * other initiator code we are effectively in ISCSI_CONN_STATE_IN_LOGIN. 19030e7468fSPeter Dunlap */ 19130e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, ISCSI_CONN_STATE_IN_LOGIN); 19230e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 19330e7468fSPeter Dunlap 19430e7468fSPeter Dunlap /* 19530e7468fSPeter Dunlap * Sync base connection information before login 19630e7468fSPeter Dunlap * A login redirection might have shifted the 19730e7468fSPeter Dunlap * current information from the base. 19830e7468fSPeter Dunlap */ 19930e7468fSPeter Dunlap bcopy(&icp->conn_base_addr, &icp->conn_curr_addr, 20030e7468fSPeter Dunlap sizeof (icp->conn_curr_addr)); 20130e7468fSPeter Dunlap 20230e7468fSPeter Dunlap itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP); 20330e7468fSPeter Dunlap ASSERT(itp != NULL); 20430e7468fSPeter Dunlap 20530e7468fSPeter Dunlap itp->t_arg = icp; 20630e7468fSPeter Dunlap itp->t_blocking = B_TRUE; 20730e7468fSPeter Dunlap rval = iscsi_login_start(itp); 20830e7468fSPeter Dunlap kmem_free(itp, sizeof (iscsi_task_t)); 20930e7468fSPeter Dunlap 21030e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 21130e7468fSPeter Dunlap 21230e7468fSPeter Dunlap return (rval); 21330e7468fSPeter Dunlap } 214fcf3ce44SJohn Forte 215fcf3ce44SJohn Forte /* 216fcf3ce44SJohn Forte * iscsi_conn_offline - This attempts to take a connection from 217fcf3ce44SJohn Forte * any state to ISCSI_CONN_STATE_FREE. 218fcf3ce44SJohn Forte */ 219fcf3ce44SJohn Forte iscsi_status_t 220fcf3ce44SJohn Forte iscsi_conn_offline(iscsi_conn_t *icp) 221fcf3ce44SJohn Forte { 222fcf3ce44SJohn Forte clock_t delay; 223fcf3ce44SJohn Forte 224fcf3ce44SJohn Forte ASSERT(icp != NULL); 225fcf3ce44SJohn Forte 226fcf3ce44SJohn Forte /* 227fcf3ce44SJohn Forte * We can only destroy a connection if its either in 228fcf3ce44SJohn Forte * a state of FREE or LOGGED. The other states are 229fcf3ce44SJohn Forte * transitionary and its unsafe to perform actions 230fcf3ce44SJohn Forte * on the connection in those states. Set a flag 231fcf3ce44SJohn Forte * on the connection to influence the transitions 232fcf3ce44SJohn Forte * to quickly complete. Then wait for a state 233fcf3ce44SJohn Forte * transition. 23430e7468fSPeter Dunlap * 23530e7468fSPeter Dunlap * ISCSI_CONN_STATE_LOGGED_IN is set immediately at the 23630e7468fSPeter Dunlap * start of CN_NOTIFY_FFP processing. icp->conn_state_ffp 23730e7468fSPeter Dunlap * is set to true at the end of ffp processing, at which 23830e7468fSPeter Dunlap * point any session updates are complete. We don't 23930e7468fSPeter Dunlap * want to start offlining the connection before we're 24030e7468fSPeter Dunlap * done completing the FFP processing since this might 24130e7468fSPeter Dunlap * interrupt the discovery process. 242fcf3ce44SJohn Forte */ 243fcf3ce44SJohn Forte delay = ddi_get_lbolt() + SEC_TO_TICK(SHUTDOWN_TIMEOUT); 244fcf3ce44SJohn Forte mutex_enter(&icp->conn_state_mutex); 245fcf3ce44SJohn Forte icp->conn_state_destroy = B_TRUE; 24630e7468fSPeter Dunlap while ((((icp->conn_state != ISCSI_CONN_STATE_FREE) && 24730e7468fSPeter Dunlap (icp->conn_state != ISCSI_CONN_STATE_LOGGED_IN)) || 24830e7468fSPeter Dunlap ((icp->conn_state == ISCSI_CONN_STATE_LOGGED_IN) && 24930e7468fSPeter Dunlap !icp->conn_state_ffp)) && 250fcf3ce44SJohn Forte (ddi_get_lbolt() < delay)) { 251fcf3ce44SJohn Forte /* wait for transition */ 252fcf3ce44SJohn Forte (void) cv_timedwait(&icp->conn_state_change, 253fcf3ce44SJohn Forte &icp->conn_state_mutex, delay); 254fcf3ce44SJohn Forte } 255fcf3ce44SJohn Forte 256fcf3ce44SJohn Forte switch (icp->conn_state) { 257fcf3ce44SJohn Forte case ISCSI_CONN_STATE_FREE: 258fcf3ce44SJohn Forte break; 259fcf3ce44SJohn Forte case ISCSI_CONN_STATE_LOGGED_IN: 26092adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States if (icp->conn_state_ffp) { 26192adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* Hold is released in iscsi_handle_logout */ 26292adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_hold(icp->conn_ic); 26330e7468fSPeter Dunlap (void) iscsi_handle_logout(icp); 26492adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States } else { 26530e7468fSPeter Dunlap icp->conn_state_destroy = B_FALSE; 26630e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 26730e7468fSPeter Dunlap return (ISCSI_STATUS_INTERNAL_ERROR); 26830e7468fSPeter Dunlap } 269fcf3ce44SJohn Forte break; 270fcf3ce44SJohn Forte case ISCSI_CONN_STATE_IN_LOGIN: 271fcf3ce44SJohn Forte case ISCSI_CONN_STATE_IN_LOGOUT: 272fcf3ce44SJohn Forte case ISCSI_CONN_STATE_FAILED: 273fcf3ce44SJohn Forte case ISCSI_CONN_STATE_POLLING: 274fcf3ce44SJohn Forte default: 275fcf3ce44SJohn Forte icp->conn_state_destroy = B_FALSE; 276fcf3ce44SJohn Forte mutex_exit(&icp->conn_state_mutex); 277fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 278fcf3ce44SJohn Forte } 279fcf3ce44SJohn Forte mutex_exit(&icp->conn_state_mutex); 280fcf3ce44SJohn Forte 281fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 282fcf3ce44SJohn Forte } 283fcf3ce44SJohn Forte 284fcf3ce44SJohn Forte /* 285fcf3ce44SJohn Forte * iscsi_conn_destroy - This destroys an iscsi connection structure 286fcf3ce44SJohn Forte * and de-associates it with the session. The connection should 287fcf3ce44SJohn Forte * already been in the ISCSI_CONN_STATE_FREE when attempting this 288fcf3ce44SJohn Forte * operation. 289fcf3ce44SJohn Forte */ 290fcf3ce44SJohn Forte iscsi_status_t 291fcf3ce44SJohn Forte iscsi_conn_destroy(iscsi_conn_t *icp) 292fcf3ce44SJohn Forte { 293fcf3ce44SJohn Forte iscsi_sess_t *isp; 294fcf3ce44SJohn Forte iscsi_conn_t *t_icp; 295fcf3ce44SJohn Forte 296fcf3ce44SJohn Forte ASSERT(icp != NULL); 297fcf3ce44SJohn Forte isp = icp->conn_sess; 298fcf3ce44SJohn Forte ASSERT(isp != NULL); 299fcf3ce44SJohn Forte 300fcf3ce44SJohn Forte if (icp->conn_state != ISCSI_CONN_STATE_FREE) { 301fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 302fcf3ce44SJohn Forte } 303fcf3ce44SJohn Forte 304fcf3ce44SJohn Forte /* Destroy transfer thread */ 305fcf3ce44SJohn Forte iscsi_thread_destroy(icp->conn_tx_thread); 30630e7468fSPeter Dunlap ddi_taskq_destroy(icp->conn_cn_taskq); 307fcf3ce44SJohn Forte 308fcf3ce44SJohn Forte /* Terminate connection queues */ 30930e7468fSPeter Dunlap iscsi_destroy_queue(&icp->conn_queue_idm_aborting); 310fcf3ce44SJohn Forte iscsi_destroy_queue(&icp->conn_queue_active); 311fcf3ce44SJohn Forte 31230e7468fSPeter Dunlap cv_destroy(&icp->conn_login_cv); 31330e7468fSPeter Dunlap mutex_destroy(&icp->conn_login_mutex); 314fcf3ce44SJohn Forte cv_destroy(&icp->conn_state_change); 315fcf3ce44SJohn Forte mutex_destroy(&icp->conn_state_mutex); 316fcf3ce44SJohn Forte 317fcf3ce44SJohn Forte /* 318fcf3ce44SJohn Forte * Remove connection from sessions linked list. 319fcf3ce44SJohn Forte */ 320fcf3ce44SJohn Forte if (isp->sess_conn_list == icp) { 321fcf3ce44SJohn Forte /* connection first item in list */ 322fcf3ce44SJohn Forte isp->sess_conn_list = icp->conn_next; 323fcf3ce44SJohn Forte /* 324fcf3ce44SJohn Forte * check if this is also the last item in the list 325fcf3ce44SJohn Forte */ 326fcf3ce44SJohn Forte if (isp->sess_conn_list_last_ptr == icp) { 327fcf3ce44SJohn Forte isp->sess_conn_list_last_ptr = NULL; 328fcf3ce44SJohn Forte } 329fcf3ce44SJohn Forte } else { 330fcf3ce44SJohn Forte /* 331fcf3ce44SJohn Forte * search session list for icp pointing 332fcf3ce44SJohn Forte * to connection being removed. Then 333fcf3ce44SJohn Forte * update that connections next pointer. 334fcf3ce44SJohn Forte */ 335fcf3ce44SJohn Forte t_icp = isp->sess_conn_list; 336fcf3ce44SJohn Forte while (t_icp->conn_next != NULL) { 337fcf3ce44SJohn Forte if (t_icp->conn_next == icp) { 338fcf3ce44SJohn Forte break; 339fcf3ce44SJohn Forte } 340fcf3ce44SJohn Forte t_icp = t_icp->conn_next; 341fcf3ce44SJohn Forte } 342fcf3ce44SJohn Forte if (t_icp->conn_next == icp) { 343fcf3ce44SJohn Forte t_icp->conn_next = icp->conn_next; 344fcf3ce44SJohn Forte /* 345fcf3ce44SJohn Forte * if this is the last connection in the list 346fcf3ce44SJohn Forte * update the last_ptr to point to t_icp 347fcf3ce44SJohn Forte */ 348fcf3ce44SJohn Forte if (isp->sess_conn_list_last_ptr == icp) { 349fcf3ce44SJohn Forte isp->sess_conn_list_last_ptr = t_icp; 350fcf3ce44SJohn Forte } 351fcf3ce44SJohn Forte } else { 352fcf3ce44SJohn Forte /* couldn't find session */ 353fcf3ce44SJohn Forte ASSERT(FALSE); 354fcf3ce44SJohn Forte } 355fcf3ce44SJohn Forte } 356fcf3ce44SJohn Forte 357fcf3ce44SJohn Forte /* Free this Connections Data */ 358fcf3ce44SJohn Forte iscsi_conn_kstat_term(icp); 359fcf3ce44SJohn Forte kmem_free(icp, sizeof (iscsi_conn_t)); 360fcf3ce44SJohn Forte 361fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 362fcf3ce44SJohn Forte } 363fcf3ce44SJohn Forte 364fcf3ce44SJohn Forte 365fcf3ce44SJohn Forte /* 366fcf3ce44SJohn Forte * iscsi_conn_set_login_min_max - set min/max login window 367fcf3ce44SJohn Forte * 368fcf3ce44SJohn Forte * Used to set the min and max login window. Input values 369fcf3ce44SJohn Forte * are in seconds. 370fcf3ce44SJohn Forte */ 371fcf3ce44SJohn Forte void 372fcf3ce44SJohn Forte iscsi_conn_set_login_min_max(iscsi_conn_t *icp, int min, int max) 373fcf3ce44SJohn Forte { 374fcf3ce44SJohn Forte ASSERT(icp != NULL); 375fcf3ce44SJohn Forte 376fcf3ce44SJohn Forte icp->conn_login_min = ddi_get_lbolt() + SEC_TO_TICK(min); 377fcf3ce44SJohn Forte icp->conn_login_max = ddi_get_lbolt() + SEC_TO_TICK(max); 378fcf3ce44SJohn Forte } 379fcf3ce44SJohn Forte 380fcf3ce44SJohn Forte 38130e7468fSPeter Dunlap /* 38230e7468fSPeter Dunlap * Process the idm notifications 38330e7468fSPeter Dunlap */ 38430e7468fSPeter Dunlap idm_status_t 38530e7468fSPeter Dunlap iscsi_client_notify(idm_conn_t *ic, idm_client_notify_t icn, uintptr_t data) 38630e7468fSPeter Dunlap { 38730e7468fSPeter Dunlap iscsi_cn_task_t *cn; 38830e7468fSPeter Dunlap iscsi_conn_t *icp = ic->ic_handle; 38930e7468fSPeter Dunlap iscsi_sess_t *isp; 390fcf3ce44SJohn Forte 391fcf3ce44SJohn Forte /* 39230e7468fSPeter Dunlap * Don't access icp if the notification is CN_CONNECT_DESTROY 39330e7468fSPeter Dunlap * since icp may have already been freed. 394fcf3ce44SJohn Forte * 3955f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States * In particular, we cannot audit the CN_CONNECT_DESTROY event. 3965f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States * 3975f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States * Handle a few cases immediately, the rest in a task queue. 398fcf3ce44SJohn Forte */ 39930e7468fSPeter Dunlap switch (icn) { 40030e7468fSPeter Dunlap case CN_CONNECT_FAIL: 40130e7468fSPeter Dunlap case CN_LOGIN_FAIL: 40230e7468fSPeter Dunlap /* 40330e7468fSPeter Dunlap * Wakeup any thread waiting for login stuff to happen. 40430e7468fSPeter Dunlap */ 40530e7468fSPeter Dunlap ASSERT(icp != NULL); 4065f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States 4075f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_enter(&icp->conn_state_mutex); 4085f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_sm_audit_event(&icp->conn_state_audit, 4095f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States SAS_ISCSI_CONN, icp->conn_state, icn, data); 4105f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_exit(&icp->conn_state_mutex); 41130e7468fSPeter Dunlap iscsi_login_update_state(icp, LOGIN_ERROR); 41230e7468fSPeter Dunlap return (IDM_STATUS_SUCCESS); 4135f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States 41430e7468fSPeter Dunlap case CN_READY_FOR_LOGIN: 41530e7468fSPeter Dunlap idm_conn_hold(ic); /* Released in CN_CONNECT_LOST */ 4165f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(icp != NULL); 4175f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States 41830e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 4195f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_sm_audit_event(&icp->conn_state_audit, 4205f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States SAS_ISCSI_CONN, icp->conn_state, icn, data); 42130e7468fSPeter Dunlap icp->conn_state_idm_connected = B_TRUE; 42230e7468fSPeter Dunlap cv_broadcast(&icp->conn_state_change); 42330e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 42430e7468fSPeter Dunlap 42530e7468fSPeter Dunlap iscsi_login_update_state(icp, LOGIN_READY); 42630e7468fSPeter Dunlap return (IDM_STATUS_SUCCESS); 4275f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States 42830e7468fSPeter Dunlap case CN_CONNECT_DESTROY: 42930e7468fSPeter Dunlap /* 43030e7468fSPeter Dunlap * We released any dependecies we had on this object in 43130e7468fSPeter Dunlap * either CN_LOGIN_FAIL or CN_CONNECT_LOST so we just need 43230e7468fSPeter Dunlap * to destroy the IDM connection now. 43330e7468fSPeter Dunlap */ 43430e7468fSPeter Dunlap idm_ini_conn_destroy(ic); 43530e7468fSPeter Dunlap return (IDM_STATUS_SUCCESS); 43630e7468fSPeter Dunlap } 437fcf3ce44SJohn Forte 438fcf3ce44SJohn Forte ASSERT(icp != NULL); 4395f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_enter(&icp->conn_state_mutex); 4405f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_sm_audit_event(&icp->conn_state_audit, 4415f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States SAS_ISCSI_CONN, icp->conn_state, icn, data); 4425f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_exit(&icp->conn_state_mutex); 44330e7468fSPeter Dunlap isp = icp->conn_sess; 444fcf3ce44SJohn Forte 445fcf3ce44SJohn Forte /* 44630e7468fSPeter Dunlap * Dispatch notifications to the taskq since they often require 44730e7468fSPeter Dunlap * long blocking operations. In the case of CN_CONNECT_DESTROY 44830e7468fSPeter Dunlap * we actually just want to destroy the connection which we 44930e7468fSPeter Dunlap * can't do in the IDM taskq context. 450fcf3ce44SJohn Forte */ 45130e7468fSPeter Dunlap cn = kmem_alloc(sizeof (*cn), KM_SLEEP); 45230e7468fSPeter Dunlap 45330e7468fSPeter Dunlap cn->ct_ic = ic; 45430e7468fSPeter Dunlap cn->ct_icn = icn; 45530e7468fSPeter Dunlap cn->ct_data = data; 45630e7468fSPeter Dunlap 45730e7468fSPeter Dunlap idm_conn_hold(ic); 45830e7468fSPeter Dunlap 45930e7468fSPeter Dunlap if (ddi_taskq_dispatch(icp->conn_cn_taskq, 46030e7468fSPeter Dunlap iscsi_client_notify_task, cn, DDI_SLEEP) != DDI_SUCCESS) { 46130e7468fSPeter Dunlap idm_conn_rele(ic); 46230e7468fSPeter Dunlap cmn_err(CE_WARN, "iscsi connection(%u) failure - " 46330e7468fSPeter Dunlap "unable to schedule notify task", icp->conn_oid); 46430e7468fSPeter Dunlap iscsi_conn_update_state(icp, ISCSI_CONN_STATE_FREE); 46530e7468fSPeter Dunlap mutex_enter(&isp->sess_state_mutex); 46630e7468fSPeter Dunlap iscsi_sess_state_machine(isp, 46730e7468fSPeter Dunlap ISCSI_SESS_EVENT_N6); 46830e7468fSPeter Dunlap mutex_exit(&isp->sess_state_mutex); 46930e7468fSPeter Dunlap } 47030e7468fSPeter Dunlap 47130e7468fSPeter Dunlap return (IDM_STATUS_SUCCESS); 47230e7468fSPeter Dunlap } 47330e7468fSPeter Dunlap 47430e7468fSPeter Dunlap static void 47530e7468fSPeter Dunlap iscsi_client_notify_task(void *cn_task_void) 476fcf3ce44SJohn Forte { 47730e7468fSPeter Dunlap iscsi_cn_task_t *cn_task = cn_task_void; 47830e7468fSPeter Dunlap iscsi_conn_t *icp; 47930e7468fSPeter Dunlap iscsi_sess_t *isp; 48030e7468fSPeter Dunlap idm_conn_t *ic; 48130e7468fSPeter Dunlap idm_client_notify_t icn; 48230e7468fSPeter Dunlap uintptr_t data; 48330e7468fSPeter Dunlap idm_ffp_disable_t disable_type; 48430e7468fSPeter Dunlap boolean_t in_login; 48530e7468fSPeter Dunlap 48630e7468fSPeter Dunlap ic = cn_task->ct_ic; 48730e7468fSPeter Dunlap icn = cn_task->ct_icn; 48830e7468fSPeter Dunlap data = cn_task->ct_data; 48930e7468fSPeter Dunlap 49030e7468fSPeter Dunlap icp = ic->ic_handle; 49130e7468fSPeter Dunlap ASSERT(icp != NULL); 49230e7468fSPeter Dunlap isp = icp->conn_sess; 49330e7468fSPeter Dunlap 49430e7468fSPeter Dunlap switch (icn) { 49530e7468fSPeter Dunlap case CN_FFP_ENABLED: 49630e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 49730e7468fSPeter Dunlap icp->conn_async_logout = B_FALSE; 49830e7468fSPeter Dunlap icp->conn_state_ffp = B_TRUE; 49930e7468fSPeter Dunlap cv_broadcast(&icp->conn_state_change); 50030e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 50130e7468fSPeter Dunlap 50230e7468fSPeter Dunlap /* 50330e7468fSPeter Dunlap * This logic assumes that the IDM login-snooping code 50419944f88Syi zhang - Sun Microsystems - Beijing China * and the initiator login code will agree to go when 50519944f88Syi zhang - Sun Microsystems - Beijing China * the connection is in FFP or final error received. 50619944f88Syi zhang - Sun Microsystems - Beijing China * The reason we do this is that we don't want to process 50719944f88Syi zhang - Sun Microsystems - Beijing China * CN_FFP_DISABLED until CN_FFP_ENABLED has been full handled. 50830e7468fSPeter Dunlap */ 50930e7468fSPeter Dunlap mutex_enter(&icp->conn_login_mutex); 51019944f88Syi zhang - Sun Microsystems - Beijing China while ((icp->conn_login_state != LOGIN_FFP) && 51119944f88Syi zhang - Sun Microsystems - Beijing China (icp->conn_login_state != LOGIN_ERROR)) { 51230e7468fSPeter Dunlap cv_wait(&icp->conn_login_cv, &icp->conn_login_mutex); 51330e7468fSPeter Dunlap } 51430e7468fSPeter Dunlap mutex_exit(&icp->conn_login_mutex); 51530e7468fSPeter Dunlap break; 51630e7468fSPeter Dunlap case CN_FFP_DISABLED: 51730e7468fSPeter Dunlap disable_type = (idm_ffp_disable_t)data; 51830e7468fSPeter Dunlap 51930e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 52030e7468fSPeter Dunlap switch (disable_type) { 52130e7468fSPeter Dunlap case FD_SESS_LOGOUT: 52230e7468fSPeter Dunlap case FD_CONN_LOGOUT: 52330e7468fSPeter Dunlap if (icp->conn_async_logout) { 52430e7468fSPeter Dunlap /* 52530e7468fSPeter Dunlap * Our logout was in response to an 52630e7468fSPeter Dunlap * async logout request so treat this 52730e7468fSPeter Dunlap * like a connection failure (we will 52830e7468fSPeter Dunlap * try to re-establish the connection) 52930e7468fSPeter Dunlap */ 53030e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 53130e7468fSPeter Dunlap ISCSI_CONN_STATE_FAILED); 53230e7468fSPeter Dunlap } else { 53330e7468fSPeter Dunlap /* 53430e7468fSPeter Dunlap * Logout due to to user config change, 53530e7468fSPeter Dunlap * we will not try to re-establish 53630e7468fSPeter Dunlap * the connection. 53730e7468fSPeter Dunlap */ 53830e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 53930e7468fSPeter Dunlap ISCSI_CONN_STATE_IN_LOGOUT); 54030e7468fSPeter Dunlap /* 54130e7468fSPeter Dunlap * Hold off generating the ISCSI_SESS_EVENT_N3 54230e7468fSPeter Dunlap * event until we get the CN_CONNECT_LOST 54330e7468fSPeter Dunlap * notification. This matches the pre-IDM 54430e7468fSPeter Dunlap * implementation better. 54530e7468fSPeter Dunlap */ 54630e7468fSPeter Dunlap } 54730e7468fSPeter Dunlap break; 54830e7468fSPeter Dunlap 54930e7468fSPeter Dunlap case FD_CONN_FAIL: 550fcf3ce44SJohn Forte default: 55119944f88Syi zhang - Sun Microsystems - Beijing China if (icp->conn_state == ISCSI_CONN_STATE_IN_LOGIN) { 55219944f88Syi zhang - Sun Microsystems - Beijing China iscsi_conn_update_state_locked(icp, 55319944f88Syi zhang - Sun Microsystems - Beijing China ISCSI_CONN_STATE_FREE); 55419944f88Syi zhang - Sun Microsystems - Beijing China } else { 55530e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 55630e7468fSPeter Dunlap ISCSI_CONN_STATE_FAILED); 55719944f88Syi zhang - Sun Microsystems - Beijing China } 55830e7468fSPeter Dunlap break; 55930e7468fSPeter Dunlap } 56030e7468fSPeter Dunlap 56130e7468fSPeter Dunlap icp->conn_state_ffp = B_FALSE; 56230e7468fSPeter Dunlap cv_broadcast(&icp->conn_state_change); 56330e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 56430e7468fSPeter Dunlap 56530e7468fSPeter Dunlap break; 56630e7468fSPeter Dunlap case CN_CONNECT_LOST: 56730e7468fSPeter Dunlap /* 56830e7468fSPeter Dunlap * We only care about CN_CONNECT_LOST if we've logged in. IDM 56930e7468fSPeter Dunlap * sends a flag as the data payload to indicate whether we 57030e7468fSPeter Dunlap * were trying to login. The CN_LOGIN_FAIL notification 57130e7468fSPeter Dunlap * gives us what we need to know for login failures and 57230e7468fSPeter Dunlap * otherwise we will need to keep a bunch of state to know 57330e7468fSPeter Dunlap * what CN_CONNECT_LOST means to us. 57430e7468fSPeter Dunlap */ 57530e7468fSPeter Dunlap in_login = (boolean_t)data; 57619944f88Syi zhang - Sun Microsystems - Beijing China if (in_login || 57719944f88Syi zhang - Sun Microsystems - Beijing China (icp->conn_prev_state == ISCSI_CONN_STATE_IN_LOGIN)) { 57830e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 57930e7468fSPeter Dunlap 58030e7468fSPeter Dunlap icp->conn_state_idm_connected = B_FALSE; 58130e7468fSPeter Dunlap cv_broadcast(&icp->conn_state_change); 58230e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 58330e7468fSPeter Dunlap 58430e7468fSPeter Dunlap /* Release connect hold from CN_READY_FOR_LOGIN */ 58530e7468fSPeter Dunlap idm_conn_rele(ic); 58630e7468fSPeter Dunlap break; 58730e7468fSPeter Dunlap } 58830e7468fSPeter Dunlap 58930e7468fSPeter Dunlap /* Any remaining commands are never going to finish */ 59030e7468fSPeter Dunlap iscsi_conn_flush_active_cmds(icp); 59130e7468fSPeter Dunlap 59230e7468fSPeter Dunlap /* 59330e7468fSPeter Dunlap * The connection is no longer active so cleanup any 59430e7468fSPeter Dunlap * references to the connection and release any holds so 59530e7468fSPeter Dunlap * that IDM can finish cleanup. 59630e7468fSPeter Dunlap */ 59730e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 59830e7468fSPeter Dunlap if (icp->conn_state != ISCSI_CONN_STATE_FAILED) { 59930e7468fSPeter Dunlap 60030e7468fSPeter Dunlap mutex_enter(&isp->sess_state_mutex); 60130e7468fSPeter Dunlap iscsi_sess_state_machine(isp, ISCSI_SESS_EVENT_N3); 60230e7468fSPeter Dunlap mutex_exit(&isp->sess_state_mutex); 60330e7468fSPeter Dunlap 60430e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 60530e7468fSPeter Dunlap ISCSI_CONN_STATE_FREE); 60630e7468fSPeter Dunlap } else { 60730e7468fSPeter Dunlap 60830e7468fSPeter Dunlap mutex_enter(&isp->sess_state_mutex); 60930e7468fSPeter Dunlap iscsi_sess_state_machine(isp, 61030e7468fSPeter Dunlap ISCSI_SESS_EVENT_N5); 61130e7468fSPeter Dunlap mutex_exit(&isp->sess_state_mutex); 61230e7468fSPeter Dunlap 61330e7468fSPeter Dunlap /* 61430e7468fSPeter Dunlap * If session type is NORMAL, try to reestablish the 61530e7468fSPeter Dunlap * connection. 61630e7468fSPeter Dunlap */ 617*cc7ef495Syi zhang - Sun Microsystems - Beijing China if ((isp->sess_type == ISCSI_SESS_TYPE_NORMAL) && 618*cc7ef495Syi zhang - Sun Microsystems - Beijing China !(ISCSI_LOGIN_TPGT_NEGO_ERROR(icp))) { 61930e7468fSPeter Dunlap iscsi_conn_retry(isp, icp); 62030e7468fSPeter Dunlap } else { 62130e7468fSPeter Dunlap 62230e7468fSPeter Dunlap mutex_enter(&isp->sess_state_mutex); 62330e7468fSPeter Dunlap iscsi_sess_state_machine(isp, 62430e7468fSPeter Dunlap ISCSI_SESS_EVENT_N6); 62530e7468fSPeter Dunlap mutex_exit(&isp->sess_state_mutex); 62630e7468fSPeter Dunlap 62730e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 62830e7468fSPeter Dunlap ISCSI_CONN_STATE_FREE); 629fcf3ce44SJohn Forte } 630fcf3ce44SJohn Forte } 631fcf3ce44SJohn Forte 63230e7468fSPeter Dunlap (void) iscsi_thread_stop(icp->conn_tx_thread); 63330e7468fSPeter Dunlap 63430e7468fSPeter Dunlap icp->conn_state_idm_connected = B_FALSE; 63530e7468fSPeter Dunlap cv_broadcast(&icp->conn_state_change); 63630e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 63730e7468fSPeter Dunlap 63830e7468fSPeter Dunlap /* Release connect hold from CN_READY_FOR_LOGIN */ 63930e7468fSPeter Dunlap idm_conn_rele(ic); 64030e7468fSPeter Dunlap break; 64130e7468fSPeter Dunlap default: 64230e7468fSPeter Dunlap ISCSI_CONN_LOG(CE_WARN, 64330e7468fSPeter Dunlap "iscsi_client_notify: unknown notification: " 64430e7468fSPeter Dunlap "%x: NOT IMPLEMENTED YET: icp: %p ic: %p ", 64530e7468fSPeter Dunlap icn, (void *)icp, (void *)ic); 64630e7468fSPeter Dunlap break; 64730e7468fSPeter Dunlap } 64830e7468fSPeter Dunlap /* free the task notify structure we allocated in iscsi_client_notify */ 64930e7468fSPeter Dunlap kmem_free(cn_task, sizeof (*cn_task)); 65030e7468fSPeter Dunlap 65130e7468fSPeter Dunlap /* Release the hold we acquired in iscsi_client_notify */ 65230e7468fSPeter Dunlap idm_conn_rele(ic); 65330e7468fSPeter Dunlap } 654fcf3ce44SJohn Forte 655fcf3ce44SJohn Forte /* 656fcf3ce44SJohn Forte * iscsi_conn_sync_params - used to update connection parameters 657fcf3ce44SJohn Forte * 658fcf3ce44SJohn Forte * Used to update connection parameters with current configured 659fcf3ce44SJohn Forte * parameters in the persistent store. This should be called 660fcf3ce44SJohn Forte * before starting to make a new iscsi connection in iscsi_login. 661fcf3ce44SJohn Forte */ 662fcf3ce44SJohn Forte iscsi_status_t 663fcf3ce44SJohn Forte iscsi_conn_sync_params(iscsi_conn_t *icp) 664fcf3ce44SJohn Forte { 665fcf3ce44SJohn Forte iscsi_sess_t *isp; 666fcf3ce44SJohn Forte iscsi_hba_t *ihp; 667fcf3ce44SJohn Forte int param_id; 668fcf3ce44SJohn Forte persistent_param_t pp; 669aff4bce5Syi zhang - Sun Microsystems - Beijing China persistent_tunable_param_t ptp; 670fcf3ce44SJohn Forte iscsi_config_sess_t *ics; 671fcf3ce44SJohn Forte int idx, size; 672fcf3ce44SJohn Forte char *name; 673fcf3ce44SJohn Forte 674fcf3ce44SJohn Forte ASSERT(icp != NULL); 675fcf3ce44SJohn Forte ASSERT((icp->conn_state == ISCSI_CONN_STATE_IN_LOGIN) || 676fcf3ce44SJohn Forte (icp->conn_state == ISCSI_CONN_STATE_FAILED) || 677fcf3ce44SJohn Forte (icp->conn_state == ISCSI_CONN_STATE_POLLING)); 678fcf3ce44SJohn Forte isp = icp->conn_sess; 679fcf3ce44SJohn Forte ASSERT(isp != NULL); 680fcf3ce44SJohn Forte ihp = isp->sess_hba; 681fcf3ce44SJohn Forte ASSERT(ihp != NULL); 682fcf3ce44SJohn Forte 683fcf3ce44SJohn Forte /* 684fcf3ce44SJohn Forte * Check if someone is trying to destroy this 685fcf3ce44SJohn Forte * connection. If so fail the sync request, 686fcf3ce44SJohn Forte * as a method of fast fail. 687fcf3ce44SJohn Forte */ 688fcf3ce44SJohn Forte if (icp->conn_state_destroy == B_TRUE) { 689fcf3ce44SJohn Forte return (ISCSI_STATUS_SHUTDOWN); 690fcf3ce44SJohn Forte } 691fcf3ce44SJohn Forte 692fcf3ce44SJohn Forte bzero(&pp, sizeof (pp)); 693fcf3ce44SJohn Forte 694fcf3ce44SJohn Forte /* First get a copy of the HBA params */ 695fcf3ce44SJohn Forte bcopy(&ihp->hba_params, &icp->conn_params, 696fcf3ce44SJohn Forte sizeof (iscsi_login_params_t)); 697aff4bce5Syi zhang - Sun Microsystems - Beijing China bcopy(&ihp->hba_tunable_params, &icp->conn_tunable_params, 698aff4bce5Syi zhang - Sun Microsystems - Beijing China sizeof (iscsi_tunable_params_t)); 699fcf3ce44SJohn Forte 700fcf3ce44SJohn Forte /* 701fcf3ce44SJohn Forte * Now we need to get the session configured 702fcf3ce44SJohn Forte * values from the persistent store and apply 703fcf3ce44SJohn Forte * them to our connection. 704fcf3ce44SJohn Forte */ 705fcf3ce44SJohn Forte (void) persistent_param_get((char *)isp->sess_name, &pp); 706fcf3ce44SJohn Forte for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM; 707fcf3ce44SJohn Forte param_id++) { 7086cefaae1SJack Meng if (iscsiboot_prop && modrootloaded && 7096cefaae1SJack Meng !iscsi_chk_bootlun_mpxio(ihp) && isp->sess_boot) { 7106cefaae1SJack Meng /* 7116cefaae1SJack Meng * iscsi boot with mpxio disabled 7126cefaae1SJack Meng * while iscsi booting target's parameter overriden 7136cefaae1SJack Meng * do no update target's parameters. 7146cefaae1SJack Meng */ 7156cefaae1SJack Meng if (pp.p_bitmap) { 7166cefaae1SJack Meng cmn_err(CE_NOTE, "Adopting " 7176cefaae1SJack Meng " default login parameters in" 7186cefaae1SJack Meng " boot session as MPxIO is disabled"); 7196cefaae1SJack Meng } 7206cefaae1SJack Meng break; 7216cefaae1SJack Meng } 722fcf3ce44SJohn Forte if (pp.p_bitmap & (1 << param_id)) { 72330e7468fSPeter Dunlap 724fcf3ce44SJohn Forte switch (param_id) { 725fcf3ce44SJohn Forte /* 726fcf3ce44SJohn Forte * Boolean parameters 727fcf3ce44SJohn Forte */ 728fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER: 729fcf3ce44SJohn Forte icp->conn_params.data_pdu_in_order = 730fcf3ce44SJohn Forte pp.p_params.data_pdu_in_order; 731fcf3ce44SJohn Forte break; 732fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_IMMEDIATE_DATA: 733fcf3ce44SJohn Forte icp->conn_params.immediate_data = 734fcf3ce44SJohn Forte pp.p_params.immediate_data; 735fcf3ce44SJohn Forte break; 736fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_INITIAL_R2T: 737fcf3ce44SJohn Forte icp->conn_params.initial_r2t = 738fcf3ce44SJohn Forte pp.p_params.initial_r2t; 739fcf3ce44SJohn Forte break; 740fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER: 741fcf3ce44SJohn Forte icp->conn_params.data_pdu_in_order = 742fcf3ce44SJohn Forte pp.p_params.data_pdu_in_order; 743fcf3ce44SJohn Forte break; 744fcf3ce44SJohn Forte /* 745fcf3ce44SJohn Forte * Integer parameters 746fcf3ce44SJohn Forte */ 747fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_HEADER_DIGEST: 748fcf3ce44SJohn Forte icp->conn_params.header_digest = 749fcf3ce44SJohn Forte pp.p_params.header_digest; 750fcf3ce44SJohn Forte break; 751fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DATA_DIGEST: 752fcf3ce44SJohn Forte icp->conn_params.data_digest = 753fcf3ce44SJohn Forte pp.p_params.data_digest; 754fcf3ce44SJohn Forte break; 755fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN: 756fcf3ce44SJohn Forte icp->conn_params.default_time_to_retain = 757fcf3ce44SJohn Forte pp.p_params.default_time_to_retain; 758fcf3ce44SJohn Forte break; 759fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT: 760fcf3ce44SJohn Forte icp->conn_params.default_time_to_wait = 761fcf3ce44SJohn Forte pp.p_params.default_time_to_wait; 762fcf3ce44SJohn Forte break; 763fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH: 764fcf3ce44SJohn Forte icp->conn_params.max_recv_data_seg_len = 765fcf3ce44SJohn Forte pp.p_params.max_recv_data_seg_len; 766fcf3ce44SJohn Forte break; 767fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH: 768fcf3ce44SJohn Forte icp->conn_params.first_burst_length = 769fcf3ce44SJohn Forte pp.p_params.first_burst_length; 770fcf3ce44SJohn Forte break; 771fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH: 772fcf3ce44SJohn Forte icp->conn_params.max_burst_length = 773fcf3ce44SJohn Forte pp.p_params.max_burst_length; 774fcf3ce44SJohn Forte break; 775fcf3ce44SJohn Forte 776fcf3ce44SJohn Forte /* 777fcf3ce44SJohn Forte * Integer parameters which currently are unsettable 778fcf3ce44SJohn Forte */ 779fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_MAX_CONNECTIONS: 780fcf3ce44SJohn Forte /* FALLTHRU */ 781fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_OUTSTANDING_R2T: 782fcf3ce44SJohn Forte /* FALLTHRU */ 783fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL: 784fcf3ce44SJohn Forte /* FALLTHRU */ 785fcf3ce44SJohn Forte default: 786fcf3ce44SJohn Forte break; 787fcf3ce44SJohn Forte } 788fcf3ce44SJohn Forte } 789fcf3ce44SJohn Forte } 790fcf3ce44SJohn Forte 791aff4bce5Syi zhang - Sun Microsystems - Beijing China if (persistent_get_tunable_param((char *)isp->sess_name, &ptp) == 792aff4bce5Syi zhang - Sun Microsystems - Beijing China B_TRUE) { 793aff4bce5Syi zhang - Sun Microsystems - Beijing China if (ptp.p_bitmap & ISCSI_TUNABLE_PARAM_RX_TIMEOUT_VALUE) { 794aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_tunable_params.recv_login_rsp_timeout = 795aff4bce5Syi zhang - Sun Microsystems - Beijing China ptp.p_params.recv_login_rsp_timeout; 796aff4bce5Syi zhang - Sun Microsystems - Beijing China } 797aff4bce5Syi zhang - Sun Microsystems - Beijing China if (ptp.p_bitmap & ISCSI_TUNABLE_PARAM_CONN_LOGIN_MAX) { 798aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_tunable_params.conn_login_max = 799aff4bce5Syi zhang - Sun Microsystems - Beijing China ptp.p_params.conn_login_max; 800aff4bce5Syi zhang - Sun Microsystems - Beijing China } 801aff4bce5Syi zhang - Sun Microsystems - Beijing China if (ptp.p_bitmap & ISCSI_TUNABLE_PARAM_LOGIN_POLLING_DELAY) { 802aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_tunable_params.polling_login_delay = 803aff4bce5Syi zhang - Sun Microsystems - Beijing China ptp.p_params.polling_login_delay; 804aff4bce5Syi zhang - Sun Microsystems - Beijing China } 805aff4bce5Syi zhang - Sun Microsystems - Beijing China } 806aff4bce5Syi zhang - Sun Microsystems - Beijing China 807fcf3ce44SJohn Forte /* Skip binding checks on discovery sessions */ 808fcf3ce44SJohn Forte if (isp->sess_type == ISCSI_SESS_TYPE_DISCOVERY) { 809fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 810fcf3ce44SJohn Forte } 811fcf3ce44SJohn Forte 812fcf3ce44SJohn Forte /* 813fcf3ce44SJohn Forte * Now we need to get the current optional connection 814fcf3ce44SJohn Forte * binding information. 815fcf3ce44SJohn Forte */ 816fcf3ce44SJohn Forte /* setup initial buffer for configured session information */ 817fcf3ce44SJohn Forte size = sizeof (*ics); 818fcf3ce44SJohn Forte ics = kmem_zalloc(size, KM_SLEEP); 819fcf3ce44SJohn Forte ics->ics_in = 1; 820fcf3ce44SJohn Forte 821fcf3ce44SJohn Forte /* get configured sessions information */ 822fcf3ce44SJohn Forte name = (char *)isp->sess_name; 823fcf3ce44SJohn Forte if (persistent_get_config_session(name, ics) == B_FALSE) { 824fcf3ce44SJohn Forte /* 825fcf3ce44SJohn Forte * If we were unable to get target level information 826fcf3ce44SJohn Forte * then check the initiator level information. 827fcf3ce44SJohn Forte */ 828fcf3ce44SJohn Forte name = (char *)isp->sess_hba->hba_name; 829fcf3ce44SJohn Forte if (persistent_get_config_session(name, ics) == B_FALSE) { 830fcf3ce44SJohn Forte /* 831fcf3ce44SJohn Forte * No hba information is found. So assume default 832fcf3ce44SJohn Forte * one session unbound behavior. 833fcf3ce44SJohn Forte */ 834fcf3ce44SJohn Forte ics->ics_out = 1; 835fcf3ce44SJohn Forte ics->ics_bound = B_FALSE; 836fcf3ce44SJohn Forte } 837fcf3ce44SJohn Forte } 838fcf3ce44SJohn Forte 8396cefaae1SJack Meng if (iscsiboot_prop && (ics->ics_out > 1) && isp->sess_boot && 8406cefaae1SJack Meng !iscsi_chk_bootlun_mpxio(ihp)) { 8416cefaae1SJack Meng /* 8426cefaae1SJack Meng * iscsi booting session with mpxio disabled, 8436cefaae1SJack Meng * no need set multiple sessions for booting session 8446cefaae1SJack Meng */ 8456cefaae1SJack Meng ics->ics_out = 1; 8466cefaae1SJack Meng ics->ics_bound = B_FALSE; 8476cefaae1SJack Meng cmn_err(CE_NOTE, "MPxIO is disabled," 8486cefaae1SJack Meng " no need to configure multiple boot sessions"); 8496cefaae1SJack Meng } 8506cefaae1SJack Meng 851fcf3ce44SJohn Forte /* 852fcf3ce44SJohn Forte * Check to make sure this session is still a configured 853fcf3ce44SJohn Forte * session. The user might have decreased the session 854fcf3ce44SJohn Forte * count. (NOTE: byte 5 of the sess_isid is the session 855fcf3ce44SJohn Forte * count (via MS/T). This counter starts at 0.) 856fcf3ce44SJohn Forte */ 8576cefaae1SJack Meng 8586cefaae1SJack Meng 859fcf3ce44SJohn Forte idx = isp->sess_isid[5]; 8606cefaae1SJack Meng 8616cefaae1SJack Meng if (iscsiboot_prop && (idx == ISCSI_MAX_CONFIG_SESSIONS)) { 8626cefaae1SJack Meng /* 8636cefaae1SJack Meng * This is temporary session for boot session propose 8646cefaae1SJack Meng * no need to bound IP for this session 8656cefaae1SJack Meng */ 8666cefaae1SJack Meng icp->conn_bound = B_FALSE; 8676cefaae1SJack Meng kmem_free(ics, sizeof (iscsi_config_sess_t)); 8686cefaae1SJack Meng return (ISCSI_STATUS_SUCCESS); 8696cefaae1SJack Meng } 8706cefaae1SJack Meng 871fcf3ce44SJohn Forte if (ics->ics_out <= idx) { 872fcf3ce44SJohn Forte /* 873fcf3ce44SJohn Forte * No longer a configured session. Return a 874fcf3ce44SJohn Forte * failure so we don't attempt to relogin. 875fcf3ce44SJohn Forte */ 876fcf3ce44SJohn Forte return (ISCSI_STATUS_SHUTDOWN); 877fcf3ce44SJohn Forte } 878fcf3ce44SJohn Forte 879fcf3ce44SJohn Forte /* 880fcf3ce44SJohn Forte * If sessions are unbound set this information on 881fcf3ce44SJohn Forte * the connection and return success. 882fcf3ce44SJohn Forte */ 883fcf3ce44SJohn Forte if (ics->ics_bound == B_FALSE) { 884fcf3ce44SJohn Forte icp->conn_bound = B_FALSE; 885fcf3ce44SJohn Forte kmem_free(ics, sizeof (iscsi_config_sess_t)); 886fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 887fcf3ce44SJohn Forte } 888fcf3ce44SJohn Forte 889fcf3ce44SJohn Forte /* 890fcf3ce44SJohn Forte * Since the sessions are bound we need to find the matching 891fcf3ce44SJohn Forte * binding information for the session's isid. If this 892fcf3ce44SJohn Forte * session's isid is > 0 then we need to get more configured 893fcf3ce44SJohn Forte * session information to find the binding info. 894fcf3ce44SJohn Forte */ 895fcf3ce44SJohn Forte if (idx > 0) { 896fcf3ce44SJohn Forte int ics_out; 897fcf3ce44SJohn Forte 898fcf3ce44SJohn Forte ics_out = ics->ics_out; 899fcf3ce44SJohn Forte /* record new size and free last buffer */ 900fcf3ce44SJohn Forte size = ISCSI_SESSION_CONFIG_SIZE(ics_out); 901fcf3ce44SJohn Forte kmem_free(ics, sizeof (*ics)); 902fcf3ce44SJohn Forte 903fcf3ce44SJohn Forte /* allocate new buffer */ 904fcf3ce44SJohn Forte ics = kmem_zalloc(size, KM_SLEEP); 905fcf3ce44SJohn Forte ics->ics_in = ics_out; 906fcf3ce44SJohn Forte 907fcf3ce44SJohn Forte /* get configured sessions information */ 908fcf3ce44SJohn Forte if (persistent_get_config_session(name, ics) != B_TRUE) { 909fcf3ce44SJohn Forte cmn_err(CE_NOTE, "iscsi session(%d) - " 910fcf3ce44SJohn Forte "unable to get configured session information\n", 911fcf3ce44SJohn Forte isp->sess_oid); 912fcf3ce44SJohn Forte kmem_free(ics, size); 913fcf3ce44SJohn Forte return (ISCSI_STATUS_SHUTDOWN); 914fcf3ce44SJohn Forte } 915fcf3ce44SJohn Forte } 916fcf3ce44SJohn Forte 917fcf3ce44SJohn Forte /* Copy correct binding information to the connection */ 918fcf3ce44SJohn Forte icp->conn_bound = B_TRUE; 919fcf3ce44SJohn Forte if (ics->ics_bindings[idx].i_insize == sizeof (struct in_addr)) { 920fcf3ce44SJohn Forte bcopy(&ics->ics_bindings[idx].i_addr.in4, 921fcf3ce44SJohn Forte &icp->conn_bound_addr.sin4.sin_addr.s_addr, 922fcf3ce44SJohn Forte sizeof (struct in_addr)); 9231050fd6dSJames Moore icp->conn_bound_addr.sin4.sin_family = AF_INET; 924fcf3ce44SJohn Forte } else { 925fcf3ce44SJohn Forte bcopy(&ics->ics_bindings[idx].i_addr.in6, 926fcf3ce44SJohn Forte &icp->conn_bound_addr.sin6.sin6_addr.s6_addr, 927fcf3ce44SJohn Forte sizeof (struct in6_addr)); 9281050fd6dSJames Moore icp->conn_bound_addr.sin6.sin6_family = AF_INET6; 929fcf3ce44SJohn Forte } 930fcf3ce44SJohn Forte 931fcf3ce44SJohn Forte kmem_free(ics, size); 932fcf3ce44SJohn Forte 933fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 934fcf3ce44SJohn Forte } 935fcf3ce44SJohn Forte 936fcf3ce44SJohn Forte /* 937fcf3ce44SJohn Forte * +--------------------------------------------------------------------+ 938fcf3ce44SJohn Forte * | Internal Connection Interfaces | 939fcf3ce44SJohn Forte * +--------------------------------------------------------------------+ 940fcf3ce44SJohn Forte */ 941fcf3ce44SJohn Forte 942fcf3ce44SJohn Forte /* 943fcf3ce44SJohn Forte * iscsi_conn_flush_active_cmds - flush all active icmdps 944fcf3ce44SJohn Forte * for a connection. 945fcf3ce44SJohn Forte */ 946fcf3ce44SJohn Forte static void 947fcf3ce44SJohn Forte iscsi_conn_flush_active_cmds(iscsi_conn_t *icp) 948fcf3ce44SJohn Forte { 949fcf3ce44SJohn Forte iscsi_cmd_t *icmdp; 950fcf3ce44SJohn Forte iscsi_sess_t *isp; 951fcf3ce44SJohn Forte boolean_t lock_held = B_FALSE; 952fcf3ce44SJohn Forte 953fcf3ce44SJohn Forte ASSERT(icp != NULL); 954fcf3ce44SJohn Forte isp = icp->conn_sess; 955fcf3ce44SJohn Forte ASSERT(isp != NULL); 956fcf3ce44SJohn Forte 957fcf3ce44SJohn Forte if (mutex_owned(&icp->conn_queue_active.mutex)) { 958fcf3ce44SJohn Forte lock_held = B_TRUE; 959fcf3ce44SJohn Forte } else { 960fcf3ce44SJohn Forte mutex_enter(&icp->conn_queue_active.mutex); 961fcf3ce44SJohn Forte } 962fcf3ce44SJohn Forte 963fcf3ce44SJohn Forte /* Flush active queue */ 964fcf3ce44SJohn Forte icmdp = icp->conn_queue_active.head; 965fcf3ce44SJohn Forte while (icmdp != NULL) { 9662b79d384Sbing zhao - Sun Microsystems - Beijing China 9672b79d384Sbing zhao - Sun Microsystems - Beijing China mutex_enter(&icmdp->cmd_mutex); 9682b79d384Sbing zhao - Sun Microsystems - Beijing China if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) { 9692b79d384Sbing zhao - Sun Microsystems - Beijing China icmdp->cmd_un.scsi.pkt_stat |= STAT_ABORTED; 9702b79d384Sbing zhao - Sun Microsystems - Beijing China } 9712b79d384Sbing zhao - Sun Microsystems - Beijing China mutex_exit(&icmdp->cmd_mutex); 9722b79d384Sbing zhao - Sun Microsystems - Beijing China 973fcf3ce44SJohn Forte iscsi_cmd_state_machine(icmdp, 974fcf3ce44SJohn Forte ISCSI_CMD_EVENT_E7, isp); 975fcf3ce44SJohn Forte icmdp = icp->conn_queue_active.head; 976fcf3ce44SJohn Forte } 977fcf3ce44SJohn Forte 97830e7468fSPeter Dunlap /* Wait for active queue to drain */ 97930e7468fSPeter Dunlap while (icp->conn_queue_active.count) { 98030e7468fSPeter Dunlap mutex_exit(&icp->conn_queue_active.mutex); 98130e7468fSPeter Dunlap delay(drv_usectohz(100000)); 98230e7468fSPeter Dunlap mutex_enter(&icp->conn_queue_active.mutex); 98330e7468fSPeter Dunlap } 98430e7468fSPeter Dunlap 985fcf3ce44SJohn Forte if (lock_held == B_FALSE) { 986fcf3ce44SJohn Forte mutex_exit(&icp->conn_queue_active.mutex); 987fcf3ce44SJohn Forte } 98830e7468fSPeter Dunlap 98930e7468fSPeter Dunlap /* Wait for IDM abort queue to drain (if necessary) */ 99030e7468fSPeter Dunlap mutex_enter(&icp->conn_queue_idm_aborting.mutex); 99130e7468fSPeter Dunlap while (icp->conn_queue_idm_aborting.count) { 99230e7468fSPeter Dunlap mutex_exit(&icp->conn_queue_idm_aborting.mutex); 99330e7468fSPeter Dunlap delay(drv_usectohz(100000)); 99430e7468fSPeter Dunlap mutex_enter(&icp->conn_queue_idm_aborting.mutex); 995fcf3ce44SJohn Forte } 99630e7468fSPeter Dunlap mutex_exit(&icp->conn_queue_idm_aborting.mutex); 997fcf3ce44SJohn Forte } 998fcf3ce44SJohn Forte 999fcf3ce44SJohn Forte /* 1000fcf3ce44SJohn Forte * iscsi_conn_retry - retry connect/login 1001fcf3ce44SJohn Forte */ 100230e7468fSPeter Dunlap void 1003fcf3ce44SJohn Forte iscsi_conn_retry(iscsi_sess_t *isp, iscsi_conn_t *icp) 1004fcf3ce44SJohn Forte { 1005fcf3ce44SJohn Forte iscsi_task_t *itp; 1006fcf3ce44SJohn Forte 1007fcf3ce44SJohn Forte ASSERT(isp != NULL); 1008fcf3ce44SJohn Forte ASSERT(icp != NULL); 1009fcf3ce44SJohn Forte 1010fcf3ce44SJohn Forte /* set login min/max time values */ 1011fcf3ce44SJohn Forte iscsi_conn_set_login_min_max(icp, 1012fcf3ce44SJohn Forte ISCSI_CONN_DEFAULT_LOGIN_MIN, 1013aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_tunable_params.conn_login_max); 1014fcf3ce44SJohn Forte 101530e7468fSPeter Dunlap ISCSI_CONN_LOG(CE_NOTE, "DEBUG: iscsi_conn_retry: icp: %p icp: %p ", 101630e7468fSPeter Dunlap (void *)icp, 101730e7468fSPeter Dunlap (void *)icp->conn_ic); 101830e7468fSPeter Dunlap 1019fcf3ce44SJohn Forte /* 1020fcf3ce44SJohn Forte * Sync base connection information before login. 1021fcf3ce44SJohn Forte * A login redirection might have shifted the 1022fcf3ce44SJohn Forte * current information from the base. 1023fcf3ce44SJohn Forte */ 1024fcf3ce44SJohn Forte bcopy(&icp->conn_base_addr, &icp->conn_curr_addr, 1025fcf3ce44SJohn Forte sizeof (icp->conn_curr_addr)); 1026fcf3ce44SJohn Forte 1027fcf3ce44SJohn Forte /* schedule login task */ 1028fcf3ce44SJohn Forte itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP); 1029fcf3ce44SJohn Forte itp->t_arg = icp; 1030fcf3ce44SJohn Forte itp->t_blocking = B_FALSE; 1031fcf3ce44SJohn Forte if (ddi_taskq_dispatch(isp->sess_taskq, 1032fcf3ce44SJohn Forte (void(*)())iscsi_login_start, itp, DDI_SLEEP) != 1033fcf3ce44SJohn Forte DDI_SUCCESS) { 1034fcf3ce44SJohn Forte kmem_free(itp, sizeof (iscsi_task_t)); 103530e7468fSPeter Dunlap cmn_err(CE_WARN, "iscsi connection(%u) failure - " 103630e7468fSPeter Dunlap "unable to schedule login task", icp->conn_oid); 1037fcf3ce44SJohn Forte 103830e7468fSPeter Dunlap iscsi_conn_update_state(icp, ISCSI_CONN_STATE_FREE); 1039fcf3ce44SJohn Forte mutex_enter(&isp->sess_state_mutex); 1040fcf3ce44SJohn Forte iscsi_sess_state_machine(isp, 1041fcf3ce44SJohn Forte ISCSI_SESS_EVENT_N6); 1042fcf3ce44SJohn Forte mutex_exit(&isp->sess_state_mutex); 1043fcf3ce44SJohn Forte } 1044fcf3ce44SJohn Forte } 104530e7468fSPeter Dunlap 104630e7468fSPeter Dunlap void 104730e7468fSPeter Dunlap iscsi_conn_update_state(iscsi_conn_t *icp, iscsi_conn_state_t 104830e7468fSPeter Dunlap next_state) 104930e7468fSPeter Dunlap { 105030e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 105130e7468fSPeter Dunlap (void) iscsi_conn_update_state_locked(icp, next_state); 105230e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 105330e7468fSPeter Dunlap } 105430e7468fSPeter Dunlap 105530e7468fSPeter Dunlap void 105630e7468fSPeter Dunlap iscsi_conn_update_state_locked(iscsi_conn_t *icp, 105730e7468fSPeter Dunlap iscsi_conn_state_t next_state) 105830e7468fSPeter Dunlap { 105930e7468fSPeter Dunlap ASSERT(mutex_owned(&icp->conn_state_mutex)); 106030e7468fSPeter Dunlap next_state = (next_state > ISCSI_CONN_STATE_MAX) ? 106130e7468fSPeter Dunlap ISCSI_CONN_STATE_MAX : next_state; 106230e7468fSPeter Dunlap idm_sm_audit_state_change(&icp->conn_state_audit, 106330e7468fSPeter Dunlap SAS_ISCSI_CONN, icp->conn_state, next_state); 106430e7468fSPeter Dunlap switch (next_state) { 106530e7468fSPeter Dunlap case ISCSI_CONN_STATE_FREE: 106630e7468fSPeter Dunlap case ISCSI_CONN_STATE_IN_LOGIN: 106730e7468fSPeter Dunlap case ISCSI_CONN_STATE_LOGGED_IN: 106830e7468fSPeter Dunlap case ISCSI_CONN_STATE_IN_LOGOUT: 106930e7468fSPeter Dunlap case ISCSI_CONN_STATE_FAILED: 107030e7468fSPeter Dunlap case ISCSI_CONN_STATE_POLLING: 107130e7468fSPeter Dunlap ISCSI_CONN_LOG(CE_NOTE, 107230e7468fSPeter Dunlap "iscsi_conn_update_state conn %p %s(%d) -> %s(%d)", 107330e7468fSPeter Dunlap (void *)icp, 107430e7468fSPeter Dunlap iscsi_ics_name[icp->conn_state], icp->conn_state, 107530e7468fSPeter Dunlap iscsi_ics_name[next_state], next_state); 107630e7468fSPeter Dunlap icp->conn_prev_state = icp->conn_state; 107730e7468fSPeter Dunlap icp->conn_state = next_state; 107830e7468fSPeter Dunlap cv_broadcast(&icp->conn_state_change); 107930e7468fSPeter Dunlap break; 108030e7468fSPeter Dunlap default: 108130e7468fSPeter Dunlap cmn_err(CE_WARN, "Update state found illegal state: %x " 108230e7468fSPeter Dunlap "prev_state: %x", next_state, icp->conn_prev_state); 108330e7468fSPeter Dunlap ASSERT(0); 108430e7468fSPeter Dunlap } 108530e7468fSPeter Dunlap } 1086