1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte * CDDL HEADER START
3fcf3ce44SJohn Forte *
4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte *
8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte * and limitations under the License.
12fcf3ce44SJohn Forte *
13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte *
19fcf3ce44SJohn Forte * CDDL HEADER END
20fcf3ce44SJohn Forte */
21fcf3ce44SJohn Forte /*
22904e51f6SJack Meng * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23fcf3ce44SJohn Forte *
24fcf3ce44SJohn Forte * iSCSI connection interfaces
25fcf3ce44SJohn Forte */
26fcf3ce44SJohn Forte
2730e7468fSPeter Dunlap #define ISCSI_ICS_NAMES
28fcf3ce44SJohn Forte #include "iscsi.h"
29fcf3ce44SJohn Forte #include "persistent.h"
306cefaae1SJack Meng #include <sys/bootprops.h>
316cefaae1SJack Meng
326cefaae1SJack Meng extern ib_boot_prop_t *iscsiboot_prop;
33fcf3ce44SJohn Forte
3430e7468fSPeter Dunlap static void iscsi_client_notify_task(void *cn_task_void);
35fcf3ce44SJohn Forte
3630e7468fSPeter Dunlap static void iscsi_conn_flush_active_cmds(iscsi_conn_t *icp);
37fcf3ce44SJohn Forte
38fcf3ce44SJohn Forte #define SHUTDOWN_TIMEOUT 180 /* seconds */
39fcf3ce44SJohn Forte
406cefaae1SJack Meng extern int modrootloaded;
4130e7468fSPeter Dunlap
4230e7468fSPeter Dunlap boolean_t iscsi_conn_logging = B_FALSE;
4330e7468fSPeter Dunlap
44cc7ef495Syi zhang - Sun Microsystems - Beijing China #define ISCSI_LOGIN_TPGT_NEGO_ERROR(icp) \
45cc7ef495Syi zhang - Sun Microsystems - Beijing China (((icp)->conn_login_state == LOGIN_ERROR) && \
46cc7ef495Syi zhang - Sun Microsystems - Beijing China ((icp)->conn_login_status == ISCSI_STATUS_LOGIN_TPGT_NEGO_FAIL))
47cc7ef495Syi zhang - Sun Microsystems - Beijing China
48fcf3ce44SJohn Forte /*
49fcf3ce44SJohn Forte * +--------------------------------------------------------------------+
50fcf3ce44SJohn Forte * | External Connection Interfaces |
51fcf3ce44SJohn Forte * +--------------------------------------------------------------------+
52fcf3ce44SJohn Forte */
53fcf3ce44SJohn Forte
54fcf3ce44SJohn Forte /*
55fcf3ce44SJohn Forte * iscsi_conn_create - This creates an iscsi connection structure and
56fcf3ce44SJohn Forte * associates it with a session structure. The session's sess_conn_list_rwlock
57fcf3ce44SJohn Forte * should be held as a writer before calling this function.
58fcf3ce44SJohn Forte */
59fcf3ce44SJohn Forte iscsi_status_t
iscsi_conn_create(struct sockaddr * addr,iscsi_sess_t * isp,iscsi_conn_t ** icpp)60fcf3ce44SJohn Forte iscsi_conn_create(struct sockaddr *addr, iscsi_sess_t *isp, iscsi_conn_t **icpp)
61fcf3ce44SJohn Forte {
62fcf3ce44SJohn Forte iscsi_conn_t *icp = NULL;
63fcf3ce44SJohn Forte char th_name[ISCSI_TH_MAX_NAME_LEN];
64fcf3ce44SJohn Forte
65fcf3ce44SJohn Forte /* See if this connection already exists */
66fcf3ce44SJohn Forte for (icp = isp->sess_conn_list; icp; icp = icp->conn_next) {
67fcf3ce44SJohn Forte
68fcf3ce44SJohn Forte /*
69fcf3ce44SJohn Forte * Compare the ioctl information to see if
70fcf3ce44SJohn Forte * its a match for this connection. (This
71fcf3ce44SJohn Forte * is done by making sure the IPs are of
72fcf3ce44SJohn Forte * the same size and then they are the
73fcf3ce44SJohn Forte * same value.
74fcf3ce44SJohn Forte */
75fcf3ce44SJohn Forte if (bcmp(&icp->conn_base_addr, addr,
76fcf3ce44SJohn Forte SIZEOF_SOCKADDR(addr)) == 0) {
77fcf3ce44SJohn Forte /* It's a match, record this connection */
78fcf3ce44SJohn Forte break;
79fcf3ce44SJohn Forte }
80fcf3ce44SJohn Forte }
81fcf3ce44SJohn Forte
82fcf3ce44SJohn Forte /* If icp is found return it */
83fcf3ce44SJohn Forte if (icp != NULL) {
84fcf3ce44SJohn Forte *icpp = icp;
85fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS);
86fcf3ce44SJohn Forte }
87fcf3ce44SJohn Forte
88fcf3ce44SJohn Forte /* We are creating the connection, allocate, and setup */
89fcf3ce44SJohn Forte icp = (iscsi_conn_t *)kmem_zalloc(sizeof (iscsi_conn_t), KM_SLEEP);
90fcf3ce44SJohn Forte
91fcf3ce44SJohn Forte /*
92fcf3ce44SJohn Forte * Setup connection
93fcf3ce44SJohn Forte */
94fcf3ce44SJohn Forte icp->conn_sig = ISCSI_SIG_CONN;
95fcf3ce44SJohn Forte icp->conn_state = ISCSI_CONN_STATE_FREE;
96fcf3ce44SJohn Forte mutex_init(&icp->conn_state_mutex, NULL, MUTEX_DRIVER, NULL);
97fcf3ce44SJohn Forte cv_init(&icp->conn_state_change, NULL, CV_DRIVER, NULL);
9830e7468fSPeter Dunlap mutex_init(&icp->conn_login_mutex, NULL, MUTEX_DRIVER, NULL);
9930e7468fSPeter Dunlap cv_init(&icp->conn_login_cv, NULL, CV_DRIVER, NULL);
100fcf3ce44SJohn Forte icp->conn_state_destroy = B_FALSE;
10130e7468fSPeter Dunlap idm_sm_audit_init(&icp->conn_state_audit);
102fcf3ce44SJohn Forte icp->conn_sess = isp;
103fcf3ce44SJohn Forte
104fcf3ce44SJohn Forte mutex_enter(&iscsi_oid_mutex);
105fcf3ce44SJohn Forte icp->conn_oid = iscsi_oid++;
106fcf3ce44SJohn Forte mutex_exit(&iscsi_oid_mutex);
107fcf3ce44SJohn Forte
10830e7468fSPeter Dunlap /*
10930e7468fSPeter Dunlap * IDM CN taskq
11030e7468fSPeter Dunlap */
11130e7468fSPeter Dunlap
11230e7468fSPeter Dunlap if (snprintf(th_name, sizeof (th_name) - 1,
11330e7468fSPeter Dunlap ISCSI_CONN_CN_TASKQ_NAME_FORMAT,
114fcf3ce44SJohn Forte icp->conn_sess->sess_hba->hba_oid, icp->conn_sess->sess_oid,
115fcf3ce44SJohn Forte icp->conn_oid) >= sizeof (th_name)) {
116fcf3ce44SJohn Forte cv_destroy(&icp->conn_state_change);
117fcf3ce44SJohn Forte mutex_destroy(&icp->conn_state_mutex);
118fcf3ce44SJohn Forte kmem_free(icp, sizeof (iscsi_conn_t));
119fcf3ce44SJohn Forte *icpp = NULL;
120fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
121fcf3ce44SJohn Forte }
122fcf3ce44SJohn Forte
12330e7468fSPeter Dunlap icp->conn_cn_taskq =
12430e7468fSPeter Dunlap ddi_taskq_create(icp->conn_sess->sess_hba->hba_dip, th_name, 1,
12530e7468fSPeter Dunlap TASKQ_DEFAULTPRI, 0);
12630e7468fSPeter Dunlap if (icp->conn_cn_taskq == NULL) {
12730e7468fSPeter Dunlap cv_destroy(&icp->conn_state_change);
12830e7468fSPeter Dunlap mutex_destroy(&icp->conn_state_mutex);
12930e7468fSPeter Dunlap kmem_free(icp, sizeof (iscsi_conn_t));
13030e7468fSPeter Dunlap *icpp = NULL;
13130e7468fSPeter Dunlap return (ISCSI_STATUS_INTERNAL_ERROR);
13230e7468fSPeter Dunlap }
133fcf3ce44SJohn Forte
134fcf3ce44SJohn Forte /* Creation of the transfer thread */
135fcf3ce44SJohn Forte if (snprintf(th_name, sizeof (th_name) - 1, ISCSI_CONN_TXTH_NAME_FORMAT,
136fcf3ce44SJohn Forte icp->conn_sess->sess_hba->hba_oid, icp->conn_sess->sess_oid,
137fcf3ce44SJohn Forte icp->conn_oid) >= sizeof (th_name)) {
138fcf3ce44SJohn Forte cv_destroy(&icp->conn_state_change);
139fcf3ce44SJohn Forte mutex_destroy(&icp->conn_state_mutex);
140fcf3ce44SJohn Forte kmem_free(icp, sizeof (iscsi_conn_t));
14130e7468fSPeter Dunlap ddi_taskq_destroy(icp->conn_cn_taskq);
142fcf3ce44SJohn Forte *icpp = NULL;
143fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
144fcf3ce44SJohn Forte }
145fcf3ce44SJohn Forte
146fcf3ce44SJohn Forte icp->conn_tx_thread = iscsi_thread_create(isp->sess_hba->hba_dip,
147fcf3ce44SJohn Forte th_name, iscsi_tx_thread, icp);
148fcf3ce44SJohn Forte
149fcf3ce44SJohn Forte /* setup connection queues */
150fcf3ce44SJohn Forte iscsi_init_queue(&icp->conn_queue_active);
15130e7468fSPeter Dunlap iscsi_init_queue(&icp->conn_queue_idm_aborting);
152fcf3ce44SJohn Forte
153fcf3ce44SJohn Forte bcopy(addr, &icp->conn_base_addr, sizeof (icp->conn_base_addr));
154fcf3ce44SJohn Forte
155fcf3ce44SJohn Forte /* Add new connection to the session connection list */
156fcf3ce44SJohn Forte icp->conn_cid = isp->sess_conn_next_cid++;
157fcf3ce44SJohn Forte if (isp->sess_conn_list == NULL) {
158fcf3ce44SJohn Forte isp->sess_conn_list = isp->sess_conn_list_last_ptr = icp;
159fcf3ce44SJohn Forte } else {
160fcf3ce44SJohn Forte isp->sess_conn_list_last_ptr->conn_next = icp;
161fcf3ce44SJohn Forte isp->sess_conn_list_last_ptr = icp;
162fcf3ce44SJohn Forte }
163fcf3ce44SJohn Forte
164fcf3ce44SJohn Forte KSTAT_INC_SESS_CNTR_CONN(isp);
165fcf3ce44SJohn Forte (void) iscsi_conn_kstat_init(icp);
166fcf3ce44SJohn Forte
167fcf3ce44SJohn Forte *icpp = icp;
168fcf3ce44SJohn Forte
169fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS);
170fcf3ce44SJohn Forte }
171fcf3ce44SJohn Forte
17230e7468fSPeter Dunlap /*
17330e7468fSPeter Dunlap * iscsi_conn_online - This attempts to take a connection from
17430e7468fSPeter Dunlap * ISCSI_CONN_STATE_FREE to ISCSI_CONN_STATE_LOGGED_IN.
17530e7468fSPeter Dunlap */
17630e7468fSPeter Dunlap iscsi_status_t
iscsi_conn_online(iscsi_conn_t * icp)17730e7468fSPeter Dunlap iscsi_conn_online(iscsi_conn_t *icp)
17830e7468fSPeter Dunlap {
17930e7468fSPeter Dunlap iscsi_task_t *itp;
18030e7468fSPeter Dunlap iscsi_status_t rval;
18130e7468fSPeter Dunlap
18230e7468fSPeter Dunlap ASSERT(icp != NULL);
18330e7468fSPeter Dunlap ASSERT(mutex_owned(&icp->conn_state_mutex));
18430e7468fSPeter Dunlap ASSERT(icp->conn_state == ISCSI_CONN_STATE_FREE);
18530e7468fSPeter Dunlap
18630e7468fSPeter Dunlap /*
18730e7468fSPeter Dunlap * If we are attempting to connect then for the purposes of the
18830e7468fSPeter Dunlap * other initiator code we are effectively in ISCSI_CONN_STATE_IN_LOGIN.
18930e7468fSPeter Dunlap */
19030e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, ISCSI_CONN_STATE_IN_LOGIN);
19130e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex);
19230e7468fSPeter Dunlap
19330e7468fSPeter Dunlap /*
19430e7468fSPeter Dunlap * Sync base connection information before login
19530e7468fSPeter Dunlap * A login redirection might have shifted the
19630e7468fSPeter Dunlap * current information from the base.
19730e7468fSPeter Dunlap */
19830e7468fSPeter Dunlap bcopy(&icp->conn_base_addr, &icp->conn_curr_addr,
19930e7468fSPeter Dunlap sizeof (icp->conn_curr_addr));
20030e7468fSPeter Dunlap
20130e7468fSPeter Dunlap itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP);
20230e7468fSPeter Dunlap ASSERT(itp != NULL);
20330e7468fSPeter Dunlap
20430e7468fSPeter Dunlap itp->t_arg = icp;
20530e7468fSPeter Dunlap itp->t_blocking = B_TRUE;
20630e7468fSPeter Dunlap rval = iscsi_login_start(itp);
20730e7468fSPeter Dunlap kmem_free(itp, sizeof (iscsi_task_t));
20830e7468fSPeter Dunlap
20930e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex);
21030e7468fSPeter Dunlap
21130e7468fSPeter Dunlap return (rval);
21230e7468fSPeter Dunlap }
213fcf3ce44SJohn Forte
214fcf3ce44SJohn Forte /*
215fcf3ce44SJohn Forte * iscsi_conn_offline - This attempts to take a connection from
216fcf3ce44SJohn Forte * any state to ISCSI_CONN_STATE_FREE.
217fcf3ce44SJohn Forte */
218fcf3ce44SJohn Forte iscsi_status_t
iscsi_conn_offline(iscsi_conn_t * icp)219fcf3ce44SJohn Forte iscsi_conn_offline(iscsi_conn_t *icp)
220fcf3ce44SJohn Forte {
221fcf3ce44SJohn Forte clock_t delay;
222fcf3ce44SJohn Forte
223fcf3ce44SJohn Forte ASSERT(icp != NULL);
224fcf3ce44SJohn Forte
225fcf3ce44SJohn Forte /*
226fcf3ce44SJohn Forte * We can only destroy a connection if its either in
227fcf3ce44SJohn Forte * a state of FREE or LOGGED. The other states are
228fcf3ce44SJohn Forte * transitionary and its unsafe to perform actions
229fcf3ce44SJohn Forte * on the connection in those states. Set a flag
230fcf3ce44SJohn Forte * on the connection to influence the transitions
231fcf3ce44SJohn Forte * to quickly complete. Then wait for a state
232fcf3ce44SJohn Forte * transition.
23330e7468fSPeter Dunlap *
23430e7468fSPeter Dunlap * ISCSI_CONN_STATE_LOGGED_IN is set immediately at the
23530e7468fSPeter Dunlap * start of CN_NOTIFY_FFP processing. icp->conn_state_ffp
23630e7468fSPeter Dunlap * is set to true at the end of ffp processing, at which
23730e7468fSPeter Dunlap * point any session updates are complete. We don't
23830e7468fSPeter Dunlap * want to start offlining the connection before we're
23930e7468fSPeter Dunlap * done completing the FFP processing since this might
24030e7468fSPeter Dunlap * interrupt the discovery process.
241fcf3ce44SJohn Forte */
242fcf3ce44SJohn Forte delay = ddi_get_lbolt() + SEC_TO_TICK(SHUTDOWN_TIMEOUT);
243fcf3ce44SJohn Forte mutex_enter(&icp->conn_state_mutex);
244fcf3ce44SJohn Forte icp->conn_state_destroy = B_TRUE;
24530e7468fSPeter Dunlap while ((((icp->conn_state != ISCSI_CONN_STATE_FREE) &&
24630e7468fSPeter Dunlap (icp->conn_state != ISCSI_CONN_STATE_LOGGED_IN)) ||
24730e7468fSPeter Dunlap ((icp->conn_state == ISCSI_CONN_STATE_LOGGED_IN) &&
24830e7468fSPeter Dunlap !icp->conn_state_ffp)) &&
249fcf3ce44SJohn Forte (ddi_get_lbolt() < delay)) {
250fcf3ce44SJohn Forte /* wait for transition */
251fcf3ce44SJohn Forte (void) cv_timedwait(&icp->conn_state_change,
252fcf3ce44SJohn Forte &icp->conn_state_mutex, delay);
253fcf3ce44SJohn Forte }
254fcf3ce44SJohn Forte
255fcf3ce44SJohn Forte switch (icp->conn_state) {
256fcf3ce44SJohn Forte case ISCSI_CONN_STATE_FREE:
257fcf3ce44SJohn Forte break;
258fcf3ce44SJohn Forte case ISCSI_CONN_STATE_LOGGED_IN:
25992adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States if (icp->conn_state_ffp) {
26092adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* Hold is released in iscsi_handle_logout */
26192adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_hold(icp->conn_ic);
26230e7468fSPeter Dunlap (void) iscsi_handle_logout(icp);
26392adbba7SPeter Cudhea - Sun Microsystems - Burlington, MA United States } else {
26430e7468fSPeter Dunlap icp->conn_state_destroy = B_FALSE;
26530e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex);
26630e7468fSPeter Dunlap return (ISCSI_STATUS_INTERNAL_ERROR);
26730e7468fSPeter Dunlap }
268fcf3ce44SJohn Forte break;
269fcf3ce44SJohn Forte case ISCSI_CONN_STATE_IN_LOGIN:
270fcf3ce44SJohn Forte case ISCSI_CONN_STATE_IN_LOGOUT:
271fcf3ce44SJohn Forte case ISCSI_CONN_STATE_FAILED:
272fcf3ce44SJohn Forte case ISCSI_CONN_STATE_POLLING:
273fcf3ce44SJohn Forte default:
274fcf3ce44SJohn Forte icp->conn_state_destroy = B_FALSE;
275fcf3ce44SJohn Forte mutex_exit(&icp->conn_state_mutex);
276fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
277fcf3ce44SJohn Forte }
278fcf3ce44SJohn Forte mutex_exit(&icp->conn_state_mutex);
279fcf3ce44SJohn Forte
280fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS);
281fcf3ce44SJohn Forte }
282fcf3ce44SJohn Forte
283fcf3ce44SJohn Forte /*
284fcf3ce44SJohn Forte * iscsi_conn_destroy - This destroys an iscsi connection structure
285fcf3ce44SJohn Forte * and de-associates it with the session. The connection should
286fcf3ce44SJohn Forte * already been in the ISCSI_CONN_STATE_FREE when attempting this
287fcf3ce44SJohn Forte * operation.
288fcf3ce44SJohn Forte */
289fcf3ce44SJohn Forte iscsi_status_t
iscsi_conn_destroy(iscsi_conn_t * icp)290fcf3ce44SJohn Forte iscsi_conn_destroy(iscsi_conn_t *icp)
291fcf3ce44SJohn Forte {
292fcf3ce44SJohn Forte iscsi_sess_t *isp;
293fcf3ce44SJohn Forte iscsi_conn_t *t_icp;
294fcf3ce44SJohn Forte
295fcf3ce44SJohn Forte ASSERT(icp != NULL);
296fcf3ce44SJohn Forte isp = icp->conn_sess;
297fcf3ce44SJohn Forte ASSERT(isp != NULL);
298fcf3ce44SJohn Forte
299fcf3ce44SJohn Forte if (icp->conn_state != ISCSI_CONN_STATE_FREE) {
300fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
301fcf3ce44SJohn Forte }
302fcf3ce44SJohn Forte
303fcf3ce44SJohn Forte /* Destroy transfer thread */
304fcf3ce44SJohn Forte iscsi_thread_destroy(icp->conn_tx_thread);
30530e7468fSPeter Dunlap ddi_taskq_destroy(icp->conn_cn_taskq);
306fcf3ce44SJohn Forte
307fcf3ce44SJohn Forte /* Terminate connection queues */
30830e7468fSPeter Dunlap iscsi_destroy_queue(&icp->conn_queue_idm_aborting);
309fcf3ce44SJohn Forte iscsi_destroy_queue(&icp->conn_queue_active);
310fcf3ce44SJohn Forte
31130e7468fSPeter Dunlap cv_destroy(&icp->conn_login_cv);
31230e7468fSPeter Dunlap mutex_destroy(&icp->conn_login_mutex);
313fcf3ce44SJohn Forte cv_destroy(&icp->conn_state_change);
314fcf3ce44SJohn Forte mutex_destroy(&icp->conn_state_mutex);
315fcf3ce44SJohn Forte
316fcf3ce44SJohn Forte /*
317fcf3ce44SJohn Forte * Remove connection from sessions linked list.
318fcf3ce44SJohn Forte */
319fcf3ce44SJohn Forte if (isp->sess_conn_list == icp) {
320fcf3ce44SJohn Forte /* connection first item in list */
321fcf3ce44SJohn Forte isp->sess_conn_list = icp->conn_next;
322fcf3ce44SJohn Forte /*
323fcf3ce44SJohn Forte * check if this is also the last item in the list
324fcf3ce44SJohn Forte */
325fcf3ce44SJohn Forte if (isp->sess_conn_list_last_ptr == icp) {
326fcf3ce44SJohn Forte isp->sess_conn_list_last_ptr = NULL;
327fcf3ce44SJohn Forte }
328fcf3ce44SJohn Forte } else {
329fcf3ce44SJohn Forte /*
330fcf3ce44SJohn Forte * search session list for icp pointing
331fcf3ce44SJohn Forte * to connection being removed. Then
332fcf3ce44SJohn Forte * update that connections next pointer.
333fcf3ce44SJohn Forte */
334fcf3ce44SJohn Forte t_icp = isp->sess_conn_list;
335fcf3ce44SJohn Forte while (t_icp->conn_next != NULL) {
336fcf3ce44SJohn Forte if (t_icp->conn_next == icp) {
337fcf3ce44SJohn Forte break;
338fcf3ce44SJohn Forte }
339fcf3ce44SJohn Forte t_icp = t_icp->conn_next;
340fcf3ce44SJohn Forte }
341fcf3ce44SJohn Forte if (t_icp->conn_next == icp) {
342fcf3ce44SJohn Forte t_icp->conn_next = icp->conn_next;
343fcf3ce44SJohn Forte /*
344fcf3ce44SJohn Forte * if this is the last connection in the list
345fcf3ce44SJohn Forte * update the last_ptr to point to t_icp
346fcf3ce44SJohn Forte */
347fcf3ce44SJohn Forte if (isp->sess_conn_list_last_ptr == icp) {
348fcf3ce44SJohn Forte isp->sess_conn_list_last_ptr = t_icp;
349fcf3ce44SJohn Forte }
350fcf3ce44SJohn Forte } else {
351fcf3ce44SJohn Forte /* couldn't find session */
352fcf3ce44SJohn Forte ASSERT(FALSE);
353fcf3ce44SJohn Forte }
354fcf3ce44SJohn Forte }
355fcf3ce44SJohn Forte
356fcf3ce44SJohn Forte /* Free this Connections Data */
357fcf3ce44SJohn Forte iscsi_conn_kstat_term(icp);
358fcf3ce44SJohn Forte kmem_free(icp, sizeof (iscsi_conn_t));
359fcf3ce44SJohn Forte
360fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS);
361fcf3ce44SJohn Forte }
362fcf3ce44SJohn Forte
363fcf3ce44SJohn Forte
364fcf3ce44SJohn Forte /*
365fcf3ce44SJohn Forte * iscsi_conn_set_login_min_max - set min/max login window
366fcf3ce44SJohn Forte *
367fcf3ce44SJohn Forte * Used to set the min and max login window. Input values
368fcf3ce44SJohn Forte * are in seconds.
369fcf3ce44SJohn Forte */
370fcf3ce44SJohn Forte void
iscsi_conn_set_login_min_max(iscsi_conn_t * icp,int min,int max)371fcf3ce44SJohn Forte iscsi_conn_set_login_min_max(iscsi_conn_t *icp, int min, int max)
372fcf3ce44SJohn Forte {
373fcf3ce44SJohn Forte ASSERT(icp != NULL);
374fcf3ce44SJohn Forte
375fcf3ce44SJohn Forte icp->conn_login_min = ddi_get_lbolt() + SEC_TO_TICK(min);
376fcf3ce44SJohn Forte icp->conn_login_max = ddi_get_lbolt() + SEC_TO_TICK(max);
377fcf3ce44SJohn Forte }
378fcf3ce44SJohn Forte
379fcf3ce44SJohn Forte
38030e7468fSPeter Dunlap /*
38130e7468fSPeter Dunlap * Process the idm notifications
38230e7468fSPeter Dunlap */
38330e7468fSPeter Dunlap idm_status_t
iscsi_client_notify(idm_conn_t * ic,idm_client_notify_t icn,uintptr_t data)38430e7468fSPeter Dunlap iscsi_client_notify(idm_conn_t *ic, idm_client_notify_t icn, uintptr_t data)
38530e7468fSPeter Dunlap {
38630e7468fSPeter Dunlap iscsi_cn_task_t *cn;
38730e7468fSPeter Dunlap iscsi_conn_t *icp = ic->ic_handle;
38830e7468fSPeter Dunlap iscsi_sess_t *isp;
389904e51f6SJack Meng uint32_t event_count;
390fcf3ce44SJohn Forte
391fcf3ce44SJohn Forte /*
39230e7468fSPeter Dunlap * Don't access icp if the notification is CN_CONNECT_DESTROY
39330e7468fSPeter Dunlap * since icp may have already been freed.
394fcf3ce44SJohn Forte *
3955f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States * In particular, we cannot audit the CN_CONNECT_DESTROY event.
3965f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States *
3975f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States * Handle a few cases immediately, the rest in a task queue.
398fcf3ce44SJohn Forte */
39930e7468fSPeter Dunlap switch (icn) {
40030e7468fSPeter Dunlap case CN_CONNECT_FAIL:
40130e7468fSPeter Dunlap case CN_LOGIN_FAIL:
40230e7468fSPeter Dunlap /*
40330e7468fSPeter Dunlap * Wakeup any thread waiting for login stuff to happen.
40430e7468fSPeter Dunlap */
40530e7468fSPeter Dunlap ASSERT(icp != NULL);
4065f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States
4075f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_enter(&icp->conn_state_mutex);
4085f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_sm_audit_event(&icp->conn_state_audit,
4095f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States SAS_ISCSI_CONN, icp->conn_state, icn, data);
4105f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_exit(&icp->conn_state_mutex);
41130e7468fSPeter Dunlap iscsi_login_update_state(icp, LOGIN_ERROR);
41230e7468fSPeter Dunlap return (IDM_STATUS_SUCCESS);
4135f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States
41430e7468fSPeter Dunlap case CN_READY_FOR_LOGIN:
41530e7468fSPeter Dunlap idm_conn_hold(ic); /* Released in CN_CONNECT_LOST */
4165f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(icp != NULL);
4175f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States
41830e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex);
4195f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_sm_audit_event(&icp->conn_state_audit,
4205f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States SAS_ISCSI_CONN, icp->conn_state, icn, data);
42130e7468fSPeter Dunlap icp->conn_state_idm_connected = B_TRUE;
42230e7468fSPeter Dunlap cv_broadcast(&icp->conn_state_change);
42330e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex);
42430e7468fSPeter Dunlap
42530e7468fSPeter Dunlap iscsi_login_update_state(icp, LOGIN_READY);
42630e7468fSPeter Dunlap return (IDM_STATUS_SUCCESS);
4275f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States
42830e7468fSPeter Dunlap case CN_CONNECT_DESTROY:
42930e7468fSPeter Dunlap /*
43030e7468fSPeter Dunlap * We released any dependecies we had on this object in
43130e7468fSPeter Dunlap * either CN_LOGIN_FAIL or CN_CONNECT_LOST so we just need
43230e7468fSPeter Dunlap * to destroy the IDM connection now.
43330e7468fSPeter Dunlap */
43430e7468fSPeter Dunlap idm_ini_conn_destroy(ic);
43530e7468fSPeter Dunlap return (IDM_STATUS_SUCCESS);
43630e7468fSPeter Dunlap }
437fcf3ce44SJohn Forte
438fcf3ce44SJohn Forte ASSERT(icp != NULL);
4395f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_enter(&icp->conn_state_mutex);
4405f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_sm_audit_event(&icp->conn_state_audit,
4415f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States SAS_ISCSI_CONN, icp->conn_state, icn, data);
4425f7d09c6SPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_exit(&icp->conn_state_mutex);
44330e7468fSPeter Dunlap isp = icp->conn_sess;
444fcf3ce44SJohn Forte
445fcf3ce44SJohn Forte /*
44630e7468fSPeter Dunlap * Dispatch notifications to the taskq since they often require
44730e7468fSPeter Dunlap * long blocking operations. In the case of CN_CONNECT_DESTROY
44830e7468fSPeter Dunlap * we actually just want to destroy the connection which we
44930e7468fSPeter Dunlap * can't do in the IDM taskq context.
450fcf3ce44SJohn Forte */
45130e7468fSPeter Dunlap cn = kmem_alloc(sizeof (*cn), KM_SLEEP);
45230e7468fSPeter Dunlap
45330e7468fSPeter Dunlap cn->ct_ic = ic;
45430e7468fSPeter Dunlap cn->ct_icn = icn;
45530e7468fSPeter Dunlap cn->ct_data = data;
45630e7468fSPeter Dunlap
45730e7468fSPeter Dunlap idm_conn_hold(ic);
45830e7468fSPeter Dunlap
45930e7468fSPeter Dunlap if (ddi_taskq_dispatch(icp->conn_cn_taskq,
46030e7468fSPeter Dunlap iscsi_client_notify_task, cn, DDI_SLEEP) != DDI_SUCCESS) {
46130e7468fSPeter Dunlap idm_conn_rele(ic);
46230e7468fSPeter Dunlap cmn_err(CE_WARN, "iscsi connection(%u) failure - "
46330e7468fSPeter Dunlap "unable to schedule notify task", icp->conn_oid);
46430e7468fSPeter Dunlap iscsi_conn_update_state(icp, ISCSI_CONN_STATE_FREE);
465904e51f6SJack Meng event_count = atomic_inc_32_nv(&isp->sess_state_event_count);
466904e51f6SJack Meng iscsi_sess_enter_state_zone(isp);
467904e51f6SJack Meng
46830e7468fSPeter Dunlap iscsi_sess_state_machine(isp,
469904e51f6SJack Meng ISCSI_SESS_EVENT_N6, event_count);
470904e51f6SJack Meng
471904e51f6SJack Meng iscsi_sess_exit_state_zone(isp);
47230e7468fSPeter Dunlap }
47330e7468fSPeter Dunlap
47430e7468fSPeter Dunlap return (IDM_STATUS_SUCCESS);
47530e7468fSPeter Dunlap }
47630e7468fSPeter Dunlap
47730e7468fSPeter Dunlap static void
iscsi_client_notify_task(void * cn_task_void)47830e7468fSPeter Dunlap iscsi_client_notify_task(void *cn_task_void)
479fcf3ce44SJohn Forte {
48030e7468fSPeter Dunlap iscsi_cn_task_t *cn_task = cn_task_void;
48130e7468fSPeter Dunlap iscsi_conn_t *icp;
48230e7468fSPeter Dunlap iscsi_sess_t *isp;
48330e7468fSPeter Dunlap idm_conn_t *ic;
48430e7468fSPeter Dunlap idm_client_notify_t icn;
48530e7468fSPeter Dunlap uintptr_t data;
48630e7468fSPeter Dunlap idm_ffp_disable_t disable_type;
48730e7468fSPeter Dunlap boolean_t in_login;
488904e51f6SJack Meng uint32_t event_count;
48930e7468fSPeter Dunlap
49030e7468fSPeter Dunlap ic = cn_task->ct_ic;
49130e7468fSPeter Dunlap icn = cn_task->ct_icn;
49230e7468fSPeter Dunlap data = cn_task->ct_data;
49330e7468fSPeter Dunlap
49430e7468fSPeter Dunlap icp = ic->ic_handle;
49530e7468fSPeter Dunlap ASSERT(icp != NULL);
49630e7468fSPeter Dunlap isp = icp->conn_sess;
49730e7468fSPeter Dunlap
49830e7468fSPeter Dunlap switch (icn) {
49930e7468fSPeter Dunlap case CN_FFP_ENABLED:
50030e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex);
50130e7468fSPeter Dunlap icp->conn_async_logout = B_FALSE;
50230e7468fSPeter Dunlap icp->conn_state_ffp = B_TRUE;
50330e7468fSPeter Dunlap cv_broadcast(&icp->conn_state_change);
50430e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex);
50530e7468fSPeter Dunlap
50630e7468fSPeter Dunlap /*
50730e7468fSPeter Dunlap * This logic assumes that the IDM login-snooping code
50819944f88Syi zhang - Sun Microsystems - Beijing China * and the initiator login code will agree to go when
50919944f88Syi zhang - Sun Microsystems - Beijing China * the connection is in FFP or final error received.
51019944f88Syi zhang - Sun Microsystems - Beijing China * The reason we do this is that we don't want to process
51119944f88Syi zhang - Sun Microsystems - Beijing China * CN_FFP_DISABLED until CN_FFP_ENABLED has been full handled.
51230e7468fSPeter Dunlap */
51330e7468fSPeter Dunlap mutex_enter(&icp->conn_login_mutex);
51419944f88Syi zhang - Sun Microsystems - Beijing China while ((icp->conn_login_state != LOGIN_FFP) &&
51519944f88Syi zhang - Sun Microsystems - Beijing China (icp->conn_login_state != LOGIN_ERROR)) {
51630e7468fSPeter Dunlap cv_wait(&icp->conn_login_cv, &icp->conn_login_mutex);
51730e7468fSPeter Dunlap }
51830e7468fSPeter Dunlap mutex_exit(&icp->conn_login_mutex);
51930e7468fSPeter Dunlap break;
52030e7468fSPeter Dunlap case CN_FFP_DISABLED:
52130e7468fSPeter Dunlap disable_type = (idm_ffp_disable_t)data;
52230e7468fSPeter Dunlap
52330e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex);
52430e7468fSPeter Dunlap switch (disable_type) {
52530e7468fSPeter Dunlap case FD_SESS_LOGOUT:
52630e7468fSPeter Dunlap case FD_CONN_LOGOUT:
52730e7468fSPeter Dunlap if (icp->conn_async_logout) {
52830e7468fSPeter Dunlap /*
52930e7468fSPeter Dunlap * Our logout was in response to an
53030e7468fSPeter Dunlap * async logout request so treat this
53130e7468fSPeter Dunlap * like a connection failure (we will
53230e7468fSPeter Dunlap * try to re-establish the connection)
53330e7468fSPeter Dunlap */
53430e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp,
53530e7468fSPeter Dunlap ISCSI_CONN_STATE_FAILED);
53630e7468fSPeter Dunlap } else {
53730e7468fSPeter Dunlap /*
53830e7468fSPeter Dunlap * Logout due to to user config change,
53930e7468fSPeter Dunlap * we will not try to re-establish
54030e7468fSPeter Dunlap * the connection.
54130e7468fSPeter Dunlap */
54230e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp,
54330e7468fSPeter Dunlap ISCSI_CONN_STATE_IN_LOGOUT);
54430e7468fSPeter Dunlap /*
54530e7468fSPeter Dunlap * Hold off generating the ISCSI_SESS_EVENT_N3
54630e7468fSPeter Dunlap * event until we get the CN_CONNECT_LOST
54730e7468fSPeter Dunlap * notification. This matches the pre-IDM
54830e7468fSPeter Dunlap * implementation better.
54930e7468fSPeter Dunlap */
55030e7468fSPeter Dunlap }
55130e7468fSPeter Dunlap break;
55230e7468fSPeter Dunlap
55330e7468fSPeter Dunlap case FD_CONN_FAIL:
554fcf3ce44SJohn Forte default:
55519944f88Syi zhang - Sun Microsystems - Beijing China if (icp->conn_state == ISCSI_CONN_STATE_IN_LOGIN) {
55619944f88Syi zhang - Sun Microsystems - Beijing China iscsi_conn_update_state_locked(icp,
55719944f88Syi zhang - Sun Microsystems - Beijing China ISCSI_CONN_STATE_FREE);
55819944f88Syi zhang - Sun Microsystems - Beijing China } else {
55930e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp,
56030e7468fSPeter Dunlap ISCSI_CONN_STATE_FAILED);
56119944f88Syi zhang - Sun Microsystems - Beijing China }
56230e7468fSPeter Dunlap break;
56330e7468fSPeter Dunlap }
56430e7468fSPeter Dunlap
56530e7468fSPeter Dunlap icp->conn_state_ffp = B_FALSE;
56630e7468fSPeter Dunlap cv_broadcast(&icp->conn_state_change);
56730e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex);
56830e7468fSPeter Dunlap
56930e7468fSPeter Dunlap break;
57030e7468fSPeter Dunlap case CN_CONNECT_LOST:
57130e7468fSPeter Dunlap /*
57230e7468fSPeter Dunlap * We only care about CN_CONNECT_LOST if we've logged in. IDM
57330e7468fSPeter Dunlap * sends a flag as the data payload to indicate whether we
57430e7468fSPeter Dunlap * were trying to login. The CN_LOGIN_FAIL notification
57530e7468fSPeter Dunlap * gives us what we need to know for login failures and
57630e7468fSPeter Dunlap * otherwise we will need to keep a bunch of state to know
57730e7468fSPeter Dunlap * what CN_CONNECT_LOST means to us.
57830e7468fSPeter Dunlap */
57930e7468fSPeter Dunlap in_login = (boolean_t)data;
58019944f88Syi zhang - Sun Microsystems - Beijing China if (in_login ||
58119944f88Syi zhang - Sun Microsystems - Beijing China (icp->conn_prev_state == ISCSI_CONN_STATE_IN_LOGIN)) {
58230e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex);
58330e7468fSPeter Dunlap
58430e7468fSPeter Dunlap icp->conn_state_idm_connected = B_FALSE;
58530e7468fSPeter Dunlap cv_broadcast(&icp->conn_state_change);
58630e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex);
58730e7468fSPeter Dunlap
58830e7468fSPeter Dunlap /* Release connect hold from CN_READY_FOR_LOGIN */
58930e7468fSPeter Dunlap idm_conn_rele(ic);
59030e7468fSPeter Dunlap break;
59130e7468fSPeter Dunlap }
59230e7468fSPeter Dunlap
59330e7468fSPeter Dunlap /* Any remaining commands are never going to finish */
59430e7468fSPeter Dunlap iscsi_conn_flush_active_cmds(icp);
59530e7468fSPeter Dunlap
59630e7468fSPeter Dunlap /*
59730e7468fSPeter Dunlap * The connection is no longer active so cleanup any
59830e7468fSPeter Dunlap * references to the connection and release any holds so
59930e7468fSPeter Dunlap * that IDM can finish cleanup.
60030e7468fSPeter Dunlap */
60130e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex);
60230e7468fSPeter Dunlap if (icp->conn_state != ISCSI_CONN_STATE_FAILED) {
603904e51f6SJack Meng mutex_exit(&icp->conn_state_mutex);
604904e51f6SJack Meng event_count = atomic_inc_32_nv(
605904e51f6SJack Meng &isp->sess_state_event_count);
606904e51f6SJack Meng iscsi_sess_enter_state_zone(isp);
60730e7468fSPeter Dunlap
608904e51f6SJack Meng iscsi_sess_state_machine(isp, ISCSI_SESS_EVENT_N3,
609904e51f6SJack Meng event_count);
61030e7468fSPeter Dunlap
611904e51f6SJack Meng iscsi_sess_exit_state_zone(isp);
612904e51f6SJack Meng
613904e51f6SJack Meng mutex_enter(&icp->conn_state_mutex);
61430e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp,
61530e7468fSPeter Dunlap ISCSI_CONN_STATE_FREE);
61630e7468fSPeter Dunlap } else {
617904e51f6SJack Meng mutex_exit(&icp->conn_state_mutex);
618904e51f6SJack Meng event_count = atomic_inc_32_nv(
619904e51f6SJack Meng &isp->sess_state_event_count);
620904e51f6SJack Meng iscsi_sess_enter_state_zone(isp);
62130e7468fSPeter Dunlap
62230e7468fSPeter Dunlap iscsi_sess_state_machine(isp,
623904e51f6SJack Meng ISCSI_SESS_EVENT_N5, event_count);
624904e51f6SJack Meng
625904e51f6SJack Meng iscsi_sess_exit_state_zone(isp);
62630e7468fSPeter Dunlap
62730e7468fSPeter Dunlap /*
62830e7468fSPeter Dunlap * If session type is NORMAL, try to reestablish the
62930e7468fSPeter Dunlap * connection.
63030e7468fSPeter Dunlap */
631cc7ef495Syi zhang - Sun Microsystems - Beijing China if ((isp->sess_type == ISCSI_SESS_TYPE_NORMAL) &&
632cc7ef495Syi zhang - Sun Microsystems - Beijing China !(ISCSI_LOGIN_TPGT_NEGO_ERROR(icp))) {
63330e7468fSPeter Dunlap iscsi_conn_retry(isp, icp);
634904e51f6SJack Meng mutex_enter(&icp->conn_state_mutex);
63530e7468fSPeter Dunlap } else {
636904e51f6SJack Meng event_count = atomic_inc_32_nv(
637904e51f6SJack Meng &isp->sess_state_event_count);
638904e51f6SJack Meng iscsi_sess_enter_state_zone(isp);
63930e7468fSPeter Dunlap
64030e7468fSPeter Dunlap iscsi_sess_state_machine(isp,
641904e51f6SJack Meng ISCSI_SESS_EVENT_N6, event_count);
64230e7468fSPeter Dunlap
643904e51f6SJack Meng iscsi_sess_exit_state_zone(isp);
644904e51f6SJack Meng
645904e51f6SJack Meng mutex_enter(&icp->conn_state_mutex);
64630e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp,
64730e7468fSPeter Dunlap ISCSI_CONN_STATE_FREE);
648fcf3ce44SJohn Forte }
649fcf3ce44SJohn Forte }
650fcf3ce44SJohn Forte
65130e7468fSPeter Dunlap (void) iscsi_thread_stop(icp->conn_tx_thread);
65230e7468fSPeter Dunlap
65330e7468fSPeter Dunlap icp->conn_state_idm_connected = B_FALSE;
65430e7468fSPeter Dunlap cv_broadcast(&icp->conn_state_change);
65530e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex);
65630e7468fSPeter Dunlap
65730e7468fSPeter Dunlap /* Release connect hold from CN_READY_FOR_LOGIN */
65830e7468fSPeter Dunlap idm_conn_rele(ic);
65930e7468fSPeter Dunlap break;
66030e7468fSPeter Dunlap default:
66130e7468fSPeter Dunlap ISCSI_CONN_LOG(CE_WARN,
66230e7468fSPeter Dunlap "iscsi_client_notify: unknown notification: "
66330e7468fSPeter Dunlap "%x: NOT IMPLEMENTED YET: icp: %p ic: %p ",
66430e7468fSPeter Dunlap icn, (void *)icp, (void *)ic);
66530e7468fSPeter Dunlap break;
66630e7468fSPeter Dunlap }
66730e7468fSPeter Dunlap /* free the task notify structure we allocated in iscsi_client_notify */
66830e7468fSPeter Dunlap kmem_free(cn_task, sizeof (*cn_task));
66930e7468fSPeter Dunlap
67030e7468fSPeter Dunlap /* Release the hold we acquired in iscsi_client_notify */
67130e7468fSPeter Dunlap idm_conn_rele(ic);
67230e7468fSPeter Dunlap }
673fcf3ce44SJohn Forte
674fcf3ce44SJohn Forte /*
675fcf3ce44SJohn Forte * iscsi_conn_sync_params - used to update connection parameters
676fcf3ce44SJohn Forte *
677fcf3ce44SJohn Forte * Used to update connection parameters with current configured
678fcf3ce44SJohn Forte * parameters in the persistent store. This should be called
679fcf3ce44SJohn Forte * before starting to make a new iscsi connection in iscsi_login.
680fcf3ce44SJohn Forte */
681fcf3ce44SJohn Forte iscsi_status_t
iscsi_conn_sync_params(iscsi_conn_t * icp)682fcf3ce44SJohn Forte iscsi_conn_sync_params(iscsi_conn_t *icp)
683fcf3ce44SJohn Forte {
684fcf3ce44SJohn Forte iscsi_sess_t *isp;
685fcf3ce44SJohn Forte iscsi_hba_t *ihp;
686fcf3ce44SJohn Forte int param_id;
687fcf3ce44SJohn Forte persistent_param_t pp;
688aff4bce5Syi zhang - Sun Microsystems - Beijing China persistent_tunable_param_t ptp;
689fcf3ce44SJohn Forte iscsi_config_sess_t *ics;
690fcf3ce44SJohn Forte int idx, size;
691fcf3ce44SJohn Forte char *name;
692fcf3ce44SJohn Forte
693fcf3ce44SJohn Forte ASSERT(icp != NULL);
694fcf3ce44SJohn Forte ASSERT((icp->conn_state == ISCSI_CONN_STATE_IN_LOGIN) ||
695fcf3ce44SJohn Forte (icp->conn_state == ISCSI_CONN_STATE_FAILED) ||
696fcf3ce44SJohn Forte (icp->conn_state == ISCSI_CONN_STATE_POLLING));
697fcf3ce44SJohn Forte isp = icp->conn_sess;
698fcf3ce44SJohn Forte ASSERT(isp != NULL);
699fcf3ce44SJohn Forte ihp = isp->sess_hba;
700fcf3ce44SJohn Forte ASSERT(ihp != NULL);
701fcf3ce44SJohn Forte
702fcf3ce44SJohn Forte /*
703fcf3ce44SJohn Forte * Check if someone is trying to destroy this
704fcf3ce44SJohn Forte * connection. If so fail the sync request,
705fcf3ce44SJohn Forte * as a method of fast fail.
706fcf3ce44SJohn Forte */
707fcf3ce44SJohn Forte if (icp->conn_state_destroy == B_TRUE) {
708fcf3ce44SJohn Forte return (ISCSI_STATUS_SHUTDOWN);
709fcf3ce44SJohn Forte }
710fcf3ce44SJohn Forte
711fcf3ce44SJohn Forte bzero(&pp, sizeof (pp));
712fcf3ce44SJohn Forte
713fcf3ce44SJohn Forte /* First get a copy of the HBA params */
714fcf3ce44SJohn Forte bcopy(&ihp->hba_params, &icp->conn_params,
715fcf3ce44SJohn Forte sizeof (iscsi_login_params_t));
716aff4bce5Syi zhang - Sun Microsystems - Beijing China bcopy(&ihp->hba_tunable_params, &icp->conn_tunable_params,
717aff4bce5Syi zhang - Sun Microsystems - Beijing China sizeof (iscsi_tunable_params_t));
718fcf3ce44SJohn Forte
719fcf3ce44SJohn Forte /*
720fcf3ce44SJohn Forte * Now we need to get the session configured
721fcf3ce44SJohn Forte * values from the persistent store and apply
722fcf3ce44SJohn Forte * them to our connection.
723fcf3ce44SJohn Forte */
724fcf3ce44SJohn Forte (void) persistent_param_get((char *)isp->sess_name, &pp);
725fcf3ce44SJohn Forte for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM;
726fcf3ce44SJohn Forte param_id++) {
7276cefaae1SJack Meng if (iscsiboot_prop && modrootloaded &&
7286cefaae1SJack Meng !iscsi_chk_bootlun_mpxio(ihp) && isp->sess_boot) {
7296cefaae1SJack Meng /*
7306cefaae1SJack Meng * iscsi boot with mpxio disabled
7316cefaae1SJack Meng * while iscsi booting target's parameter overriden
7326cefaae1SJack Meng * do no update target's parameters.
7336cefaae1SJack Meng */
7346cefaae1SJack Meng if (pp.p_bitmap) {
7356cefaae1SJack Meng cmn_err(CE_NOTE, "Adopting "
7366cefaae1SJack Meng " default login parameters in"
7376cefaae1SJack Meng " boot session as MPxIO is disabled");
7386cefaae1SJack Meng }
7396cefaae1SJack Meng break;
7406cefaae1SJack Meng }
741fcf3ce44SJohn Forte if (pp.p_bitmap & (1 << param_id)) {
74230e7468fSPeter Dunlap
743fcf3ce44SJohn Forte switch (param_id) {
744fcf3ce44SJohn Forte /*
745fcf3ce44SJohn Forte * Boolean parameters
746fcf3ce44SJohn Forte */
747fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER:
748fcf3ce44SJohn Forte icp->conn_params.data_pdu_in_order =
749fcf3ce44SJohn Forte pp.p_params.data_pdu_in_order;
750fcf3ce44SJohn Forte break;
751fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_IMMEDIATE_DATA:
752fcf3ce44SJohn Forte icp->conn_params.immediate_data =
753fcf3ce44SJohn Forte pp.p_params.immediate_data;
754fcf3ce44SJohn Forte break;
755fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_INITIAL_R2T:
756fcf3ce44SJohn Forte icp->conn_params.initial_r2t =
757fcf3ce44SJohn Forte pp.p_params.initial_r2t;
758fcf3ce44SJohn Forte break;
759fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER:
760fcf3ce44SJohn Forte icp->conn_params.data_pdu_in_order =
761fcf3ce44SJohn Forte pp.p_params.data_pdu_in_order;
762fcf3ce44SJohn Forte break;
763fcf3ce44SJohn Forte /*
764fcf3ce44SJohn Forte * Integer parameters
765fcf3ce44SJohn Forte */
766fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_HEADER_DIGEST:
767fcf3ce44SJohn Forte icp->conn_params.header_digest =
768fcf3ce44SJohn Forte pp.p_params.header_digest;
769fcf3ce44SJohn Forte break;
770fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DATA_DIGEST:
771fcf3ce44SJohn Forte icp->conn_params.data_digest =
772fcf3ce44SJohn Forte pp.p_params.data_digest;
773fcf3ce44SJohn Forte break;
774fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN:
775fcf3ce44SJohn Forte icp->conn_params.default_time_to_retain =
776fcf3ce44SJohn Forte pp.p_params.default_time_to_retain;
777fcf3ce44SJohn Forte break;
778fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT:
779fcf3ce44SJohn Forte icp->conn_params.default_time_to_wait =
780fcf3ce44SJohn Forte pp.p_params.default_time_to_wait;
781fcf3ce44SJohn Forte break;
782fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH:
783fcf3ce44SJohn Forte icp->conn_params.max_recv_data_seg_len =
784fcf3ce44SJohn Forte pp.p_params.max_recv_data_seg_len;
785fcf3ce44SJohn Forte break;
786fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH:
787fcf3ce44SJohn Forte icp->conn_params.first_burst_length =
788fcf3ce44SJohn Forte pp.p_params.first_burst_length;
789fcf3ce44SJohn Forte break;
790fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH:
791fcf3ce44SJohn Forte icp->conn_params.max_burst_length =
792fcf3ce44SJohn Forte pp.p_params.max_burst_length;
793fcf3ce44SJohn Forte break;
794fcf3ce44SJohn Forte
795fcf3ce44SJohn Forte /*
796fcf3ce44SJohn Forte * Integer parameters which currently are unsettable
797fcf3ce44SJohn Forte */
798fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_MAX_CONNECTIONS:
799fcf3ce44SJohn Forte /* FALLTHRU */
800fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_OUTSTANDING_R2T:
801fcf3ce44SJohn Forte /* FALLTHRU */
802fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL:
803fcf3ce44SJohn Forte /* FALLTHRU */
804fcf3ce44SJohn Forte default:
805fcf3ce44SJohn Forte break;
806fcf3ce44SJohn Forte }
807fcf3ce44SJohn Forte }
808fcf3ce44SJohn Forte }
809fcf3ce44SJohn Forte
810aff4bce5Syi zhang - Sun Microsystems - Beijing China if (persistent_get_tunable_param((char *)isp->sess_name, &ptp) ==
811aff4bce5Syi zhang - Sun Microsystems - Beijing China B_TRUE) {
812aff4bce5Syi zhang - Sun Microsystems - Beijing China if (ptp.p_bitmap & ISCSI_TUNABLE_PARAM_RX_TIMEOUT_VALUE) {
813aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_tunable_params.recv_login_rsp_timeout =
814aff4bce5Syi zhang - Sun Microsystems - Beijing China ptp.p_params.recv_login_rsp_timeout;
815aff4bce5Syi zhang - Sun Microsystems - Beijing China }
816aff4bce5Syi zhang - Sun Microsystems - Beijing China if (ptp.p_bitmap & ISCSI_TUNABLE_PARAM_CONN_LOGIN_MAX) {
817aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_tunable_params.conn_login_max =
818aff4bce5Syi zhang - Sun Microsystems - Beijing China ptp.p_params.conn_login_max;
819aff4bce5Syi zhang - Sun Microsystems - Beijing China }
820aff4bce5Syi zhang - Sun Microsystems - Beijing China if (ptp.p_bitmap & ISCSI_TUNABLE_PARAM_LOGIN_POLLING_DELAY) {
821aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_tunable_params.polling_login_delay =
822aff4bce5Syi zhang - Sun Microsystems - Beijing China ptp.p_params.polling_login_delay;
823aff4bce5Syi zhang - Sun Microsystems - Beijing China }
824aff4bce5Syi zhang - Sun Microsystems - Beijing China }
825aff4bce5Syi zhang - Sun Microsystems - Beijing China
826fcf3ce44SJohn Forte /* Skip binding checks on discovery sessions */
827fcf3ce44SJohn Forte if (isp->sess_type == ISCSI_SESS_TYPE_DISCOVERY) {
828fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS);
829fcf3ce44SJohn Forte }
830fcf3ce44SJohn Forte
831fcf3ce44SJohn Forte /*
832fcf3ce44SJohn Forte * Now we need to get the current optional connection
833fcf3ce44SJohn Forte * binding information.
834fcf3ce44SJohn Forte */
835fcf3ce44SJohn Forte /* setup initial buffer for configured session information */
836fcf3ce44SJohn Forte size = sizeof (*ics);
837fcf3ce44SJohn Forte ics = kmem_zalloc(size, KM_SLEEP);
838fcf3ce44SJohn Forte ics->ics_in = 1;
839fcf3ce44SJohn Forte
840fcf3ce44SJohn Forte /* get configured sessions information */
841fcf3ce44SJohn Forte name = (char *)isp->sess_name;
842fcf3ce44SJohn Forte if (persistent_get_config_session(name, ics) == B_FALSE) {
843fcf3ce44SJohn Forte /*
844fcf3ce44SJohn Forte * If we were unable to get target level information
845fcf3ce44SJohn Forte * then check the initiator level information.
846fcf3ce44SJohn Forte */
847fcf3ce44SJohn Forte name = (char *)isp->sess_hba->hba_name;
848fcf3ce44SJohn Forte if (persistent_get_config_session(name, ics) == B_FALSE) {
849fcf3ce44SJohn Forte /*
850fcf3ce44SJohn Forte * No hba information is found. So assume default
851fcf3ce44SJohn Forte * one session unbound behavior.
852fcf3ce44SJohn Forte */
853fcf3ce44SJohn Forte ics->ics_out = 1;
854fcf3ce44SJohn Forte ics->ics_bound = B_FALSE;
855fcf3ce44SJohn Forte }
856fcf3ce44SJohn Forte }
857fcf3ce44SJohn Forte
8586cefaae1SJack Meng if (iscsiboot_prop && (ics->ics_out > 1) && isp->sess_boot &&
8596cefaae1SJack Meng !iscsi_chk_bootlun_mpxio(ihp)) {
8606cefaae1SJack Meng /*
8616cefaae1SJack Meng * iscsi booting session with mpxio disabled,
8626cefaae1SJack Meng * no need set multiple sessions for booting session
8636cefaae1SJack Meng */
8646cefaae1SJack Meng ics->ics_out = 1;
8656cefaae1SJack Meng ics->ics_bound = B_FALSE;
8666cefaae1SJack Meng cmn_err(CE_NOTE, "MPxIO is disabled,"
8676cefaae1SJack Meng " no need to configure multiple boot sessions");
8686cefaae1SJack Meng }
8696cefaae1SJack Meng
870fcf3ce44SJohn Forte /*
871fcf3ce44SJohn Forte * Check to make sure this session is still a configured
872fcf3ce44SJohn Forte * session. The user might have decreased the session
873fcf3ce44SJohn Forte * count. (NOTE: byte 5 of the sess_isid is the session
874fcf3ce44SJohn Forte * count (via MS/T). This counter starts at 0.)
875fcf3ce44SJohn Forte */
8766cefaae1SJack Meng
8776cefaae1SJack Meng
878fcf3ce44SJohn Forte idx = isp->sess_isid[5];
8796cefaae1SJack Meng
8806cefaae1SJack Meng if (iscsiboot_prop && (idx == ISCSI_MAX_CONFIG_SESSIONS)) {
8816cefaae1SJack Meng /*
8826cefaae1SJack Meng * This is temporary session for boot session propose
8836cefaae1SJack Meng * no need to bound IP for this session
8846cefaae1SJack Meng */
8856cefaae1SJack Meng icp->conn_bound = B_FALSE;
8866cefaae1SJack Meng kmem_free(ics, sizeof (iscsi_config_sess_t));
8876cefaae1SJack Meng return (ISCSI_STATUS_SUCCESS);
8886cefaae1SJack Meng }
8896cefaae1SJack Meng
890fcf3ce44SJohn Forte if (ics->ics_out <= idx) {
891fcf3ce44SJohn Forte /*
892fcf3ce44SJohn Forte * No longer a configured session. Return a
893fcf3ce44SJohn Forte * failure so we don't attempt to relogin.
894fcf3ce44SJohn Forte */
895fcf3ce44SJohn Forte return (ISCSI_STATUS_SHUTDOWN);
896fcf3ce44SJohn Forte }
897fcf3ce44SJohn Forte
898fcf3ce44SJohn Forte /*
899fcf3ce44SJohn Forte * If sessions are unbound set this information on
900fcf3ce44SJohn Forte * the connection and return success.
901fcf3ce44SJohn Forte */
902fcf3ce44SJohn Forte if (ics->ics_bound == B_FALSE) {
903fcf3ce44SJohn Forte icp->conn_bound = B_FALSE;
904fcf3ce44SJohn Forte kmem_free(ics, sizeof (iscsi_config_sess_t));
905fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS);
906fcf3ce44SJohn Forte }
907fcf3ce44SJohn Forte
908fcf3ce44SJohn Forte /*
909fcf3ce44SJohn Forte * Since the sessions are bound we need to find the matching
910fcf3ce44SJohn Forte * binding information for the session's isid. If this
911fcf3ce44SJohn Forte * session's isid is > 0 then we need to get more configured
912fcf3ce44SJohn Forte * session information to find the binding info.
913fcf3ce44SJohn Forte */
914fcf3ce44SJohn Forte if (idx > 0) {
915fcf3ce44SJohn Forte int ics_out;
916fcf3ce44SJohn Forte
917fcf3ce44SJohn Forte ics_out = ics->ics_out;
918fcf3ce44SJohn Forte /* record new size and free last buffer */
919fcf3ce44SJohn Forte size = ISCSI_SESSION_CONFIG_SIZE(ics_out);
920fcf3ce44SJohn Forte kmem_free(ics, sizeof (*ics));
921fcf3ce44SJohn Forte
922fcf3ce44SJohn Forte /* allocate new buffer */
923fcf3ce44SJohn Forte ics = kmem_zalloc(size, KM_SLEEP);
924fcf3ce44SJohn Forte ics->ics_in = ics_out;
925fcf3ce44SJohn Forte
926fcf3ce44SJohn Forte /* get configured sessions information */
927fcf3ce44SJohn Forte if (persistent_get_config_session(name, ics) != B_TRUE) {
928fcf3ce44SJohn Forte cmn_err(CE_NOTE, "iscsi session(%d) - "
929fcf3ce44SJohn Forte "unable to get configured session information\n",
930fcf3ce44SJohn Forte isp->sess_oid);
931fcf3ce44SJohn Forte kmem_free(ics, size);
932fcf3ce44SJohn Forte return (ISCSI_STATUS_SHUTDOWN);
933fcf3ce44SJohn Forte }
934fcf3ce44SJohn Forte }
935fcf3ce44SJohn Forte
936fcf3ce44SJohn Forte /* Copy correct binding information to the connection */
937fcf3ce44SJohn Forte icp->conn_bound = B_TRUE;
938fcf3ce44SJohn Forte if (ics->ics_bindings[idx].i_insize == sizeof (struct in_addr)) {
939fcf3ce44SJohn Forte bcopy(&ics->ics_bindings[idx].i_addr.in4,
940fcf3ce44SJohn Forte &icp->conn_bound_addr.sin4.sin_addr.s_addr,
941fcf3ce44SJohn Forte sizeof (struct in_addr));
9421050fd6dSJames Moore icp->conn_bound_addr.sin4.sin_family = AF_INET;
943fcf3ce44SJohn Forte } else {
944fcf3ce44SJohn Forte bcopy(&ics->ics_bindings[idx].i_addr.in6,
945fcf3ce44SJohn Forte &icp->conn_bound_addr.sin6.sin6_addr.s6_addr,
946fcf3ce44SJohn Forte sizeof (struct in6_addr));
9471050fd6dSJames Moore icp->conn_bound_addr.sin6.sin6_family = AF_INET6;
948fcf3ce44SJohn Forte }
949fcf3ce44SJohn Forte
950fcf3ce44SJohn Forte kmem_free(ics, size);
951fcf3ce44SJohn Forte
952fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS);
953fcf3ce44SJohn Forte }
954fcf3ce44SJohn Forte
955fcf3ce44SJohn Forte /*
956fcf3ce44SJohn Forte * +--------------------------------------------------------------------+
957fcf3ce44SJohn Forte * | Internal Connection Interfaces |
958fcf3ce44SJohn Forte * +--------------------------------------------------------------------+
959fcf3ce44SJohn Forte */
960fcf3ce44SJohn Forte
961fcf3ce44SJohn Forte /*
962fcf3ce44SJohn Forte * iscsi_conn_flush_active_cmds - flush all active icmdps
963fcf3ce44SJohn Forte * for a connection.
964fcf3ce44SJohn Forte */
965fcf3ce44SJohn Forte static void
iscsi_conn_flush_active_cmds(iscsi_conn_t * icp)966fcf3ce44SJohn Forte iscsi_conn_flush_active_cmds(iscsi_conn_t *icp)
967fcf3ce44SJohn Forte {
968fcf3ce44SJohn Forte iscsi_cmd_t *icmdp;
969fcf3ce44SJohn Forte iscsi_sess_t *isp;
970fcf3ce44SJohn Forte boolean_t lock_held = B_FALSE;
971fcf3ce44SJohn Forte
972fcf3ce44SJohn Forte ASSERT(icp != NULL);
973fcf3ce44SJohn Forte isp = icp->conn_sess;
974fcf3ce44SJohn Forte ASSERT(isp != NULL);
975fcf3ce44SJohn Forte
976fcf3ce44SJohn Forte if (mutex_owned(&icp->conn_queue_active.mutex)) {
977fcf3ce44SJohn Forte lock_held = B_TRUE;
978fcf3ce44SJohn Forte } else {
979fcf3ce44SJohn Forte mutex_enter(&icp->conn_queue_active.mutex);
980fcf3ce44SJohn Forte }
981fcf3ce44SJohn Forte
982fcf3ce44SJohn Forte /* Flush active queue */
983fcf3ce44SJohn Forte icmdp = icp->conn_queue_active.head;
984fcf3ce44SJohn Forte while (icmdp != NULL) {
9852b79d384Sbing zhao - Sun Microsystems - Beijing China
9862b79d384Sbing zhao - Sun Microsystems - Beijing China mutex_enter(&icmdp->cmd_mutex);
9872b79d384Sbing zhao - Sun Microsystems - Beijing China if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
9882b79d384Sbing zhao - Sun Microsystems - Beijing China icmdp->cmd_un.scsi.pkt_stat |= STAT_ABORTED;
9892b79d384Sbing zhao - Sun Microsystems - Beijing China }
9902b79d384Sbing zhao - Sun Microsystems - Beijing China mutex_exit(&icmdp->cmd_mutex);
9912b79d384Sbing zhao - Sun Microsystems - Beijing China
992fcf3ce44SJohn Forte iscsi_cmd_state_machine(icmdp,
993fcf3ce44SJohn Forte ISCSI_CMD_EVENT_E7, isp);
994fcf3ce44SJohn Forte icmdp = icp->conn_queue_active.head;
995fcf3ce44SJohn Forte }
996fcf3ce44SJohn Forte
99730e7468fSPeter Dunlap /* Wait for active queue to drain */
99830e7468fSPeter Dunlap while (icp->conn_queue_active.count) {
99930e7468fSPeter Dunlap mutex_exit(&icp->conn_queue_active.mutex);
100030e7468fSPeter Dunlap delay(drv_usectohz(100000));
100130e7468fSPeter Dunlap mutex_enter(&icp->conn_queue_active.mutex);
100230e7468fSPeter Dunlap }
100330e7468fSPeter Dunlap
1004fcf3ce44SJohn Forte if (lock_held == B_FALSE) {
1005fcf3ce44SJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
1006fcf3ce44SJohn Forte }
100730e7468fSPeter Dunlap
100830e7468fSPeter Dunlap /* Wait for IDM abort queue to drain (if necessary) */
100930e7468fSPeter Dunlap mutex_enter(&icp->conn_queue_idm_aborting.mutex);
101030e7468fSPeter Dunlap while (icp->conn_queue_idm_aborting.count) {
101130e7468fSPeter Dunlap mutex_exit(&icp->conn_queue_idm_aborting.mutex);
101230e7468fSPeter Dunlap delay(drv_usectohz(100000));
101330e7468fSPeter Dunlap mutex_enter(&icp->conn_queue_idm_aborting.mutex);
1014fcf3ce44SJohn Forte }
101530e7468fSPeter Dunlap mutex_exit(&icp->conn_queue_idm_aborting.mutex);
1016fcf3ce44SJohn Forte }
1017fcf3ce44SJohn Forte
1018fcf3ce44SJohn Forte /*
1019fcf3ce44SJohn Forte * iscsi_conn_retry - retry connect/login
1020fcf3ce44SJohn Forte */
102130e7468fSPeter Dunlap void
iscsi_conn_retry(iscsi_sess_t * isp,iscsi_conn_t * icp)1022fcf3ce44SJohn Forte iscsi_conn_retry(iscsi_sess_t *isp, iscsi_conn_t *icp)
1023fcf3ce44SJohn Forte {
1024fcf3ce44SJohn Forte iscsi_task_t *itp;
1025904e51f6SJack Meng uint32_t event_count;
1026fcf3ce44SJohn Forte
1027fcf3ce44SJohn Forte ASSERT(isp != NULL);
1028fcf3ce44SJohn Forte ASSERT(icp != NULL);
1029fcf3ce44SJohn Forte
1030fcf3ce44SJohn Forte /* set login min/max time values */
1031fcf3ce44SJohn Forte iscsi_conn_set_login_min_max(icp,
1032fcf3ce44SJohn Forte ISCSI_CONN_DEFAULT_LOGIN_MIN,
1033aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_tunable_params.conn_login_max);
1034fcf3ce44SJohn Forte
103530e7468fSPeter Dunlap ISCSI_CONN_LOG(CE_NOTE, "DEBUG: iscsi_conn_retry: icp: %p icp: %p ",
103630e7468fSPeter Dunlap (void *)icp,
103730e7468fSPeter Dunlap (void *)icp->conn_ic);
103830e7468fSPeter Dunlap
1039fcf3ce44SJohn Forte /*
1040fcf3ce44SJohn Forte * Sync base connection information before login.
1041fcf3ce44SJohn Forte * A login redirection might have shifted the
1042fcf3ce44SJohn Forte * current information from the base.
1043fcf3ce44SJohn Forte */
1044fcf3ce44SJohn Forte bcopy(&icp->conn_base_addr, &icp->conn_curr_addr,
1045fcf3ce44SJohn Forte sizeof (icp->conn_curr_addr));
1046fcf3ce44SJohn Forte
1047fcf3ce44SJohn Forte /* schedule login task */
1048fcf3ce44SJohn Forte itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP);
1049fcf3ce44SJohn Forte itp->t_arg = icp;
1050fcf3ce44SJohn Forte itp->t_blocking = B_FALSE;
1051904e51f6SJack Meng if (ddi_taskq_dispatch(isp->sess_login_taskq,
1052*9fe633fdSToomas Soome iscsi_login_cb, itp, DDI_SLEEP) !=
1053fcf3ce44SJohn Forte DDI_SUCCESS) {
1054fcf3ce44SJohn Forte kmem_free(itp, sizeof (iscsi_task_t));
105530e7468fSPeter Dunlap cmn_err(CE_WARN, "iscsi connection(%u) failure - "
105630e7468fSPeter Dunlap "unable to schedule login task", icp->conn_oid);
1057fcf3ce44SJohn Forte
105830e7468fSPeter Dunlap iscsi_conn_update_state(icp, ISCSI_CONN_STATE_FREE);
1059904e51f6SJack Meng event_count = atomic_inc_32_nv(
1060904e51f6SJack Meng &isp->sess_state_event_count);
1061904e51f6SJack Meng iscsi_sess_enter_state_zone(isp);
1062904e51f6SJack Meng
1063fcf3ce44SJohn Forte iscsi_sess_state_machine(isp,
1064904e51f6SJack Meng ISCSI_SESS_EVENT_N6, event_count);
1065904e51f6SJack Meng
1066904e51f6SJack Meng iscsi_sess_exit_state_zone(isp);
1067fcf3ce44SJohn Forte }
1068fcf3ce44SJohn Forte }
106930e7468fSPeter Dunlap
107030e7468fSPeter Dunlap void
iscsi_conn_update_state(iscsi_conn_t * icp,iscsi_conn_state_t next_state)1071*9fe633fdSToomas Soome iscsi_conn_update_state(iscsi_conn_t *icp, iscsi_conn_state_t next_state)
107230e7468fSPeter Dunlap {
107330e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex);
107430e7468fSPeter Dunlap (void) iscsi_conn_update_state_locked(icp, next_state);
107530e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex);
107630e7468fSPeter Dunlap }
107730e7468fSPeter Dunlap
107830e7468fSPeter Dunlap void
iscsi_conn_update_state_locked(iscsi_conn_t * icp,iscsi_conn_state_t next_state)1079*9fe633fdSToomas Soome iscsi_conn_update_state_locked(iscsi_conn_t *icp, iscsi_conn_state_t next_state)
108030e7468fSPeter Dunlap {
108130e7468fSPeter Dunlap ASSERT(mutex_owned(&icp->conn_state_mutex));
108230e7468fSPeter Dunlap next_state = (next_state > ISCSI_CONN_STATE_MAX) ?
108330e7468fSPeter Dunlap ISCSI_CONN_STATE_MAX : next_state;
108430e7468fSPeter Dunlap idm_sm_audit_state_change(&icp->conn_state_audit,
108530e7468fSPeter Dunlap SAS_ISCSI_CONN, icp->conn_state, next_state);
108630e7468fSPeter Dunlap switch (next_state) {
108730e7468fSPeter Dunlap case ISCSI_CONN_STATE_FREE:
108830e7468fSPeter Dunlap case ISCSI_CONN_STATE_IN_LOGIN:
108930e7468fSPeter Dunlap case ISCSI_CONN_STATE_LOGGED_IN:
109030e7468fSPeter Dunlap case ISCSI_CONN_STATE_IN_LOGOUT:
109130e7468fSPeter Dunlap case ISCSI_CONN_STATE_FAILED:
109230e7468fSPeter Dunlap case ISCSI_CONN_STATE_POLLING:
109330e7468fSPeter Dunlap ISCSI_CONN_LOG(CE_NOTE,
109430e7468fSPeter Dunlap "iscsi_conn_update_state conn %p %s(%d) -> %s(%d)",
109530e7468fSPeter Dunlap (void *)icp,
109630e7468fSPeter Dunlap iscsi_ics_name[icp->conn_state], icp->conn_state,
109730e7468fSPeter Dunlap iscsi_ics_name[next_state], next_state);
109830e7468fSPeter Dunlap icp->conn_prev_state = icp->conn_state;
109930e7468fSPeter Dunlap icp->conn_state = next_state;
110030e7468fSPeter Dunlap cv_broadcast(&icp->conn_state_change);
110130e7468fSPeter Dunlap break;
110230e7468fSPeter Dunlap default:
110330e7468fSPeter Dunlap cmn_err(CE_WARN, "Update state found illegal state: %x "
110430e7468fSPeter Dunlap "prev_state: %x", next_state, icp->conn_prev_state);
110530e7468fSPeter Dunlap ASSERT(0);
110630e7468fSPeter Dunlap }
110730e7468fSPeter Dunlap }
1108