17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM * CDDL HEADER START
37836SJohn.Forte@Sun.COM *
47836SJohn.Forte@Sun.COM * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM *
87836SJohn.Forte@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM * and limitations under the License.
127836SJohn.Forte@Sun.COM *
137836SJohn.Forte@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM *
197836SJohn.Forte@Sun.COM * CDDL HEADER END
207836SJohn.Forte@Sun.COM */
217836SJohn.Forte@Sun.COM /*
22*12161SJack.Meng@Sun.COM * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
237836SJohn.Forte@Sun.COM *
247836SJohn.Forte@Sun.COM * iSCSI session interfaces
257836SJohn.Forte@Sun.COM */
267836SJohn.Forte@Sun.COM
278194SJack.Meng@Sun.COM #include <sys/bootprops.h>
287836SJohn.Forte@Sun.COM #include "iscsi.h"
297836SJohn.Forte@Sun.COM #include "persistent.h"
307836SJohn.Forte@Sun.COM #include "iscsi_targetparam.h"
317836SJohn.Forte@Sun.COM
327836SJohn.Forte@Sun.COM #define ISCSI_SESS_ENUM_TIMEOUT_DEFAULT 60
337836SJohn.Forte@Sun.COM #define SCSI_INQUIRY_PQUAL_MASK 0xE0
347836SJohn.Forte@Sun.COM
359162SPeter.Dunlap@Sun.COM boolean_t iscsi_sess_logging = B_FALSE;
367836SJohn.Forte@Sun.COM /*
377836SJohn.Forte@Sun.COM * used to store report lun information found
387836SJohn.Forte@Sun.COM *
397836SJohn.Forte@Sun.COM * lun_valid: if TRUE means the entry contains a valid entry
407836SJohn.Forte@Sun.COM * lun_found: if TRUE means the lun has been found in the sess_lun_list
417836SJohn.Forte@Sun.COM * lun_num: contains the lun_number
42*12161SJack.Meng@Sun.COM * lun_addr_type: indicates lun's type of addressing
437836SJohn.Forte@Sun.COM */
447836SJohn.Forte@Sun.COM typedef struct replun_data {
457836SJohn.Forte@Sun.COM boolean_t lun_valid;
467836SJohn.Forte@Sun.COM boolean_t lun_found;
477836SJohn.Forte@Sun.COM uint16_t lun_num;
48*12161SJack.Meng@Sun.COM uint8_t lun_addr_type;
497836SJohn.Forte@Sun.COM } replun_data_t;
507836SJohn.Forte@Sun.COM
517836SJohn.Forte@Sun.COM int iscsi_sess_enum_timeout = ISCSI_SESS_ENUM_TIMEOUT_DEFAULT;
527836SJohn.Forte@Sun.COM
537836SJohn.Forte@Sun.COM /*
547836SJohn.Forte@Sun.COM * The following private tunable, settable via
557836SJohn.Forte@Sun.COM * set iscsi:iscsi_sess_max_delay = 64
567836SJohn.Forte@Sun.COM * in /etc/system, provides customer relief for configurations max interval in
577836SJohn.Forte@Sun.COM * seconds of retry for a unreachable target during the login.
587836SJohn.Forte@Sun.COM */
597836SJohn.Forte@Sun.COM int iscsi_sess_max_delay = ISCSI_DEFAULT_MAX_STORM_DELAY;
607836SJohn.Forte@Sun.COM
61*12161SJack.Meng@Sun.COM /*
62*12161SJack.Meng@Sun.COM * Warning messages for the session scsi enumeration
63*12161SJack.Meng@Sun.COM */
64*12161SJack.Meng@Sun.COM static const char *iscsi_sess_enum_warn_msgs[] = {
65*12161SJack.Meng@Sun.COM "completed",
66*12161SJack.Meng@Sun.COM "partially successful",
67*12161SJack.Meng@Sun.COM "IO failures",
68*12161SJack.Meng@Sun.COM "submitted",
69*12161SJack.Meng@Sun.COM "unable to submit the enumeration",
70*12161SJack.Meng@Sun.COM "session is gone",
71*12161SJack.Meng@Sun.COM "test unit ready failed"
72*12161SJack.Meng@Sun.COM };
73*12161SJack.Meng@Sun.COM
747836SJohn.Forte@Sun.COM /* internal interfaces */
757836SJohn.Forte@Sun.COM /* LINTED E_STATIC_UNUSED */
767836SJohn.Forte@Sun.COM static iscsi_sess_t *iscsi_sess_alloc(iscsi_hba_t *ihp, iscsi_sess_type_t type);
777836SJohn.Forte@Sun.COM static char *iscsi_sess_event_str(iscsi_sess_event_t event);
787836SJohn.Forte@Sun.COM static iscsi_status_t iscsi_sess_threads_create(iscsi_sess_t *isp);
797836SJohn.Forte@Sun.COM static void iscsi_sess_flush(iscsi_sess_t *isp);
807836SJohn.Forte@Sun.COM static void iscsi_sess_offline_luns(iscsi_sess_t *isp);
817836SJohn.Forte@Sun.COM static iscsi_status_t retrieve_lundata(uint32_t lun_count, unsigned char *buf,
827836SJohn.Forte@Sun.COM iscsi_sess_t *isp, uint16_t *lun_data, uint8_t *lun_addr_type);
837836SJohn.Forte@Sun.COM
847836SJohn.Forte@Sun.COM /* internal state machine interfaces */
857836SJohn.Forte@Sun.COM static void iscsi_sess_state_free(iscsi_sess_t *isp,
86*12161SJack.Meng@Sun.COM iscsi_sess_event_t event, uint32_t event_count);
877836SJohn.Forte@Sun.COM static void iscsi_sess_state_logged_in(iscsi_sess_t *isp,
88*12161SJack.Meng@Sun.COM iscsi_sess_event_t event, uint32_t event_count);
897836SJohn.Forte@Sun.COM static void iscsi_sess_state_failed(iscsi_sess_t *isp,
90*12161SJack.Meng@Sun.COM iscsi_sess_event_t event, uint32_t event_count);
917836SJohn.Forte@Sun.COM static void iscsi_sess_state_in_flush(iscsi_sess_t *isp,
92*12161SJack.Meng@Sun.COM iscsi_sess_event_t event, uint32_t event_count);
937836SJohn.Forte@Sun.COM static void iscsi_sess_state_flushed(iscsi_sess_t *isp,
94*12161SJack.Meng@Sun.COM iscsi_sess_event_t event, uint32_t event_count);
957836SJohn.Forte@Sun.COM
967836SJohn.Forte@Sun.COM /* internal enumeration interfaces */
977836SJohn.Forte@Sun.COM static void iscsi_sess_enumeration(void *arg);
98*12161SJack.Meng@Sun.COM static iscsi_status_t iscsi_sess_testunitready(iscsi_sess_t *isp,
99*12161SJack.Meng@Sun.COM uint32_t event_count);
100*12161SJack.Meng@Sun.COM static iscsi_status_t iscsi_sess_reportluns(iscsi_sess_t *isp,
101*12161SJack.Meng@Sun.COM uint32_t event_count);
1027836SJohn.Forte@Sun.COM static void iscsi_sess_inquiry(iscsi_sess_t *isp, uint16_t lun_num,
103*12161SJack.Meng@Sun.COM uint8_t lun_addr_type, uint32_t event_count, iscsi_lun_t *ilp);
1049780SBing.Zhao@Sun.COM static void iscsi_sess_update_busy_luns(iscsi_sess_t *isp, boolean_t clear);
105*12161SJack.Meng@Sun.COM static void iscsi_sess_enum_warn(iscsi_sess_t *isp, iscsi_enum_result_t r);
1067836SJohn.Forte@Sun.COM
1077836SJohn.Forte@Sun.COM /*
1087836SJohn.Forte@Sun.COM * +--------------------------------------------------------------------+
1097836SJohn.Forte@Sun.COM * | External Session Interfaces |
1107836SJohn.Forte@Sun.COM * +--------------------------------------------------------------------+
1117836SJohn.Forte@Sun.COM */
1127836SJohn.Forte@Sun.COM iscsi_sess_t *
iscsi_sess_create(iscsi_hba_t * ihp,iSCSIDiscoveryMethod_t method,struct sockaddr * addr_dsc,char * target_name,int tpgt,uchar_t isid_lsb,iscsi_sess_type_t type,uint32_t * oid)1137836SJohn.Forte@Sun.COM iscsi_sess_create(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method,
1147836SJohn.Forte@Sun.COM struct sockaddr *addr_dsc, char *target_name, int tpgt, uchar_t isid_lsb,
1157836SJohn.Forte@Sun.COM iscsi_sess_type_t type, uint32_t *oid)
1167836SJohn.Forte@Sun.COM {
1177836SJohn.Forte@Sun.COM iscsi_sess_t *isp = NULL;
1187836SJohn.Forte@Sun.COM int len = 0;
1197836SJohn.Forte@Sun.COM char *tq_name;
1207836SJohn.Forte@Sun.COM char *th_name;
12111476SBing.Zhao@Sun.COM iscsi_status_t status;
1227836SJohn.Forte@Sun.COM
1237836SJohn.Forte@Sun.COM len = strlen(target_name);
1247836SJohn.Forte@Sun.COM
1258277SJack.Meng@Sun.COM clean_failed_sess:
1268277SJack.Meng@Sun.COM if (isp != NULL) {
1278277SJack.Meng@Sun.COM (void) iscsi_sess_destroy(isp);
1288277SJack.Meng@Sun.COM }
1298277SJack.Meng@Sun.COM
1307836SJohn.Forte@Sun.COM for (isp = ihp->hba_sess_list; isp; isp = isp->sess_next) {
1317836SJohn.Forte@Sun.COM /* Match target name and LSB ISID */
1327836SJohn.Forte@Sun.COM if ((strcmp((char *)isp->sess_name, target_name) == 0) &&
1337836SJohn.Forte@Sun.COM (isp->sess_isid[5] == isid_lsb)) {
1347836SJohn.Forte@Sun.COM
1357836SJohn.Forte@Sun.COM /* Match TPGT */
1367836SJohn.Forte@Sun.COM if (isp->sess_tpgt_conf == tpgt) {
1377836SJohn.Forte@Sun.COM /* Found mathing session, return oid/ptr */
1387836SJohn.Forte@Sun.COM *oid = isp->sess_oid;
13911476SBing.Zhao@Sun.COM if (isp->sess_wd_thread != NULL &&
14011476SBing.Zhao@Sun.COM isp->sess_ic_thread != NULL) {
1418277SJack.Meng@Sun.COM return (isp);
1428277SJack.Meng@Sun.COM }
14311476SBing.Zhao@Sun.COM
1448277SJack.Meng@Sun.COM if (isp->sess_wd_thread == NULL) {
14511476SBing.Zhao@Sun.COM /*
14611476SBing.Zhao@Sun.COM * Under rare cases wd thread is already
14711476SBing.Zhao@Sun.COM * freed, create it if so.
14811476SBing.Zhao@Sun.COM */
14911476SBing.Zhao@Sun.COM th_name = kmem_zalloc(
15011476SBing.Zhao@Sun.COM ISCSI_TH_MAX_NAME_LEN, KM_SLEEP);
15111476SBing.Zhao@Sun.COM if (snprintf(th_name,
15211476SBing.Zhao@Sun.COM (ISCSI_TH_MAX_NAME_LEN - 1),
15311476SBing.Zhao@Sun.COM ISCSI_SESS_WD_NAME_FORMAT,
15411476SBing.Zhao@Sun.COM ihp->hba_oid, isp->sess_oid) <
15511476SBing.Zhao@Sun.COM ISCSI_TH_MAX_NAME_LEN) {
15611476SBing.Zhao@Sun.COM isp->sess_wd_thread =
15711476SBing.Zhao@Sun.COM iscsi_thread_create(
15811476SBing.Zhao@Sun.COM ihp->hba_dip,
15911476SBing.Zhao@Sun.COM th_name,
16011476SBing.Zhao@Sun.COM iscsi_wd_thread,
16111476SBing.Zhao@Sun.COM isp);
16211476SBing.Zhao@Sun.COM (void) iscsi_thread_start(
16311476SBing.Zhao@Sun.COM isp->sess_wd_thread);
16411476SBing.Zhao@Sun.COM }
16511476SBing.Zhao@Sun.COM kmem_free(th_name,
16611476SBing.Zhao@Sun.COM ISCSI_TH_MAX_NAME_LEN);
16711476SBing.Zhao@Sun.COM if (isp->sess_wd_thread == NULL) {
16811476SBing.Zhao@Sun.COM /* No way to save it */
16911476SBing.Zhao@Sun.COM goto clean_failed_sess;
17011476SBing.Zhao@Sun.COM }
17111476SBing.Zhao@Sun.COM }
17211476SBing.Zhao@Sun.COM
17311476SBing.Zhao@Sun.COM if (isp->sess_ic_thread == NULL) {
17411476SBing.Zhao@Sun.COM status = iscsi_sess_threads_create(isp);
17511476SBing.Zhao@Sun.COM if (status != ISCSI_STATUS_SUCCESS) {
17611476SBing.Zhao@Sun.COM goto clean_failed_sess;
17711476SBing.Zhao@Sun.COM }
1788277SJack.Meng@Sun.COM }
1797836SJohn.Forte@Sun.COM return (isp);
1807836SJohn.Forte@Sun.COM }
1817836SJohn.Forte@Sun.COM
1827836SJohn.Forte@Sun.COM /*
1837836SJohn.Forte@Sun.COM * Also protect against creating duplicate
1847836SJohn.Forte@Sun.COM * sessions with different configured tpgt
1857836SJohn.Forte@Sun.COM * values. default vs. defined.
1867836SJohn.Forte@Sun.COM */
1877836SJohn.Forte@Sun.COM if ((((isp->sess_tpgt_conf == ISCSI_DEFAULT_TPGT) &&
1887836SJohn.Forte@Sun.COM (tpgt != ISCSI_DEFAULT_TPGT)) ||
1897836SJohn.Forte@Sun.COM ((isp->sess_tpgt_conf != ISCSI_DEFAULT_TPGT) &&
1907836SJohn.Forte@Sun.COM (tpgt == ISCSI_DEFAULT_TPGT)))) {
1917836SJohn.Forte@Sun.COM /* Dangerous configuration. Fail Request */
1927836SJohn.Forte@Sun.COM return (NULL);
1937836SJohn.Forte@Sun.COM }
1947836SJohn.Forte@Sun.COM }
1957836SJohn.Forte@Sun.COM }
1967836SJohn.Forte@Sun.COM
1977836SJohn.Forte@Sun.COM isp = (iscsi_sess_t *)kmem_zalloc(sizeof (iscsi_sess_t), KM_SLEEP);
1987836SJohn.Forte@Sun.COM /*
1997836SJohn.Forte@Sun.COM * If this session is not a Send Targets session, set the target
2007836SJohn.Forte@Sun.COM * that this session is associated with.
2017836SJohn.Forte@Sun.COM */
2027836SJohn.Forte@Sun.COM if (strncmp(target_name, SENDTARGETS_DISCOVERY,
2037836SJohn.Forte@Sun.COM strlen(SENDTARGETS_DISCOVERY))) {
2047836SJohn.Forte@Sun.COM isp->sess_target_oid = iscsi_targetparam_get_oid(
2057836SJohn.Forte@Sun.COM (uchar_t *)target_name);
2067836SJohn.Forte@Sun.COM }
2077836SJohn.Forte@Sun.COM
2088194SJack.Meng@Sun.COM if (method & iSCSIDiscoveryMethodBoot) {
2098194SJack.Meng@Sun.COM /* This is boot session. */
2108194SJack.Meng@Sun.COM isp->sess_boot = B_TRUE;
2118194SJack.Meng@Sun.COM } else {
2128194SJack.Meng@Sun.COM isp->sess_boot = B_FALSE;
2138194SJack.Meng@Sun.COM }
2148194SJack.Meng@Sun.COM
2157836SJohn.Forte@Sun.COM /* Associate session with this discovery method */
2168194SJack.Meng@Sun.COM method = method & ~(iSCSIDiscoveryMethodBoot);
2178194SJack.Meng@Sun.COM
2187836SJohn.Forte@Sun.COM isp->sess_discovered_by = method;
2197836SJohn.Forte@Sun.COM if (addr_dsc == NULL) {
2207836SJohn.Forte@Sun.COM bzero(&isp->sess_discovered_addr,
2217836SJohn.Forte@Sun.COM sizeof (isp->sess_discovered_addr));
2227836SJohn.Forte@Sun.COM } else {
2237836SJohn.Forte@Sun.COM bcopy(addr_dsc, &isp->sess_discovered_addr,
2247836SJohn.Forte@Sun.COM SIZEOF_SOCKADDR(addr_dsc));
2257836SJohn.Forte@Sun.COM }
2267836SJohn.Forte@Sun.COM
2277836SJohn.Forte@Sun.COM /* assign unique key for the session */
2287836SJohn.Forte@Sun.COM mutex_enter(&iscsi_oid_mutex);
2297836SJohn.Forte@Sun.COM isp->sess_oid = iscsi_oid++;
2307836SJohn.Forte@Sun.COM *oid = isp->sess_oid;
2317836SJohn.Forte@Sun.COM mutex_exit(&iscsi_oid_mutex);
2327836SJohn.Forte@Sun.COM
2337836SJohn.Forte@Sun.COM /* setup session parameters */
2347836SJohn.Forte@Sun.COM isp->sess_name_length = 0;
2357836SJohn.Forte@Sun.COM isp->sess_sig = ISCSI_SIG_SESS;
2367836SJohn.Forte@Sun.COM isp->sess_state = ISCSI_SESS_STATE_FREE;
237*12161SJack.Meng@Sun.COM rw_init(&isp->sess_state_rwlock, NULL, RW_DRIVER, NULL);
2389780SBing.Zhao@Sun.COM mutex_init(&isp->sess_reset_mutex, NULL, MUTEX_DRIVER, NULL);
2397836SJohn.Forte@Sun.COM isp->sess_hba = ihp;
2407836SJohn.Forte@Sun.COM
2417836SJohn.Forte@Sun.COM isp->sess_isid[0] = ISCSI_SUN_ISID_0;
2427836SJohn.Forte@Sun.COM isp->sess_isid[1] = ISCSI_SUN_ISID_1;
2437836SJohn.Forte@Sun.COM isp->sess_isid[2] = ISCSI_SUN_ISID_2;
2447836SJohn.Forte@Sun.COM isp->sess_isid[3] = ISCSI_SUN_ISID_3;
2457836SJohn.Forte@Sun.COM isp->sess_isid[4] = 0;
2467836SJohn.Forte@Sun.COM isp->sess_isid[5] = isid_lsb;
2477836SJohn.Forte@Sun.COM
2487836SJohn.Forte@Sun.COM isp->sess_cmdsn = 1;
2497836SJohn.Forte@Sun.COM isp->sess_expcmdsn = 1;
2507836SJohn.Forte@Sun.COM isp->sess_maxcmdsn = 1;
2517836SJohn.Forte@Sun.COM isp->sess_last_err = NoError;
2527836SJohn.Forte@Sun.COM isp->sess_tsid = 0;
2537836SJohn.Forte@Sun.COM isp->sess_type = type;
2549780SBing.Zhao@Sun.COM isp->sess_reset_in_progress = B_FALSE;
25511424SJack.Meng@Sun.COM isp->sess_boot_nic_reset = B_FALSE;
2569162SPeter.Dunlap@Sun.COM idm_sm_audit_init(&isp->sess_state_audit);
2577836SJohn.Forte@Sun.COM
2587836SJohn.Forte@Sun.COM /* copy default driver login parameters */
2597836SJohn.Forte@Sun.COM bcopy(&ihp->hba_params, &isp->sess_params,
2607836SJohn.Forte@Sun.COM sizeof (iscsi_login_params_t));
2617836SJohn.Forte@Sun.COM
2627836SJohn.Forte@Sun.COM /* copy target name into session */
2637836SJohn.Forte@Sun.COM bcopy((char *)target_name, isp->sess_name, len);
2647836SJohn.Forte@Sun.COM isp->sess_name_length = len;
2657836SJohn.Forte@Sun.COM isp->sess_tpgt_conf = tpgt;
2667836SJohn.Forte@Sun.COM isp->sess_tpgt_nego = ISCSI_DEFAULT_TPGT;
2677836SJohn.Forte@Sun.COM
2687836SJohn.Forte@Sun.COM /* initialize pending and completion queues */
2697836SJohn.Forte@Sun.COM iscsi_init_queue(&isp->sess_queue_pending);
2707836SJohn.Forte@Sun.COM iscsi_init_queue(&isp->sess_queue_completion);
2717836SJohn.Forte@Sun.COM
2727836SJohn.Forte@Sun.COM /* setup sessions lun list */
2737836SJohn.Forte@Sun.COM isp->sess_lun_list = NULL;
2747836SJohn.Forte@Sun.COM rw_init(&isp->sess_lun_list_rwlock, NULL, RW_DRIVER, NULL);
2757836SJohn.Forte@Sun.COM
2767836SJohn.Forte@Sun.COM /* setup sessions connection list */
2777836SJohn.Forte@Sun.COM isp->sess_conn_act = NULL;
2787836SJohn.Forte@Sun.COM isp->sess_conn_list = NULL;
2797836SJohn.Forte@Sun.COM rw_init(&isp->sess_conn_list_rwlock, NULL, RW_DRIVER, NULL);
2807836SJohn.Forte@Sun.COM
2817836SJohn.Forte@Sun.COM mutex_init(&isp->sess_cmdsn_mutex, NULL, MUTEX_DRIVER, NULL);
2827836SJohn.Forte@Sun.COM
2837836SJohn.Forte@Sun.COM /* create the session task queue */
2847836SJohn.Forte@Sun.COM tq_name = kmem_zalloc(ISCSI_TH_MAX_NAME_LEN, KM_SLEEP);
2857836SJohn.Forte@Sun.COM if (snprintf(tq_name, (ISCSI_TH_MAX_NAME_LEN - 1),
2867836SJohn.Forte@Sun.COM ISCSI_SESS_LOGIN_TASKQ_NAME_FORMAT, ihp->hba_oid, isp->sess_oid) <
2877836SJohn.Forte@Sun.COM ISCSI_TH_MAX_NAME_LEN) {
288*12161SJack.Meng@Sun.COM isp->sess_login_taskq = ddi_taskq_create(ihp->hba_dip,
289*12161SJack.Meng@Sun.COM tq_name, 1, TASKQ_DEFAULTPRI, 0);
290*12161SJack.Meng@Sun.COM }
291*12161SJack.Meng@Sun.COM if (isp->sess_login_taskq == NULL) {
292*12161SJack.Meng@Sun.COM kmem_free(tq_name, ISCSI_TH_MAX_NAME_LEN);
293*12161SJack.Meng@Sun.COM goto iscsi_sess_cleanup2;
294*12161SJack.Meng@Sun.COM }
295*12161SJack.Meng@Sun.COM
296*12161SJack.Meng@Sun.COM if (snprintf(tq_name, (ISCSI_TH_MAX_NAME_LEN - 1),
297*12161SJack.Meng@Sun.COM ISCSI_SESS_ENUM_TASKQ_NAME_FORMAT, ihp->hba_oid, isp->sess_oid) <
298*12161SJack.Meng@Sun.COM ISCSI_TH_MAX_NAME_LEN) {
299*12161SJack.Meng@Sun.COM isp->sess_enum_taskq = ddi_taskq_create(ihp->hba_dip,
3007836SJohn.Forte@Sun.COM tq_name, 1, TASKQ_DEFAULTPRI, 0);
3017836SJohn.Forte@Sun.COM }
3027836SJohn.Forte@Sun.COM kmem_free(tq_name, ISCSI_TH_MAX_NAME_LEN);
303*12161SJack.Meng@Sun.COM if (isp->sess_enum_taskq == NULL) {
304*12161SJack.Meng@Sun.COM goto iscsi_sess_cleanup1;
3057836SJohn.Forte@Sun.COM }
3067836SJohn.Forte@Sun.COM /* startup watchdog */
3077836SJohn.Forte@Sun.COM th_name = kmem_zalloc(ISCSI_TH_MAX_NAME_LEN, KM_SLEEP);
3087836SJohn.Forte@Sun.COM if (snprintf(th_name, (ISCSI_TH_MAX_NAME_LEN - 1),
3097836SJohn.Forte@Sun.COM ISCSI_SESS_WD_NAME_FORMAT, ihp->hba_oid, isp->sess_oid) <
3107836SJohn.Forte@Sun.COM ISCSI_TH_MAX_NAME_LEN) {
3117836SJohn.Forte@Sun.COM isp->sess_wd_thread = iscsi_thread_create(ihp->hba_dip,
3127836SJohn.Forte@Sun.COM th_name, iscsi_wd_thread, isp);
3137836SJohn.Forte@Sun.COM (void) iscsi_thread_start(isp->sess_wd_thread);
3147836SJohn.Forte@Sun.COM }
31511476SBing.Zhao@Sun.COM
3167836SJohn.Forte@Sun.COM kmem_free(th_name, ISCSI_TH_MAX_NAME_LEN);
3177836SJohn.Forte@Sun.COM if (isp->sess_wd_thread == NULL) {
318*12161SJack.Meng@Sun.COM goto iscsi_sess_cleanup0;
3197836SJohn.Forte@Sun.COM }
3207836SJohn.Forte@Sun.COM
32111476SBing.Zhao@Sun.COM status = iscsi_sess_threads_create(isp);
32211476SBing.Zhao@Sun.COM if (status != ISCSI_STATUS_SUCCESS) {
32311476SBing.Zhao@Sun.COM goto iscsi_sess_cleanup1;
32411476SBing.Zhao@Sun.COM }
32511476SBing.Zhao@Sun.COM
3267836SJohn.Forte@Sun.COM /* Add new target to the hba target list */
3277836SJohn.Forte@Sun.COM if (ihp->hba_sess_list == NULL) {
3287836SJohn.Forte@Sun.COM ihp->hba_sess_list = isp;
3297836SJohn.Forte@Sun.COM } else {
3307836SJohn.Forte@Sun.COM isp->sess_next = ihp->hba_sess_list;
3317836SJohn.Forte@Sun.COM ihp->hba_sess_list = isp;
3327836SJohn.Forte@Sun.COM }
3337836SJohn.Forte@Sun.COM KSTAT_INC_HBA_CNTR_SESS(ihp);
3347836SJohn.Forte@Sun.COM
3357836SJohn.Forte@Sun.COM (void) iscsi_sess_kstat_init(isp);
3367836SJohn.Forte@Sun.COM
337*12161SJack.Meng@Sun.COM if (type == ISCSI_SESS_TYPE_NORMAL) {
338*12161SJack.Meng@Sun.COM isp->sess_enum_status = ISCSI_SESS_ENUM_FREE;
339*12161SJack.Meng@Sun.COM isp->sess_enum_result = ISCSI_SESS_ENUM_COMPLETE;
340*12161SJack.Meng@Sun.COM isp->sess_enum_result_count = 0;
341*12161SJack.Meng@Sun.COM mutex_init(&isp->sess_enum_lock, NULL, MUTEX_DRIVER, NULL);
342*12161SJack.Meng@Sun.COM cv_init(&isp->sess_enum_cv, NULL, CV_DRIVER, NULL);
343*12161SJack.Meng@Sun.COM }
3447836SJohn.Forte@Sun.COM
345*12161SJack.Meng@Sun.COM mutex_init(&isp->sess_state_wmutex, NULL, MUTEX_DRIVER, NULL);
346*12161SJack.Meng@Sun.COM cv_init(&isp->sess_state_wcv, NULL, CV_DRIVER, NULL);
347*12161SJack.Meng@Sun.COM isp->sess_state_hasw = B_FALSE;
348*12161SJack.Meng@Sun.COM
349*12161SJack.Meng@Sun.COM isp->sess_state_event_count = 0;
350*12161SJack.Meng@Sun.COM
351*12161SJack.Meng@Sun.COM return (isp);
352*12161SJack.Meng@Sun.COM iscsi_sess_cleanup0:
353*12161SJack.Meng@Sun.COM ddi_taskq_destroy(isp->sess_enum_taskq);
3547836SJohn.Forte@Sun.COM iscsi_sess_cleanup1:
355*12161SJack.Meng@Sun.COM ddi_taskq_destroy(isp->sess_login_taskq);
3567836SJohn.Forte@Sun.COM iscsi_sess_cleanup2:
35711476SBing.Zhao@Sun.COM if (isp->sess_wd_thread != NULL) {
35811476SBing.Zhao@Sun.COM iscsi_thread_destroy(isp->sess_wd_thread);
35911476SBing.Zhao@Sun.COM isp->sess_wd_thread = NULL;
36011476SBing.Zhao@Sun.COM }
36111476SBing.Zhao@Sun.COM if (isp->sess_ic_thread != NULL) {
36211476SBing.Zhao@Sun.COM iscsi_thread_destroy(isp->sess_ic_thread);
36311476SBing.Zhao@Sun.COM isp->sess_ic_thread = NULL;
36411476SBing.Zhao@Sun.COM }
3657836SJohn.Forte@Sun.COM mutex_destroy(&isp->sess_cmdsn_mutex);
3667836SJohn.Forte@Sun.COM rw_destroy(&isp->sess_conn_list_rwlock);
3677836SJohn.Forte@Sun.COM rw_destroy(&isp->sess_lun_list_rwlock);
3687836SJohn.Forte@Sun.COM iscsi_destroy_queue(&isp->sess_queue_completion);
3697836SJohn.Forte@Sun.COM iscsi_destroy_queue(&isp->sess_queue_pending);
370*12161SJack.Meng@Sun.COM rw_destroy(&isp->sess_state_rwlock);
3719780SBing.Zhao@Sun.COM mutex_destroy(&isp->sess_reset_mutex);
3727836SJohn.Forte@Sun.COM kmem_free(isp, sizeof (iscsi_sess_t));
3737836SJohn.Forte@Sun.COM
3747836SJohn.Forte@Sun.COM return (NULL);
3757836SJohn.Forte@Sun.COM }
3767836SJohn.Forte@Sun.COM
3777836SJohn.Forte@Sun.COM /*
3787836SJohn.Forte@Sun.COM * iscsi_sess_get - return the session structure for based on a
3797836SJohn.Forte@Sun.COM * passed in oid and hba instance.
3807836SJohn.Forte@Sun.COM */
3817836SJohn.Forte@Sun.COM int
iscsi_sess_get(uint32_t oid,iscsi_hba_t * ihp,iscsi_sess_t ** ispp)3827836SJohn.Forte@Sun.COM iscsi_sess_get(uint32_t oid, iscsi_hba_t *ihp, iscsi_sess_t **ispp)
3837836SJohn.Forte@Sun.COM {
3847836SJohn.Forte@Sun.COM int rval = 0;
3857836SJohn.Forte@Sun.COM iscsi_sess_t *isp = NULL;
3867836SJohn.Forte@Sun.COM
3877836SJohn.Forte@Sun.COM ASSERT(ihp != NULL);
3887836SJohn.Forte@Sun.COM ASSERT(ispp != NULL);
3897836SJohn.Forte@Sun.COM
3907836SJohn.Forte@Sun.COM /* See if we already created this session */
3917836SJohn.Forte@Sun.COM for (isp = ihp->hba_sess_list; isp; isp = isp->sess_next) {
3927836SJohn.Forte@Sun.COM /* compare target name as the unique identifier */
3937836SJohn.Forte@Sun.COM if (isp->sess_oid == oid) {
3947836SJohn.Forte@Sun.COM /* Found matching session */
3957836SJohn.Forte@Sun.COM break;
3967836SJohn.Forte@Sun.COM }
3977836SJohn.Forte@Sun.COM }
3987836SJohn.Forte@Sun.COM
3997836SJohn.Forte@Sun.COM /* If not null this session is already available */
4007836SJohn.Forte@Sun.COM if (isp != NULL) {
4017836SJohn.Forte@Sun.COM /* Existing session, return it */
4027836SJohn.Forte@Sun.COM *ispp = isp;
4037836SJohn.Forte@Sun.COM } else {
4047836SJohn.Forte@Sun.COM rval = EFAULT;
4057836SJohn.Forte@Sun.COM }
4067836SJohn.Forte@Sun.COM return (rval);
4077836SJohn.Forte@Sun.COM }
4087836SJohn.Forte@Sun.COM
4097836SJohn.Forte@Sun.COM /*
4107836SJohn.Forte@Sun.COM * iscsi_sess_online - initiate online of sessions connections
4117836SJohn.Forte@Sun.COM */
4127836SJohn.Forte@Sun.COM void
iscsi_sess_online(void * arg)4138488SBing.Zhao@Sun.COM iscsi_sess_online(void *arg)
4147836SJohn.Forte@Sun.COM {
4158488SBing.Zhao@Sun.COM iscsi_sess_t *isp;
4167836SJohn.Forte@Sun.COM iscsi_hba_t *ihp;
4177836SJohn.Forte@Sun.COM iscsi_conn_t *icp;
4187836SJohn.Forte@Sun.COM int idx;
419*12161SJack.Meng@Sun.COM uint32_t event_count;
4207836SJohn.Forte@Sun.COM
4218488SBing.Zhao@Sun.COM isp = (iscsi_sess_t *)arg;
4228488SBing.Zhao@Sun.COM
4237836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
4247836SJohn.Forte@Sun.COM ihp = isp->sess_hba;
4257836SJohn.Forte@Sun.COM ASSERT(ihp != NULL);
4267836SJohn.Forte@Sun.COM
4277836SJohn.Forte@Sun.COM /*
4287836SJohn.Forte@Sun.COM * Stale /dev links can cause us to get floods
4297836SJohn.Forte@Sun.COM * of config requests. To prevent these repeated
4307836SJohn.Forte@Sun.COM * requests from causing unneeded login to the
4317836SJohn.Forte@Sun.COM * unreachable target, we won't try it during
4327836SJohn.Forte@Sun.COM * the delay.
4337836SJohn.Forte@Sun.COM */
4347836SJohn.Forte@Sun.COM if (ddi_get_lbolt() < isp->sess_failure_lbolt +
4357836SJohn.Forte@Sun.COM SEC_TO_TICK(isp->sess_storm_delay)) {
4367836SJohn.Forte@Sun.COM return;
4377836SJohn.Forte@Sun.COM }
4387836SJohn.Forte@Sun.COM
4397836SJohn.Forte@Sun.COM /*
4407836SJohn.Forte@Sun.COM * Perform a crude version of round robin to
4417836SJohn.Forte@Sun.COM * determine which connection to use for
4427836SJohn.Forte@Sun.COM * this session. Since byte 5 in session ID
4437836SJohn.Forte@Sun.COM * is overridden for full feature session,
4447836SJohn.Forte@Sun.COM * the connection to be selected depends on
4457836SJohn.Forte@Sun.COM * the result of sess_isid[5] devided by the
4467836SJohn.Forte@Sun.COM * next connection ID.
4477836SJohn.Forte@Sun.COM * If MS/T is enabled and there are multiple
4487836SJohn.Forte@Sun.COM * IPs are available on the target, we can
4497836SJohn.Forte@Sun.COM * select different IPs to connect in this
4507836SJohn.Forte@Sun.COM * way.
4517836SJohn.Forte@Sun.COM */
4527836SJohn.Forte@Sun.COM icp = isp->sess_conn_act;
4537836SJohn.Forte@Sun.COM if (icp == NULL) {
4547836SJohn.Forte@Sun.COM icp = isp->sess_conn_list;
4557836SJohn.Forte@Sun.COM for (idx = 0; idx < (isp->sess_isid[5] %
4567836SJohn.Forte@Sun.COM isp->sess_conn_next_cid); idx++) {
4577836SJohn.Forte@Sun.COM ASSERT(icp->conn_next != NULL);
4587836SJohn.Forte@Sun.COM icp = icp->conn_next;
4597836SJohn.Forte@Sun.COM }
4607836SJohn.Forte@Sun.COM isp->sess_conn_act = icp;
4617836SJohn.Forte@Sun.COM }
4627836SJohn.Forte@Sun.COM
4637836SJohn.Forte@Sun.COM if (icp == NULL) {
4647836SJohn.Forte@Sun.COM cmn_err(CE_NOTE, "iscsi session(%d) - "
4657836SJohn.Forte@Sun.COM "no connection assigned", isp->sess_oid);
4667836SJohn.Forte@Sun.COM return;
4677836SJohn.Forte@Sun.COM }
4687836SJohn.Forte@Sun.COM
4697836SJohn.Forte@Sun.COM /*
4707836SJohn.Forte@Sun.COM * If connection is in free state, start
4717836SJohn.Forte@Sun.COM * login. If already logged in, try to
4727836SJohn.Forte@Sun.COM * re-enumerate LUs on the session.
4737836SJohn.Forte@Sun.COM */
4747836SJohn.Forte@Sun.COM mutex_enter(&icp->conn_state_mutex);
4757836SJohn.Forte@Sun.COM if (icp->conn_state == ISCSI_CONN_STATE_FREE) {
4767836SJohn.Forte@Sun.COM /*
4777836SJohn.Forte@Sun.COM * attempt to login into the first connection in our connection
4787836SJohn.Forte@Sun.COM * list. If this fails, we will try the next connection
4797836SJohn.Forte@Sun.COM * in our list until end of the list.
4807836SJohn.Forte@Sun.COM */
4817836SJohn.Forte@Sun.COM while (icp != NULL) {
4829162SPeter.Dunlap@Sun.COM if (iscsi_conn_online(icp) == ISCSI_STATUS_SUCCESS) {
4837836SJohn.Forte@Sun.COM mutex_exit(&icp->conn_state_mutex);
4847836SJohn.Forte@Sun.COM break;
4857836SJohn.Forte@Sun.COM } else {
4867836SJohn.Forte@Sun.COM mutex_exit(&icp->conn_state_mutex);
4877836SJohn.Forte@Sun.COM icp = icp->conn_next;
4887836SJohn.Forte@Sun.COM if (icp != NULL) {
4897836SJohn.Forte@Sun.COM mutex_enter(&icp->conn_state_mutex);
4907836SJohn.Forte@Sun.COM }
4917836SJohn.Forte@Sun.COM }
4927836SJohn.Forte@Sun.COM }
4937836SJohn.Forte@Sun.COM isp->sess_conn_act = icp;
4947836SJohn.Forte@Sun.COM if (icp == NULL) {
4957836SJohn.Forte@Sun.COM /* the target for this session is unreachable */
4967836SJohn.Forte@Sun.COM isp->sess_failure_lbolt = ddi_get_lbolt();
4977836SJohn.Forte@Sun.COM if (isp->sess_storm_delay == 0) {
4987836SJohn.Forte@Sun.COM isp->sess_storm_delay++;
4997836SJohn.Forte@Sun.COM } else {
5007836SJohn.Forte@Sun.COM
5017836SJohn.Forte@Sun.COM if ((isp->sess_storm_delay * 2) <
5027836SJohn.Forte@Sun.COM iscsi_sess_max_delay) {
5037836SJohn.Forte@Sun.COM isp->sess_storm_delay =
5047836SJohn.Forte@Sun.COM isp->sess_storm_delay * 2;
5057836SJohn.Forte@Sun.COM } else {
5067836SJohn.Forte@Sun.COM isp->sess_storm_delay =
5077836SJohn.Forte@Sun.COM iscsi_sess_max_delay;
5087836SJohn.Forte@Sun.COM }
5097836SJohn.Forte@Sun.COM }
5107836SJohn.Forte@Sun.COM
5117836SJohn.Forte@Sun.COM } else {
5127836SJohn.Forte@Sun.COM isp->sess_storm_delay = 0;
5137836SJohn.Forte@Sun.COM isp->sess_failure_lbolt = 0;
5147836SJohn.Forte@Sun.COM }
5157836SJohn.Forte@Sun.COM } else if (icp->conn_state == ISCSI_CONN_STATE_LOGGED_IN) {
5167836SJohn.Forte@Sun.COM mutex_exit(&icp->conn_state_mutex);
517*12161SJack.Meng@Sun.COM event_count = atomic_inc_32_nv(&isp->sess_state_event_count);
518*12161SJack.Meng@Sun.COM iscsi_sess_enter_state_zone(isp);
5197836SJohn.Forte@Sun.COM iscsi_sess_state_machine(isp,
520*12161SJack.Meng@Sun.COM ISCSI_SESS_EVENT_N1, event_count);
521*12161SJack.Meng@Sun.COM iscsi_sess_exit_state_zone(isp);
5227836SJohn.Forte@Sun.COM } else {
5237836SJohn.Forte@Sun.COM mutex_exit(&icp->conn_state_mutex);
5247836SJohn.Forte@Sun.COM }
5257836SJohn.Forte@Sun.COM }
5267836SJohn.Forte@Sun.COM
5277836SJohn.Forte@Sun.COM /*
5287836SJohn.Forte@Sun.COM * iscsi_sess_destroy - Destroys a iscsi session structure
5297836SJohn.Forte@Sun.COM * and de-associates it from the hba.
5307836SJohn.Forte@Sun.COM */
5317836SJohn.Forte@Sun.COM iscsi_status_t
iscsi_sess_destroy(iscsi_sess_t * isp)5327836SJohn.Forte@Sun.COM iscsi_sess_destroy(iscsi_sess_t *isp)
5337836SJohn.Forte@Sun.COM {
5347836SJohn.Forte@Sun.COM iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
5358049SLarry.Liu@Sun.COM iscsi_status_t tmprval = ISCSI_STATUS_SUCCESS;
5367836SJohn.Forte@Sun.COM iscsi_hba_t *ihp;
5377836SJohn.Forte@Sun.COM iscsi_sess_t *t_isp;
5387836SJohn.Forte@Sun.COM iscsi_lun_t *ilp;
5397836SJohn.Forte@Sun.COM iscsi_conn_t *icp;
5407836SJohn.Forte@Sun.COM
5417836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
5427836SJohn.Forte@Sun.COM ihp = isp->sess_hba;
5437836SJohn.Forte@Sun.COM ASSERT(ihp != NULL);
5447836SJohn.Forte@Sun.COM
5457836SJohn.Forte@Sun.COM /*
5467836SJohn.Forte@Sun.COM * The first step in tearing down the session
5477836SJohn.Forte@Sun.COM * has to be offlining all the LUNs. This will
5487836SJohn.Forte@Sun.COM * ensure there is no outstanding IO by upper
5497836SJohn.Forte@Sun.COM * level drivers. If this fails then we are
5507836SJohn.Forte@Sun.COM * unable to destroy the session.
5518049SLarry.Liu@Sun.COM *
5528049SLarry.Liu@Sun.COM * Try all luns and continue upon failure
5538049SLarry.Liu@Sun.COM * to remove what is removable before returning
5548049SLarry.Liu@Sun.COM * the last error.
5557836SJohn.Forte@Sun.COM */
5567836SJohn.Forte@Sun.COM rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
5577836SJohn.Forte@Sun.COM ilp = isp->sess_lun_list;
5587836SJohn.Forte@Sun.COM while (ilp != NULL) {
5598049SLarry.Liu@Sun.COM iscsi_lun_t *ilp_next = ilp->lun_next;
5608049SLarry.Liu@Sun.COM
5618049SLarry.Liu@Sun.COM tmprval = iscsi_lun_destroy(ihp, ilp);
5628049SLarry.Liu@Sun.COM if (!ISCSI_SUCCESS(tmprval)) {
5638049SLarry.Liu@Sun.COM rval = tmprval;
5647836SJohn.Forte@Sun.COM }
5658049SLarry.Liu@Sun.COM ilp = ilp_next;
5667836SJohn.Forte@Sun.COM }
5677836SJohn.Forte@Sun.COM rw_exit(&isp->sess_lun_list_rwlock);
5687836SJohn.Forte@Sun.COM
5698049SLarry.Liu@Sun.COM if (!ISCSI_SUCCESS(rval)) {
5708049SLarry.Liu@Sun.COM return (rval);
5718049SLarry.Liu@Sun.COM }
5728049SLarry.Liu@Sun.COM
5737836SJohn.Forte@Sun.COM /* The next step is to logout of the connections. */
5749162SPeter.Dunlap@Sun.COM rw_enter(&isp->sess_conn_list_rwlock, RW_WRITER);
5757836SJohn.Forte@Sun.COM icp = isp->sess_conn_list;
5767836SJohn.Forte@Sun.COM while (icp != NULL) {
5777836SJohn.Forte@Sun.COM rval = iscsi_conn_offline(icp);
5787836SJohn.Forte@Sun.COM if (ISCSI_SUCCESS(rval)) {
5797836SJohn.Forte@Sun.COM /* Succes, Continue processing... */
5807836SJohn.Forte@Sun.COM icp = icp->conn_next;
5817836SJohn.Forte@Sun.COM } else {
5827836SJohn.Forte@Sun.COM /* Failure, Stop processing... */
5837836SJohn.Forte@Sun.COM rw_exit(&isp->sess_conn_list_rwlock);
5847836SJohn.Forte@Sun.COM return (rval);
5857836SJohn.Forte@Sun.COM }
5867836SJohn.Forte@Sun.COM }
5879162SPeter.Dunlap@Sun.COM rw_exit(&isp->sess_conn_list_rwlock);
5887836SJohn.Forte@Sun.COM
5897836SJohn.Forte@Sun.COM /*
5907836SJohn.Forte@Sun.COM * At this point all connections should be in
5917836SJohn.Forte@Sun.COM * a FREE state which will have pushed the session
5927836SJohn.Forte@Sun.COM * to a FREE state.
5937836SJohn.Forte@Sun.COM */
5949162SPeter.Dunlap@Sun.COM ASSERT(isp->sess_state == ISCSI_SESS_STATE_FREE ||
5959162SPeter.Dunlap@Sun.COM isp->sess_state == ISCSI_SESS_STATE_FAILED);
5967836SJohn.Forte@Sun.COM
5977836SJohn.Forte@Sun.COM /* Stop watchdog before destroying connections */
5988277SJack.Meng@Sun.COM if (isp->sess_wd_thread) {
5998277SJack.Meng@Sun.COM iscsi_thread_destroy(isp->sess_wd_thread);
6008277SJack.Meng@Sun.COM isp->sess_wd_thread = NULL;
6018277SJack.Meng@Sun.COM }
6027836SJohn.Forte@Sun.COM
6037836SJohn.Forte@Sun.COM /* Destroy connections */
6047836SJohn.Forte@Sun.COM rw_enter(&isp->sess_conn_list_rwlock, RW_WRITER);
6057836SJohn.Forte@Sun.COM icp = isp->sess_conn_list;
6067836SJohn.Forte@Sun.COM while (icp != NULL) {
6077836SJohn.Forte@Sun.COM rval = iscsi_conn_destroy(icp);
6087836SJohn.Forte@Sun.COM if (!ISCSI_SUCCESS(rval)) {
6097836SJohn.Forte@Sun.COM rw_exit(&isp->sess_conn_list_rwlock);
6107836SJohn.Forte@Sun.COM return (rval);
6117836SJohn.Forte@Sun.COM }
6127836SJohn.Forte@Sun.COM icp = isp->sess_conn_list;
6137836SJohn.Forte@Sun.COM }
6147836SJohn.Forte@Sun.COM rw_exit(&isp->sess_conn_list_rwlock);
6157836SJohn.Forte@Sun.COM
61611476SBing.Zhao@Sun.COM /* Destroy Session ic thread */
61711476SBing.Zhao@Sun.COM if (isp->sess_ic_thread != NULL) {
61811476SBing.Zhao@Sun.COM iscsi_thread_destroy(isp->sess_ic_thread);
61911476SBing.Zhao@Sun.COM isp->sess_ic_thread = NULL;
62011476SBing.Zhao@Sun.COM }
62111476SBing.Zhao@Sun.COM
6227836SJohn.Forte@Sun.COM /* Destroy session task queue */
623*12161SJack.Meng@Sun.COM ddi_taskq_destroy(isp->sess_enum_taskq);
624*12161SJack.Meng@Sun.COM ddi_taskq_destroy(isp->sess_login_taskq);
6257836SJohn.Forte@Sun.COM
6267836SJohn.Forte@Sun.COM /* destroy pending and completion queues */
6277836SJohn.Forte@Sun.COM iscsi_destroy_queue(&isp->sess_queue_pending);
6287836SJohn.Forte@Sun.COM iscsi_destroy_queue(&isp->sess_queue_completion);
6297836SJohn.Forte@Sun.COM
6307836SJohn.Forte@Sun.COM /* Remove session from ihp */
6317836SJohn.Forte@Sun.COM if (ihp->hba_sess_list == isp) {
6327836SJohn.Forte@Sun.COM /* session first item in list */
6337836SJohn.Forte@Sun.COM ihp->hba_sess_list = isp->sess_next;
6347836SJohn.Forte@Sun.COM } else {
6357836SJohn.Forte@Sun.COM /*
6367836SJohn.Forte@Sun.COM * search hba list for isp pointing
6377836SJohn.Forte@Sun.COM * to session being removed. Then
6387836SJohn.Forte@Sun.COM * update that sessions next pointer.
6397836SJohn.Forte@Sun.COM */
6407836SJohn.Forte@Sun.COM t_isp = ihp->hba_sess_list;
6417836SJohn.Forte@Sun.COM while (t_isp->sess_next != NULL) {
6427836SJohn.Forte@Sun.COM if (t_isp->sess_next == isp) {
6437836SJohn.Forte@Sun.COM break;
6447836SJohn.Forte@Sun.COM }
6457836SJohn.Forte@Sun.COM t_isp = t_isp->sess_next;
6467836SJohn.Forte@Sun.COM }
6477836SJohn.Forte@Sun.COM if (t_isp->sess_next == isp) {
6487836SJohn.Forte@Sun.COM t_isp->sess_next = isp->sess_next;
6497836SJohn.Forte@Sun.COM } else {
6507836SJohn.Forte@Sun.COM /* couldn't find session */
6517836SJohn.Forte@Sun.COM ASSERT(FALSE);
6527836SJohn.Forte@Sun.COM }
6537836SJohn.Forte@Sun.COM }
6547836SJohn.Forte@Sun.COM
655*12161SJack.Meng@Sun.COM if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
656*12161SJack.Meng@Sun.COM /* Wait for all enum requests complete */
657*12161SJack.Meng@Sun.COM mutex_enter(&isp->sess_enum_lock);
658*12161SJack.Meng@Sun.COM while (isp->sess_enum_result_count > 0) {
659*12161SJack.Meng@Sun.COM cv_wait(&isp->sess_enum_cv, &isp->sess_enum_lock);
660*12161SJack.Meng@Sun.COM }
661*12161SJack.Meng@Sun.COM mutex_exit(&isp->sess_enum_lock);
662*12161SJack.Meng@Sun.COM }
663*12161SJack.Meng@Sun.COM
6647836SJohn.Forte@Sun.COM /* Destroy this Sessions Data */
6657836SJohn.Forte@Sun.COM (void) iscsi_sess_kstat_term(isp);
6667836SJohn.Forte@Sun.COM rw_destroy(&isp->sess_lun_list_rwlock);
6677836SJohn.Forte@Sun.COM rw_destroy(&isp->sess_conn_list_rwlock);
6687836SJohn.Forte@Sun.COM mutex_destroy(&isp->sess_cmdsn_mutex);
669*12161SJack.Meng@Sun.COM rw_destroy(&isp->sess_state_rwlock);
6709780SBing.Zhao@Sun.COM mutex_destroy(&isp->sess_reset_mutex);
671*12161SJack.Meng@Sun.COM if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
672*12161SJack.Meng@Sun.COM mutex_destroy(&isp->sess_enum_lock);
673*12161SJack.Meng@Sun.COM cv_destroy(&isp->sess_enum_cv);
674*12161SJack.Meng@Sun.COM }
675*12161SJack.Meng@Sun.COM mutex_destroy(&isp->sess_state_wmutex);
676*12161SJack.Meng@Sun.COM cv_destroy(&isp->sess_state_wcv);
6777836SJohn.Forte@Sun.COM kmem_free(isp, sizeof (iscsi_sess_t));
6787836SJohn.Forte@Sun.COM return (rval);
6797836SJohn.Forte@Sun.COM }
6807836SJohn.Forte@Sun.COM
6818194SJack.Meng@Sun.COM extern ib_boot_prop_t *iscsiboot_prop;
6827836SJohn.Forte@Sun.COM /*
6837836SJohn.Forte@Sun.COM * static iscsi_sess_set_auth -
6847836SJohn.Forte@Sun.COM *
6857836SJohn.Forte@Sun.COM */
6867836SJohn.Forte@Sun.COM boolean_t
iscsi_sess_set_auth(iscsi_sess_t * isp)6877836SJohn.Forte@Sun.COM iscsi_sess_set_auth(iscsi_sess_t *isp)
6887836SJohn.Forte@Sun.COM {
6897836SJohn.Forte@Sun.COM char *init_name;
6907836SJohn.Forte@Sun.COM iscsi_chap_props_t *chap = NULL;
6917836SJohn.Forte@Sun.COM iscsi_auth_props_t *auth = NULL;
6928194SJack.Meng@Sun.COM uchar_t *tmp = NULL;
6937836SJohn.Forte@Sun.COM
6947836SJohn.Forte@Sun.COM if (isp == (iscsi_sess_t *)NULL) {
6957836SJohn.Forte@Sun.COM return (B_FALSE);
6967836SJohn.Forte@Sun.COM }
6977836SJohn.Forte@Sun.COM
6987836SJohn.Forte@Sun.COM /* Obtain initiator's name */
6997836SJohn.Forte@Sun.COM if (isp->sess_hba == (iscsi_hba_t *)NULL) {
7007836SJohn.Forte@Sun.COM return (B_FALSE);
7017836SJohn.Forte@Sun.COM }
7028194SJack.Meng@Sun.COM
7037836SJohn.Forte@Sun.COM init_name = (char *)isp->sess_hba->hba_name;
7047836SJohn.Forte@Sun.COM
7057836SJohn.Forte@Sun.COM /* Zero out the session authentication structure */
7067836SJohn.Forte@Sun.COM bzero(&isp->sess_auth, sizeof (iscsi_auth_t));
7077836SJohn.Forte@Sun.COM
7088194SJack.Meng@Sun.COM if (isp->sess_boot == B_FALSE) {
7098194SJack.Meng@Sun.COM
7108194SJack.Meng@Sun.COM auth = (iscsi_auth_props_t *)kmem_zalloc
7118194SJack.Meng@Sun.COM (sizeof (iscsi_auth_props_t), KM_SLEEP);
7128194SJack.Meng@Sun.COM /* Obtain target's authentication settings. */
7138194SJack.Meng@Sun.COM if (persistent_auth_get((char *)isp->sess_name, auth)
7148194SJack.Meng@Sun.COM != B_TRUE) {
7158194SJack.Meng@Sun.COM /*
7168194SJack.Meng@Sun.COM * If no target authentication settings found,
7178194SJack.Meng@Sun.COM * try to obtain system wide configuration
7188194SJack.Meng@Sun.COM * (from the initiator).
7198194SJack.Meng@Sun.COM */
7208194SJack.Meng@Sun.COM bzero(auth, sizeof (*auth));
7218194SJack.Meng@Sun.COM if (persistent_auth_get(init_name, auth) != B_TRUE) {
7228194SJack.Meng@Sun.COM bzero(auth, sizeof (*auth));
7238194SJack.Meng@Sun.COM auth->a_auth_method = authMethodNone;
7248194SJack.Meng@Sun.COM }
7258194SJack.Meng@Sun.COM
7268194SJack.Meng@Sun.COM /*
7278194SJack.Meng@Sun.COM * We do not support system wide bi-directional
7288194SJack.Meng@Sun.COM * auth flag.
7298194SJack.Meng@Sun.COM */
7308194SJack.Meng@Sun.COM auth->a_bi_auth = B_FALSE;
7318194SJack.Meng@Sun.COM }
7328194SJack.Meng@Sun.COM
7338194SJack.Meng@Sun.COM chap = (iscsi_chap_props_t *)kmem_zalloc
7348194SJack.Meng@Sun.COM (sizeof (iscsi_chap_props_t), KM_SLEEP);
7357836SJohn.Forte@Sun.COM
7368194SJack.Meng@Sun.COM /*
7378194SJack.Meng@Sun.COM * Initialize the target-side chap name to the session name
7388194SJack.Meng@Sun.COM * if no chap settings have been saved for the current session.
7398194SJack.Meng@Sun.COM */
7408194SJack.Meng@Sun.COM if (persistent_chap_get((char *)isp->sess_name, chap)
7418194SJack.Meng@Sun.COM == B_FALSE) {
7428194SJack.Meng@Sun.COM int name_len = strlen((char *)isp->sess_name);
7438194SJack.Meng@Sun.COM bcopy((char *)isp->sess_name, chap->c_user, name_len);
7448194SJack.Meng@Sun.COM chap->c_user_len = name_len;
7458194SJack.Meng@Sun.COM (void) (persistent_chap_set((char *)isp->sess_name,
7468194SJack.Meng@Sun.COM chap));
7478194SJack.Meng@Sun.COM bzero(chap, sizeof (*chap));
7488194SJack.Meng@Sun.COM }
7497836SJohn.Forte@Sun.COM
7508194SJack.Meng@Sun.COM if (auth->a_auth_method & authMethodCHAP) {
7518194SJack.Meng@Sun.COM /* Obtain initiator's CHAP settings. */
7528194SJack.Meng@Sun.COM if (persistent_chap_get(init_name, chap) == B_FALSE) {
7538194SJack.Meng@Sun.COM /* No initiator secret defined. */
7548194SJack.Meng@Sun.COM kmem_free(chap, sizeof (iscsi_chap_props_t));
7558194SJack.Meng@Sun.COM /* Set authentication method to NONE */
7568194SJack.Meng@Sun.COM isp->sess_auth.password_length = 0;
7578194SJack.Meng@Sun.COM kmem_free(auth, sizeof (iscsi_auth_props_t));
7588194SJack.Meng@Sun.COM return (B_FALSE);
7598194SJack.Meng@Sun.COM }
7608194SJack.Meng@Sun.COM
7618194SJack.Meng@Sun.COM bcopy(chap->c_user, isp->sess_auth.username,
7628194SJack.Meng@Sun.COM sizeof (chap->c_user));
7638194SJack.Meng@Sun.COM bcopy(chap->c_secret, isp->sess_auth.password,
7648194SJack.Meng@Sun.COM sizeof (chap->c_secret));
7658194SJack.Meng@Sun.COM isp->sess_auth.password_length = chap->c_secret_len;
7668194SJack.Meng@Sun.COM } else {
7677836SJohn.Forte@Sun.COM /* Set authentication method to NONE */
7687836SJohn.Forte@Sun.COM isp->sess_auth.password_length = 0;
7698194SJack.Meng@Sun.COM }
7708194SJack.Meng@Sun.COM
7718194SJack.Meng@Sun.COM /*
7728194SJack.Meng@Sun.COM * Consider enabling bidirectional authentication only if
7738194SJack.Meng@Sun.COM * authentication method is not NONE.
7748194SJack.Meng@Sun.COM */
7758194SJack.Meng@Sun.COM if (auth->a_auth_method & authMethodCHAP &&
7768194SJack.Meng@Sun.COM auth->a_bi_auth == B_TRUE) {
7778194SJack.Meng@Sun.COM /* Enable bi-directional authentication. */
7788194SJack.Meng@Sun.COM isp->sess_auth.bidirectional_auth = 1;
7798194SJack.Meng@Sun.COM
7808194SJack.Meng@Sun.COM bzero(chap, sizeof (*chap));
7818194SJack.Meng@Sun.COM /* Obtain target's CHAP settings. */
7828194SJack.Meng@Sun.COM if (persistent_chap_get((char *)isp->sess_name, chap)
7838194SJack.Meng@Sun.COM == B_TRUE) {
7848194SJack.Meng@Sun.COM bcopy(chap->c_secret,
7858194SJack.Meng@Sun.COM isp->sess_auth.password_in,
7868194SJack.Meng@Sun.COM sizeof (chap->c_secret));
7878194SJack.Meng@Sun.COM bcopy(chap->c_user, isp->sess_auth.username_in,
7888194SJack.Meng@Sun.COM strlen((char *)chap->c_user));
7898194SJack.Meng@Sun.COM isp->sess_auth.password_length_in =
7908194SJack.Meng@Sun.COM chap->c_secret_len;
7918194SJack.Meng@Sun.COM } else {
7928194SJack.Meng@Sun.COM /*
7938194SJack.Meng@Sun.COM * No target secret defined.
7948194SJack.Meng@Sun.COM * RADIUS server should have been enabled.
7958194SJack.Meng@Sun.COM */
7968194SJack.Meng@Sun.COM /* EMPTY */
7978194SJack.Meng@Sun.COM }
7988194SJack.Meng@Sun.COM } else {
7998194SJack.Meng@Sun.COM /* Disable bi-directional authentication */
8008194SJack.Meng@Sun.COM isp->sess_auth.bidirectional_auth = 0;
8018194SJack.Meng@Sun.COM }
8028194SJack.Meng@Sun.COM
8038194SJack.Meng@Sun.COM if (auth != NULL) {
8047836SJohn.Forte@Sun.COM kmem_free(auth, sizeof (iscsi_auth_props_t));
8058194SJack.Meng@Sun.COM }
8068194SJack.Meng@Sun.COM if (chap != NULL) {
8078194SJack.Meng@Sun.COM kmem_free(chap, sizeof (iscsi_chap_props_t));
8088194SJack.Meng@Sun.COM }
8098194SJack.Meng@Sun.COM } else {
8108194SJack.Meng@Sun.COM /*
8118194SJack.Meng@Sun.COM * This session is boot session. We will use the CHAP and
8128194SJack.Meng@Sun.COM * the user name got from the boot property structure instead
8138194SJack.Meng@Sun.COM * of persistent sotre.
8148194SJack.Meng@Sun.COM */
8158194SJack.Meng@Sun.COM if (iscsiboot_prop == NULL) {
8167836SJohn.Forte@Sun.COM return (B_FALSE);
8177836SJohn.Forte@Sun.COM }
8187836SJohn.Forte@Sun.COM
8198194SJack.Meng@Sun.COM if (iscsiboot_prop->boot_init.ini_chap_sec == NULL) {
8208194SJack.Meng@Sun.COM return (B_FALSE);
8218194SJack.Meng@Sun.COM }
8228194SJack.Meng@Sun.COM
8238194SJack.Meng@Sun.COM /* CHAP secret */
8248194SJack.Meng@Sun.COM (void) bcopy(iscsiboot_prop->boot_init.ini_chap_sec,
8258194SJack.Meng@Sun.COM isp->sess_auth.password,
8268194SJack.Meng@Sun.COM strlen((char *)iscsiboot_prop->boot_init.ini_chap_sec));
8277836SJohn.Forte@Sun.COM
8288194SJack.Meng@Sun.COM /*
8298194SJack.Meng@Sun.COM * If chap name is not set,
8308194SJack.Meng@Sun.COM * we will use initiator name instead.
8318194SJack.Meng@Sun.COM */
8328194SJack.Meng@Sun.COM if (iscsiboot_prop->boot_init.ini_chap_name == NULL) {
8338194SJack.Meng@Sun.COM (void) bcopy(init_name, isp->sess_auth.username,
8348194SJack.Meng@Sun.COM strlen(init_name));
8358194SJack.Meng@Sun.COM } else {
8368194SJack.Meng@Sun.COM tmp = iscsiboot_prop->boot_init.ini_chap_name;
8378194SJack.Meng@Sun.COM (void) bcopy(tmp,
8388194SJack.Meng@Sun.COM isp->sess_auth.username, strlen((char *)tmp));
8398194SJack.Meng@Sun.COM }
8408194SJack.Meng@Sun.COM
8418194SJack.Meng@Sun.COM isp->sess_auth.password_length =
8428194SJack.Meng@Sun.COM strlen((char *)iscsiboot_prop->boot_init.ini_chap_sec);
8437836SJohn.Forte@Sun.COM
8448194SJack.Meng@Sun.COM if (iscsiboot_prop->boot_tgt.tgt_chap_sec != NULL) {
8458194SJack.Meng@Sun.COM /*
8468194SJack.Meng@Sun.COM * Bidirectional authentication is required.
8478194SJack.Meng@Sun.COM */
8488194SJack.Meng@Sun.COM tmp = iscsiboot_prop->boot_tgt.tgt_chap_sec;
8498194SJack.Meng@Sun.COM (void) bcopy(tmp,
8508194SJack.Meng@Sun.COM isp->sess_auth.password_in, strlen((char *)tmp));
8518194SJack.Meng@Sun.COM
8527836SJohn.Forte@Sun.COM /*
8538194SJack.Meng@Sun.COM * If the target's chap name is not set, we will use
8548194SJack.Meng@Sun.COM * session name instead.
8557836SJohn.Forte@Sun.COM */
8568194SJack.Meng@Sun.COM if (iscsiboot_prop->boot_tgt.tgt_chap_name == NULL) {
8578194SJack.Meng@Sun.COM (void) bcopy(isp->sess_name,
8588194SJack.Meng@Sun.COM isp->sess_auth.username_in,
8598194SJack.Meng@Sun.COM isp->sess_name_length);
8608194SJack.Meng@Sun.COM } else {
8618194SJack.Meng@Sun.COM tmp = iscsiboot_prop->boot_tgt.tgt_chap_name;
8628194SJack.Meng@Sun.COM (void) bcopy(tmp,
8638194SJack.Meng@Sun.COM isp->sess_auth.username_in,
8648194SJack.Meng@Sun.COM strlen((char *)tmp));
8658194SJack.Meng@Sun.COM }
8668194SJack.Meng@Sun.COM tmp = iscsiboot_prop->boot_tgt.tgt_chap_sec;
8678194SJack.Meng@Sun.COM isp->sess_auth.password_length_in =
8688194SJack.Meng@Sun.COM strlen((char *)tmp);
8698194SJack.Meng@Sun.COM isp->sess_auth.bidirectional_auth = 1;
8707836SJohn.Forte@Sun.COM }
8717836SJohn.Forte@Sun.COM }
8727836SJohn.Forte@Sun.COM
8737836SJohn.Forte@Sun.COM /* Set up authentication buffers only if configured */
8747836SJohn.Forte@Sun.COM if ((isp->sess_auth.password_length != 0) ||
8757836SJohn.Forte@Sun.COM (isp->sess_auth.password_length_in != 0)) {
8767836SJohn.Forte@Sun.COM isp->sess_auth.num_auth_buffers = 5;
8777836SJohn.Forte@Sun.COM isp->sess_auth.auth_buffers[0].address =
8787836SJohn.Forte@Sun.COM &(isp->sess_auth.auth_client_block);
8797836SJohn.Forte@Sun.COM isp->sess_auth.auth_buffers[0].length =
8807836SJohn.Forte@Sun.COM sizeof (isp->sess_auth.auth_client_block);
8817836SJohn.Forte@Sun.COM isp->sess_auth.auth_buffers[1].address =
8827836SJohn.Forte@Sun.COM &(isp->sess_auth.auth_recv_string_block);
8837836SJohn.Forte@Sun.COM isp->sess_auth.auth_buffers[1].length =
8847836SJohn.Forte@Sun.COM sizeof (isp->sess_auth.auth_recv_string_block);
8857836SJohn.Forte@Sun.COM isp->sess_auth.auth_buffers[2].address =
8867836SJohn.Forte@Sun.COM &(isp->sess_auth.auth_send_string_block);
8877836SJohn.Forte@Sun.COM isp->sess_auth.auth_buffers[2].length =
8887836SJohn.Forte@Sun.COM sizeof (isp->sess_auth.auth_send_string_block);
8897836SJohn.Forte@Sun.COM isp->sess_auth.auth_buffers[3].address =
8907836SJohn.Forte@Sun.COM &(isp->sess_auth.auth_recv_binary_block);
8917836SJohn.Forte@Sun.COM isp->sess_auth.auth_buffers[3].length =
8927836SJohn.Forte@Sun.COM sizeof (isp->sess_auth.auth_recv_binary_block);
8937836SJohn.Forte@Sun.COM isp->sess_auth.auth_buffers[4].address =
8947836SJohn.Forte@Sun.COM &(isp->sess_auth.auth_send_binary_block);
8957836SJohn.Forte@Sun.COM isp->sess_auth.auth_buffers[4].length =
8967836SJohn.Forte@Sun.COM sizeof (isp->sess_auth.auth_send_binary_block);
8977836SJohn.Forte@Sun.COM }
8987836SJohn.Forte@Sun.COM
8997836SJohn.Forte@Sun.COM return (B_TRUE);
9007836SJohn.Forte@Sun.COM }
9017836SJohn.Forte@Sun.COM
9029162SPeter.Dunlap@Sun.COM /*
9039162SPeter.Dunlap@Sun.COM * iscsi_sess_reserve_itt - Used to reserve an ITT hash slot
9049162SPeter.Dunlap@Sun.COM */
9059162SPeter.Dunlap@Sun.COM iscsi_status_t
iscsi_sess_reserve_scsi_itt(iscsi_cmd_t * icmdp)9069162SPeter.Dunlap@Sun.COM iscsi_sess_reserve_scsi_itt(iscsi_cmd_t *icmdp)
9079162SPeter.Dunlap@Sun.COM {
9089162SPeter.Dunlap@Sun.COM idm_task_t *itp;
9099162SPeter.Dunlap@Sun.COM iscsi_conn_t *icp = icmdp->cmd_conn;
9109162SPeter.Dunlap@Sun.COM itp = idm_task_alloc(icp->conn_ic);
9119162SPeter.Dunlap@Sun.COM if (itp == NULL)
9129162SPeter.Dunlap@Sun.COM return (ISCSI_STATUS_INTERNAL_ERROR);
9139162SPeter.Dunlap@Sun.COM itp->idt_private = icmdp;
9149162SPeter.Dunlap@Sun.COM icmdp->cmd_itp = itp;
9159162SPeter.Dunlap@Sun.COM icmdp->cmd_itt = itp->idt_tt;
9169162SPeter.Dunlap@Sun.COM return (ISCSI_STATUS_SUCCESS);
9179162SPeter.Dunlap@Sun.COM }
9189162SPeter.Dunlap@Sun.COM
9199162SPeter.Dunlap@Sun.COM /*
9209162SPeter.Dunlap@Sun.COM * iscsi_sess_release_scsi_itt - Used to release ITT hash slot
9219162SPeter.Dunlap@Sun.COM */
9229162SPeter.Dunlap@Sun.COM void
iscsi_sess_release_scsi_itt(iscsi_cmd_t * icmdp)9239162SPeter.Dunlap@Sun.COM iscsi_sess_release_scsi_itt(iscsi_cmd_t *icmdp)
9249162SPeter.Dunlap@Sun.COM {
9259162SPeter.Dunlap@Sun.COM idm_task_free(icmdp->cmd_itp);
9269162SPeter.Dunlap@Sun.COM }
9277836SJohn.Forte@Sun.COM
9287836SJohn.Forte@Sun.COM /*
9297836SJohn.Forte@Sun.COM * iscsi_sess_reserve_itt - Used to reserve an ITT hash slot
9307836SJohn.Forte@Sun.COM */
9317836SJohn.Forte@Sun.COM iscsi_status_t
iscsi_sess_reserve_itt(iscsi_sess_t * isp,iscsi_cmd_t * icmdp)9327836SJohn.Forte@Sun.COM iscsi_sess_reserve_itt(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
9337836SJohn.Forte@Sun.COM {
9347836SJohn.Forte@Sun.COM /* If no more slots are open fail reservation */
9357836SJohn.Forte@Sun.COM if (isp->sess_cmd_table_count >= ISCSI_CMD_TABLE_SIZE) {
9367836SJohn.Forte@Sun.COM return (ISCSI_STATUS_ITT_TABLE_FULL);
9377836SJohn.Forte@Sun.COM }
9387836SJohn.Forte@Sun.COM
9397836SJohn.Forte@Sun.COM /*
9409162SPeter.Dunlap@Sun.COM * Keep itt values out of the range used by IDM
9419162SPeter.Dunlap@Sun.COM */
9429162SPeter.Dunlap@Sun.COM if (isp->sess_itt < IDM_TASKIDS_MAX)
9439162SPeter.Dunlap@Sun.COM isp->sess_itt = IDM_TASKIDS_MAX;
9449162SPeter.Dunlap@Sun.COM
9459162SPeter.Dunlap@Sun.COM /*
9467836SJohn.Forte@Sun.COM * Find the next available slot. Normally its the
9477836SJohn.Forte@Sun.COM * slot pointed to by the session's sess_itt value.
9487836SJohn.Forte@Sun.COM * If this is not true the table has become fragmented.
9497836SJohn.Forte@Sun.COM * Fragmentation can occur during max loads and IOs
9507836SJohn.Forte@Sun.COM * are completed out of order. Defragmentation will
9517836SJohn.Forte@Sun.COM * occur when IO slows down and ITT slots are released.
9527836SJohn.Forte@Sun.COM */
9537836SJohn.Forte@Sun.COM while (isp->sess_cmd_table[isp->sess_itt %
9547836SJohn.Forte@Sun.COM ISCSI_CMD_TABLE_SIZE] != NULL) {
9557836SJohn.Forte@Sun.COM isp->sess_itt++;
9567836SJohn.Forte@Sun.COM }
9577836SJohn.Forte@Sun.COM
9587836SJohn.Forte@Sun.COM /* reserve slot and update counters */
9597836SJohn.Forte@Sun.COM icmdp->cmd_itt = isp->sess_itt;
9609162SPeter.Dunlap@Sun.COM isp->sess_cmd_table[isp->sess_itt %
9617836SJohn.Forte@Sun.COM ISCSI_CMD_TABLE_SIZE] = icmdp;
9627836SJohn.Forte@Sun.COM isp->sess_cmd_table_count++;
9637836SJohn.Forte@Sun.COM isp->sess_itt++;
9647836SJohn.Forte@Sun.COM
9657836SJohn.Forte@Sun.COM return (ISCSI_STATUS_SUCCESS);
9667836SJohn.Forte@Sun.COM }
9677836SJohn.Forte@Sun.COM
9687836SJohn.Forte@Sun.COM /*
9697836SJohn.Forte@Sun.COM * iscsi_sess_release_itt - Used to release ITT hash slot
9707836SJohn.Forte@Sun.COM */
9717836SJohn.Forte@Sun.COM void
iscsi_sess_release_itt(iscsi_sess_t * isp,iscsi_cmd_t * icmdp)9727836SJohn.Forte@Sun.COM iscsi_sess_release_itt(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
9737836SJohn.Forte@Sun.COM {
9747836SJohn.Forte@Sun.COM int hash_index = (icmdp->cmd_itt % ISCSI_CMD_TABLE_SIZE);
9757836SJohn.Forte@Sun.COM
9767836SJohn.Forte@Sun.COM ASSERT(isp->sess_cmd_table[hash_index] != NULL);
9777836SJohn.Forte@Sun.COM
9787836SJohn.Forte@Sun.COM /* release slot and update counters */
9797836SJohn.Forte@Sun.COM isp->sess_cmd_table[hash_index] = NULL;
9807836SJohn.Forte@Sun.COM isp->sess_cmd_table_count--;
9817836SJohn.Forte@Sun.COM }
9827836SJohn.Forte@Sun.COM
9837836SJohn.Forte@Sun.COM /*
9847836SJohn.Forte@Sun.COM * iscsi_sess_redrive_io - Used to redrive IO on connections in
9857836SJohn.Forte@Sun.COM * a full feature state.
9867836SJohn.Forte@Sun.COM */
9877836SJohn.Forte@Sun.COM void
iscsi_sess_redrive_io(iscsi_sess_t * isp)9887836SJohn.Forte@Sun.COM iscsi_sess_redrive_io(iscsi_sess_t *isp)
9897836SJohn.Forte@Sun.COM {
9907836SJohn.Forte@Sun.COM iscsi_conn_t *icp;
9917836SJohn.Forte@Sun.COM
9927836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
9937836SJohn.Forte@Sun.COM
9947836SJohn.Forte@Sun.COM icp = isp->sess_conn_list;
9957836SJohn.Forte@Sun.COM while (icp != NULL) {
9967836SJohn.Forte@Sun.COM if (ISCSI_CONN_STATE_FULL_FEATURE(
9977836SJohn.Forte@Sun.COM icp->conn_state)) {
99810185SJack.Meng@Sun.COM (void) iscsi_thread_send_wakeup(
9997836SJohn.Forte@Sun.COM icp->conn_tx_thread);
10007836SJohn.Forte@Sun.COM }
10017836SJohn.Forte@Sun.COM icp = icp->conn_next;
10027836SJohn.Forte@Sun.COM }
10037836SJohn.Forte@Sun.COM }
10047836SJohn.Forte@Sun.COM
10057836SJohn.Forte@Sun.COM /*
10067836SJohn.Forte@Sun.COM * iscsi_sess_state_machine -
10077836SJohn.Forte@Sun.COM *
10087836SJohn.Forte@Sun.COM * 7.3.1 Session State Diagram for an Initiator
10097836SJohn.Forte@Sun.COM *
10107836SJohn.Forte@Sun.COM * Symbolic Names for States:
10117836SJohn.Forte@Sun.COM * Q1: FREE - State on instantiation of after cleanup
10127836SJohn.Forte@Sun.COM * Q3: LOGGED_IN - Waiting for all session events.
10137836SJohn.Forte@Sun.COM * Q4: FAILED - Waiting for session recovery or session cont.
10147836SJohn.Forte@Sun.COM * Q5: IN_FLUSH - A login parameter has changed. We are in the
10157836SJohn.Forte@Sun.COM * process of flushing active, aborting, and
10167836SJohn.Forte@Sun.COM * completed queues. Once flushed the iscsi_ic_thread()
10177836SJohn.Forte@Sun.COM * will drop of drop connections (T14) and reconnect
10187836SJohn.Forte@Sun.COM * to the target with new values.
10197836SJohn.Forte@Sun.COM * Q6: FLUSHED - Active, Aborting and Completed Queues flushed.
10207836SJohn.Forte@Sun.COM * Awaiting reconnect or failure. iscsi_tx/ic_threads
10217836SJohn.Forte@Sun.COM * are still running and might be timing-out IOs.
10227836SJohn.Forte@Sun.COM * State Q3/4 represent the Full Feature Phase operation of the session.
10237836SJohn.Forte@Sun.COM *
10247836SJohn.Forte@Sun.COM * The state diagram is as follows:
10257836SJohn.Forte@Sun.COM *
102612001SZhang.Yi@Sun.COM * ------ (N5/6/7 == NOOP)
102712001SZhang.Yi@Sun.COM * / Q1 \
102812001SZhang.Yi@Sun.COM * +------------------------->\ /<-------------+
102912001SZhang.Yi@Sun.COM * | ---+--- |
103012001SZhang.Yi@Sun.COM * | N5 |N1 |
103112001SZhang.Yi@Sun.COM * | +------+ +-------------+ | |
103212001SZhang.Yi@Sun.COM * | | V V | V |
103312001SZhang.Yi@Sun.COM * | | ----+-- -----+ |
103412001SZhang.Yi@Sun.COM * |N6|N5/7 / Q4 \ / Q3 \(N6 == NOOP) |
103512001SZhang.Yi@Sun.COM * +--+-----\ /----+--->\ /-----+---------+
103612001SZhang.Yi@Sun.COM * | ------- /N1 -+---- | N3|
103712001SZhang.Yi@Sun.COM * | (N7 == NOOP) / N7| ^ N1/3/5| |
103812001SZhang.Yi@Sun.COM * | / | +-------+ |
103912001SZhang.Yi@Sun.COM * | +-------+ / | |
104012001SZhang.Yi@Sun.COM * | | V / v |
104112001SZhang.Yi@Sun.COM * | | ------- -+---- |
104212001SZhang.Yi@Sun.COM * |N6|N6 / Q6 \ N5 / Q5 \ |
104312001SZhang.Yi@Sun.COM * +--+-----\ /<--------\ /-----+---------+
104412001SZhang.Yi@Sun.COM * ------- ------ | N3
104512001SZhang.Yi@Sun.COM * (N7 == NOOP) ^ N1/3/5|
104612001SZhang.Yi@Sun.COM * +-------+
10477836SJohn.Forte@Sun.COM *
10487836SJohn.Forte@Sun.COM * The state transition table is as follows:
10497836SJohn.Forte@Sun.COM *
105012001SZhang.Yi@Sun.COM * +------+------+----+--------+----+
105112001SZhang.Yi@Sun.COM * |Q1 |Q3 |Q4 |Q5 |Q6 |
105212001SZhang.Yi@Sun.COM * -----+------+------+----+--------+----+
105312001SZhang.Yi@Sun.COM * Q1 |N5/6/7|N1 | - | | |
105412001SZhang.Yi@Sun.COM * -----+------+------+----+--------+----+
105512001SZhang.Yi@Sun.COM * Q3 |N3 |N1/3/5|N5 |N7 | |
105612001SZhang.Yi@Sun.COM * -----+------+------+----+--------+----+
105712001SZhang.Yi@Sun.COM * Q4 |N6 |N1 |N5/7| | |
105812001SZhang.Yi@Sun.COM * -----+------+------+----+--------+----+
105912001SZhang.Yi@Sun.COM * Q5 |N3 | | |N1/3/5/7|N6 |
106012001SZhang.Yi@Sun.COM * -----+------+------+----+--------+----+
106112001SZhang.Yi@Sun.COM * Q6 |N6 |N1 |N6/7| | |
106212001SZhang.Yi@Sun.COM * -----+------+------+----+--------+----+
10637836SJohn.Forte@Sun.COM *
10647836SJohn.Forte@Sun.COM * Event definitions:
10657836SJohn.Forte@Sun.COM *
10667836SJohn.Forte@Sun.COM * -N1: A connection logged in
10677836SJohn.Forte@Sun.COM * -N3: A connection logged out
10687836SJohn.Forte@Sun.COM * -N5: A connection failed
10697836SJohn.Forte@Sun.COM * -N6: Session state timeout occurred, or a session
10707836SJohn.Forte@Sun.COM * reinstatement cleared this session instance. This results in
10717836SJohn.Forte@Sun.COM * the freeing of all associated resources and the session state
10727836SJohn.Forte@Sun.COM * is discarded.
10737836SJohn.Forte@Sun.COM * -N7: Login parameters for session have changed.
10747836SJohn.Forte@Sun.COM * Re-negeotation required.
1075*12161SJack.Meng@Sun.COM *
1076*12161SJack.Meng@Sun.COM * Any caller to the state machine (and so as a state writer) must
1077*12161SJack.Meng@Sun.COM * enter the state zone before calling this function, and vice versa
1078*12161SJack.Meng@Sun.COM * any caller that doesn't change the state machine shouldn't enter
1079*12161SJack.Meng@Sun.COM * the zone, and should act as a reader for a better performance.
1080*12161SJack.Meng@Sun.COM *
1081*12161SJack.Meng@Sun.COM * The handler of state transition shouldn't try to enter the state
1082*12161SJack.Meng@Sun.COM * zone in the same thread or dead lock will occur.
10837836SJohn.Forte@Sun.COM */
10847836SJohn.Forte@Sun.COM void
iscsi_sess_state_machine(iscsi_sess_t * isp,iscsi_sess_event_t event,uint32_t event_count)1085*12161SJack.Meng@Sun.COM iscsi_sess_state_machine(iscsi_sess_t *isp, iscsi_sess_event_t event,
1086*12161SJack.Meng@Sun.COM uint32_t event_count)
10877836SJohn.Forte@Sun.COM {
10887836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
1089*12161SJack.Meng@Sun.COM ASSERT(rw_read_locked(&isp->sess_state_rwlock) == 0);
10907836SJohn.Forte@Sun.COM
10917836SJohn.Forte@Sun.COM DTRACE_PROBE3(event, iscsi_sess_t *, isp,
10927836SJohn.Forte@Sun.COM char *, iscsi_sess_state_str(isp->sess_state),
10937836SJohn.Forte@Sun.COM char *, iscsi_sess_event_str(event));
10947836SJohn.Forte@Sun.COM
10959162SPeter.Dunlap@Sun.COM /* Audit event */
10969162SPeter.Dunlap@Sun.COM idm_sm_audit_event(&isp->sess_state_audit,
10979162SPeter.Dunlap@Sun.COM SAS_ISCSI_SESS, isp->sess_state, event, NULL);
10989162SPeter.Dunlap@Sun.COM
10997836SJohn.Forte@Sun.COM isp->sess_prev_state = isp->sess_state;
11007836SJohn.Forte@Sun.COM isp->sess_state_lbolt = ddi_get_lbolt();
11017836SJohn.Forte@Sun.COM
11029162SPeter.Dunlap@Sun.COM ISCSI_SESS_LOG(CE_NOTE,
1103*12161SJack.Meng@Sun.COM "DEBUG: sess_state: isp: %p state: %d event: %d event count: %d",
1104*12161SJack.Meng@Sun.COM (void *)isp, isp->sess_state, event, event_count);
11057836SJohn.Forte@Sun.COM switch (isp->sess_state) {
11067836SJohn.Forte@Sun.COM case ISCSI_SESS_STATE_FREE:
1107*12161SJack.Meng@Sun.COM iscsi_sess_state_free(isp, event, event_count);
11087836SJohn.Forte@Sun.COM break;
11097836SJohn.Forte@Sun.COM case ISCSI_SESS_STATE_LOGGED_IN:
1110*12161SJack.Meng@Sun.COM iscsi_sess_state_logged_in(isp, event, event_count);
11117836SJohn.Forte@Sun.COM break;
11127836SJohn.Forte@Sun.COM case ISCSI_SESS_STATE_FAILED:
1113*12161SJack.Meng@Sun.COM iscsi_sess_state_failed(isp, event, event_count);
11147836SJohn.Forte@Sun.COM break;
11157836SJohn.Forte@Sun.COM case ISCSI_SESS_STATE_IN_FLUSH:
1116*12161SJack.Meng@Sun.COM iscsi_sess_state_in_flush(isp, event, event_count);
11177836SJohn.Forte@Sun.COM break;
11187836SJohn.Forte@Sun.COM case ISCSI_SESS_STATE_FLUSHED:
1119*12161SJack.Meng@Sun.COM iscsi_sess_state_flushed(isp, event, event_count);
11207836SJohn.Forte@Sun.COM break;
11217836SJohn.Forte@Sun.COM default:
11227836SJohn.Forte@Sun.COM ASSERT(FALSE);
11237836SJohn.Forte@Sun.COM }
11249162SPeter.Dunlap@Sun.COM
11259162SPeter.Dunlap@Sun.COM /* Audit state change */
11269162SPeter.Dunlap@Sun.COM if (isp->sess_prev_state != isp->sess_state) {
11279162SPeter.Dunlap@Sun.COM idm_sm_audit_state_change(&isp->sess_state_audit,
11289162SPeter.Dunlap@Sun.COM SAS_ISCSI_SESS, isp->sess_prev_state, isp->sess_state);
11299162SPeter.Dunlap@Sun.COM }
11307836SJohn.Forte@Sun.COM }
11317836SJohn.Forte@Sun.COM
11327836SJohn.Forte@Sun.COM
11337836SJohn.Forte@Sun.COM /*
11347836SJohn.Forte@Sun.COM * iscsi_sess_state_str -
11357836SJohn.Forte@Sun.COM *
11367836SJohn.Forte@Sun.COM */
11377836SJohn.Forte@Sun.COM char *
iscsi_sess_state_str(iscsi_sess_state_t state)11387836SJohn.Forte@Sun.COM iscsi_sess_state_str(iscsi_sess_state_t state)
11397836SJohn.Forte@Sun.COM {
11407836SJohn.Forte@Sun.COM switch (state) {
11417836SJohn.Forte@Sun.COM case ISCSI_SESS_STATE_FREE:
11427836SJohn.Forte@Sun.COM return ("free");
11437836SJohn.Forte@Sun.COM case ISCSI_SESS_STATE_LOGGED_IN:
11447836SJohn.Forte@Sun.COM return ("logged_in");
11457836SJohn.Forte@Sun.COM case ISCSI_SESS_STATE_FAILED:
11467836SJohn.Forte@Sun.COM return ("failed");
11477836SJohn.Forte@Sun.COM case ISCSI_SESS_STATE_IN_FLUSH:
11487836SJohn.Forte@Sun.COM return ("in_flush");
11497836SJohn.Forte@Sun.COM case ISCSI_SESS_STATE_FLUSHED:
11507836SJohn.Forte@Sun.COM return ("flushed");
11517836SJohn.Forte@Sun.COM default:
11527836SJohn.Forte@Sun.COM return ("unknown");
11537836SJohn.Forte@Sun.COM }
11547836SJohn.Forte@Sun.COM }
11557836SJohn.Forte@Sun.COM
11567836SJohn.Forte@Sun.COM
11577836SJohn.Forte@Sun.COM /*
11587836SJohn.Forte@Sun.COM * +--------------------------------------------------------------------+
11597836SJohn.Forte@Sun.COM * | Internal Session Interfaces |
11607836SJohn.Forte@Sun.COM * +--------------------------------------------------------------------+
11617836SJohn.Forte@Sun.COM */
11627836SJohn.Forte@Sun.COM
11637836SJohn.Forte@Sun.COM
11647836SJohn.Forte@Sun.COM /*
11657836SJohn.Forte@Sun.COM * iscsi_sess_state_free -
11667836SJohn.Forte@Sun.COM *
11677836SJohn.Forte@Sun.COM */
11687836SJohn.Forte@Sun.COM static void
iscsi_sess_state_free(iscsi_sess_t * isp,iscsi_sess_event_t event,uint32_t event_count)1169*12161SJack.Meng@Sun.COM iscsi_sess_state_free(iscsi_sess_t *isp, iscsi_sess_event_t event,
1170*12161SJack.Meng@Sun.COM uint32_t event_count)
11717836SJohn.Forte@Sun.COM {
11727836SJohn.Forte@Sun.COM iscsi_hba_t *ihp;
1173*12161SJack.Meng@Sun.COM iscsi_enum_result_t enum_result;
11747836SJohn.Forte@Sun.COM
11757836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
11767836SJohn.Forte@Sun.COM ihp = isp->sess_hba;
11777836SJohn.Forte@Sun.COM ASSERT(ihp != NULL);
11787836SJohn.Forte@Sun.COM ASSERT(isp->sess_state == ISCSI_SESS_STATE_FREE);
11797836SJohn.Forte@Sun.COM
11807836SJohn.Forte@Sun.COM /* switch on event change */
11817836SJohn.Forte@Sun.COM switch (event) {
11827836SJohn.Forte@Sun.COM /*
11837836SJohn.Forte@Sun.COM * -N1: A connection logged in
11847836SJohn.Forte@Sun.COM */
11857836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N1:
118611476SBing.Zhao@Sun.COM isp->sess_state = ISCSI_SESS_STATE_LOGGED_IN;
1187*12161SJack.Meng@Sun.COM rw_downgrade(&isp->sess_state_rwlock);
118811476SBing.Zhao@Sun.COM if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
118911476SBing.Zhao@Sun.COM cmn_err(CE_NOTE,
119011476SBing.Zhao@Sun.COM "!iscsi session(%u) %s online\n",
119111476SBing.Zhao@Sun.COM isp->sess_oid, isp->sess_name);
1192*12161SJack.Meng@Sun.COM enum_result =
1193*12161SJack.Meng@Sun.COM iscsi_sess_enum_request(isp, B_TRUE,
1194*12161SJack.Meng@Sun.COM event_count);
1195*12161SJack.Meng@Sun.COM if (enum_result == ISCSI_SESS_ENUM_SUBMITTED) {
1196*12161SJack.Meng@Sun.COM enum_result =
1197*12161SJack.Meng@Sun.COM iscsi_sess_enum_query(isp);
1198*12161SJack.Meng@Sun.COM }
1199*12161SJack.Meng@Sun.COM if (enum_result != ISCSI_SESS_ENUM_COMPLETE) {
1200*12161SJack.Meng@Sun.COM iscsi_sess_enum_warn(isp, enum_result);
12017836SJohn.Forte@Sun.COM }
12027836SJohn.Forte@Sun.COM }
12037836SJohn.Forte@Sun.COM break;
12047836SJohn.Forte@Sun.COM
12057836SJohn.Forte@Sun.COM /*
120612001SZhang.Yi@Sun.COM * -N5: A connection failed
120712001SZhang.Yi@Sun.COM */
120812001SZhang.Yi@Sun.COM case ISCSI_SESS_EVENT_N5:
120912001SZhang.Yi@Sun.COM /* NOOP - not connected */
121012001SZhang.Yi@Sun.COM break;
121112001SZhang.Yi@Sun.COM
121212001SZhang.Yi@Sun.COM /*
12137836SJohn.Forte@Sun.COM * -N6: Session state timeout occurred, or a session
12147836SJohn.Forte@Sun.COM * reinstatement cleared this session instance. This results in
12157836SJohn.Forte@Sun.COM * the freeing of all associated resources and the session state
12167836SJohn.Forte@Sun.COM * is discarded.
12177836SJohn.Forte@Sun.COM */
12187836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N6:
12197836SJohn.Forte@Sun.COM /* FALLTHRU */
12207836SJohn.Forte@Sun.COM
12217836SJohn.Forte@Sun.COM /*
12227836SJohn.Forte@Sun.COM * -N7: Login parameters for session have changed.
12237836SJohn.Forte@Sun.COM * Re-negeotation required.
12247836SJohn.Forte@Sun.COM */
12257836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N7:
12267836SJohn.Forte@Sun.COM /* NOOP - not connected */
12277836SJohn.Forte@Sun.COM break;
12287836SJohn.Forte@Sun.COM
12297836SJohn.Forte@Sun.COM /* All other events are invalid for this state */
12307836SJohn.Forte@Sun.COM default:
12317836SJohn.Forte@Sun.COM ASSERT(FALSE);
12327836SJohn.Forte@Sun.COM }
12337836SJohn.Forte@Sun.COM }
12347836SJohn.Forte@Sun.COM
12357836SJohn.Forte@Sun.COM
12367836SJohn.Forte@Sun.COM /*
12377836SJohn.Forte@Sun.COM * iscsi_sess_logged_in -
12387836SJohn.Forte@Sun.COM *
12397836SJohn.Forte@Sun.COM */
12407836SJohn.Forte@Sun.COM static void
iscsi_sess_state_logged_in(iscsi_sess_t * isp,iscsi_sess_event_t event,uint32_t event_count)1241*12161SJack.Meng@Sun.COM iscsi_sess_state_logged_in(iscsi_sess_t *isp, iscsi_sess_event_t event,
1242*12161SJack.Meng@Sun.COM uint32_t event_count)
12437836SJohn.Forte@Sun.COM {
1244*12161SJack.Meng@Sun.COM iscsi_enum_result_t enum_result;
12457836SJohn.Forte@Sun.COM
12467836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
12477836SJohn.Forte@Sun.COM ASSERT(isp->sess_state == ISCSI_SESS_STATE_LOGGED_IN);
12487836SJohn.Forte@Sun.COM
12497836SJohn.Forte@Sun.COM /* switch on event change */
12507836SJohn.Forte@Sun.COM switch (event) {
12517836SJohn.Forte@Sun.COM /*
12527836SJohn.Forte@Sun.COM * -N1: At least one transport connection reached the
12537836SJohn.Forte@Sun.COM * LOGGED_IN state
12547836SJohn.Forte@Sun.COM */
12557836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N1:
12567836SJohn.Forte@Sun.COM /*
12577836SJohn.Forte@Sun.COM * A different connection already logged in. If the
12587836SJohn.Forte@Sun.COM * session is NORMAL, just re-enumerate the session.
12597836SJohn.Forte@Sun.COM */
1260*12161SJack.Meng@Sun.COM if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
1261*12161SJack.Meng@Sun.COM rw_downgrade(&isp->sess_state_rwlock);
1262*12161SJack.Meng@Sun.COM enum_result =
1263*12161SJack.Meng@Sun.COM iscsi_sess_enum_request(isp, B_TRUE, event_count);
1264*12161SJack.Meng@Sun.COM if (enum_result == ISCSI_SESS_ENUM_SUBMITTED) {
1265*12161SJack.Meng@Sun.COM enum_result = iscsi_sess_enum_query(isp);
1266*12161SJack.Meng@Sun.COM }
1267*12161SJack.Meng@Sun.COM if (enum_result != ISCSI_SESS_ENUM_COMPLETE) {
1268*12161SJack.Meng@Sun.COM iscsi_sess_enum_warn(isp, enum_result);
1269*12161SJack.Meng@Sun.COM }
12707836SJohn.Forte@Sun.COM }
12717836SJohn.Forte@Sun.COM break;
12727836SJohn.Forte@Sun.COM
12737836SJohn.Forte@Sun.COM /*
12747836SJohn.Forte@Sun.COM * -N3: A connection logged out.
12757836SJohn.Forte@Sun.COM */
12767836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N3:
12777836SJohn.Forte@Sun.COM /* FALLTHRU */
12787836SJohn.Forte@Sun.COM
12797836SJohn.Forte@Sun.COM /*
12807836SJohn.Forte@Sun.COM * -N5: A connection failed
12817836SJohn.Forte@Sun.COM */
12827836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N5:
12837836SJohn.Forte@Sun.COM /*
12847836SJohn.Forte@Sun.COM * MC/S: If this is the last connection to
12857836SJohn.Forte@Sun.COM * fail then move the the failed state.
12867836SJohn.Forte@Sun.COM */
12877836SJohn.Forte@Sun.COM if (event == ISCSI_SESS_EVENT_N3) {
12887836SJohn.Forte@Sun.COM isp->sess_state = ISCSI_SESS_STATE_FREE;
12897836SJohn.Forte@Sun.COM } else {
12907836SJohn.Forte@Sun.COM isp->sess_state = ISCSI_SESS_STATE_FAILED;
12917836SJohn.Forte@Sun.COM }
1292*12161SJack.Meng@Sun.COM rw_downgrade(&isp->sess_state_rwlock);
12937836SJohn.Forte@Sun.COM
12947836SJohn.Forte@Sun.COM /* no longer connected reset nego tpgt */
12957836SJohn.Forte@Sun.COM isp->sess_tpgt_nego = ISCSI_DEFAULT_TPGT;
12967836SJohn.Forte@Sun.COM
12977836SJohn.Forte@Sun.COM iscsi_sess_flush(isp);
12987836SJohn.Forte@Sun.COM
12997836SJohn.Forte@Sun.COM if (event == ISCSI_SESS_EVENT_N3) {
13007836SJohn.Forte@Sun.COM if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
13017836SJohn.Forte@Sun.COM cmn_err(CE_NOTE,
13027836SJohn.Forte@Sun.COM "!iscsi session(%u) %s offline\n",
13037836SJohn.Forte@Sun.COM isp->sess_oid, isp->sess_name);
13047836SJohn.Forte@Sun.COM }
13058336SJack.Meng@Sun.COM /*
13068336SJack.Meng@Sun.COM * During the process of offlining the LUNs
13078336SJack.Meng@Sun.COM * our ic thread might be calling back into
13088336SJack.Meng@Sun.COM * the driver via a target driver failure
13098336SJack.Meng@Sun.COM * path to do a reset or something
13108336SJack.Meng@Sun.COM * we need to release the sess_state_mutex
13118336SJack.Meng@Sun.COM * while we are killing these threads so
13128336SJack.Meng@Sun.COM * they don't get deadlocked.
13138336SJack.Meng@Sun.COM */
13147836SJohn.Forte@Sun.COM iscsi_sess_offline_luns(isp);
13157836SJohn.Forte@Sun.COM }
13167836SJohn.Forte@Sun.COM
13179780SBing.Zhao@Sun.COM mutex_enter(&isp->sess_reset_mutex);
13189780SBing.Zhao@Sun.COM isp->sess_reset_in_progress = B_FALSE;
13199780SBing.Zhao@Sun.COM mutex_exit(&isp->sess_reset_mutex);
13209780SBing.Zhao@Sun.COM /* update busy luns if needed */
13219780SBing.Zhao@Sun.COM iscsi_sess_update_busy_luns(isp, B_TRUE);
13229780SBing.Zhao@Sun.COM
13237836SJohn.Forte@Sun.COM break;
13247836SJohn.Forte@Sun.COM
13257836SJohn.Forte@Sun.COM /*
13267836SJohn.Forte@Sun.COM * -N6: Session state timeout occurred, or a session
13277836SJohn.Forte@Sun.COM * reinstatement cleared this session instance. This results in
13287836SJohn.Forte@Sun.COM * the freeing of all associated resources and the session state
13297836SJohn.Forte@Sun.COM * is discarded.
13307836SJohn.Forte@Sun.COM */
13317836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N6:
13327836SJohn.Forte@Sun.COM /* NOOP - Not last connection */
13337836SJohn.Forte@Sun.COM break;
13347836SJohn.Forte@Sun.COM
13357836SJohn.Forte@Sun.COM /*
13367836SJohn.Forte@Sun.COM * -N7: Login parameters for session have changed.
13377836SJohn.Forte@Sun.COM * Re-negeotation required.
13387836SJohn.Forte@Sun.COM */
13397836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N7:
13407836SJohn.Forte@Sun.COM isp->sess_state = ISCSI_SESS_STATE_IN_FLUSH;
13417836SJohn.Forte@Sun.COM break;
13427836SJohn.Forte@Sun.COM
13437836SJohn.Forte@Sun.COM /* All other events are invalid for this state */
13447836SJohn.Forte@Sun.COM default:
13457836SJohn.Forte@Sun.COM ASSERT(FALSE);
13467836SJohn.Forte@Sun.COM }
13477836SJohn.Forte@Sun.COM }
13487836SJohn.Forte@Sun.COM
13497836SJohn.Forte@Sun.COM
13507836SJohn.Forte@Sun.COM /*
13517836SJohn.Forte@Sun.COM * iscsi_sess_state_failed -
13527836SJohn.Forte@Sun.COM *
13537836SJohn.Forte@Sun.COM */
13547836SJohn.Forte@Sun.COM static void
iscsi_sess_state_failed(iscsi_sess_t * isp,iscsi_sess_event_t event,uint32_t event_count)1355*12161SJack.Meng@Sun.COM iscsi_sess_state_failed(iscsi_sess_t *isp, iscsi_sess_event_t event,
1356*12161SJack.Meng@Sun.COM uint32_t event_count)
13577836SJohn.Forte@Sun.COM {
13587836SJohn.Forte@Sun.COM iscsi_hba_t *ihp;
1359*12161SJack.Meng@Sun.COM iscsi_enum_result_t enum_result;
13607836SJohn.Forte@Sun.COM
13617836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
13627836SJohn.Forte@Sun.COM ihp = isp->sess_hba;
13637836SJohn.Forte@Sun.COM ASSERT(ihp != NULL);
13647836SJohn.Forte@Sun.COM ASSERT(isp->sess_state == ISCSI_SESS_STATE_FAILED);
13657836SJohn.Forte@Sun.COM
13667836SJohn.Forte@Sun.COM /* switch on event change */
13677836SJohn.Forte@Sun.COM switch (event) {
13687836SJohn.Forte@Sun.COM /* -N1: A session continuation attempt succeeded */
13697836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N1:
137011476SBing.Zhao@Sun.COM isp->sess_state = ISCSI_SESS_STATE_LOGGED_IN;
1371*12161SJack.Meng@Sun.COM rw_downgrade(&isp->sess_state_rwlock);
1372*12161SJack.Meng@Sun.COM if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
1373*12161SJack.Meng@Sun.COM enum_result =
1374*12161SJack.Meng@Sun.COM iscsi_sess_enum_request(isp, B_TRUE,
1375*12161SJack.Meng@Sun.COM event_count);
1376*12161SJack.Meng@Sun.COM if (enum_result == ISCSI_SESS_ENUM_SUBMITTED) {
1377*12161SJack.Meng@Sun.COM enum_result =
1378*12161SJack.Meng@Sun.COM iscsi_sess_enum_query(isp);
137911476SBing.Zhao@Sun.COM }
1380*12161SJack.Meng@Sun.COM if (enum_result != ISCSI_SESS_ENUM_COMPLETE) {
1381*12161SJack.Meng@Sun.COM iscsi_sess_enum_warn(isp, enum_result);
1382*12161SJack.Meng@Sun.COM }
13837836SJohn.Forte@Sun.COM }
13847836SJohn.Forte@Sun.COM break;
13857836SJohn.Forte@Sun.COM
13867836SJohn.Forte@Sun.COM /*
138712001SZhang.Yi@Sun.COM * -N5: A connection failed
138812001SZhang.Yi@Sun.COM */
138912001SZhang.Yi@Sun.COM case ISCSI_SESS_EVENT_N5:
139012001SZhang.Yi@Sun.COM /* NOOP - not connected */
139112001SZhang.Yi@Sun.COM break;
139212001SZhang.Yi@Sun.COM
139312001SZhang.Yi@Sun.COM /*
13947836SJohn.Forte@Sun.COM * -N6: Session state timeout occurred, or a session
13957836SJohn.Forte@Sun.COM * reinstatement cleared this session instance. This results in
13967836SJohn.Forte@Sun.COM * the freeing of all associated resources and the session state
13977836SJohn.Forte@Sun.COM * is discarded.
13987836SJohn.Forte@Sun.COM */
13997836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N6:
14007836SJohn.Forte@Sun.COM isp->sess_state = ISCSI_SESS_STATE_FREE;
14017836SJohn.Forte@Sun.COM
14027836SJohn.Forte@Sun.COM if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
14037836SJohn.Forte@Sun.COM cmn_err(CE_NOTE, "!iscsi session(%u) %s offline\n",
14047836SJohn.Forte@Sun.COM isp->sess_oid, isp->sess_name);
14057836SJohn.Forte@Sun.COM }
14067836SJohn.Forte@Sun.COM
1407*12161SJack.Meng@Sun.COM rw_downgrade(&isp->sess_state_rwlock);
14087836SJohn.Forte@Sun.COM iscsi_sess_offline_luns(isp);
14097836SJohn.Forte@Sun.COM break;
14107836SJohn.Forte@Sun.COM
14117836SJohn.Forte@Sun.COM /*
14127836SJohn.Forte@Sun.COM * -N7: Login parameters for session have changed.
14137836SJohn.Forte@Sun.COM * Re-negeotation required.
14147836SJohn.Forte@Sun.COM */
14157836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N7:
14167836SJohn.Forte@Sun.COM /* NOOP - not connected */
14177836SJohn.Forte@Sun.COM break;
14187836SJohn.Forte@Sun.COM
14197836SJohn.Forte@Sun.COM /* All other events are invalid for this state */
14207836SJohn.Forte@Sun.COM default:
14217836SJohn.Forte@Sun.COM ASSERT(FALSE);
14227836SJohn.Forte@Sun.COM }
14237836SJohn.Forte@Sun.COM }
14247836SJohn.Forte@Sun.COM
14257836SJohn.Forte@Sun.COM /*
14267836SJohn.Forte@Sun.COM * iscsi_sess_state_in_flush -
14277836SJohn.Forte@Sun.COM *
14287836SJohn.Forte@Sun.COM */
1429*12161SJack.Meng@Sun.COM /* ARGSUSED */
14307836SJohn.Forte@Sun.COM static void
iscsi_sess_state_in_flush(iscsi_sess_t * isp,iscsi_sess_event_t event,uint32_t event_count)1431*12161SJack.Meng@Sun.COM iscsi_sess_state_in_flush(iscsi_sess_t *isp, iscsi_sess_event_t event,
1432*12161SJack.Meng@Sun.COM uint32_t event_count)
14337836SJohn.Forte@Sun.COM {
14347836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
14357836SJohn.Forte@Sun.COM ASSERT(isp->sess_state == ISCSI_SESS_STATE_IN_FLUSH);
14367836SJohn.Forte@Sun.COM
14377836SJohn.Forte@Sun.COM /* switch on event change */
14387836SJohn.Forte@Sun.COM switch (event) {
14397836SJohn.Forte@Sun.COM /* -N1: A session continuation attempt succeeded */
14407836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N1:
14417836SJohn.Forte@Sun.COM /* NOOP - connections already online */
14427836SJohn.Forte@Sun.COM break;
14437836SJohn.Forte@Sun.COM
14447836SJohn.Forte@Sun.COM /*
14457836SJohn.Forte@Sun.COM * -N3: A connection logged out.
14467836SJohn.Forte@Sun.COM */
14477836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N3:
14487836SJohn.Forte@Sun.COM /* FALLTHRU */
14497836SJohn.Forte@Sun.COM
14507836SJohn.Forte@Sun.COM /*
14517836SJohn.Forte@Sun.COM * -N5: A connection failed
14527836SJohn.Forte@Sun.COM */
14537836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N5:
14547836SJohn.Forte@Sun.COM /*
14557836SJohn.Forte@Sun.COM * MC/S: If this is the last connection to
14567836SJohn.Forte@Sun.COM * fail then move the the failed state.
14577836SJohn.Forte@Sun.COM */
14587836SJohn.Forte@Sun.COM if (event == ISCSI_SESS_EVENT_N3) {
14597836SJohn.Forte@Sun.COM isp->sess_state = ISCSI_SESS_STATE_FREE;
14607836SJohn.Forte@Sun.COM } else {
14617836SJohn.Forte@Sun.COM isp->sess_state = ISCSI_SESS_STATE_FLUSHED;
14627836SJohn.Forte@Sun.COM }
1463*12161SJack.Meng@Sun.COM rw_downgrade(&isp->sess_state_rwlock);
14647836SJohn.Forte@Sun.COM
14657836SJohn.Forte@Sun.COM /* no longer connected reset nego tpgt */
14667836SJohn.Forte@Sun.COM isp->sess_tpgt_nego = ISCSI_DEFAULT_TPGT;
14677836SJohn.Forte@Sun.COM iscsi_sess_flush(isp);
14687836SJohn.Forte@Sun.COM
14697836SJohn.Forte@Sun.COM if (event == ISCSI_SESS_EVENT_N3) {
14707836SJohn.Forte@Sun.COM if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
14717836SJohn.Forte@Sun.COM cmn_err(CE_NOTE,
14727836SJohn.Forte@Sun.COM "!iscsi session(%u) %s offline\n",
14737836SJohn.Forte@Sun.COM isp->sess_oid, isp->sess_name);
14747836SJohn.Forte@Sun.COM }
14758336SJack.Meng@Sun.COM /*
14768336SJack.Meng@Sun.COM * During the process of offlining the LUNs
14778336SJack.Meng@Sun.COM * our ic thread might be calling back into
14788336SJack.Meng@Sun.COM * the driver via a target driver failure
14798336SJack.Meng@Sun.COM * path to do a reset or something
14808336SJack.Meng@Sun.COM * we need to release the sess_state_mutex
14818336SJack.Meng@Sun.COM * while we are killing these threads so
14828336SJack.Meng@Sun.COM * they don't get deadlocked.
14838336SJack.Meng@Sun.COM */
14847836SJohn.Forte@Sun.COM iscsi_sess_offline_luns(isp);
14857836SJohn.Forte@Sun.COM }
14867836SJohn.Forte@Sun.COM
14879780SBing.Zhao@Sun.COM mutex_enter(&isp->sess_reset_mutex);
14889780SBing.Zhao@Sun.COM isp->sess_reset_in_progress = B_FALSE;
14899780SBing.Zhao@Sun.COM mutex_exit(&isp->sess_reset_mutex);
14909780SBing.Zhao@Sun.COM /* update busy luns if needed */
14919780SBing.Zhao@Sun.COM iscsi_sess_update_busy_luns(isp, B_TRUE);
14929780SBing.Zhao@Sun.COM
14937836SJohn.Forte@Sun.COM break;
14947836SJohn.Forte@Sun.COM
14957836SJohn.Forte@Sun.COM /*
14967836SJohn.Forte@Sun.COM * -N6: Session state timeout occurred, or a session
14977836SJohn.Forte@Sun.COM * reinstatement cleared this session instance. This results in
14987836SJohn.Forte@Sun.COM * the freeing of all associated resources and the session state
14997836SJohn.Forte@Sun.COM * is discarded.
15007836SJohn.Forte@Sun.COM */
15017836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N6:
15027836SJohn.Forte@Sun.COM /* NOOP - Not last connection */
15037836SJohn.Forte@Sun.COM break;
15047836SJohn.Forte@Sun.COM
15057836SJohn.Forte@Sun.COM /*
15067836SJohn.Forte@Sun.COM * -N7: Login parameters for session have changed.
15077836SJohn.Forte@Sun.COM * Re-negeotation required.
15087836SJohn.Forte@Sun.COM */
15097836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N7:
15107836SJohn.Forte@Sun.COM /* NOOP - Already attempting to update */
15117836SJohn.Forte@Sun.COM break;
15127836SJohn.Forte@Sun.COM
15137836SJohn.Forte@Sun.COM /* All other events are invalid for this state */
15147836SJohn.Forte@Sun.COM default:
15157836SJohn.Forte@Sun.COM ASSERT(FALSE);
15167836SJohn.Forte@Sun.COM }
15177836SJohn.Forte@Sun.COM }
15187836SJohn.Forte@Sun.COM
15197836SJohn.Forte@Sun.COM
15207836SJohn.Forte@Sun.COM /*
15217836SJohn.Forte@Sun.COM * iscsi_sess_state_flushed -
15227836SJohn.Forte@Sun.COM *
15237836SJohn.Forte@Sun.COM */
15247836SJohn.Forte@Sun.COM static void
iscsi_sess_state_flushed(iscsi_sess_t * isp,iscsi_sess_event_t event,uint32_t event_count)1525*12161SJack.Meng@Sun.COM iscsi_sess_state_flushed(iscsi_sess_t *isp, iscsi_sess_event_t event,
1526*12161SJack.Meng@Sun.COM uint32_t event_count)
15277836SJohn.Forte@Sun.COM {
15287836SJohn.Forte@Sun.COM iscsi_hba_t *ihp;
1529*12161SJack.Meng@Sun.COM iscsi_enum_result_t enum_result;
15307836SJohn.Forte@Sun.COM
15317836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
15327836SJohn.Forte@Sun.COM ASSERT(isp->sess_state == ISCSI_SESS_STATE_FLUSHED);
15337836SJohn.Forte@Sun.COM ihp = isp->sess_hba;
15347836SJohn.Forte@Sun.COM ASSERT(ihp != NULL);
15357836SJohn.Forte@Sun.COM
15367836SJohn.Forte@Sun.COM /* switch on event change */
15377836SJohn.Forte@Sun.COM switch (event) {
15387836SJohn.Forte@Sun.COM /* -N1: A session continuation attempt succeeded */
15397836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N1:
154011476SBing.Zhao@Sun.COM isp->sess_state = ISCSI_SESS_STATE_LOGGED_IN;
1541*12161SJack.Meng@Sun.COM rw_downgrade(&isp->sess_state_rwlock);
1542*12161SJack.Meng@Sun.COM if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
1543*12161SJack.Meng@Sun.COM enum_result =
1544*12161SJack.Meng@Sun.COM iscsi_sess_enum_request(isp, B_TRUE,
1545*12161SJack.Meng@Sun.COM event_count);
1546*12161SJack.Meng@Sun.COM if (enum_result == ISCSI_SESS_ENUM_SUBMITTED) {
1547*12161SJack.Meng@Sun.COM enum_result =
1548*12161SJack.Meng@Sun.COM iscsi_sess_enum_query(isp);
154911476SBing.Zhao@Sun.COM }
1550*12161SJack.Meng@Sun.COM if (enum_result != ISCSI_SESS_ENUM_COMPLETE) {
1551*12161SJack.Meng@Sun.COM iscsi_sess_enum_warn(isp, enum_result);
1552*12161SJack.Meng@Sun.COM }
15537836SJohn.Forte@Sun.COM }
15547836SJohn.Forte@Sun.COM break;
15557836SJohn.Forte@Sun.COM
15567836SJohn.Forte@Sun.COM /*
15577836SJohn.Forte@Sun.COM * -N6: Session state timeout occurred, or a session
15587836SJohn.Forte@Sun.COM * reinstatement cleared this session instance. This results in
15597836SJohn.Forte@Sun.COM * the freeing of all associated resources and the session state
15607836SJohn.Forte@Sun.COM * is discarded.
15617836SJohn.Forte@Sun.COM */
15627836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N6:
15637836SJohn.Forte@Sun.COM isp->sess_state = ISCSI_SESS_STATE_FREE;
1564*12161SJack.Meng@Sun.COM rw_downgrade(&isp->sess_state_rwlock);
15657836SJohn.Forte@Sun.COM
15667836SJohn.Forte@Sun.COM if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
15677836SJohn.Forte@Sun.COM cmn_err(CE_NOTE, "!iscsi session(%u) %s offline\n",
15687836SJohn.Forte@Sun.COM isp->sess_oid, isp->sess_name);
15697836SJohn.Forte@Sun.COM }
15707836SJohn.Forte@Sun.COM
15717836SJohn.Forte@Sun.COM iscsi_sess_offline_luns(isp);
15727836SJohn.Forte@Sun.COM break;
15737836SJohn.Forte@Sun.COM
15747836SJohn.Forte@Sun.COM /*
15757836SJohn.Forte@Sun.COM * -N7: Login parameters for session have changed.
15767836SJohn.Forte@Sun.COM * Re-negeotation required.
15777836SJohn.Forte@Sun.COM */
15787836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N7:
15797836SJohn.Forte@Sun.COM /* NOOP - not connected */
15807836SJohn.Forte@Sun.COM break;
15817836SJohn.Forte@Sun.COM
15827836SJohn.Forte@Sun.COM /* All other events are invalid for this state */
15837836SJohn.Forte@Sun.COM default:
15847836SJohn.Forte@Sun.COM ASSERT(FALSE);
15857836SJohn.Forte@Sun.COM }
15867836SJohn.Forte@Sun.COM }
15877836SJohn.Forte@Sun.COM
15887836SJohn.Forte@Sun.COM /*
15897836SJohn.Forte@Sun.COM * iscsi_sess_event_str -
15907836SJohn.Forte@Sun.COM *
15917836SJohn.Forte@Sun.COM */
15927836SJohn.Forte@Sun.COM static char *
iscsi_sess_event_str(iscsi_sess_event_t event)15937836SJohn.Forte@Sun.COM iscsi_sess_event_str(iscsi_sess_event_t event)
15947836SJohn.Forte@Sun.COM {
15957836SJohn.Forte@Sun.COM switch (event) {
15967836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N1:
15977836SJohn.Forte@Sun.COM return ("N1");
15987836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N3:
15997836SJohn.Forte@Sun.COM return ("N3");
16007836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N5:
16017836SJohn.Forte@Sun.COM return ("N5");
16027836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N6:
16037836SJohn.Forte@Sun.COM return ("N6");
16047836SJohn.Forte@Sun.COM case ISCSI_SESS_EVENT_N7:
16057836SJohn.Forte@Sun.COM return ("N7");
16067836SJohn.Forte@Sun.COM default:
16077836SJohn.Forte@Sun.COM return ("unknown");
16087836SJohn.Forte@Sun.COM }
16097836SJohn.Forte@Sun.COM }
16107836SJohn.Forte@Sun.COM
16117836SJohn.Forte@Sun.COM /*
16127836SJohn.Forte@Sun.COM * iscsi_sess_thread_create -
16137836SJohn.Forte@Sun.COM *
16147836SJohn.Forte@Sun.COM */
16157836SJohn.Forte@Sun.COM static iscsi_status_t
iscsi_sess_threads_create(iscsi_sess_t * isp)16167836SJohn.Forte@Sun.COM iscsi_sess_threads_create(iscsi_sess_t *isp)
16177836SJohn.Forte@Sun.COM {
16187836SJohn.Forte@Sun.COM iscsi_hba_t *ihp;
16197836SJohn.Forte@Sun.COM char th_name[ISCSI_TH_MAX_NAME_LEN];
16207836SJohn.Forte@Sun.COM
16217836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
16227836SJohn.Forte@Sun.COM ihp = isp->sess_hba;
16237836SJohn.Forte@Sun.COM ASSERT(ihp != NULL);
16247836SJohn.Forte@Sun.COM
16257836SJohn.Forte@Sun.COM /* Completion thread creation. */
16267836SJohn.Forte@Sun.COM if (snprintf(th_name, sizeof (th_name) - 1,
16277836SJohn.Forte@Sun.COM ISCSI_SESS_IOTH_NAME_FORMAT, ihp->hba_oid,
16287836SJohn.Forte@Sun.COM isp->sess_oid) >= sizeof (th_name)) {
16297836SJohn.Forte@Sun.COM return (ISCSI_STATUS_INTERNAL_ERROR);
16307836SJohn.Forte@Sun.COM }
16317836SJohn.Forte@Sun.COM
16327836SJohn.Forte@Sun.COM isp->sess_ic_thread = iscsi_thread_create(ihp->hba_dip,
16337836SJohn.Forte@Sun.COM th_name, iscsi_ic_thread, isp);
16347836SJohn.Forte@Sun.COM
16357836SJohn.Forte@Sun.COM if (isp->sess_ic_thread == NULL) {
16367836SJohn.Forte@Sun.COM return (ISCSI_STATUS_INTERNAL_ERROR);
16377836SJohn.Forte@Sun.COM }
16387836SJohn.Forte@Sun.COM
16397836SJohn.Forte@Sun.COM (void) iscsi_thread_start(isp->sess_ic_thread);
16407836SJohn.Forte@Sun.COM
16417836SJohn.Forte@Sun.COM return (ISCSI_STATUS_SUCCESS);
16427836SJohn.Forte@Sun.COM }
16437836SJohn.Forte@Sun.COM
16447836SJohn.Forte@Sun.COM /*
16457836SJohn.Forte@Sun.COM * iscsi_sess_enumeration - This function is used to drive the enumeration
16467836SJohn.Forte@Sun.COM * of LUs on a session. It will first prepare the target by sending test
16477836SJohn.Forte@Sun.COM * unit ready commands, then it will issue a report luns. If the report
16487836SJohn.Forte@Sun.COM * luns is successful then it will process all the luns in the report.
16497836SJohn.Forte@Sun.COM * If report luns is not successful we will do a stepping enumeration
16507836SJohn.Forte@Sun.COM * of luns until no more luns are found.
16517836SJohn.Forte@Sun.COM */
16527836SJohn.Forte@Sun.COM static void
iscsi_sess_enumeration(void * arg)16537836SJohn.Forte@Sun.COM iscsi_sess_enumeration(void *arg)
16547836SJohn.Forte@Sun.COM {
16557836SJohn.Forte@Sun.COM iscsi_task_t *itp = (iscsi_task_t *)arg;
16567836SJohn.Forte@Sun.COM iscsi_sess_t *isp;
16577836SJohn.Forte@Sun.COM iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
1658*12161SJack.Meng@Sun.COM iscsi_enum_result_t enum_result = ISCSI_SESS_ENUM_COMPLETE;
1659*12161SJack.Meng@Sun.COM uint32_t event_count = itp->t_event_count;
16607836SJohn.Forte@Sun.COM
16617836SJohn.Forte@Sun.COM ASSERT(itp != NULL);
16627836SJohn.Forte@Sun.COM isp = (iscsi_sess_t *)itp->t_arg;
16637836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
16647836SJohn.Forte@Sun.COM
16657836SJohn.Forte@Sun.COM /*
16667836SJohn.Forte@Sun.COM * Send initial TEST_UNIT_READY to target. If it fails this we
16677836SJohn.Forte@Sun.COM * stop our enumeration as the target is not responding properly.
16687836SJohn.Forte@Sun.COM */
1669*12161SJack.Meng@Sun.COM rval = iscsi_sess_testunitready(isp, event_count);
16707836SJohn.Forte@Sun.COM if (ISCSI_SUCCESS(rval)) {
16717836SJohn.Forte@Sun.COM /*
16727836SJohn.Forte@Sun.COM * Now we know the target is ready start our enumeration with
16737836SJohn.Forte@Sun.COM * REPORT LUNs, If this fails we will have to fall back to
16747836SJohn.Forte@Sun.COM * stepping
16757836SJohn.Forte@Sun.COM */
1676*12161SJack.Meng@Sun.COM rval = iscsi_sess_reportluns(isp, event_count);
16777836SJohn.Forte@Sun.COM if (!ISCSI_SUCCESS(rval)) {
16787836SJohn.Forte@Sun.COM /*
16797836SJohn.Forte@Sun.COM * report luns failed so lets just check for LUN 0.
16807836SJohn.Forte@Sun.COM * This will match fcp's enumeration support and
16817836SJohn.Forte@Sun.COM * avoid issues with older devices like the A5K that
16827836SJohn.Forte@Sun.COM * respond poorly.
16837836SJohn.Forte@Sun.COM */
16847836SJohn.Forte@Sun.COM if (isp->sess_lun_list == NULL) {
1685*12161SJack.Meng@Sun.COM iscsi_sess_inquiry(isp, 0, 0, event_count,
1686*12161SJack.Meng@Sun.COM NULL);
16877836SJohn.Forte@Sun.COM }
16887836SJohn.Forte@Sun.COM }
16897836SJohn.Forte@Sun.COM } else {
1690*12161SJack.Meng@Sun.COM enum_result = ISCSI_SESS_ENUM_TUR_FAIL;
16917836SJohn.Forte@Sun.COM }
16927836SJohn.Forte@Sun.COM
1693*12161SJack.Meng@Sun.COM kmem_free(itp, sizeof (iscsi_task_t));
1694*12161SJack.Meng@Sun.COM mutex_enter(&isp->sess_enum_lock);
1695*12161SJack.Meng@Sun.COM if (isp->sess_enum_result_count != 0) {
1696*12161SJack.Meng@Sun.COM isp->sess_enum_status = ISCSI_SESS_ENUM_DONE;
1697*12161SJack.Meng@Sun.COM } else {
1698*12161SJack.Meng@Sun.COM isp->sess_enum_status = ISCSI_SESS_ENUM_FREE;
16997836SJohn.Forte@Sun.COM }
1700*12161SJack.Meng@Sun.COM isp->sess_enum_result = enum_result;
1701*12161SJack.Meng@Sun.COM cv_broadcast(&isp->sess_enum_cv);
1702*12161SJack.Meng@Sun.COM mutex_exit(&isp->sess_enum_lock);
17037836SJohn.Forte@Sun.COM }
17047836SJohn.Forte@Sun.COM
17057836SJohn.Forte@Sun.COM /*
17067836SJohn.Forte@Sun.COM * iscsi_sess_testunitready - This is used during enumeration to
17077836SJohn.Forte@Sun.COM * ensure an array is ready to be enumerated.
17087836SJohn.Forte@Sun.COM */
17097836SJohn.Forte@Sun.COM static iscsi_status_t
iscsi_sess_testunitready(iscsi_sess_t * isp,uint32_t event_count)1710*12161SJack.Meng@Sun.COM iscsi_sess_testunitready(iscsi_sess_t *isp, uint32_t event_count)
17117836SJohn.Forte@Sun.COM {
17127836SJohn.Forte@Sun.COM iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
17137836SJohn.Forte@Sun.COM int retries = 0;
17147836SJohn.Forte@Sun.COM struct uscsi_cmd ucmd;
17157836SJohn.Forte@Sun.COM char cdb[CDB_GROUP0];
17167836SJohn.Forte@Sun.COM
17177836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
17187836SJohn.Forte@Sun.COM
17197836SJohn.Forte@Sun.COM /* loop until successful sending test unit ready or retries out */
1720*12161SJack.Meng@Sun.COM while ((retries++ < 3) &&
1721*12161SJack.Meng@Sun.COM (isp->sess_state_event_count == event_count)) {
17227836SJohn.Forte@Sun.COM /* cdb is all zeros */
17237836SJohn.Forte@Sun.COM bzero(&cdb[0], CDB_GROUP0);
17247836SJohn.Forte@Sun.COM
17257836SJohn.Forte@Sun.COM /* setup uscsi cmd */
17267836SJohn.Forte@Sun.COM bzero(&ucmd, sizeof (struct uscsi_cmd));
17277836SJohn.Forte@Sun.COM ucmd.uscsi_timeout = iscsi_sess_enum_timeout;
17287836SJohn.Forte@Sun.COM ucmd.uscsi_cdb = &cdb[0];
17297836SJohn.Forte@Sun.COM ucmd.uscsi_cdblen = CDB_GROUP0;
17307836SJohn.Forte@Sun.COM
17317836SJohn.Forte@Sun.COM /* send test unit ready to lun zero on this session */
17327836SJohn.Forte@Sun.COM rval = iscsi_handle_passthru(isp, 0, &ucmd);
17337836SJohn.Forte@Sun.COM
17347836SJohn.Forte@Sun.COM /*
17357836SJohn.Forte@Sun.COM * If passthru was successful then we were able to
17367836SJohn.Forte@Sun.COM * communicate with the target, continue enumeration.
17377836SJohn.Forte@Sun.COM */
17387836SJohn.Forte@Sun.COM if (ISCSI_SUCCESS(rval)) {
17397836SJohn.Forte@Sun.COM break;
17407836SJohn.Forte@Sun.COM }
1741*12161SJack.Meng@Sun.COM }
17427836SJohn.Forte@Sun.COM
17437836SJohn.Forte@Sun.COM return (rval);
17447836SJohn.Forte@Sun.COM }
17457836SJohn.Forte@Sun.COM
17467836SJohn.Forte@Sun.COM #define SCSI_REPORTLUNS_ADDRESS_SIZE 8
17477836SJohn.Forte@Sun.COM #define SCSI_REPORTLUNS_ADDRESS_MASK 0xC0
17487836SJohn.Forte@Sun.COM #define SCSI_REPORTLUNS_ADDRESS_PERIPHERAL 0x00
17497836SJohn.Forte@Sun.COM #define SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE 0x40
17507836SJohn.Forte@Sun.COM #define SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT 0x80
17517836SJohn.Forte@Sun.COM #define SCSI_REPORTLUNS_ADDRESS_EXTENDED_UNIT 0xC0
17527836SJohn.Forte@Sun.COM #define SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT_2B 0x00
17537836SJohn.Forte@Sun.COM #define SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT_4B 0x01
17547836SJohn.Forte@Sun.COM #define SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT_6B 0x10
17557836SJohn.Forte@Sun.COM #define SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT_8B 0x20
17567836SJohn.Forte@Sun.COM #define SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT_SIZE 0x30
17577836SJohn.Forte@Sun.COM
17587836SJohn.Forte@Sun.COM /*
17597836SJohn.Forte@Sun.COM * iscsi_sess_reportluns - This is used during enumeration to
17607836SJohn.Forte@Sun.COM * ensure an array is ready to be enumerated.
17617836SJohn.Forte@Sun.COM */
17627836SJohn.Forte@Sun.COM static iscsi_status_t
iscsi_sess_reportluns(iscsi_sess_t * isp,uint32_t event_count)1763*12161SJack.Meng@Sun.COM iscsi_sess_reportluns(iscsi_sess_t *isp, uint32_t event_count)
17647836SJohn.Forte@Sun.COM {
17657836SJohn.Forte@Sun.COM iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
17667836SJohn.Forte@Sun.COM iscsi_hba_t *ihp;
17677836SJohn.Forte@Sun.COM struct uscsi_cmd ucmd;
17687836SJohn.Forte@Sun.COM unsigned char cdb[CDB_GROUP5];
17697836SJohn.Forte@Sun.COM unsigned char *buf = NULL;
17707836SJohn.Forte@Sun.COM int buf_len = sizeof (struct scsi_inquiry);
17717836SJohn.Forte@Sun.COM uint32_t lun_list_length = 0;
17727836SJohn.Forte@Sun.COM uint16_t lun_num = 0;
17737836SJohn.Forte@Sun.COM uint8_t lun_addr_type = 0;
17747836SJohn.Forte@Sun.COM uint32_t lun_count = 0;
17757836SJohn.Forte@Sun.COM uint32_t lun_start = 0;
17767836SJohn.Forte@Sun.COM uint32_t lun_total = 0;
17777836SJohn.Forte@Sun.COM int retries = 0;
17788866Sandrew.rutz@sun.com iscsi_lun_t *ilp_next;
17797836SJohn.Forte@Sun.COM iscsi_lun_t *ilp = NULL;
17807836SJohn.Forte@Sun.COM replun_data_t *saved_replun_ptr = NULL;
17817836SJohn.Forte@Sun.COM
17827836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
17837836SJohn.Forte@Sun.COM ihp = isp->sess_hba;
17847836SJohn.Forte@Sun.COM ASSERT(ihp != NULL);
17857836SJohn.Forte@Sun.COM
17867836SJohn.Forte@Sun.COM /*
17877836SJohn.Forte@Sun.COM * Attempt to send report luns until we successfully
17887836SJohn.Forte@Sun.COM * get all the data or the retries run out.
17897836SJohn.Forte@Sun.COM */
1790*12161SJack.Meng@Sun.COM while ((retries++ < 3) &&
1791*12161SJack.Meng@Sun.COM (isp->sess_state_event_count == event_count)) {
17927836SJohn.Forte@Sun.COM /*
17937836SJohn.Forte@Sun.COM * Allocate our buffer based on current buf_len.
17947836SJohn.Forte@Sun.COM * buf_len may change after we received a response
17957836SJohn.Forte@Sun.COM * from the target.
17967836SJohn.Forte@Sun.COM */
17977836SJohn.Forte@Sun.COM if (buf == NULL) {
17987836SJohn.Forte@Sun.COM buf = kmem_zalloc(buf_len, KM_SLEEP);
17997836SJohn.Forte@Sun.COM }
18007836SJohn.Forte@Sun.COM
18017836SJohn.Forte@Sun.COM /* setup cdb */
18027836SJohn.Forte@Sun.COM bzero(&cdb, CDB_GROUP5);
18037836SJohn.Forte@Sun.COM cdb[0] = SCMD_REPORT_LUNS;
18047836SJohn.Forte@Sun.COM cdb[6] = (buf_len & 0xff000000) >> 24;
18057836SJohn.Forte@Sun.COM cdb[7] = (buf_len & 0x00ff0000) >> 16;
18067836SJohn.Forte@Sun.COM cdb[8] = (buf_len & 0x0000ff00) >> 8;
18077836SJohn.Forte@Sun.COM cdb[9] = (buf_len & 0x000000ff);
18087836SJohn.Forte@Sun.COM
18097836SJohn.Forte@Sun.COM /* setup uscsi cmd */
18107836SJohn.Forte@Sun.COM bzero(&ucmd, sizeof (struct uscsi_cmd));
18117836SJohn.Forte@Sun.COM ucmd.uscsi_flags = USCSI_READ;
18127836SJohn.Forte@Sun.COM ucmd.uscsi_timeout = iscsi_sess_enum_timeout;
18137836SJohn.Forte@Sun.COM ucmd.uscsi_cdb = (char *)&cdb[0];
18147836SJohn.Forte@Sun.COM ucmd.uscsi_cdblen = CDB_GROUP5;
18157836SJohn.Forte@Sun.COM ucmd.uscsi_bufaddr = (char *)buf;
18167836SJohn.Forte@Sun.COM ucmd.uscsi_buflen = buf_len;
18177836SJohn.Forte@Sun.COM
18187836SJohn.Forte@Sun.COM /* send uscsi cmd to lun 0 on session */
18197836SJohn.Forte@Sun.COM rval = iscsi_handle_passthru(isp, 0, &ucmd);
18207836SJohn.Forte@Sun.COM
18217836SJohn.Forte@Sun.COM /* If passthru successful but not scsi status update istatus */
18227836SJohn.Forte@Sun.COM if (ISCSI_SUCCESS(rval) &&
18237836SJohn.Forte@Sun.COM (ucmd.uscsi_status != STATUS_GOOD)) {
18247836SJohn.Forte@Sun.COM rval = ISCSI_STATUS_USCSI_FAILED;
18257836SJohn.Forte@Sun.COM }
18267836SJohn.Forte@Sun.COM
18277836SJohn.Forte@Sun.COM /* If successful, check if we have all the data */
18287836SJohn.Forte@Sun.COM if (ISCSI_SUCCESS(rval)) {
18297836SJohn.Forte@Sun.COM /* total data - header (SCSI_REPORTLUNS_ADDRESS_SIZE) */
18307836SJohn.Forte@Sun.COM lun_list_length = htonl(*(uint32_t *)buf);
18317836SJohn.Forte@Sun.COM
18327836SJohn.Forte@Sun.COM if (buf_len >= lun_list_length +
18337836SJohn.Forte@Sun.COM SCSI_REPORTLUNS_ADDRESS_SIZE) {
18347836SJohn.Forte@Sun.COM /* we have all the data, were done */
18357836SJohn.Forte@Sun.COM break;
18367836SJohn.Forte@Sun.COM }
18377836SJohn.Forte@Sun.COM
18387836SJohn.Forte@Sun.COM /*
18397836SJohn.Forte@Sun.COM * We don't have all the data. free up the
18407836SJohn.Forte@Sun.COM * memory for the next pass and update the
18417836SJohn.Forte@Sun.COM * buf_len
18427836SJohn.Forte@Sun.COM */
18437836SJohn.Forte@Sun.COM kmem_free(buf, buf_len);
18447836SJohn.Forte@Sun.COM buf = NULL;
18457836SJohn.Forte@Sun.COM buf_len = lun_list_length +
18467836SJohn.Forte@Sun.COM SCSI_REPORTLUNS_ADDRESS_SIZE;
18477836SJohn.Forte@Sun.COM } else {
18487836SJohn.Forte@Sun.COM retries++;
18497836SJohn.Forte@Sun.COM }
1850*12161SJack.Meng@Sun.COM }
18517836SJohn.Forte@Sun.COM
1852*12161SJack.Meng@Sun.COM if (isp->sess_state_event_count != event_count) {
1853*12161SJack.Meng@Sun.COM if (buf != NULL) {
1854*12161SJack.Meng@Sun.COM kmem_free(buf, buf_len);
1855*12161SJack.Meng@Sun.COM buf = NULL;
1856*12161SJack.Meng@Sun.COM }
1857*12161SJack.Meng@Sun.COM return (rval);
1858*12161SJack.Meng@Sun.COM }
18597836SJohn.Forte@Sun.COM
1860*12161SJack.Meng@Sun.COM /* If not successful go no further */
18617836SJohn.Forte@Sun.COM if (!ISCSI_SUCCESS(rval)) {
18627836SJohn.Forte@Sun.COM kmem_free(buf, buf_len);
18637836SJohn.Forte@Sun.COM return (rval);
18647836SJohn.Forte@Sun.COM }
18657836SJohn.Forte@Sun.COM
18667836SJohn.Forte@Sun.COM /*
18677836SJohn.Forte@Sun.COM * find out the number of luns returned by the SCSI ReportLun call
18687836SJohn.Forte@Sun.COM * and allocate buffer space
18697836SJohn.Forte@Sun.COM */
18707836SJohn.Forte@Sun.COM lun_total = lun_list_length / SCSI_REPORTLUNS_ADDRESS_SIZE;
18717836SJohn.Forte@Sun.COM saved_replun_ptr = kmem_zalloc(lun_total * sizeof (replun_data_t),
18727836SJohn.Forte@Sun.COM KM_SLEEP);
18737836SJohn.Forte@Sun.COM
18747836SJohn.Forte@Sun.COM /*
18757836SJohn.Forte@Sun.COM * walk the isp->sess_lun_list
18767836SJohn.Forte@Sun.COM * for each lun in this list
18777836SJohn.Forte@Sun.COM * look to see if this lun is in the SCSI ReportLun list we
18787836SJohn.Forte@Sun.COM * just retrieved
1879*12161SJack.Meng@Sun.COM * if it is in the SCSI ReportLun list and it is already ONLINE or
1880*12161SJack.Meng@Sun.COM * if it is in the SCSI ReportLun list and it is OFFLINE or
1881*12161SJack.Meng@Sun.COM * if it isn't in the SCSI ReportLunlist or then
1882*12161SJack.Meng@Sun.COM * issue the iscsi_sess_inquiry() to handle
18837836SJohn.Forte@Sun.COM *
18847836SJohn.Forte@Sun.COM * as we walk the SCSI ReportLun list, we save this lun information
18857836SJohn.Forte@Sun.COM * into the buffer we just allocated. This will save us from
18867836SJohn.Forte@Sun.COM * having to figure out this information later
18877836SJohn.Forte@Sun.COM */
18887836SJohn.Forte@Sun.COM lun_start = 0;
18898500Sandrew.rutz@sun.com rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
18908866Sandrew.rutz@sun.com for (ilp = isp->sess_lun_list; ilp; ilp = ilp_next) {
1891*12161SJack.Meng@Sun.COM if (isp->sess_state_event_count != event_count)
1892*12161SJack.Meng@Sun.COM break;
1893*12161SJack.Meng@Sun.COM
18948866Sandrew.rutz@sun.com ilp_next = ilp->lun_next;
18958866Sandrew.rutz@sun.com
18969162SPeter.Dunlap@Sun.COM for (lun_count = lun_start; lun_count < lun_total;
18979162SPeter.Dunlap@Sun.COM lun_count++) {
18989162SPeter.Dunlap@Sun.COM /*
18999162SPeter.Dunlap@Sun.COM * if the first lun in saved_replun_ptr buffer has
19009162SPeter.Dunlap@Sun.COM * already been found we can move on and do not
19019162SPeter.Dunlap@Sun.COM * have to check this lun in the future
19029162SPeter.Dunlap@Sun.COM */
19037836SJohn.Forte@Sun.COM if (lun_count == lun_start &&
19047836SJohn.Forte@Sun.COM saved_replun_ptr[lun_start].lun_found) {
19057836SJohn.Forte@Sun.COM lun_start++;
19067836SJohn.Forte@Sun.COM continue;
19077836SJohn.Forte@Sun.COM }
19087836SJohn.Forte@Sun.COM /*
19097836SJohn.Forte@Sun.COM * check to see if the lun we are looking for is in the
19107836SJohn.Forte@Sun.COM * saved_replun_ptr buffer
19117836SJohn.Forte@Sun.COM * if it is, process the lun
19127836SJohn.Forte@Sun.COM * if it isn't, then we must go to SCSI
19137836SJohn.Forte@Sun.COM * Report Lun buffer
19147836SJohn.Forte@Sun.COM * we retrieved to get lun info
19157836SJohn.Forte@Sun.COM */
1916*12161SJack.Meng@Sun.COM if ((saved_replun_ptr[lun_count].lun_valid
1917*12161SJack.Meng@Sun.COM == B_TRUE) &&
1918*12161SJack.Meng@Sun.COM (saved_replun_ptr[lun_count].lun_num
1919*12161SJack.Meng@Sun.COM == ilp->lun_num)) {
19207836SJohn.Forte@Sun.COM /*
1921*12161SJack.Meng@Sun.COM * the lun we are looking for is found,
1922*12161SJack.Meng@Sun.COM * give it to iscsi_sess_inquiry()
19237836SJohn.Forte@Sun.COM */
1924*12161SJack.Meng@Sun.COM rw_exit(&isp->sess_lun_list_rwlock);
1925*12161SJack.Meng@Sun.COM iscsi_sess_inquiry(isp, ilp->lun_num,
1926*12161SJack.Meng@Sun.COM saved_replun_ptr[lun_count].lun_addr_type,
1927*12161SJack.Meng@Sun.COM event_count, ilp);
1928*12161SJack.Meng@Sun.COM rw_enter(&isp->sess_lun_list_rwlock,
1929*12161SJack.Meng@Sun.COM RW_WRITER);
1930*12161SJack.Meng@Sun.COM saved_replun_ptr[lun_count].lun_found
1931*12161SJack.Meng@Sun.COM = B_TRUE;
19327836SJohn.Forte@Sun.COM break;
1933*12161SJack.Meng@Sun.COM } else {
19349162SPeter.Dunlap@Sun.COM /*
1935*12161SJack.Meng@Sun.COM * lun information is not found in the
1936*12161SJack.Meng@Sun.COM * saved_replun buffer, retrieve lun
1937*12161SJack.Meng@Sun.COM * information from the SCSI Report Lun buffer
1938*12161SJack.Meng@Sun.COM * and store this information in the
1939*12161SJack.Meng@Sun.COM * saved_replun buffer
19409162SPeter.Dunlap@Sun.COM */
1941*12161SJack.Meng@Sun.COM if (retrieve_lundata(lun_count, buf, isp,
1942*12161SJack.Meng@Sun.COM &lun_num, &lun_addr_type) !=
1943*12161SJack.Meng@Sun.COM ISCSI_STATUS_SUCCESS) {
1944*12161SJack.Meng@Sun.COM continue;
1945*12161SJack.Meng@Sun.COM }
1946*12161SJack.Meng@Sun.COM saved_replun_ptr[lun_count].lun_valid = B_TRUE;
1947*12161SJack.Meng@Sun.COM saved_replun_ptr[lun_count].lun_num = lun_num;
1948*12161SJack.Meng@Sun.COM saved_replun_ptr[lun_count].lun_addr_type =
1949*12161SJack.Meng@Sun.COM lun_addr_type;
1950*12161SJack.Meng@Sun.COM if (ilp->lun_num == lun_num) {
1951*12161SJack.Meng@Sun.COM /*
1952*12161SJack.Meng@Sun.COM * lun is found in the SCSI Report Lun
1953*12161SJack.Meng@Sun.COM * buffer, give it to inquiry
1954*12161SJack.Meng@Sun.COM */
1955*12161SJack.Meng@Sun.COM rw_exit(&isp->sess_lun_list_rwlock);
1956*12161SJack.Meng@Sun.COM iscsi_sess_inquiry(isp, lun_num,
1957*12161SJack.Meng@Sun.COM lun_addr_type, event_count, ilp);
1958*12161SJack.Meng@Sun.COM rw_enter(&isp->sess_lun_list_rwlock,
1959*12161SJack.Meng@Sun.COM RW_WRITER);
1960*12161SJack.Meng@Sun.COM saved_replun_ptr[lun_count].lun_found
1961*12161SJack.Meng@Sun.COM = B_TRUE;
19627836SJohn.Forte@Sun.COM break;
19637836SJohn.Forte@Sun.COM }
19647836SJohn.Forte@Sun.COM }
19657836SJohn.Forte@Sun.COM }
19667836SJohn.Forte@Sun.COM
19677836SJohn.Forte@Sun.COM if (lun_count == lun_total) {
19689162SPeter.Dunlap@Sun.COM /*
19699162SPeter.Dunlap@Sun.COM * this lun we found in the sess->lun_list does
19709162SPeter.Dunlap@Sun.COM * not exist anymore, need to offline this lun
19719162SPeter.Dunlap@Sun.COM */
19727836SJohn.Forte@Sun.COM
1973*12161SJack.Meng@Sun.COM DTRACE_PROBE2(
1974*12161SJack.Meng@Sun.COM sess_reportluns_lun_no_longer_exists,
19757836SJohn.Forte@Sun.COM int, ilp->lun_num, int, ilp->lun_state);
19767836SJohn.Forte@Sun.COM
19778500Sandrew.rutz@sun.com (void) iscsi_lun_destroy(ihp, ilp);
19787836SJohn.Forte@Sun.COM }
19797836SJohn.Forte@Sun.COM }
19807836SJohn.Forte@Sun.COM rw_exit(&isp->sess_lun_list_rwlock);
19817836SJohn.Forte@Sun.COM /*
19827836SJohn.Forte@Sun.COM * look for new luns that we found in the SCSI Report Lun buffer that
19837836SJohn.Forte@Sun.COM * we did not have in the sess->lun_list and add them into the list
19847836SJohn.Forte@Sun.COM */
19857836SJohn.Forte@Sun.COM for (lun_count = lun_start; lun_count < lun_total; lun_count++) {
19867836SJohn.Forte@Sun.COM if (saved_replun_ptr[lun_count].lun_valid == B_FALSE) {
19877836SJohn.Forte@Sun.COM /*
19887836SJohn.Forte@Sun.COM * lun information is not in the
19897836SJohn.Forte@Sun.COM * saved_replun buffer, retrieve
19907836SJohn.Forte@Sun.COM * it from the SCSI Report Lun buffer
19917836SJohn.Forte@Sun.COM */
19927836SJohn.Forte@Sun.COM if (retrieve_lundata(lun_count, buf, isp,
19937836SJohn.Forte@Sun.COM &lun_num, &lun_addr_type) != ISCSI_STATUS_SUCCESS) {
19947836SJohn.Forte@Sun.COM continue;
19957836SJohn.Forte@Sun.COM }
19967836SJohn.Forte@Sun.COM } else {
19979162SPeter.Dunlap@Sun.COM /*
19989162SPeter.Dunlap@Sun.COM * lun information is in the saved_replun buffer
19999162SPeter.Dunlap@Sun.COM * if this lun has been found already,
20009162SPeter.Dunlap@Sun.COM * then we can move on
20019162SPeter.Dunlap@Sun.COM */
20027836SJohn.Forte@Sun.COM if (saved_replun_ptr[lun_count].lun_found == B_TRUE) {
20037836SJohn.Forte@Sun.COM continue;
20047836SJohn.Forte@Sun.COM }
20057836SJohn.Forte@Sun.COM lun_num = saved_replun_ptr[lun_count].lun_num;
2006*12161SJack.Meng@Sun.COM lun_addr_type =
2007*12161SJack.Meng@Sun.COM saved_replun_ptr[lun_count].lun_addr_type;
20087836SJohn.Forte@Sun.COM }
20097836SJohn.Forte@Sun.COM
20107836SJohn.Forte@Sun.COM
20117836SJohn.Forte@Sun.COM /* New luns found should not conflict with existing luns */
20127836SJohn.Forte@Sun.COM rw_enter(&isp->sess_lun_list_rwlock, RW_READER);
20137836SJohn.Forte@Sun.COM for (ilp = isp->sess_lun_list; ilp; ilp = ilp->lun_next) {
20147836SJohn.Forte@Sun.COM if (ilp->lun_num == lun_num) {
20157836SJohn.Forte@Sun.COM break;
20167836SJohn.Forte@Sun.COM }
20177836SJohn.Forte@Sun.COM }
20187836SJohn.Forte@Sun.COM rw_exit(&isp->sess_lun_list_rwlock);
20197836SJohn.Forte@Sun.COM
20207836SJohn.Forte@Sun.COM if (ilp == NULL) {
20217836SJohn.Forte@Sun.COM /* new lun found, add this lun */
2022*12161SJack.Meng@Sun.COM iscsi_sess_inquiry(isp, lun_num, lun_addr_type,
2023*12161SJack.Meng@Sun.COM event_count, NULL);
20247836SJohn.Forte@Sun.COM } else {
20257836SJohn.Forte@Sun.COM cmn_err(CE_NOTE,
20267836SJohn.Forte@Sun.COM "!Duplicate Lun Number(%d) recieved from "
20277836SJohn.Forte@Sun.COM "Target(%s)", lun_num, isp->sess_name);
20287836SJohn.Forte@Sun.COM }
20297836SJohn.Forte@Sun.COM }
2030*12161SJack.Meng@Sun.COM if (buf != NULL) {
2031*12161SJack.Meng@Sun.COM kmem_free(buf, buf_len);
2032*12161SJack.Meng@Sun.COM }
2033*12161SJack.Meng@Sun.COM kmem_free(saved_replun_ptr, lun_total * sizeof (replun_data_t));
20347836SJohn.Forte@Sun.COM
20357836SJohn.Forte@Sun.COM return (rval);
20367836SJohn.Forte@Sun.COM }
20377836SJohn.Forte@Sun.COM
20387836SJohn.Forte@Sun.COM #define ISCSI_MAX_INQUIRY_BUF_SIZE 0xFF
20397836SJohn.Forte@Sun.COM #define ISCSI_MAX_INQUIRY_RETRIES 3
20407836SJohn.Forte@Sun.COM
20417836SJohn.Forte@Sun.COM /*
20427836SJohn.Forte@Sun.COM * iscsi_sess_inquiry - Final processing of a LUN before we create a tgt
2043*12161SJack.Meng@Sun.COM * mapping, if necessary the old lun will be deleted.
2044*12161SJack.Meng@Sun.COM *
2045*12161SJack.Meng@Sun.COM * We need to collect the stardard inquiry page and the
20467836SJohn.Forte@Sun.COM * vendor identification page for this LUN. If both of these are
20477836SJohn.Forte@Sun.COM * successful and the identification page contains a NAA or EUI type
20487836SJohn.Forte@Sun.COM * we will continue. Otherwise we fail the creation of a tgt for
20497836SJohn.Forte@Sun.COM * this LUN.
20507836SJohn.Forte@Sun.COM *
2051*12161SJack.Meng@Sun.COM * Keep the old lun unchanged if it is online and following things are
2052*12161SJack.Meng@Sun.COM * match, lun_addr_type, lun_type, and lun_guid.
2053*12161SJack.Meng@Sun.COM *
2054*12161SJack.Meng@Sun.COM * Online the old lun if it is offline/invalid and those three things
2055*12161SJack.Meng@Sun.COM * are match.
2056*12161SJack.Meng@Sun.COM *
2057*12161SJack.Meng@Sun.COM * Online a new lun if the old lun is offline and any of those three things
2058*12161SJack.Meng@Sun.COM * is not match, and needs to destroy the old first.
2059*12161SJack.Meng@Sun.COM *
2060*12161SJack.Meng@Sun.COM * Destroy the old lun and online the new lun if the old is online/invalid
2061*12161SJack.Meng@Sun.COM * and any of those three things is not match, and then online the new lun
20627836SJohn.Forte@Sun.COM */
20637836SJohn.Forte@Sun.COM static void
iscsi_sess_inquiry(iscsi_sess_t * isp,uint16_t lun_num,uint8_t lun_addr_type,uint32_t event_count,iscsi_lun_t * ilp)2064*12161SJack.Meng@Sun.COM iscsi_sess_inquiry(iscsi_sess_t *isp, uint16_t lun_num, uint8_t lun_addr_type,
2065*12161SJack.Meng@Sun.COM uint32_t event_count, iscsi_lun_t *ilp)
20667836SJohn.Forte@Sun.COM {
20677836SJohn.Forte@Sun.COM iscsi_status_t rval;
20687836SJohn.Forte@Sun.COM struct uscsi_cmd ucmd;
20697836SJohn.Forte@Sun.COM uchar_t cdb[CDB_GROUP0];
20707836SJohn.Forte@Sun.COM uchar_t *inq;
20717836SJohn.Forte@Sun.COM size_t inq_len;
20727836SJohn.Forte@Sun.COM uchar_t *inq83;
20737836SJohn.Forte@Sun.COM size_t inq83_len;
20747836SJohn.Forte@Sun.COM int retries;
20757836SJohn.Forte@Sun.COM ddi_devid_t devid;
20767836SJohn.Forte@Sun.COM char *guid = NULL;
2077*12161SJack.Meng@Sun.COM iscsi_hba_t *ihp;
2078*12161SJack.Meng@Sun.COM iscsi_status_t status = ISCSI_STATUS_SUCCESS;
2079*12161SJack.Meng@Sun.COM boolean_t inq_ready = B_FALSE;
2080*12161SJack.Meng@Sun.COM boolean_t inq83_ready = B_FALSE;
2081*12161SJack.Meng@Sun.COM boolean_t nochange = B_FALSE;
2082*12161SJack.Meng@Sun.COM uchar_t lun_type;
20837836SJohn.Forte@Sun.COM
20847836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
2085*12161SJack.Meng@Sun.COM ihp = isp->sess_hba;
2086*12161SJack.Meng@Sun.COM ASSERT(ihp != NULL);
20877836SJohn.Forte@Sun.COM
20887836SJohn.Forte@Sun.COM inq = kmem_zalloc(ISCSI_MAX_INQUIRY_BUF_SIZE, KM_SLEEP);
20897836SJohn.Forte@Sun.COM inq83 = kmem_zalloc(ISCSI_MAX_INQUIRY_BUF_SIZE, KM_SLEEP);
20907836SJohn.Forte@Sun.COM
2091*12161SJack.Meng@Sun.COM if (ilp == NULL) {
2092*12161SJack.Meng@Sun.COM /* easy case, just to create the new lun */
2093*12161SJack.Meng@Sun.COM goto sess_inq;
2094*12161SJack.Meng@Sun.COM }
2095*12161SJack.Meng@Sun.COM
2096*12161SJack.Meng@Sun.COM if (ilp->lun_addr_type != lun_addr_type) {
2097*12161SJack.Meng@Sun.COM goto offline_old;
2098*12161SJack.Meng@Sun.COM }
2099*12161SJack.Meng@Sun.COM
2100*12161SJack.Meng@Sun.COM goto sess_inq;
2101*12161SJack.Meng@Sun.COM
2102*12161SJack.Meng@Sun.COM offline_old:
2103*12161SJack.Meng@Sun.COM if (isp->sess_state_event_count != event_count) {
2104*12161SJack.Meng@Sun.COM goto inq_done;
2105*12161SJack.Meng@Sun.COM }
2106*12161SJack.Meng@Sun.COM
2107*12161SJack.Meng@Sun.COM status = iscsi_lun_destroy(ihp, ilp);
2108*12161SJack.Meng@Sun.COM if (status != ISCSI_STATUS_SUCCESS) {
2109*12161SJack.Meng@Sun.COM /* have to abort the process */
2110*12161SJack.Meng@Sun.COM cmn_err(CE_WARN, "iscsi session(%u) is unable to offline"
2111*12161SJack.Meng@Sun.COM " obsolete logical unit %d", isp->sess_oid, lun_num);
2112*12161SJack.Meng@Sun.COM goto inq_done;
2113*12161SJack.Meng@Sun.COM }
2114*12161SJack.Meng@Sun.COM ilp = NULL;
2115*12161SJack.Meng@Sun.COM
2116*12161SJack.Meng@Sun.COM sess_inq:
2117*12161SJack.Meng@Sun.COM if (inq_ready == B_TRUE) {
2118*12161SJack.Meng@Sun.COM goto sess_inq83;
2119*12161SJack.Meng@Sun.COM }
21207836SJohn.Forte@Sun.COM /*
21217836SJohn.Forte@Sun.COM * STANDARD INQUIRY - We need the standard inquiry information
21227836SJohn.Forte@Sun.COM * to feed into the scsi_hba_nodename_compatible_get function.
21237836SJohn.Forte@Sun.COM * This function is used to detemine which driver will bind
21247836SJohn.Forte@Sun.COM * on top of us, via the compatible id.
21257836SJohn.Forte@Sun.COM */
21267836SJohn.Forte@Sun.COM bzero(&cdb, CDB_GROUP0);
21277836SJohn.Forte@Sun.COM cdb[0] = SCMD_INQUIRY;
21287836SJohn.Forte@Sun.COM cdb[4] = ISCSI_MAX_INQUIRY_BUF_SIZE;
21297836SJohn.Forte@Sun.COM
21307836SJohn.Forte@Sun.COM bzero(&ucmd, sizeof (struct uscsi_cmd));
21317836SJohn.Forte@Sun.COM ucmd.uscsi_flags = USCSI_READ;
21327836SJohn.Forte@Sun.COM ucmd.uscsi_timeout = iscsi_sess_enum_timeout;
21337836SJohn.Forte@Sun.COM ucmd.uscsi_cdb = (char *)&cdb[0];
21347836SJohn.Forte@Sun.COM ucmd.uscsi_cdblen = CDB_GROUP0;
21357836SJohn.Forte@Sun.COM ucmd.uscsi_bufaddr = (char *)inq;
21367836SJohn.Forte@Sun.COM ucmd.uscsi_buflen = ISCSI_MAX_INQUIRY_BUF_SIZE;
21377836SJohn.Forte@Sun.COM
21387836SJohn.Forte@Sun.COM /* Attempt to get inquiry information until successful or retries */
21397836SJohn.Forte@Sun.COM retries = 0;
2140*12161SJack.Meng@Sun.COM while ((retries++ < ISCSI_MAX_INQUIRY_RETRIES) &&
2141*12161SJack.Meng@Sun.COM (isp->sess_state_event_count == event_count)) {
21427836SJohn.Forte@Sun.COM /* issue passthru */
21437836SJohn.Forte@Sun.COM rval = iscsi_handle_passthru(isp, lun_num, &ucmd);
21447836SJohn.Forte@Sun.COM
21457836SJohn.Forte@Sun.COM /* If we were successful but scsi stat failed update istatus */
21467836SJohn.Forte@Sun.COM if (ISCSI_SUCCESS(rval) &&
21477836SJohn.Forte@Sun.COM (ucmd.uscsi_status != STATUS_GOOD)) {
21487836SJohn.Forte@Sun.COM rval = ISCSI_STATUS_USCSI_FAILED;
21497836SJohn.Forte@Sun.COM }
21507836SJohn.Forte@Sun.COM
21517836SJohn.Forte@Sun.COM /* If successful break */
21527836SJohn.Forte@Sun.COM if (ISCSI_SUCCESS(rval)) {
21537836SJohn.Forte@Sun.COM inq_len = ISCSI_MAX_INQUIRY_BUF_SIZE - ucmd.uscsi_resid;
21547836SJohn.Forte@Sun.COM break;
21557836SJohn.Forte@Sun.COM }
21567836SJohn.Forte@Sun.COM
21577836SJohn.Forte@Sun.COM /* loop until we are successful or retries run out */
2158*12161SJack.Meng@Sun.COM }
21597836SJohn.Forte@Sun.COM
21607836SJohn.Forte@Sun.COM /* If failed don't continue */
21617836SJohn.Forte@Sun.COM if (!ISCSI_SUCCESS(rval)) {
21627836SJohn.Forte@Sun.COM cmn_err(CE_NOTE, "iscsi session(%u) unable to enumerate "
21637836SJohn.Forte@Sun.COM "logical unit - inquiry failed lun %d",
21647836SJohn.Forte@Sun.COM isp->sess_oid, lun_num);
21657836SJohn.Forte@Sun.COM
21667836SJohn.Forte@Sun.COM goto inq_done;
21677836SJohn.Forte@Sun.COM }
2168*12161SJack.Meng@Sun.COM inq_ready = B_TRUE;
21697836SJohn.Forte@Sun.COM
2170*12161SJack.Meng@Sun.COM sess_inq83:
21717836SJohn.Forte@Sun.COM /*
21727836SJohn.Forte@Sun.COM * T-10 SPC Section 6.4.2. Standard INQUIRY Peripheral
21737836SJohn.Forte@Sun.COM * qualifier of 000b is the only type we should attempt
21747836SJohn.Forte@Sun.COM * to plumb under the IO stack.
21757836SJohn.Forte@Sun.COM */
21767836SJohn.Forte@Sun.COM if ((inq[0] & SCSI_INQUIRY_PQUAL_MASK) != 0x00) {
2177*12161SJack.Meng@Sun.COM /* shouldn't enumerate, destroy the old one if exists */
2178*12161SJack.Meng@Sun.COM if (ilp != NULL) {
2179*12161SJack.Meng@Sun.COM goto offline_old;
2180*12161SJack.Meng@Sun.COM }
21817836SJohn.Forte@Sun.COM goto inq_done;
21827836SJohn.Forte@Sun.COM }
21837836SJohn.Forte@Sun.COM
21847836SJohn.Forte@Sun.COM /*
2185*12161SJack.Meng@Sun.COM * If lun type has changed
2186*12161SJack.Meng@Sun.COM */
2187*12161SJack.Meng@Sun.COM lun_type = ((struct scsi_inquiry *)inq)->inq_dtype & DTYPE_MASK;
2188*12161SJack.Meng@Sun.COM if ((ilp != NULL) && (ilp->lun_type != lun_type)) {
2189*12161SJack.Meng@Sun.COM goto offline_old;
2190*12161SJack.Meng@Sun.COM }
2191*12161SJack.Meng@Sun.COM
2192*12161SJack.Meng@Sun.COM if (inq83_ready == B_TRUE) {
2193*12161SJack.Meng@Sun.COM goto guid_ready;
2194*12161SJack.Meng@Sun.COM }
2195*12161SJack.Meng@Sun.COM
2196*12161SJack.Meng@Sun.COM /*
21977836SJohn.Forte@Sun.COM * VENDOR IDENTIFICATION INQUIRY - This will be used to identify
21987836SJohn.Forte@Sun.COM * a unique lunId. This Id is passed to the mdi alloc calls so
21997836SJohn.Forte@Sun.COM * we can properly plumb into scsi_vhci/mpxio.
22007836SJohn.Forte@Sun.COM */
22017836SJohn.Forte@Sun.COM
22027836SJohn.Forte@Sun.COM bzero(&cdb, CDB_GROUP0);
22037836SJohn.Forte@Sun.COM cdb[0] = SCMD_INQUIRY;
22047836SJohn.Forte@Sun.COM cdb[1] = 0x01; /* EVP bit */
22057836SJohn.Forte@Sun.COM cdb[2] = 0x83;
22067836SJohn.Forte@Sun.COM cdb[4] = ISCSI_MAX_INQUIRY_BUF_SIZE;
22077836SJohn.Forte@Sun.COM
22087836SJohn.Forte@Sun.COM ucmd.uscsi_flags = USCSI_READ;
22097836SJohn.Forte@Sun.COM ucmd.uscsi_timeout = iscsi_sess_enum_timeout;
22107836SJohn.Forte@Sun.COM ucmd.uscsi_cdb = (char *)&cdb[0];
22117836SJohn.Forte@Sun.COM ucmd.uscsi_cdblen = CDB_GROUP0;
22127836SJohn.Forte@Sun.COM ucmd.uscsi_bufaddr = (char *)inq83;
22137836SJohn.Forte@Sun.COM ucmd.uscsi_buflen = ISCSI_MAX_INQUIRY_BUF_SIZE;
22147836SJohn.Forte@Sun.COM
22157836SJohn.Forte@Sun.COM /* Attempt to get inquiry information until successful or retries */
22167836SJohn.Forte@Sun.COM retries = 0;
2217*12161SJack.Meng@Sun.COM while ((retries++ < ISCSI_MAX_INQUIRY_RETRIES) &&
2218*12161SJack.Meng@Sun.COM (isp->sess_state_event_count == event_count)) {
22197836SJohn.Forte@Sun.COM /* issue passthru command */
22207836SJohn.Forte@Sun.COM rval = iscsi_handle_passthru(isp, lun_num, &ucmd);
22217836SJohn.Forte@Sun.COM
22227836SJohn.Forte@Sun.COM /* If we were successful but scsi stat failed update istatus */
22237836SJohn.Forte@Sun.COM if (ISCSI_SUCCESS(rval) &&
22247836SJohn.Forte@Sun.COM (ucmd.uscsi_status != STATUS_GOOD)) {
22257836SJohn.Forte@Sun.COM rval = ISCSI_STATUS_USCSI_FAILED;
22267836SJohn.Forte@Sun.COM }
22277836SJohn.Forte@Sun.COM
22287836SJohn.Forte@Sun.COM /* Break if successful */
22297836SJohn.Forte@Sun.COM if (ISCSI_SUCCESS(rval)) {
22307836SJohn.Forte@Sun.COM inq83_len = ISCSI_MAX_INQUIRY_BUF_SIZE -
22317836SJohn.Forte@Sun.COM ucmd.uscsi_resid;
22327836SJohn.Forte@Sun.COM break;
22337836SJohn.Forte@Sun.COM }
2234*12161SJack.Meng@Sun.COM }
22357836SJohn.Forte@Sun.COM
22367836SJohn.Forte@Sun.COM /*
22377836SJohn.Forte@Sun.COM * If we were successful collecting page 83 data attempt
22387836SJohn.Forte@Sun.COM * to generate a GUID. If no GUID can be generated then
22397836SJohn.Forte@Sun.COM * the logical unit will skip attempt to plumb under
22407836SJohn.Forte@Sun.COM * scsi_vhci/mpxio.
22417836SJohn.Forte@Sun.COM */
22427836SJohn.Forte@Sun.COM if (ISCSI_SUCCESS(rval)) {
22437836SJohn.Forte@Sun.COM /* create DEVID from inquiry data */
22447836SJohn.Forte@Sun.COM if (ddi_devid_scsi_encode(
22457836SJohn.Forte@Sun.COM DEVID_SCSI_ENCODE_VERSION_LATEST, NULL,
22467836SJohn.Forte@Sun.COM inq, inq_len, NULL, 0, inq83, inq83_len, &devid) ==
22477836SJohn.Forte@Sun.COM DDI_SUCCESS) {
22487836SJohn.Forte@Sun.COM
22497836SJohn.Forte@Sun.COM /* extract GUID from DEVID */
22507836SJohn.Forte@Sun.COM guid = ddi_devid_to_guid(devid);
22517836SJohn.Forte@Sun.COM
22527836SJohn.Forte@Sun.COM /* devid no longer needed */
22537836SJohn.Forte@Sun.COM ddi_devid_free(devid);
22547836SJohn.Forte@Sun.COM }
22557836SJohn.Forte@Sun.COM }
2256*12161SJack.Meng@Sun.COM inq83_ready = B_TRUE;
22577836SJohn.Forte@Sun.COM
2258*12161SJack.Meng@Sun.COM guid_ready:
2259*12161SJack.Meng@Sun.COM
2260*12161SJack.Meng@Sun.COM if (ilp != NULL) {
2261*12161SJack.Meng@Sun.COM if ((guid == NULL) && (ilp->lun_guid == NULL)) {
2262*12161SJack.Meng@Sun.COM nochange = B_TRUE;
2263*12161SJack.Meng@Sun.COM }
2264*12161SJack.Meng@Sun.COM
2265*12161SJack.Meng@Sun.COM if ((guid != NULL) && (ilp->lun_guid != NULL) &&
2266*12161SJack.Meng@Sun.COM ((strlen(guid) + 1) == ilp->lun_guid_size) &&
2267*12161SJack.Meng@Sun.COM (bcmp(guid, ilp->lun_guid, ilp->lun_guid_size) == 0)) {
2268*12161SJack.Meng@Sun.COM nochange = B_TRUE;
2269*12161SJack.Meng@Sun.COM }
2270*12161SJack.Meng@Sun.COM
2271*12161SJack.Meng@Sun.COM if (nochange != B_TRUE) {
2272*12161SJack.Meng@Sun.COM goto offline_old;
2273*12161SJack.Meng@Sun.COM }
22747836SJohn.Forte@Sun.COM
2275*12161SJack.Meng@Sun.COM if (ilp->lun_state & (ISCSI_LUN_STATE_OFFLINE |
2276*12161SJack.Meng@Sun.COM ISCSI_LUN_STATE_INVALID)) {
2277*12161SJack.Meng@Sun.COM if (isp->sess_state_event_count == event_count) {
2278*12161SJack.Meng@Sun.COM (void) iscsi_lun_online(ihp, ilp);
2279*12161SJack.Meng@Sun.COM }
2280*12161SJack.Meng@Sun.COM }
2281*12161SJack.Meng@Sun.COM } else {
2282*12161SJack.Meng@Sun.COM if (isp->sess_state_event_count == event_count) {
2283*12161SJack.Meng@Sun.COM (void) iscsi_lun_create(isp, lun_num, lun_addr_type,
2284*12161SJack.Meng@Sun.COM (struct scsi_inquiry *)inq, guid);
2285*12161SJack.Meng@Sun.COM }
2286*12161SJack.Meng@Sun.COM }
2287*12161SJack.Meng@Sun.COM
2288*12161SJack.Meng@Sun.COM inq_done:
22897836SJohn.Forte@Sun.COM if (guid != NULL) {
2290*12161SJack.Meng@Sun.COM /* guid is no longer needed */
22917836SJohn.Forte@Sun.COM ddi_devid_free_guid(guid);
22927836SJohn.Forte@Sun.COM }
22937836SJohn.Forte@Sun.COM
22947836SJohn.Forte@Sun.COM /* free up memory now that we are done */
22957836SJohn.Forte@Sun.COM kmem_free(inq, ISCSI_MAX_INQUIRY_BUF_SIZE);
22967836SJohn.Forte@Sun.COM kmem_free(inq83, ISCSI_MAX_INQUIRY_BUF_SIZE);
22977836SJohn.Forte@Sun.COM }
22987836SJohn.Forte@Sun.COM
22997836SJohn.Forte@Sun.COM static iscsi_status_t
retrieve_lundata(uint32_t lun_count,unsigned char * buf,iscsi_sess_t * isp,uint16_t * lun_num,uint8_t * lun_addr_type)23007836SJohn.Forte@Sun.COM retrieve_lundata(uint32_t lun_count, unsigned char *buf, iscsi_sess_t *isp,
23017836SJohn.Forte@Sun.COM uint16_t *lun_num, uint8_t *lun_addr_type)
23027836SJohn.Forte@Sun.COM {
23037836SJohn.Forte@Sun.COM uint32_t lun_idx = 0;
23047836SJohn.Forte@Sun.COM
23057836SJohn.Forte@Sun.COM ASSERT(lun_num != NULL);
23067836SJohn.Forte@Sun.COM ASSERT(lun_addr_type != NULL);
23077836SJohn.Forte@Sun.COM
23087836SJohn.Forte@Sun.COM lun_idx = (lun_count + 1) * SCSI_REPORTLUNS_ADDRESS_SIZE;
23097836SJohn.Forte@Sun.COM /* determine report luns addressing type */
23107836SJohn.Forte@Sun.COM switch (buf[lun_idx] & SCSI_REPORTLUNS_ADDRESS_MASK) {
23117836SJohn.Forte@Sun.COM /*
23127836SJohn.Forte@Sun.COM * Vendors in the field have been found to be concatenating
23137836SJohn.Forte@Sun.COM * bus/target/lun to equal the complete lun value instead
23147836SJohn.Forte@Sun.COM * of switching to flat space addressing
23157836SJohn.Forte@Sun.COM */
23167836SJohn.Forte@Sun.COM /* 00b - peripheral device addressing method */
23177836SJohn.Forte@Sun.COM case SCSI_REPORTLUNS_ADDRESS_PERIPHERAL:
23187836SJohn.Forte@Sun.COM /* FALLTHRU */
23197836SJohn.Forte@Sun.COM /* 10b - logical unit addressing method */
23207836SJohn.Forte@Sun.COM case SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT:
23217836SJohn.Forte@Sun.COM /* FALLTHRU */
23227836SJohn.Forte@Sun.COM /* 01b - flat space addressing method */
23237836SJohn.Forte@Sun.COM case SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE:
23247836SJohn.Forte@Sun.COM /* byte0 bit0-5=msb lun byte1 bit0-7=lsb lun */
23257836SJohn.Forte@Sun.COM *lun_addr_type = (buf[lun_idx] &
23267836SJohn.Forte@Sun.COM SCSI_REPORTLUNS_ADDRESS_MASK) >> 6;
23277836SJohn.Forte@Sun.COM *lun_num = (buf[lun_idx] & 0x3F) << 8;
23287836SJohn.Forte@Sun.COM *lun_num |= buf[lun_idx + 1];
23297836SJohn.Forte@Sun.COM return (ISCSI_STATUS_SUCCESS);
23307836SJohn.Forte@Sun.COM default: /* protocol error */
23317836SJohn.Forte@Sun.COM cmn_err(CE_NOTE, "iscsi session(%u) unable "
23327836SJohn.Forte@Sun.COM "to enumerate logical units - report "
23337836SJohn.Forte@Sun.COM "luns returned an unsupported format",
23347836SJohn.Forte@Sun.COM isp->sess_oid);
23357836SJohn.Forte@Sun.COM break;
23367836SJohn.Forte@Sun.COM }
23377836SJohn.Forte@Sun.COM return (ISCSI_STATUS_INTERNAL_ERROR);
23387836SJohn.Forte@Sun.COM }
23397836SJohn.Forte@Sun.COM
23407836SJohn.Forte@Sun.COM /*
23417836SJohn.Forte@Sun.COM * iscsi_sess_flush - flushes remaining pending io on the session
23427836SJohn.Forte@Sun.COM */
23437836SJohn.Forte@Sun.COM static void
iscsi_sess_flush(iscsi_sess_t * isp)23447836SJohn.Forte@Sun.COM iscsi_sess_flush(iscsi_sess_t *isp)
23457836SJohn.Forte@Sun.COM {
23467836SJohn.Forte@Sun.COM iscsi_cmd_t *icmdp;
23477836SJohn.Forte@Sun.COM
23487836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
23497836SJohn.Forte@Sun.COM ASSERT(isp->sess_state != ISCSI_SESS_STATE_LOGGED_IN);
23507836SJohn.Forte@Sun.COM
23517836SJohn.Forte@Sun.COM /*
23527836SJohn.Forte@Sun.COM * Flush out any remaining commands in the pending
23537836SJohn.Forte@Sun.COM * queue.
23547836SJohn.Forte@Sun.COM */
23557836SJohn.Forte@Sun.COM mutex_enter(&isp->sess_queue_pending.mutex);
23567836SJohn.Forte@Sun.COM icmdp = isp->sess_queue_pending.head;
23577836SJohn.Forte@Sun.COM while (icmdp != NULL) {
23589780SBing.Zhao@Sun.COM if (isp->sess_state == ISCSI_SESS_STATE_FAILED) {
23599780SBing.Zhao@Sun.COM mutex_enter(&icmdp->cmd_mutex);
23609780SBing.Zhao@Sun.COM if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
23619780SBing.Zhao@Sun.COM icmdp->cmd_un.scsi.pkt_stat |= STAT_ABORTED;
23629780SBing.Zhao@Sun.COM }
23639780SBing.Zhao@Sun.COM mutex_exit(&icmdp->cmd_mutex);
23649780SBing.Zhao@Sun.COM }
23659780SBing.Zhao@Sun.COM
23667836SJohn.Forte@Sun.COM iscsi_cmd_state_machine(icmdp,
23677836SJohn.Forte@Sun.COM ISCSI_CMD_EVENT_E7, isp);
23687836SJohn.Forte@Sun.COM icmdp = isp->sess_queue_pending.head;
23697836SJohn.Forte@Sun.COM }
23707836SJohn.Forte@Sun.COM mutex_exit(&isp->sess_queue_pending.mutex);
23717836SJohn.Forte@Sun.COM }
23727836SJohn.Forte@Sun.COM
23737836SJohn.Forte@Sun.COM /*
23747836SJohn.Forte@Sun.COM * iscsi_sess_offline_luns - offline all this sessions luns
23757836SJohn.Forte@Sun.COM */
23767836SJohn.Forte@Sun.COM static void
iscsi_sess_offline_luns(iscsi_sess_t * isp)23777836SJohn.Forte@Sun.COM iscsi_sess_offline_luns(iscsi_sess_t *isp)
23787836SJohn.Forte@Sun.COM {
23797836SJohn.Forte@Sun.COM iscsi_lun_t *ilp;
23807836SJohn.Forte@Sun.COM iscsi_hba_t *ihp;
23817836SJohn.Forte@Sun.COM
23827836SJohn.Forte@Sun.COM ASSERT(isp != NULL);
23837836SJohn.Forte@Sun.COM ASSERT(isp->sess_state != ISCSI_SESS_STATE_LOGGED_IN);
23847836SJohn.Forte@Sun.COM ihp = isp->sess_hba;
23857836SJohn.Forte@Sun.COM ASSERT(ihp != NULL);
23867836SJohn.Forte@Sun.COM
23877836SJohn.Forte@Sun.COM rw_enter(&isp->sess_lun_list_rwlock, RW_READER);
23887836SJohn.Forte@Sun.COM ilp = isp->sess_lun_list;
23897836SJohn.Forte@Sun.COM while (ilp != NULL) {
23907836SJohn.Forte@Sun.COM (void) iscsi_lun_offline(ihp, ilp, B_FALSE);
23917836SJohn.Forte@Sun.COM ilp = ilp->lun_next;
23927836SJohn.Forte@Sun.COM }
23937836SJohn.Forte@Sun.COM rw_exit(&isp->sess_lun_list_rwlock);
23947836SJohn.Forte@Sun.COM }
23957836SJohn.Forte@Sun.COM
23967836SJohn.Forte@Sun.COM /*
23977836SJohn.Forte@Sun.COM * iscsi_sess_get_by_target - return the session structure for based on a
23987836SJohn.Forte@Sun.COM * passed in target oid and hba instance. NOTE: There may be
23997836SJohn.Forte@Sun.COM * multiple sessions associated with any given target. In this case,
24007836SJohn.Forte@Sun.COM * we will return the first matching session. This function
24017836SJohn.Forte@Sun.COM * is intended to be used in retrieving target info that is constant
24027836SJohn.Forte@Sun.COM * across sessions (target name, alias, etc.).
24037836SJohn.Forte@Sun.COM */
24047836SJohn.Forte@Sun.COM int
iscsi_sess_get_by_target(uint32_t target_oid,iscsi_hba_t * ihp,iscsi_sess_t ** ispp)24057836SJohn.Forte@Sun.COM iscsi_sess_get_by_target(uint32_t target_oid, iscsi_hba_t *ihp,
24067836SJohn.Forte@Sun.COM iscsi_sess_t **ispp)
24077836SJohn.Forte@Sun.COM {
24087836SJohn.Forte@Sun.COM int rval = 0;
24097836SJohn.Forte@Sun.COM iscsi_sess_t *isp = NULL;
24107836SJohn.Forte@Sun.COM
24117836SJohn.Forte@Sun.COM ASSERT(ihp != NULL);
24127836SJohn.Forte@Sun.COM ASSERT(ispp != NULL);
24137836SJohn.Forte@Sun.COM
24147836SJohn.Forte@Sun.COM /* See if we already created this session */
24157836SJohn.Forte@Sun.COM for (isp = ihp->hba_sess_list; isp; isp = isp->sess_next) {
24167836SJohn.Forte@Sun.COM /*
24177836SJohn.Forte@Sun.COM * Look for a session associated to the given target.
24187836SJohn.Forte@Sun.COM * Return the first one found.
24197836SJohn.Forte@Sun.COM */
24207836SJohn.Forte@Sun.COM if (isp->sess_target_oid == target_oid) {
24217836SJohn.Forte@Sun.COM /* Found matching session */
24227836SJohn.Forte@Sun.COM break;
24237836SJohn.Forte@Sun.COM }
24247836SJohn.Forte@Sun.COM }
24257836SJohn.Forte@Sun.COM
24267836SJohn.Forte@Sun.COM /* If not null this session is already available */
24277836SJohn.Forte@Sun.COM if (isp != NULL) {
24287836SJohn.Forte@Sun.COM /* Existing session, return it */
24297836SJohn.Forte@Sun.COM *ispp = isp;
24307836SJohn.Forte@Sun.COM } else {
24317836SJohn.Forte@Sun.COM rval = EFAULT;
24327836SJohn.Forte@Sun.COM }
24337836SJohn.Forte@Sun.COM return (rval);
24347836SJohn.Forte@Sun.COM }
24359780SBing.Zhao@Sun.COM
24369780SBing.Zhao@Sun.COM static void
iscsi_sess_update_busy_luns(iscsi_sess_t * isp,boolean_t clear)24379780SBing.Zhao@Sun.COM iscsi_sess_update_busy_luns(iscsi_sess_t *isp, boolean_t clear)
24389780SBing.Zhao@Sun.COM {
24399780SBing.Zhao@Sun.COM iscsi_lun_t *ilp;
24409780SBing.Zhao@Sun.COM iscsi_hba_t *ihp;
24419780SBing.Zhao@Sun.COM
24429780SBing.Zhao@Sun.COM ASSERT(isp != NULL);
24439780SBing.Zhao@Sun.COM ihp = isp->sess_hba;
24449780SBing.Zhao@Sun.COM ASSERT(ihp != NULL);
24459780SBing.Zhao@Sun.COM
24469780SBing.Zhao@Sun.COM rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
24479780SBing.Zhao@Sun.COM ilp = isp->sess_lun_list;
24489780SBing.Zhao@Sun.COM while (ilp != NULL) {
24499780SBing.Zhao@Sun.COM if (clear == B_TRUE) {
24509780SBing.Zhao@Sun.COM ilp->lun_state &= ~ISCSI_LUN_STATE_BUSY;
24519780SBing.Zhao@Sun.COM } else {
24529780SBing.Zhao@Sun.COM ilp->lun_state |= ISCSI_LUN_STATE_BUSY;
24539780SBing.Zhao@Sun.COM }
24549780SBing.Zhao@Sun.COM ilp = ilp->lun_next;
24559780SBing.Zhao@Sun.COM }
24569780SBing.Zhao@Sun.COM rw_exit(&isp->sess_lun_list_rwlock);
24579780SBing.Zhao@Sun.COM }
2458*12161SJack.Meng@Sun.COM
2459*12161SJack.Meng@Sun.COM /*
2460*12161SJack.Meng@Sun.COM * Submits the scsi enumeration request. Returns
2461*12161SJack.Meng@Sun.COM * ISCSI_SESS_ENUM_SUBMITTED upon success, or others if failures are met.
2462*12161SJack.Meng@Sun.COM * If the request is submitted and the wait is set to B_TRUE, the caller
2463*12161SJack.Meng@Sun.COM * must call iscsi_sess_enum_query at a later time to unblock next enum
2464*12161SJack.Meng@Sun.COM */
2465*12161SJack.Meng@Sun.COM iscsi_enum_result_t
iscsi_sess_enum_request(iscsi_sess_t * isp,boolean_t wait,uint32_t event_count)2466*12161SJack.Meng@Sun.COM iscsi_sess_enum_request(iscsi_sess_t *isp, boolean_t wait,
2467*12161SJack.Meng@Sun.COM uint32_t event_count) {
2468*12161SJack.Meng@Sun.COM iscsi_task_t *itp;
2469*12161SJack.Meng@Sun.COM
2470*12161SJack.Meng@Sun.COM itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP);
2471*12161SJack.Meng@Sun.COM itp->t_arg = isp;
2472*12161SJack.Meng@Sun.COM itp->t_event_count = event_count;
2473*12161SJack.Meng@Sun.COM
2474*12161SJack.Meng@Sun.COM mutex_enter(&isp->sess_enum_lock);
2475*12161SJack.Meng@Sun.COM while ((isp->sess_enum_status != ISCSI_SESS_ENUM_FREE) &&
2476*12161SJack.Meng@Sun.COM (isp->sess_enum_status != ISCSI_SESS_ENUM_INPROG)) {
2477*12161SJack.Meng@Sun.COM cv_wait(&isp->sess_enum_cv, &isp->sess_enum_lock);
2478*12161SJack.Meng@Sun.COM }
2479*12161SJack.Meng@Sun.COM if (isp->sess_enum_status == ISCSI_SESS_ENUM_INPROG) {
2480*12161SJack.Meng@Sun.COM /* easy case */
2481*12161SJack.Meng@Sun.COM if (wait == B_TRUE) {
2482*12161SJack.Meng@Sun.COM isp->sess_enum_result_count ++;
2483*12161SJack.Meng@Sun.COM }
2484*12161SJack.Meng@Sun.COM mutex_exit(&isp->sess_enum_lock);
2485*12161SJack.Meng@Sun.COM kmem_free(itp, sizeof (iscsi_task_t));
2486*12161SJack.Meng@Sun.COM return (ISCSI_SESS_ENUM_SUBMITTED);
2487*12161SJack.Meng@Sun.COM }
2488*12161SJack.Meng@Sun.COM
2489*12161SJack.Meng@Sun.COM ASSERT(isp->sess_enum_status == ISCSI_SESS_ENUM_FREE);
2490*12161SJack.Meng@Sun.COM ASSERT(isp->sess_enum_result_count == 0);
2491*12161SJack.Meng@Sun.COM
2492*12161SJack.Meng@Sun.COM isp->sess_enum_status = ISCSI_SESS_ENUM_INPROG;
2493*12161SJack.Meng@Sun.COM if (ddi_taskq_dispatch(isp->sess_enum_taskq,
2494*12161SJack.Meng@Sun.COM iscsi_sess_enumeration, itp, DDI_SLEEP) != DDI_SUCCESS) {
2495*12161SJack.Meng@Sun.COM isp->sess_enum_status = ISCSI_SESS_ENUM_FREE;
2496*12161SJack.Meng@Sun.COM mutex_exit(&isp->sess_enum_lock);
2497*12161SJack.Meng@Sun.COM kmem_free(itp, sizeof (iscsi_task_t));
2498*12161SJack.Meng@Sun.COM return (ISCSI_SESS_ENUM_SUBFAIL);
2499*12161SJack.Meng@Sun.COM }
2500*12161SJack.Meng@Sun.COM if (wait == B_TRUE) {
2501*12161SJack.Meng@Sun.COM isp->sess_enum_result_count ++;
2502*12161SJack.Meng@Sun.COM }
2503*12161SJack.Meng@Sun.COM mutex_exit(&isp->sess_enum_lock);
2504*12161SJack.Meng@Sun.COM return (ISCSI_SESS_ENUM_SUBMITTED);
2505*12161SJack.Meng@Sun.COM }
2506*12161SJack.Meng@Sun.COM
2507*12161SJack.Meng@Sun.COM /*
2508*12161SJack.Meng@Sun.COM * Wait and query the result of the enumeration.
2509*12161SJack.Meng@Sun.COM * The last caller is responsible for kicking off the DONE status
2510*12161SJack.Meng@Sun.COM */
2511*12161SJack.Meng@Sun.COM iscsi_enum_result_t
iscsi_sess_enum_query(iscsi_sess_t * isp)2512*12161SJack.Meng@Sun.COM iscsi_sess_enum_query(iscsi_sess_t *isp) {
2513*12161SJack.Meng@Sun.COM iscsi_enum_result_t ret = ISCSI_SESS_ENUM_IOFAIL;
2514*12161SJack.Meng@Sun.COM
2515*12161SJack.Meng@Sun.COM mutex_enter(&isp->sess_enum_lock);
2516*12161SJack.Meng@Sun.COM while (isp->sess_enum_status != ISCSI_SESS_ENUM_DONE) {
2517*12161SJack.Meng@Sun.COM cv_wait(&isp->sess_enum_cv, &isp->sess_enum_lock);
2518*12161SJack.Meng@Sun.COM }
2519*12161SJack.Meng@Sun.COM ret = isp->sess_enum_result;
2520*12161SJack.Meng@Sun.COM isp->sess_enum_result_count --;
2521*12161SJack.Meng@Sun.COM if (isp->sess_enum_result_count == 0) {
2522*12161SJack.Meng@Sun.COM isp->sess_enum_status = ISCSI_SESS_ENUM_FREE;
2523*12161SJack.Meng@Sun.COM cv_broadcast(&isp->sess_enum_cv);
2524*12161SJack.Meng@Sun.COM }
2525*12161SJack.Meng@Sun.COM mutex_exit(&isp->sess_enum_lock);
2526*12161SJack.Meng@Sun.COM
2527*12161SJack.Meng@Sun.COM return (ret);
2528*12161SJack.Meng@Sun.COM }
2529*12161SJack.Meng@Sun.COM
2530*12161SJack.Meng@Sun.COM static void
iscsi_sess_enum_warn(iscsi_sess_t * isp,iscsi_enum_result_t r)2531*12161SJack.Meng@Sun.COM iscsi_sess_enum_warn(iscsi_sess_t *isp, iscsi_enum_result_t r) {
2532*12161SJack.Meng@Sun.COM cmn_err(CE_WARN, "iscsi session (%u) enumeration fails - %s",
2533*12161SJack.Meng@Sun.COM isp->sess_oid, iscsi_sess_enum_warn_msgs[r]);
2534*12161SJack.Meng@Sun.COM }
2535*12161SJack.Meng@Sun.COM
2536*12161SJack.Meng@Sun.COM void
iscsi_sess_enter_state_zone(iscsi_sess_t * isp)2537*12161SJack.Meng@Sun.COM iscsi_sess_enter_state_zone(iscsi_sess_t *isp) {
2538*12161SJack.Meng@Sun.COM mutex_enter(&isp->sess_state_wmutex);
2539*12161SJack.Meng@Sun.COM while (isp->sess_state_hasw == B_TRUE) {
2540*12161SJack.Meng@Sun.COM cv_wait(&isp->sess_state_wcv, &isp->sess_state_wmutex);
2541*12161SJack.Meng@Sun.COM }
2542*12161SJack.Meng@Sun.COM isp->sess_state_hasw = B_TRUE;
2543*12161SJack.Meng@Sun.COM mutex_exit(&isp->sess_state_wmutex);
2544*12161SJack.Meng@Sun.COM
2545*12161SJack.Meng@Sun.COM rw_enter(&isp->sess_state_rwlock, RW_WRITER);
2546*12161SJack.Meng@Sun.COM }
2547*12161SJack.Meng@Sun.COM
2548*12161SJack.Meng@Sun.COM void
iscsi_sess_exit_state_zone(iscsi_sess_t * isp)2549*12161SJack.Meng@Sun.COM iscsi_sess_exit_state_zone(iscsi_sess_t *isp) {
2550*12161SJack.Meng@Sun.COM rw_exit(&isp->sess_state_rwlock);
2551*12161SJack.Meng@Sun.COM
2552*12161SJack.Meng@Sun.COM mutex_enter(&isp->sess_state_wmutex);
2553*12161SJack.Meng@Sun.COM isp->sess_state_hasw = B_FALSE;
2554*12161SJack.Meng@Sun.COM cv_signal(&isp->sess_state_wcv);
2555*12161SJack.Meng@Sun.COM mutex_exit(&isp->sess_state_wmutex);
2556*12161SJack.Meng@Sun.COM }
2557