1a6d42e7dSPeter Dunlap /*
2a6d42e7dSPeter Dunlap  * CDDL HEADER START
3a6d42e7dSPeter Dunlap  *
4a6d42e7dSPeter Dunlap  * The contents of this file are subject to the terms of the
5a6d42e7dSPeter Dunlap  * Common Development and Distribution License (the "License").
6a6d42e7dSPeter Dunlap  * You may not use this file except in compliance with the License.
7a6d42e7dSPeter Dunlap  *
8a6d42e7dSPeter Dunlap  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9a6d42e7dSPeter Dunlap  * or http://www.opensolaris.org/os/licensing.
10a6d42e7dSPeter Dunlap  * See the License for the specific language governing permissions
11a6d42e7dSPeter Dunlap  * and limitations under the License.
12a6d42e7dSPeter Dunlap  *
13a6d42e7dSPeter Dunlap  * When distributing Covered Code, include this CDDL HEADER in each
14a6d42e7dSPeter Dunlap  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15a6d42e7dSPeter Dunlap  * If applicable, add the following below this CDDL HEADER, with the
16a6d42e7dSPeter Dunlap  * fields enclosed by brackets "[]" replaced with your own identifying
17a6d42e7dSPeter Dunlap  * information: Portions Copyright [yyyy] [name of copyright owner]
18a6d42e7dSPeter Dunlap  *
19a6d42e7dSPeter Dunlap  * CDDL HEADER END
20a6d42e7dSPeter Dunlap  */
21a6d42e7dSPeter Dunlap /*
22d618d68dSPriya Krishnan  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
233e2514dcSDan McDonald  *
24*61dfa509SRick McNeal  * Copyright 2017 Nexenta Systems, Inc.
252727bb05STim Kordas  * Copyright (c) 2017, Joyent, Inc.  All rights reserved.
266319b0c7SGarrett D'Amore  */
27a6d42e7dSPeter Dunlap 
28a6d42e7dSPeter Dunlap #include <sys/cpuvar.h>
29a6d42e7dSPeter Dunlap #include <sys/types.h>
30a6d42e7dSPeter Dunlap #include <sys/conf.h>
31a6d42e7dSPeter Dunlap #include <sys/stat.h>
32a6d42e7dSPeter Dunlap #include <sys/file.h>
33a6d42e7dSPeter Dunlap #include <sys/ddi.h>
34a6d42e7dSPeter Dunlap #include <sys/sunddi.h>
35a6d42e7dSPeter Dunlap #include <sys/modctl.h>
36a6d42e7dSPeter Dunlap #include <sys/sysmacros.h>
37a6d42e7dSPeter Dunlap #include <sys/socket.h>
38a6d42e7dSPeter Dunlap #include <sys/strsubr.h>
39a6d42e7dSPeter Dunlap #include <sys/nvpair.h>
40a6d42e7dSPeter Dunlap 
41a6d42e7dSPeter Dunlap #include <sys/stmf.h>
42a6d42e7dSPeter Dunlap #include <sys/stmf_ioctl.h>
43a6d42e7dSPeter Dunlap #include <sys/portif.h>
44a6d42e7dSPeter Dunlap #include <sys/idm/idm.h>
45a6d42e7dSPeter Dunlap #include <sys/idm/idm_conn_sm.h>
464558d122SViswanathan Kannappan 
474558d122SViswanathan Kannappan #include "iscsit_isns.h"
484558d122SViswanathan Kannappan #include "iscsit.h"
49a6d42e7dSPeter Dunlap 
50a6d42e7dSPeter Dunlap #define	ISCSIT_VERSION		BUILD_DATE "-1.18dev"
52a6d42e7dSPeter Dunlap 
53a6d42e7dSPeter Dunlap /*
54a6d42e7dSPeter Dunlap  * DDI entry points.
55a6d42e7dSPeter Dunlap  */
56a6d42e7dSPeter Dunlap static int iscsit_drv_attach(dev_info_t *, ddi_attach_cmd_t);
57a6d42e7dSPeter Dunlap static int iscsit_drv_detach(dev_info_t *, ddi_detach_cmd_t);
58a6d42e7dSPeter Dunlap static int iscsit_drv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
59a6d42e7dSPeter Dunlap static int iscsit_drv_open(dev_t *, int, int, cred_t *);
60a6d42e7dSPeter Dunlap static int iscsit_drv_close(dev_t, int, int, cred_t *);
61a6d42e7dSPeter Dunlap static boolean_t iscsit_drv_busy(void);
62a6d42e7dSPeter Dunlap static int iscsit_drv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
63a6d42e7dSPeter Dunlap 
64a6d42e7dSPeter Dunlap extern struct mod_ops mod_miscops;
65a6d42e7dSPeter Dunlap 
66a6d42e7dSPeter Dunlap 
67a6d42e7dSPeter Dunlap static struct cb_ops iscsit_cb_ops = {
68a6d42e7dSPeter Dunlap 	iscsit_drv_open,	/* cb_open */
69a6d42e7dSPeter Dunlap 	iscsit_drv_close,	/* cb_close */
70a6d42e7dSPeter Dunlap 	nodev,			/* cb_strategy */
71a6d42e7dSPeter Dunlap 	nodev,			/* cb_print */
72a6d42e7dSPeter Dunlap 	nodev,			/* cb_dump */
73a6d42e7dSPeter Dunlap 	nodev,			/* cb_read */
74a6d42e7dSPeter Dunlap 	nodev,			/* cb_write */
75a6d42e7dSPeter Dunlap 	iscsit_drv_ioctl,	/* cb_ioctl */
76a6d42e7dSPeter Dunlap 	nodev,			/* cb_devmap */
77a6d42e7dSPeter Dunlap 	nodev,			/* cb_mmap */
78a6d42e7dSPeter Dunlap 	nodev,			/* cb_segmap */
79a6d42e7dSPeter Dunlap 	nochpoll,		/* cb_chpoll */
80a6d42e7dSPeter Dunlap 	ddi_prop_op,		/* cb_prop_op */
81a6d42e7dSPeter Dunlap 	NULL,			/* cb_streamtab */
82a6d42e7dSPeter Dunlap 	D_MP,			/* cb_flag */
83a6d42e7dSPeter Dunlap 	CB_REV,			/* cb_rev */
84a6d42e7dSPeter Dunlap 	nodev,			/* cb_aread */
85a6d42e7dSPeter Dunlap 	nodev,			/* cb_awrite */
86a6d42e7dSPeter Dunlap };
87a6d42e7dSPeter Dunlap 
88a6d42e7dSPeter Dunlap static struct dev_ops iscsit_dev_ops = {
89a6d42e7dSPeter Dunlap 	DEVO_REV,		/* devo_rev */
90a6d42e7dSPeter Dunlap 	0,			/* devo_refcnt */
91a6d42e7dSPeter Dunlap 	iscsit_drv_getinfo,	/* devo_getinfo */
92a6d42e7dSPeter Dunlap 	nulldev,		/* devo_identify */
93a6d42e7dSPeter Dunlap 	nulldev,		/* devo_probe */
94a6d42e7dSPeter Dunlap 	iscsit_drv_attach,	/* devo_attach */
95a6d42e7dSPeter Dunlap 	iscsit_drv_detach,	/* devo_detach */
96a6d42e7dSPeter Dunlap 	nodev,			/* devo_reset */
97a6d42e7dSPeter Dunlap 	&iscsit_cb_ops,		/* devo_cb_ops */
98a6d42e7dSPeter Dunlap 	NULL,			/* devo_bus_ops */
99a6d42e7dSPeter Dunlap 	NULL,			/* devo_power */
10063528ae4SJames Moore 	ddi_quiesce_not_needed,	/* quiesce */
101a6d42e7dSPeter Dunlap };
102a6d42e7dSPeter Dunlap 
103a6d42e7dSPeter Dunlap static struct modldrv modldrv = {
104a6d42e7dSPeter Dunlap 	&mod_driverops,
105a6d42e7dSPeter Dunlap 	"iSCSI Target",
106a6d42e7dSPeter Dunlap 	&iscsit_dev_ops,
107a6d42e7dSPeter Dunlap };
108a6d42e7dSPeter Dunlap 
109a6d42e7dSPeter Dunlap static struct modlinkage modlinkage = {
110a6d42e7dSPeter Dunlap 	MODREV_1,
111a6d42e7dSPeter Dunlap 	&modldrv,
112a6d42e7dSPeter Dunlap 	NULL,
113a6d42e7dSPeter Dunlap };
114a6d42e7dSPeter Dunlap 
115a6d42e7dSPeter Dunlap 
116a6d42e7dSPeter Dunlap iscsit_global_t iscsit_global;
117a6d42e7dSPeter Dunlap 
118a6d42e7dSPeter Dunlap kmem_cache_t	*iscsit_status_pdu_cache;
119a6d42e7dSPeter Dunlap 
120a6d42e7dSPeter Dunlap boolean_t	iscsit_sm_logging = B_FALSE;
121a6d42e7dSPeter Dunlap 
1223fc1e17eSPriya Krishnan kmutex_t	login_sm_session_mutex;
1233fc1e17eSPriya Krishnan 
124a6d42e7dSPeter Dunlap static idm_status_t iscsit_init(dev_info_t *dip);
125a6d42e7dSPeter Dunlap static idm_status_t iscsit_enable_svc(iscsit_hostinfo_t *hostinfo);
126a6d42e7dSPeter Dunlap static void iscsit_disable_svc(void);
127a6d42e7dSPeter Dunlap 
1282727bb05STim Kordas static boolean_t
129d618d68dSPriya Krishnan iscsit_check_cmdsn_and_queue(idm_pdu_t *rx_pdu);
130d618d68dSPriya Krishnan 
131d618d68dSPriya Krishnan static void
132d618d68dSPriya Krishnan iscsit_add_pdu_to_queue(iscsit_sess_t *ist, idm_pdu_t *rx_pdu);
133d618d68dSPriya Krishnan 
134d618d68dSPriya Krishnan static idm_pdu_t *
135d618d68dSPriya Krishnan iscsit_remove_pdu_from_queue(iscsit_sess_t *ist, uint32_t cmdsn);
136d618d68dSPriya Krishnan 
137d618d68dSPriya Krishnan static void
138d618d68dSPriya Krishnan iscsit_process_pdu_in_queue(iscsit_sess_t *ist);
139d618d68dSPriya Krishnan 
140d618d68dSPriya Krishnan static void
141d618d68dSPriya Krishnan iscsit_rxpdu_queue_monitor_session(iscsit_sess_t *ist);
142d618d68dSPriya Krishnan 
143d618d68dSPriya Krishnan static void
144d618d68dSPriya Krishnan iscsit_rxpdu_queue_monitor(void *arg);
145d618d68dSPriya Krishnan 
146d618d68dSPriya Krishnan static void
147d618d68dSPriya Krishnan iscsit_post_staged_pdu(idm_pdu_t *rx_pdu);
148d618d68dSPriya Krishnan 
149d618d68dSPriya Krishnan static void
150d618d68dSPriya Krishnan iscsit_post_scsi_cmd(idm_conn_t *ic, idm_pdu_t *rx_pdu);
151d618d68dSPriya Krishnan 
152a6d42e7dSPeter Dunlap static void
153a6d42e7dSPeter Dunlap iscsit_op_scsi_task_mgmt(iscsit_conn_t *ict, idm_pdu_t *rx_pdu);
154a6d42e7dSPeter Dunlap 
155a6d42e7dSPeter Dunlap static void
156a6d42e7dSPeter Dunlap iscsit_pdu_op_noop(iscsit_conn_t *ict, idm_pdu_t *rx_pdu);
157a6d42e7dSPeter Dunlap 
158a6d42e7dSPeter Dunlap static void
159a6d42e7dSPeter Dunlap iscsit_pdu_op_login_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu);
160a6d42e7dSPeter Dunlap 
161a6d42e7dSPeter Dunlap void
162a6d42e7dSPeter Dunlap iscsit_pdu_op_text_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu);
163a6d42e7dSPeter Dunlap 
164a6d42e7dSPeter Dunlap static void
165a6d42e7dSPeter Dunlap iscsit_pdu_op_logout_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu);
166a6d42e7dSPeter Dunlap 
167a6d42e7dSPeter Dunlap int iscsit_cmd_window();
168a6d42e7dSPeter Dunlap 
169d618d68dSPriya Krishnan static  int
170d618d68dSPriya Krishnan iscsit_sna_lt(uint32_t sn1, uint32_t sn2);
171d618d68dSPriya Krishnan 
172a6d42e7dSPeter Dunlap void
173a6d42e7dSPeter Dunlap iscsit_set_cmdsn(iscsit_conn_t *ict, idm_pdu_t *rx_pdu);
174a6d42e7dSPeter Dunlap 
175a6d42e7dSPeter Dunlap static void
176a6d42e7dSPeter Dunlap iscsit_deferred_dispatch(idm_pdu_t *rx_pdu);
177a6d42e7dSPeter Dunlap 
178a6d42e7dSPeter Dunlap static void
179a6d42e7dSPeter Dunlap iscsit_deferred(void *rx_pdu_void);
180a6d42e7dSPeter Dunlap 
181a6d42e7dSPeter Dunlap static idm_status_t
182a6d42e7dSPeter Dunlap iscsit_conn_accept(idm_conn_t *ic);
183a6d42e7dSPeter Dunlap 
184a6d42e7dSPeter Dunlap static idm_status_t
185a6d42e7dSPeter Dunlap iscsit_ffp_enabled(idm_conn_t *ic);
186a6d42e7dSPeter Dunlap 
187a6d42e7dSPeter Dunlap static idm_status_t
188a6d42e7dSPeter Dunlap iscsit_ffp_disabled(idm_conn_t *ic, idm_ffp_disable_t disable_class);
189a6d42e7dSPeter Dunlap 
190a6d42e7dSPeter Dunlap static idm_status_t
191a6d42e7dSPeter Dunlap iscsit_conn_lost(idm_conn_t *ic);
192a6d42e7dSPeter Dunlap 
193a6d42e7dSPeter Dunlap static idm_status_t
194a6d42e7dSPeter Dunlap iscsit_conn_destroy(idm_conn_t *ic);
195a6d42e7dSPeter Dunlap 
196a6d42e7dSPeter Dunlap static stmf_data_buf_t *
197a6d42e7dSPeter Dunlap iscsit_dbuf_alloc(scsi_task_t *task, uint32_t size, uint32_t *pminsize,
198a6d42e7dSPeter Dunlap     uint32_t flags);
199a6d42e7dSPeter Dunlap 
200a6d42e7dSPeter Dunlap static void
201a6d42e7dSPeter Dunlap iscsit_dbuf_free(stmf_dbuf_store_t *ds, stmf_data_buf_t *dbuf);
202a6d42e7dSPeter Dunlap 
203a6d42e7dSPeter Dunlap static void
204a6d42e7dSPeter Dunlap iscsit_buf_xfer_cb(idm_buf_t *idb, idm_status_t status);
205a6d42e7dSPeter Dunlap 
206a6d42e7dSPeter Dunlap static void
207a6d42e7dSPeter Dunlap iscsit_send_good_status_done(idm_pdu_t *pdu, idm_status_t status);
208a6d42e7dSPeter Dunlap 
209a6d42e7dSPeter Dunlap static void
210a6d42e7dSPeter Dunlap iscsit_send_status_done(idm_pdu_t *pdu, idm_status_t status);
211a6d42e7dSPeter Dunlap 
212a6d42e7dSPeter Dunlap static stmf_status_t
213a6d42e7dSPeter Dunlap iscsit_idm_to_stmf(idm_status_t idmrc);
214a6d42e7dSPeter Dunlap 
215a6d42e7dSPeter Dunlap static iscsit_task_t *
216a6d42e7dSPeter Dunlap iscsit_task_alloc(iscsit_conn_t *ict);
217a6d42e7dSPeter Dunlap 
218a6d42e7dSPeter Dunlap static void
219a6d42e7dSPeter Dunlap iscsit_task_free(iscsit_task_t *itask);
220a6d42e7dSPeter Dunlap 
221a6d42e7dSPeter Dunlap static iscsit_task_t *
222a6d42e7dSPeter Dunlap iscsit_tm_task_alloc(iscsit_conn_t *ict);
223a6d42e7dSPeter Dunlap 
224a6d42e7dSPeter Dunlap static void
225a6d42e7dSPeter Dunlap iscsit_tm_task_free(iscsit_task_t *itask);
226a6d42e7dSPeter Dunlap 
22772cf3143Speter dunlap static idm_status_t
22872cf3143Speter dunlap iscsit_task_start(iscsit_task_t *itask);
22972cf3143Speter dunlap 
23072cf3143Speter dunlap static void
23172cf3143Speter dunlap iscsit_task_done(iscsit_task_t *itask);
23272cf3143Speter dunlap 
233a6d42e7dSPeter Dunlap static int
234a6d42e7dSPeter Dunlap iscsit_status_pdu_constructor(void *pdu_void, void *arg, int flags);
235a6d42e7dSPeter Dunlap 
236a6d42e7dSPeter Dunlap static void
237a6d42e7dSPeter Dunlap iscsit_pp_cb(struct stmf_port_provider *pp, int cmd, void *arg, uint32_t flags);
238a6d42e7dSPeter Dunlap 
239a6d42e7dSPeter Dunlap static it_cfg_status_t
240a6d42e7dSPeter Dunlap iscsit_config_merge(it_config_t *cfg);
241a6d42e7dSPeter Dunlap 
242a6d42e7dSPeter Dunlap static idm_status_t
243a6d42e7dSPeter Dunlap iscsit_login_fail(idm_conn_t *ic);
244a6d42e7dSPeter Dunlap 
24572cf3143Speter dunlap static boolean_t iscsit_cmdsn_in_window(iscsit_conn_t *ict, uint32_t cmdsn);
24672cf3143Speter dunlap static void iscsit_send_direct_scsi_resp(iscsit_conn_t *ict, idm_pdu_t *rx_pdu,
24772cf3143Speter dunlap     uint8_t response, uint8_t cmd_status);
24872cf3143Speter dunlap static void iscsit_send_task_mgmt_resp(idm_pdu_t *tm_resp_pdu,
24972cf3143Speter dunlap     uint8_t tm_status);
25072cf3143Speter dunlap 
251d618d68dSPriya Krishnan /*
252d618d68dSPriya Krishnan  * MC/S: Out-of-order commands are staged on a session-wide wait
253d618d68dSPriya Krishnan  * queue until a system-tunable threshold is reached. A separate
254d618d68dSPriya Krishnan  * thread is used to scan the staging queue on all the session,
255d618d68dSPriya Krishnan  * If a delayed PDU does not arrive within a timeout, the target
256d618d68dSPriya Krishnan  * will advance to the staged PDU that is next in sequence, skipping
257d618d68dSPriya Krishnan  * over the missing PDU(s) to go past a hole in the sequence.
258d618d68dSPriya Krishnan  */
259d618d68dSPriya Krishnan volatile int rxpdu_queue_threshold = ISCSIT_RXPDU_QUEUE_THRESHOLD;
260d618d68dSPriya Krishnan 
261d618d68dSPriya Krishnan static kmutex_t		iscsit_rxpdu_queue_monitor_mutex;
262d618d68dSPriya Krishnan kthread_t		*iscsit_rxpdu_queue_monitor_thr_id;
263d618d68dSPriya Krishnan static kt_did_t		iscsit_rxpdu_queue_monitor_thr_did;
264d618d68dSPriya Krishnan static boolean_t	iscsit_rxpdu_queue_monitor_thr_running;
265d618d68dSPriya Krishnan static kcondvar_t	iscsit_rxpdu_queue_monitor_cv;
266d618d68dSPriya Krishnan 
267a6d42e7dSPeter Dunlap int
_init(void)268a6d42e7dSPeter Dunlap _init(void)
269a6d42e7dSPeter Dunlap {
270a6d42e7dSPeter Dunlap 	int rc;
271a6d42e7dSPeter Dunlap 
272a6d42e7dSPeter Dunlap 	rw_init(&iscsit_global.global_rwlock, NULL, RW_DRIVER, NULL);
2738c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	mutex_init(&iscsit_global.global_state_mutex, NULL,
2748c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	    MUTEX_DRIVER, NULL);
275a6d42e7dSPeter Dunlap 	iscsit_global.global_svc_state = ISE_DETACHED;
276a6d42e7dSPeter Dunlap 
277d618d68dSPriya Krishnan 	mutex_init(&iscsit_rxpdu_queue_monitor_mutex, NULL,
278d618d68dSPriya Krishnan 	    MUTEX_DRIVER, NULL);
2793fc1e17eSPriya Krishnan 	mutex_init(&login_sm_session_mutex, NULL, MUTEX_DRIVER, NULL);
280d618d68dSPriya Krishnan 	iscsit_rxpdu_queue_monitor_thr_id = NULL;
281d618d68dSPriya Krishnan 	iscsit_rxpdu_queue_monitor_thr_running = B_FALSE;
282d618d68dSPriya Krishnan 	cv_init(&iscsit_rxpdu_queue_monitor_cv, NULL, CV_DEFAULT, NULL);
283d618d68dSPriya Krishnan 
284a6d42e7dSPeter Dunlap 	if ((rc = mod_install(&modlinkage)) != 0) {
2858c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		mutex_destroy(&iscsit_global.global_state_mutex);
286a6d42e7dSPeter Dunlap 		rw_destroy(&iscsit_global.global_rwlock);
287a6d42e7dSPeter Dunlap 		return (rc);
288a6d42e7dSPeter Dunlap 	}
289a6d42e7dSPeter Dunlap 
290a6d42e7dSPeter Dunlap 	return (rc);
291a6d42e7dSPeter Dunlap }
292a6d42e7dSPeter Dunlap 
293a6d42e7dSPeter Dunlap int
_info(struct modinfo * modinfop)294a6d42e7dSPeter Dunlap _info(struct modinfo *modinfop)
295a6d42e7dSPeter Dunlap {
296a6d42e7dSPeter Dunlap 	return (mod_info(&modlinkage, modinfop));
297a6d42e7dSPeter Dunlap }
298a6d42e7dSPeter Dunlap 
299a6d42e7dSPeter Dunlap int
_fini(void)300a6d42e7dSPeter Dunlap _fini(void)
301a6d42e7dSPeter Dunlap {
302a6d42e7dSPeter Dunlap 	int rc;
303a6d42e7dSPeter Dunlap 
304a6d42e7dSPeter Dunlap 	rc = mod_remove(&modlinkage);
305a6d42e7dSPeter Dunlap 
306a6d42e7dSPeter Dunlap 	if (rc == 0) {
307d618d68dSPriya Krishnan 		mutex_destroy(&iscsit_rxpdu_queue_monitor_mutex);
3083fc1e17eSPriya Krishnan 		mutex_destroy(&login_sm_session_mutex);
309d618d68dSPriya Krishnan 		cv_destroy(&iscsit_rxpdu_queue_monitor_cv);
3108c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		mutex_destroy(&iscsit_global.global_state_mutex);
311a6d42e7dSPeter Dunlap 		rw_destroy(&iscsit_global.global_rwlock);
312a6d42e7dSPeter Dunlap 	}
313a6d42e7dSPeter Dunlap 
314a6d42e7dSPeter Dunlap 	return (rc);
315a6d42e7dSPeter Dunlap }
316a6d42e7dSPeter Dunlap 
317a6d42e7dSPeter Dunlap /*
318a6d42e7dSPeter Dunlap  * DDI entry points.
319a6d42e7dSPeter Dunlap  */
320a6d42e7dSPeter Dunlap 
321a6d42e7dSPeter Dunlap /* ARGSUSED */
322a6d42e7dSPeter Dunlap static int
iscsit_drv_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)323a6d42e7dSPeter Dunlap iscsit_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
324a6d42e7dSPeter Dunlap     void **result)
325a6d42e7dSPeter Dunlap {
326a6d42e7dSPeter Dunlap 	ulong_t instance = getminor((dev_t)arg);
327a6d42e7dSPeter Dunlap 
328a6d42e7dSPeter Dunlap 	switch (cmd) {
329a6d42e7dSPeter Dunlap 	case DDI_INFO_DEVT2DEVINFO:
330a6d42e7dSPeter Dunlap 		*result = iscsit_global.global_dip;
331a6d42e7dSPeter Dunlap 		return (DDI_SUCCESS);
332a6d42e7dSPeter Dunlap 
333a6d42e7dSPeter Dunlap 	case DDI_INFO_DEVT2INSTANCE:
334a6d42e7dSPeter Dunlap 		*result = (void *)instance;
335a6d42e7dSPeter Dunlap 		return (DDI_SUCCESS);
336a6d42e7dSPeter Dunlap 
337a6d42e7dSPeter Dunlap 	default:
338a6d42e7dSPeter Dunlap 		break;
339a6d42e7dSPeter Dunlap 	}
340a6d42e7dSPeter Dunlap 
341a6d42e7dSPeter Dunlap 	return (DDI_FAILURE);
342a6d42e7dSPeter Dunlap }
343a6d42e7dSPeter Dunlap 
344a6d42e7dSPeter Dunlap static int
iscsit_drv_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)345a6d42e7dSPeter Dunlap iscsit_drv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
346a6d42e7dSPeter Dunlap {
347a6d42e7dSPeter Dunlap 	if (cmd != DDI_ATTACH) {
348a6d42e7dSPeter Dunlap 		return (DDI_FAILURE);
349a6d42e7dSPeter Dunlap 	}
350a6d42e7dSPeter Dunlap 
351a6d42e7dSPeter Dunlap 	if (ddi_get_instance(dip) != 0) {
352a6d42e7dSPeter Dunlap 		/* we only allow instance 0 to attach */
353a6d42e7dSPeter Dunlap 		return (DDI_FAILURE);
354a6d42e7dSPeter Dunlap 	}
355a6d42e7dSPeter Dunlap 
356a6d42e7dSPeter Dunlap 	/* create the minor node */
357a6d42e7dSPeter Dunlap 	if (ddi_create_minor_node(dip, ISCSIT_MODNAME, S_IFCHR, 0,
358a6d42e7dSPeter Dunlap 	    DDI_PSEUDO, 0) != DDI_SUCCESS) {
359a6d42e7dSPeter Dunlap 		cmn_err(CE_WARN, "iscsit_drv_attach: "
360a6d42e7dSPeter Dunlap 		    "failed creating minor node");
361a6d42e7dSPeter Dunlap 		return (DDI_FAILURE);
362a6d42e7dSPeter Dunlap 	}
363a6d42e7dSPeter Dunlap 
364a6d42e7dSPeter Dunlap 	if (iscsit_init(dip) != IDM_STATUS_SUCCESS) {
365a6d42e7dSPeter Dunlap 		cmn_err(CE_WARN, "iscsit_drv_attach: "
366a6d42e7dSPeter Dunlap 		    "failed to initialize");
367a6d42e7dSPeter Dunlap 		ddi_remove_minor_node(dip, NULL);
368a6d42e7dSPeter Dunlap 		return (DDI_FAILURE);
369a6d42e7dSPeter Dunlap 	}
370a6d42e7dSPeter Dunlap 
371a6d42e7dSPeter Dunlap 	iscsit_global.global_svc_state = ISE_DISABLED;
372a6d42e7dSPeter Dunlap 	iscsit_global.global_dip = dip;
373a6d42e7dSPeter Dunlap 
374a6d42e7dSPeter Dunlap 	return (DDI_SUCCESS);
375a6d42e7dSPeter Dunlap }
376a6d42e7dSPeter Dunlap 
377a6d42e7dSPeter Dunlap /*ARGSUSED*/
378a6d42e7dSPeter Dunlap static int
iscsit_drv_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)379a6d42e7dSPeter Dunlap iscsit_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
380a6d42e7dSPeter Dunlap {
381a6d42e7dSPeter Dunlap 	if (cmd != DDI_DETACH)
382a6d42e7dSPeter Dunlap 		return (DDI_FAILURE);
383a6d42e7dSPeter Dunlap 
3848c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	/*
3858c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 * drv_detach is called in a context that owns the
3868c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 * device node for the /dev/pseudo device.  If this thread blocks
3878c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 * for any resource, other threads that need the /dev/pseudo device
3888c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 * may end up in a deadlock with this thread.Hence, we use a
3898c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 * separate lock just for the structures that drv_detach needs
3908c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 * to access.
3918c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 */
3928c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	mutex_enter(&iscsit_global.global_state_mutex);
393a6d42e7dSPeter Dunlap 	if (iscsit_drv_busy()) {
3948c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		mutex_exit(&iscsit_global.global_state_mutex);
395a6d42e7dSPeter Dunlap 		return (EBUSY);
396a6d42e7dSPeter Dunlap 	}
397a6d42e7dSPeter Dunlap 
398a6d42e7dSPeter Dunlap 	iscsit_global.global_dip = NULL;
399a6d42e7dSPeter Dunlap 	ddi_remove_minor_node(dip, NULL);
400a6d42e7dSPeter Dunlap 
401a6d42e7dSPeter Dunlap 	ldi_ident_release(iscsit_global.global_li);
402a6d42e7dSPeter Dunlap 	iscsit_global.global_svc_state = ISE_DETACHED;
403a6d42e7dSPeter Dunlap 
4048c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	mutex_exit(&iscsit_global.global_state_mutex);
405a6d42e7dSPeter Dunlap 
406a6d42e7dSPeter Dunlap 	return (DDI_SUCCESS);
407a6d42e7dSPeter Dunlap }
408a6d42e7dSPeter Dunlap 
409a6d42e7dSPeter Dunlap /*ARGSUSED*/
410a6d42e7dSPeter Dunlap static int
iscsit_drv_open(dev_t * devp,int flag,int otyp,cred_t * credp)411a6d42e7dSPeter Dunlap iscsit_drv_open(dev_t *devp, int flag, int otyp, cred_t *credp)
412a6d42e7dSPeter Dunlap {
413a6d42e7dSPeter Dunlap 	return (0);
414a6d42e7dSPeter Dunlap }
415a6d42e7dSPeter Dunlap 
416a6d42e7dSPeter Dunlap /* ARGSUSED */
417a6d42e7dSPeter Dunlap static int
iscsit_drv_close(dev_t dev,int flag,int otyp,cred_t * credp)418a6d42e7dSPeter Dunlap iscsit_drv_close(dev_t dev, int flag, int otyp, cred_t *credp)
419a6d42e7dSPeter Dunlap {
420a6d42e7dSPeter Dunlap 	return (0);
421a6d42e7dSPeter Dunlap }
422a6d42e7dSPeter Dunlap 
423a6d42e7dSPeter Dunlap static boolean_t
iscsit_drv_busy(void)424a6d42e7dSPeter Dunlap iscsit_drv_busy(void)
425a6d42e7dSPeter Dunlap {
4268c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	ASSERT(MUTEX_HELD(&iscsit_global.global_state_mutex));
4278c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 
428a6d42e7dSPeter Dunlap 	switch (iscsit_global.global_svc_state) {
429a6d42e7dSPeter Dunlap 	case ISE_DISABLED:
430a6d42e7dSPeter Dunlap 	case ISE_DETACHED:
431a6d42e7dSPeter Dunlap 		return (B_FALSE);
432a6d42e7dSPeter Dunlap 	default:
433a6d42e7dSPeter Dunlap 		return (B_TRUE);
434a6d42e7dSPeter Dunlap 	}
435a6d42e7dSPeter Dunlap 	/* NOTREACHED */
436a6d42e7dSPeter Dunlap }
437a6d42e7dSPeter Dunlap 
438a6d42e7dSPeter Dunlap /* ARGSUSED */
439a6d42e7dSPeter Dunlap static int
iscsit_drv_ioctl(dev_t drv,int cmd,intptr_t argp,int flag,cred_t * cred,int * retval)440a6d42e7dSPeter Dunlap iscsit_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flag, cred_t *cred,
441a6d42e7dSPeter Dunlap     int *retval)
442a6d42e7dSPeter Dunlap {
443a6d42e7dSPeter Dunlap 	iscsit_ioc_set_config_t		setcfg;
444a6d42e7dSPeter Dunlap 	iscsit_ioc_set_config32_t	setcfg32;
44507a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	char				*cfg_pnvlist = NULL;
44607a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	nvlist_t			*cfg_nvlist = NULL;
44707a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	it_config_t			*cfg = NULL;
448a6d42e7dSPeter Dunlap 	idm_status_t			idmrc;
449a6d42e7dSPeter Dunlap 	int				rc = 0;
450a6d42e7dSPeter Dunlap 
451a6d42e7dSPeter Dunlap 	if (drv_priv(cred) != 0) {
452a6d42e7dSPeter Dunlap 		return (EPERM);
453a6d42e7dSPeter Dunlap 	}
454a6d42e7dSPeter Dunlap 
4558c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	mutex_enter(&iscsit_global.global_state_mutex);
456a6d42e7dSPeter Dunlap 
457a6d42e7dSPeter Dunlap 	/*
458a6d42e7dSPeter Dunlap 	 * Validate ioctl requests against global service state
459a6d42e7dSPeter Dunlap 	 */
460a6d42e7dSPeter Dunlap 	switch (iscsit_global.global_svc_state) {
461a6d42e7dSPeter Dunlap 	case ISE_ENABLED:
462a6d42e7dSPeter Dunlap 		if (cmd == ISCSIT_IOC_DISABLE_SVC) {
463a6d42e7dSPeter Dunlap 			iscsit_global.global_svc_state = ISE_DISABLING;
464a6d42e7dSPeter Dunlap 		} else if (cmd == ISCSIT_IOC_ENABLE_SVC) {
465a6d42e7dSPeter Dunlap 			/* Already enabled */
4668c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			mutex_exit(&iscsit_global.global_state_mutex);
467a6d42e7dSPeter Dunlap 			return (0);
468a6d42e7dSPeter Dunlap 		} else {
469a6d42e7dSPeter Dunlap 			iscsit_global.global_svc_state = ISE_BUSY;
470a6d42e7dSPeter Dunlap 		}
471a6d42e7dSPeter Dunlap 		break;
472a6d42e7dSPeter Dunlap 	case ISE_DISABLED:
473a6d42e7dSPeter Dunlap 		if (cmd == ISCSIT_IOC_ENABLE_SVC) {
474a6d42e7dSPeter Dunlap 			iscsit_global.global_svc_state = ISE_ENABLING;
475a6d42e7dSPeter Dunlap 		} else if (cmd == ISCSIT_IOC_DISABLE_SVC) {
476a6d42e7dSPeter Dunlap 			/* Already disabled */
4778c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			mutex_exit(&iscsit_global.global_state_mutex);
478a6d42e7dSPeter Dunlap 			return (0);
479a6d42e7dSPeter Dunlap 		} else {
480a6d42e7dSPeter Dunlap 			rc = EFAULT;
481a6d42e7dSPeter Dunlap 		}
482a6d42e7dSPeter Dunlap 		break;
4838c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	case ISE_BUSY:
484a6d42e7dSPeter Dunlap 	case ISE_ENABLING:
485a6d42e7dSPeter Dunlap 	case ISE_DISABLING:
486a6d42e7dSPeter Dunlap 		rc = EAGAIN;
487a6d42e7dSPeter Dunlap 		break;
488a6d42e7dSPeter Dunlap 	case ISE_DETACHED:
489a6d42e7dSPeter Dunlap 	default:
490a6d42e7dSPeter Dunlap 		rc = EFAULT;
491a6d42e7dSPeter Dunlap 		break;
492a6d42e7dSPeter Dunlap 	}
493a6d42e7dSPeter Dunlap 
4948c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	mutex_exit(&iscsit_global.global_state_mutex);
495a6d42e7dSPeter Dunlap 	if (rc != 0)
496a6d42e7dSPeter Dunlap 		return (rc);
497a6d42e7dSPeter Dunlap 
498a6d42e7dSPeter Dunlap 	/* Handle ioctl request (enable/disable have already been handled) */
499a6d42e7dSPeter Dunlap 	switch (cmd) {
500a6d42e7dSPeter Dunlap 	case ISCSIT_IOC_SET_CONFIG:
50107a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		/* Any errors must set state back to ISE_ENABLED */
502a6d42e7dSPeter Dunlap 		switch (ddi_model_convert_from(flag & FMODELS)) {
503a6d42e7dSPeter Dunlap 		case DDI_MODEL_ILP32:
504a6d42e7dSPeter Dunlap 			if (ddi_copyin((void *)argp, &setcfg32,
50507a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			    sizeof (iscsit_ioc_set_config32_t), flag) != 0) {
50607a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 				rc = EFAULT;
50707a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 				goto cleanup;
50807a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			}
509a6d42e7dSPeter Dunlap 
510a6d42e7dSPeter Dunlap 			setcfg.set_cfg_pnvlist =
511a6d42e7dSPeter Dunlap 			    (char *)((uintptr_t)setcfg32.set_cfg_pnvlist);
512a6d42e7dSPeter Dunlap 			setcfg.set_cfg_vers = setcfg32.set_cfg_vers;
513a6d42e7dSPeter Dunlap 			setcfg.set_cfg_pnvlist_len =
514a6d42e7dSPeter Dunlap 			    setcfg32.set_cfg_pnvlist_len;
515a6d42e7dSPeter Dunlap 			break;
516a6d42e7dSPeter Dunlap 		case DDI_MODEL_NONE:
517a6d42e7dSPeter Dunlap 			if (ddi_copyin((void *)argp, &setcfg,
51807a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			    sizeof (iscsit_ioc_set_config_t), flag) != 0) {
51907a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 				rc = EFAULT;
52007a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 				goto cleanup;
52107a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			}
522a6d42e7dSPeter Dunlap 			break;
523fcc214c3SCharles Ting 		default:
524fcc214c3SCharles Ting 			rc = EFAULT;
525fcc214c3SCharles Ting 			goto cleanup;
526a6d42e7dSPeter Dunlap 		}
527a6d42e7dSPeter Dunlap 
528a6d42e7dSPeter Dunlap 		/* Check API version */
529a6d42e7dSPeter Dunlap 		if (setcfg.set_cfg_vers != ISCSIT_API_VERS0) {
53007a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			rc = EINVAL;
53107a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			goto cleanup;
532a6d42e7dSPeter Dunlap 		}
533a6d42e7dSPeter Dunlap 
534a6d42e7dSPeter Dunlap 		/* Config is in packed nvlist format so unpack it */
535a6d42e7dSPeter Dunlap 		cfg_pnvlist = kmem_alloc(setcfg.set_cfg_pnvlist_len,
536a6d42e7dSPeter Dunlap 		    KM_SLEEP);
537a6d42e7dSPeter Dunlap 		ASSERT(cfg_pnvlist != NULL);
538a6d42e7dSPeter Dunlap 
539a6d42e7dSPeter Dunlap 		if (ddi_copyin(setcfg.set_cfg_pnvlist, cfg_pnvlist,
540a6d42e7dSPeter Dunlap 		    setcfg.set_cfg_pnvlist_len, flag) != 0) {
54107a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			rc = EFAULT;
54207a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			goto cleanup;
543a6d42e7dSPeter Dunlap 		}
544a6d42e7dSPeter Dunlap 
54507a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		rc = nvlist_unpack(cfg_pnvlist, setcfg.set_cfg_pnvlist_len,
54607a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		    &cfg_nvlist, KM_SLEEP);
54707a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		if (rc != 0) {
54807a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			goto cleanup;
549a6d42e7dSPeter Dunlap 		}
550a6d42e7dSPeter Dunlap 
551a6d42e7dSPeter Dunlap 		/* Translate nvlist */
55207a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		rc = it_nv_to_config(cfg_nvlist, &cfg);
55307a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		if (rc != 0) {
554a6d42e7dSPeter Dunlap 			cmn_err(CE_WARN, "Configuration is invalid");
55507a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			goto cleanup;
556a6d42e7dSPeter Dunlap 		}
557a6d42e7dSPeter Dunlap 
558a6d42e7dSPeter Dunlap 		/* Update config */
55907a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		rc = iscsit_config_merge(cfg);
56007a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		/* FALLTHROUGH */
56107a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 
56207a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States cleanup:
56307a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		if (cfg)
56407a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			it_config_free_cmn(cfg);
56507a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		if (cfg_pnvlist)
566a6d42e7dSPeter Dunlap 			kmem_free(cfg_pnvlist, setcfg.set_cfg_pnvlist_len);
567*61dfa509SRick McNeal 		if (cfg_nvlist)
568*61dfa509SRick McNeal 			nvlist_free(cfg_nvlist);
569a6d42e7dSPeter Dunlap 
570a6d42e7dSPeter Dunlap 		/*
571a6d42e7dSPeter Dunlap 		 * Now that the reconfig is complete set our state back to
572a6d42e7dSPeter Dunlap 		 * enabled.
573a6d42e7dSPeter Dunlap 		 */
5748c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		mutex_enter(&iscsit_global.global_state_mutex);
575a6d42e7dSPeter Dunlap 		iscsit_global.global_svc_state = ISE_ENABLED;
5768c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		mutex_exit(&iscsit_global.global_state_mutex);
577a6d42e7dSPeter Dunlap 		break;
578a6d42e7dSPeter Dunlap 	case ISCSIT_IOC_ENABLE_SVC: {
579a6d42e7dSPeter Dunlap 		iscsit_hostinfo_t hostinfo;
580a6d42e7dSPeter Dunlap 
581a6d42e7dSPeter Dunlap 		if (ddi_copyin((void *)argp, &hostinfo.length,
582a6d42e7dSPeter Dunlap 		    sizeof (hostinfo.length), flag) != 0) {
5838c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			mutex_enter(&iscsit_global.global_state_mutex);
584a6d42e7dSPeter Dunlap 			iscsit_global.global_svc_state = ISE_DISABLED;
5858c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			mutex_exit(&iscsit_global.global_state_mutex);
586a6d42e7dSPeter Dunlap 			return (EFAULT);
587a6d42e7dSPeter Dunlap 		}
588a6d42e7dSPeter Dunlap 
589a6d42e7dSPeter Dunlap 		if (hostinfo.length > sizeof (hostinfo.fqhn))
590a6d42e7dSPeter Dunlap 			hostinfo.length = sizeof (hostinfo.fqhn);
591a6d42e7dSPeter Dunlap 
592a6d42e7dSPeter Dunlap 		if (ddi_copyin((void *)((caddr_t)argp +
593a6d42e7dSPeter Dunlap 		    sizeof (hostinfo.length)), &hostinfo.fqhn,
594a6d42e7dSPeter Dunlap 		    hostinfo.length, flag) != 0) {
5958c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			mutex_enter(&iscsit_global.global_state_mutex);
596a6d42e7dSPeter Dunlap 			iscsit_global.global_svc_state = ISE_DISABLED;
5978c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			mutex_exit(&iscsit_global.global_state_mutex);
598a6d42e7dSPeter Dunlap 			return (EFAULT);
599a6d42e7dSPeter Dunlap 		}
600a6d42e7dSPeter Dunlap 
601a6d42e7dSPeter Dunlap 		idmrc = iscsit_enable_svc(&hostinfo);
6028c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		mutex_enter(&iscsit_global.global_state_mutex);
603a6d42e7dSPeter Dunlap 		if (idmrc == IDM_STATUS_SUCCESS) {
604a6d42e7dSPeter Dunlap 			iscsit_global.global_svc_state = ISE_ENABLED;
605a6d42e7dSPeter Dunlap 		} else {
606a6d42e7dSPeter Dunlap 			rc = EIO;
607a6d42e7dSPeter Dunlap 			iscsit_global.global_svc_state = ISE_DISABLED;
608a6d42e7dSPeter Dunlap 		}
6098c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		mutex_exit(&iscsit_global.global_state_mutex);
610a6d42e7dSPeter Dunlap 		break;
611a6d42e7dSPeter Dunlap 	}
612a6d42e7dSPeter Dunlap 	case ISCSIT_IOC_DISABLE_SVC:
613a6d42e7dSPeter Dunlap 		iscsit_disable_svc();
6148c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		mutex_enter(&iscsit_global.global_state_mutex);
615a6d42e7dSPeter Dunlap 		iscsit_global.global_svc_state = ISE_DISABLED;
6168c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		mutex_exit(&iscsit_global.global_state_mutex);
617a6d42e7dSPeter Dunlap 		break;
61807a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 
619a6d42e7dSPeter Dunlap 	default:
620a6d42e7dSPeter Dunlap 		rc = EINVAL;
6218c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		mutex_enter(&iscsit_global.global_state_mutex);
62207a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		iscsit_global.global_svc_state = ISE_ENABLED;
6238c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		mutex_exit(&iscsit_global.global_state_mutex);
624a6d42e7dSPeter Dunlap 	}
625a6d42e7dSPeter Dunlap 
626a6d42e7dSPeter Dunlap 	return (rc);
627a6d42e7dSPeter Dunlap }
628a6d42e7dSPeter Dunlap 
629a6d42e7dSPeter Dunlap static idm_status_t
iscsit_init(dev_info_t * dip)630a6d42e7dSPeter Dunlap iscsit_init(dev_info_t *dip)
631a6d42e7dSPeter Dunlap {
632a6d42e7dSPeter Dunlap 	int			rc;
633a6d42e7dSPeter Dunlap 
634a6d42e7dSPeter Dunlap 	rc = ldi_ident_from_dip(dip, &iscsit_global.global_li);
635a6d42e7dSPeter Dunlap 	ASSERT(rc == 0);  /* Failure indicates invalid argument */
636a6d42e7dSPeter Dunlap 
637a6d42e7dSPeter Dunlap 	iscsit_global.global_svc_state = ISE_DISABLED;
638a6d42e7dSPeter Dunlap 
639a6d42e7dSPeter Dunlap 	return (IDM_STATUS_SUCCESS);
640a6d42e7dSPeter Dunlap }
641a6d42e7dSPeter Dunlap 
642a6d42e7dSPeter Dunlap /*
643a6d42e7dSPeter Dunlap  * iscsit_enable_svc
644a6d42e7dSPeter Dunlap  *
645a6d42e7dSPeter Dunlap  * registers all the configured targets and target portals with STMF
646a6d42e7dSPeter Dunlap  */
647a6d42e7dSPeter Dunlap static idm_status_t
iscsit_enable_svc(iscsit_hostinfo_t * hostinfo)648a6d42e7dSPeter Dunlap iscsit_enable_svc(iscsit_hostinfo_t *hostinfo)
649a6d42e7dSPeter Dunlap {
650a6d42e7dSPeter Dunlap 	stmf_port_provider_t	*pp;
651a6d42e7dSPeter Dunlap 	stmf_dbuf_store_t	*dbuf_store;
652a6d42e7dSPeter Dunlap 	boolean_t		did_iscsit_isns_init;
653a6d42e7dSPeter Dunlap 	idm_status_t		retval = IDM_STATUS_SUCCESS;
654a6d42e7dSPeter Dunlap 
655a6d42e7dSPeter Dunlap 	ASSERT(iscsit_global.global_svc_state == ISE_ENABLING);
656a6d42e7dSPeter Dunlap 
657a6d42e7dSPeter Dunlap 	/*
658a6d42e7dSPeter Dunlap 	 * Make sure that can tell if we have partially allocated
659a6d42e7dSPeter Dunlap 	 * in case we need to exit and tear down anything allocated.
660a6d42e7dSPeter Dunlap 	 */
661a6d42e7dSPeter Dunlap 	iscsit_global.global_tsih_pool = NULL;
662a6d42e7dSPeter Dunlap 	iscsit_global.global_dbuf_store = NULL;
663a6d42e7dSPeter Dunlap 	iscsit_status_pdu_cache = NULL;
664a6d42e7dSPeter Dunlap 	pp = NULL;
665a6d42e7dSPeter Dunlap 	iscsit_global.global_pp = NULL;
666a6d42e7dSPeter Dunlap 	iscsit_global.global_default_tpg = NULL;
667a6d42e7dSPeter Dunlap 	did_iscsit_isns_init = B_FALSE;
668a6d42e7dSPeter Dunlap 	iscsit_global.global_dispatch_taskq = NULL;
669a6d42e7dSPeter Dunlap 
670a6d42e7dSPeter Dunlap 	/* Setup remaining fields in iscsit_global_t */
671a6d42e7dSPeter Dunlap 	idm_refcnt_init(&iscsit_global.global_refcnt,
672a6d42e7dSPeter Dunlap 	    &iscsit_global);
673a6d42e7dSPeter Dunlap 
674a6d42e7dSPeter Dunlap 	avl_create(&iscsit_global.global_discovery_sessions,
675a6d42e7dSPeter Dunlap 	    iscsit_sess_avl_compare, sizeof (iscsit_sess_t),
676a6d42e7dSPeter Dunlap 	    offsetof(iscsit_sess_t, ist_tgt_ln));
677a6d42e7dSPeter Dunlap 
678a6d42e7dSPeter Dunlap 	avl_create(&iscsit_global.global_target_list,
679a6d42e7dSPeter Dunlap 	    iscsit_tgt_avl_compare, sizeof (iscsit_tgt_t),
680a6d42e7dSPeter Dunlap 	    offsetof(iscsit_tgt_t, target_global_ln));
681a6d42e7dSPeter Dunlap 
682a6d42e7dSPeter Dunlap 	list_create(&iscsit_global.global_deleted_target_list,
683a6d42e7dSPeter Dunlap 	    sizeof (iscsit_tgt_t),
684a6d42e7dSPeter Dunlap 	    offsetof(iscsit_tgt_t, target_global_deleted_ln));
685a6d42e7dSPeter Dunlap 
686a6d42e7dSPeter Dunlap 	avl_create(&iscsit_global.global_tpg_list,
687a6d42e7dSPeter Dunlap 	    iscsit_tpg_avl_compare, sizeof (iscsit_tpg_t),
688a6d42e7dSPeter Dunlap 	    offsetof(iscsit_tpg_t, tpg_global_ln));
689a6d42e7dSPeter Dunlap 
690a6d42e7dSPeter Dunlap 	avl_create(&iscsit_global.global_ini_list,
691a6d42e7dSPeter Dunlap 	    iscsit_ini_avl_compare, sizeof (iscsit_ini_t),
692a6d42e7dSPeter Dunlap 	    offsetof(iscsit_ini_t, ini_global_ln));
693a6d42e7dSPeter Dunlap 
694a6d42e7dSPeter Dunlap 	iscsit_global.global_tsih_pool = vmem_create("iscsit_tsih_pool",
695a6d42e7dSPeter Dunlap 	    (void *)1, ISCSI_MAX_TSIH, 1, NULL, NULL, NULL, 0,
696a6d42e7dSPeter Dunlap 	    VM_SLEEP | VMC_IDENTIFIER);
697a6d42e7dSPeter Dunlap 
698a6d42e7dSPeter Dunlap 	/*
699a6d42e7dSPeter Dunlap 	 * Setup STMF dbuf store.  Our buffers are bound to a specific
700a6d42e7dSPeter Dunlap 	 * connection so we really can't let STMF cache buffers for us.
701a6d42e7dSPeter Dunlap 	 * Consequently we'll just allocate one global buffer store.
702a6d42e7dSPeter Dunlap 	 */
703a6d42e7dSPeter Dunlap 	dbuf_store = stmf_alloc(STMF_STRUCT_DBUF_STORE, 0, 0);
704a6d42e7dSPeter Dunlap 	if (dbuf_store == NULL) {
705a6d42e7dSPeter Dunlap 		retval = IDM_STATUS_FAIL;
706a6d42e7dSPeter Dunlap 		goto tear_down_and_return;
707a6d42e7dSPeter Dunlap 	}
708a6d42e7dSPeter Dunlap 	dbuf_store->ds_alloc_data_buf = iscsit_dbuf_alloc;
709a6d42e7dSPeter Dunlap 	dbuf_store->ds_free_data_buf = iscsit_dbuf_free;
710a6d42e7dSPeter Dunlap 	dbuf_store->ds_port_private = NULL;
711a6d42e7dSPeter Dunlap 	iscsit_global.global_dbuf_store = dbuf_store;
712a6d42e7dSPeter Dunlap 
713a6d42e7dSPeter Dunlap 	/* Status PDU cache */
714a6d42e7dSPeter Dunlap 	iscsit_status_pdu_cache = kmem_cache_create("iscsit_status_pdu_cache",
715a6d42e7dSPeter Dunlap 	    sizeof (idm_pdu_t) + sizeof (iscsi_scsi_rsp_hdr_t), 8,
716a6d42e7dSPeter Dunlap 	    &iscsit_status_pdu_constructor,
717a6d42e7dSPeter Dunlap 	    NULL, NULL, NULL, NULL, KM_SLEEP);
718a6d42e7dSPeter Dunlap 
719a6d42e7dSPeter Dunlap 	/* Default TPG and portal */
720a6d42e7dSPeter Dunlap 	iscsit_global.global_default_tpg = iscsit_tpg_createdefault();
721a6d42e7dSPeter Dunlap 	if (iscsit_global.global_default_tpg == NULL) {
722a6d42e7dSPeter Dunlap 		retval = IDM_STATUS_FAIL;
723a6d42e7dSPeter Dunlap 		goto tear_down_and_return;
724a6d42e7dSPeter Dunlap 	}
725a6d42e7dSPeter Dunlap 
726a6d42e7dSPeter Dunlap 	/* initialize isns client */
727a6d42e7dSPeter Dunlap 	(void) iscsit_isns_init(hostinfo);
728a6d42e7dSPeter Dunlap 	did_iscsit_isns_init = B_TRUE;
729a6d42e7dSPeter Dunlap 
730a6d42e7dSPeter Dunlap 	/* Register port provider */
731a6d42e7dSPeter Dunlap 	pp = stmf_alloc(STMF_STRUCT_PORT_PROVIDER, 0, 0);
732a6d42e7dSPeter Dunlap 	if (pp == NULL) {
733a6d42e7dSPeter Dunlap 		retval = IDM_STATUS_FAIL;
734a6d42e7dSPeter Dunlap 		goto tear_down_and_return;
735a6d42e7dSPeter Dunlap 	}
736a6d42e7dSPeter Dunlap 
737a6d42e7dSPeter Dunlap 	pp->pp_portif_rev = PORTIF_REV_1;
738a6d42e7dSPeter Dunlap 	pp->pp_instance = 0;
739a6d42e7dSPeter Dunlap 	pp->pp_name = ISCSIT_MODNAME;
740a6d42e7dSPeter Dunlap 	pp->pp_cb = iscsit_pp_cb;
741a6d42e7dSPeter Dunlap 
742a6d42e7dSPeter Dunlap 	iscsit_global.global_pp = pp;
743a6d42e7dSPeter Dunlap 
744a6d42e7dSPeter Dunlap 
745a6d42e7dSPeter Dunlap 	if (stmf_register_port_provider(pp) != STMF_SUCCESS) {
746a6d42e7dSPeter Dunlap 		retval = IDM_STATUS_FAIL;
747a6d42e7dSPeter Dunlap 		goto tear_down_and_return;
748a6d42e7dSPeter Dunlap 	}
749a6d42e7dSPeter Dunlap 
750a6d42e7dSPeter Dunlap 	iscsit_global.global_dispatch_taskq = taskq_create("iscsit_dispatch",
751a6d42e7dSPeter Dunlap 	    1, minclsyspri, 16, 16, TASKQ_PREPOPULATE);
752a6d42e7dSPeter Dunlap 
753d618d68dSPriya Krishnan 	/* Scan staged PDUs, meaningful in MC/S situations */
754d618d68dSPriya Krishnan 	iscsit_rxpdu_queue_monitor_start();
755d618d68dSPriya Krishnan 
756a6d42e7dSPeter Dunlap 	return (IDM_STATUS_SUCCESS);
757a6d42e7dSPeter Dunlap 
758a6d42e7dSPeter Dunlap tear_down_and_return:
759a6d42e7dSPeter Dunlap 
760a6d42e7dSPeter Dunlap 	if (iscsit_global.global_dispatch_taskq) {
761a6d42e7dSPeter Dunlap 		taskq_destroy(iscsit_global.global_dispatch_taskq);
762a6d42e7dSPeter Dunlap 		iscsit_global.global_dispatch_taskq = NULL;
763a6d42e7dSPeter Dunlap 	}
764a6d42e7dSPeter Dunlap 
765a6d42e7dSPeter Dunlap 	if (did_iscsit_isns_init)
766a6d42e7dSPeter Dunlap 		iscsit_isns_fini();
767a6d42e7dSPeter Dunlap 
768a6d42e7dSPeter Dunlap 	if (iscsit_global.global_default_tpg) {
769a6d42e7dSPeter Dunlap 		iscsit_tpg_destroydefault(iscsit_global.global_default_tpg);
770a6d42e7dSPeter Dunlap 		iscsit_global.global_default_tpg = NULL;
771a6d42e7dSPeter Dunlap 	}
772a6d42e7dSPeter Dunlap 
773a6d42e7dSPeter Dunlap 	if (iscsit_global.global_pp)
774a6d42e7dSPeter Dunlap 		iscsit_global.global_pp = NULL;
775a6d42e7dSPeter Dunlap 
776a6d42e7dSPeter Dunlap 	if (pp)
777a6d42e7dSPeter Dunlap 		stmf_free(pp);
778a6d42e7dSPeter Dunlap 
779a6d42e7dSPeter Dunlap 	if (iscsit_status_pdu_cache) {
780a6d42e7dSPeter Dunlap 		kmem_cache_destroy(iscsit_status_pdu_cache);
781a6d42e7dSPeter Dunlap 		iscsit_status_pdu_cache = NULL;
782a6d42e7dSPeter Dunlap 	}
783a6d42e7dSPeter Dunlap 
784a6d42e7dSPeter Dunlap 	if (iscsit_global.global_dbuf_store) {
785a6d42e7dSPeter Dunlap 		stmf_free(iscsit_global.global_dbuf_store);
786a6d42e7dSPeter Dunlap 		iscsit_global.global_dbuf_store = NULL;
787a6d42e7dSPeter Dunlap 	}
788a6d42e7dSPeter Dunlap 
789a6d42e7dSPeter Dunlap 	if (iscsit_global.global_tsih_pool) {
790a6d42e7dSPeter Dunlap 		vmem_destroy(iscsit_global.global_tsih_pool);
791a6d42e7dSPeter Dunlap 		iscsit_global.global_tsih_pool = NULL;
792a6d42e7dSPeter Dunlap 	}
793a6d42e7dSPeter Dunlap 
794a6d42e7dSPeter Dunlap 	avl_destroy(&iscsit_global.global_ini_list);
795a6d42e7dSPeter Dunlap 	avl_destroy(&iscsit_global.global_tpg_list);
796a6d42e7dSPeter Dunlap 	list_destroy(&iscsit_global.global_deleted_target_list);
797a6d42e7dSPeter Dunlap 	avl_destroy(&iscsit_global.global_target_list);
798a6d42e7dSPeter Dunlap 	avl_destroy(&iscsit_global.global_discovery_sessions);
799a6d42e7dSPeter Dunlap 
800a6d42e7dSPeter Dunlap 	idm_refcnt_destroy(&iscsit_global.global_refcnt);
801a6d42e7dSPeter Dunlap 
802a6d42e7dSPeter Dunlap 	return (retval);
803a6d42e7dSPeter Dunlap }
804a6d42e7dSPeter Dunlap 
805a6d42e7dSPeter Dunlap /*
806a6d42e7dSPeter Dunlap  * iscsit_disable_svc
807a6d42e7dSPeter Dunlap  *
808a6d42e7dSPeter Dunlap  * clean up all existing connections and deregister targets from STMF
809a6d42e7dSPeter Dunlap  */
810a6d42e7dSPeter Dunlap static void
iscsit_disable_svc(void)811a6d42e7dSPeter Dunlap iscsit_disable_svc(void)
812a6d42e7dSPeter Dunlap {
813a6d42e7dSPeter Dunlap 	iscsit_sess_t	*sess;
814a6d42e7dSPeter Dunlap 
815a6d42e7dSPeter Dunlap 	ASSERT(iscsit_global.global_svc_state == ISE_DISABLING);
816a6d42e7dSPeter Dunlap 
817d618d68dSPriya Krishnan 	iscsit_rxpdu_queue_monitor_stop();
818d618d68dSPriya Krishnan 
819a6d42e7dSPeter Dunlap 	/* tear down discovery sessions */
820a6d42e7dSPeter Dunlap 	for (sess = avl_first(&iscsit_global.global_discovery_sessions);
821a6d42e7dSPeter Dunlap 	    sess != NULL;
822a6d42e7dSPeter Dunlap 	    sess = AVL_NEXT(&iscsit_global.global_discovery_sessions, sess))
823a6d42e7dSPeter Dunlap 		iscsit_sess_close(sess);
824a6d42e7dSPeter Dunlap 
825a6d42e7dSPeter Dunlap 	/*
826a6d42e7dSPeter Dunlap 	 * Passing NULL to iscsit_config_merge tells it to go to an empty
827a6d42e7dSPeter Dunlap 	 * config.
828a6d42e7dSPeter Dunlap 	 */
829a6d42e7dSPeter Dunlap 	(void) iscsit_config_merge(NULL);
830a6d42e7dSPeter Dunlap 
831a6d42e7dSPeter Dunlap 	/*
832a6d42e7dSPeter Dunlap 	 * Wait until there are no more global references
833a6d42e7dSPeter Dunlap 	 */
834a6d42e7dSPeter Dunlap 	idm_refcnt_wait_ref(&iscsit_global.global_refcnt);
835a6d42e7dSPeter Dunlap 	idm_refcnt_destroy(&iscsit_global.global_refcnt);
836a6d42e7dSPeter Dunlap 
837a6d42e7dSPeter Dunlap 	/*
838a6d42e7dSPeter Dunlap 	 * Default TPG must be destroyed after global_refcnt is 0.
839a6d42e7dSPeter Dunlap 	 */
840a6d42e7dSPeter Dunlap 	iscsit_tpg_destroydefault(iscsit_global.global_default_tpg);
841a6d42e7dSPeter Dunlap 
842a6d42e7dSPeter Dunlap 	avl_destroy(&iscsit_global.global_discovery_sessions);
843a6d42e7dSPeter Dunlap 	list_destroy(&iscsit_global.global_deleted_target_list);
844a6d42e7dSPeter Dunlap 	avl_destroy(&iscsit_global.global_target_list);
845a6d42e7dSPeter Dunlap 	avl_destroy(&iscsit_global.global_tpg_list);
846a6d42e7dSPeter Dunlap 	avl_destroy(&iscsit_global.global_ini_list);
847a6d42e7dSPeter Dunlap 
848a6d42e7dSPeter Dunlap 	taskq_destroy(iscsit_global.global_dispatch_taskq);
849a6d42e7dSPeter Dunlap 
850a6d42e7dSPeter Dunlap 	iscsit_isns_fini();
851a6d42e7dSPeter Dunlap 
852a6d42e7dSPeter Dunlap 	stmf_free(iscsit_global.global_dbuf_store);
853a6d42e7dSPeter Dunlap 	iscsit_global.global_dbuf_store = NULL;
854a6d42e7dSPeter Dunlap 
855a6d42e7dSPeter Dunlap 	(void) stmf_deregister_port_provider(iscsit_global.global_pp);
856a6d42e7dSPeter Dunlap 	stmf_free(iscsit_global.global_pp);
857a6d42e7dSPeter Dunlap 	iscsit_global.global_pp = NULL;
858a6d42e7dSPeter Dunlap 
859a6d42e7dSPeter Dunlap 	kmem_cache_destroy(iscsit_status_pdu_cache);
860a6d42e7dSPeter Dunlap 	iscsit_status_pdu_cache = NULL;
861a6d42e7dSPeter Dunlap 
862a6d42e7dSPeter Dunlap 	vmem_destroy(iscsit_global.global_tsih_pool);
863a6d42e7dSPeter Dunlap 	iscsit_global.global_tsih_pool = NULL;
864a6d42e7dSPeter Dunlap }
865a6d42e7dSPeter Dunlap 
866a6d42e7dSPeter Dunlap void
iscsit_global_hold()867a6d42e7dSPeter Dunlap iscsit_global_hold()
868a6d42e7dSPeter Dunlap {
8698c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	/*
8708c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 * To take out a global hold, we must either own the global
8718c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 * state mutex or we must be running inside of an ioctl that
8728c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 * has set the global state to ISE_BUSY, ISE_DISABLING, or
8738c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 * ISE_ENABLING.  We don't track the "owner" for these flags,
8748c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 * so just checking if they are set is enough for now.
8758c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 */
8768c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	ASSERT((iscsit_global.global_svc_state == ISE_ENABLING) ||
8778c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	    (iscsit_global.global_svc_state == ISE_DISABLING) ||
8788c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	    (iscsit_global.global_svc_state == ISE_BUSY) ||
8798c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	    MUTEX_HELD(&iscsit_global.global_state_mutex));
8808c629652SPeter Cudhea - Sun Microsystems - Burlington, MA United States 
881a6d42e7dSPeter Dunlap 	idm_refcnt_hold(&iscsit_global.global_refcnt);
882a6d42e7dSPeter Dunlap }
883a6d42e7dSPeter Dunlap 
884a6d42e7dSPeter Dunlap void
iscsit_global_rele()885a6d42e7dSPeter Dunlap iscsit_global_rele()
886a6d42e7dSPeter Dunlap {
887a6d42e7dSPeter Dunlap 	idm_refcnt_rele(&iscsit_global.global_refcnt);
888a6d42e7dSPeter Dunlap }
889a6d42e7dSPeter Dunlap 
890a6d42e7dSPeter Dunlap void
iscsit_global_wait_ref()891a6d42e7dSPeter Dunlap iscsit_global_wait_ref()
892a6d42e7dSPeter Dunlap {
893a6d42e7dSPeter Dunlap 	idm_refcnt_wait_ref(&iscsit_global.global_refcnt);
894a6d42e7dSPeter Dunlap }
895a6d42e7dSPeter Dunlap 
896a6d42e7dSPeter Dunlap /*
897a6d42e7dSPeter Dunlap  * IDM callbacks
898a6d42e7dSPeter Dunlap  */
899a6d42e7dSPeter Dunlap 
900a6d42e7dSPeter Dunlap /*ARGSUSED*/
901a6d42e7dSPeter Dunlap void
iscsit_rx_pdu(idm_conn_t * ic,idm_pdu_t * rx_pdu)902a6d42e7dSPeter Dunlap iscsit_rx_pdu(idm_conn_t *ic, idm_pdu_t *rx_pdu)
903a6d42e7dSPeter Dunlap {
904a6d42e7dSPeter Dunlap 	iscsit_conn_t *ict = ic->ic_handle;
905a6d42e7dSPeter Dunlap 	switch (IDM_PDU_OPCODE(rx_pdu)) {
906a6d42e7dSPeter Dunlap 	case ISCSI_OP_SCSI_CMD:
907a6d42e7dSPeter Dunlap 		ASSERT(0); /* Shouldn't happen */
908a6d42e7dSPeter Dunlap 		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
909a6d42e7dSPeter Dunlap 		break;
910a6d42e7dSPeter Dunlap 	case ISCSI_OP_SNACK_CMD:
911a6d42e7dSPeter Dunlap 		/*
912a6d42e7dSPeter Dunlap 		 * We'll need to handle this when we support ERL1/2.  For
913a6d42e7dSPeter Dunlap 		 * now we treat it as a protocol error.
914a6d42e7dSPeter Dunlap 		 */
915a6d42e7dSPeter Dunlap 		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
9161f99504aSToomas Soome 		idm_conn_event(ic, CE_TRANSPORT_FAIL, 0);
917a6d42e7dSPeter Dunlap 		break;
918a6d42e7dSPeter Dunlap 	case ISCSI_OP_SCSI_TASK_MGT_MSG:
919d618d68dSPriya Krishnan 		if (iscsit_check_cmdsn_and_queue(rx_pdu)) {
920d618d68dSPriya Krishnan 			iscsit_set_cmdsn(ict, rx_pdu);
921d618d68dSPriya Krishnan 			iscsit_op_scsi_task_mgmt(ict, rx_pdu);
922d618d68dSPriya Krishnan 		}
923a6d42e7dSPeter Dunlap 		break;
924a6d42e7dSPeter Dunlap 	case ISCSI_OP_NOOP_OUT:
925a6d42e7dSPeter Dunlap 	case ISCSI_OP_LOGIN_CMD:
926a6d42e7dSPeter Dunlap 	case ISCSI_OP_TEXT_CMD:
927a6d42e7dSPeter Dunlap 	case ISCSI_OP_LOGOUT_CMD:
928a6d42e7dSPeter Dunlap 		/*
929a6d42e7dSPeter Dunlap 		 * If/when we switch to userland processing these PDU's
930a6d42e7dSPeter Dunlap 		 * will be handled by iscsitd.
931a6d42e7dSPeter Dunlap 		 */
932a6d42e7dSPeter Dunlap 		iscsit_deferred_dispatch(rx_pdu);
933a6d42e7dSPeter Dunlap 		break;
934a6d42e7dSPeter Dunlap 	default:
935a6d42e7dSPeter Dunlap 		/* Protocol error */
936a6d42e7dSPeter Dunlap 		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
9371f99504aSToomas Soome 		idm_conn_event(ic, CE_TRANSPORT_FAIL, 0);
938a6d42e7dSPeter Dunlap 		break;
939a6d42e7dSPeter Dunlap 	}
940a6d42e7dSPeter Dunlap }
941a6d42e7dSPeter Dunlap 
942a6d42e7dSPeter Dunlap /*ARGSUSED*/
943a6d42e7dSPeter Dunlap void
iscsit_rx_pdu_error(idm_conn_t * ic,idm_pdu_t * rx_pdu,idm_status_t status)944a6d42e7dSPeter Dunlap iscsit_rx_pdu_error(idm_conn_t *ic, idm_pdu_t *rx_pdu, idm_status_t status)
945a6d42e7dSPeter Dunlap {
946a6d42e7dSPeter Dunlap 	idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
947a6d42e7dSPeter Dunlap }
948a6d42e7dSPeter Dunlap 
949a481fa48SRick McNeal /*
950a481fa48SRick McNeal  * iscsit_rx_scsi_rsp -- cause the connection to be closed if response rx'd
951a481fa48SRick McNeal  *
952a481fa48SRick McNeal  * A target sends an SCSI Response PDU, it should never receive one.
953a481fa48SRick McNeal  * This has been seen when running the Codemonicon suite of tests which
954a481fa48SRick McNeal  * does negative testing of the protocol. If such a condition occurs using
955a481fa48SRick McNeal  * a normal initiator it most likely means there's data corruption in the
956a481fa48SRick McNeal  * header and that's grounds for dropping the connection as well.
957a481fa48SRick McNeal  */
958a481fa48SRick McNeal void
iscsit_rx_scsi_rsp(idm_conn_t * ic,idm_pdu_t * rx_pdu)959a481fa48SRick McNeal iscsit_rx_scsi_rsp(idm_conn_t *ic, idm_pdu_t *rx_pdu)
960a481fa48SRick McNeal {
961a481fa48SRick McNeal 	idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
9621f99504aSToomas Soome 	idm_conn_event(ic, CE_TRANSPORT_FAIL, 0);
963a481fa48SRick McNeal }
964a481fa48SRick McNeal 
965a6d42e7dSPeter Dunlap void
iscsit_task_aborted(idm_task_t * idt,idm_status_t status)966a6d42e7dSPeter Dunlap iscsit_task_aborted(idm_task_t *idt, idm_status_t status)
967a6d42e7dSPeter Dunlap {
968a6d42e7dSPeter Dunlap 	iscsit_task_t *itask = idt->idt_private;
969a6d42e7dSPeter Dunlap 
970a6d42e7dSPeter Dunlap 	switch (status) {
971a6d42e7dSPeter Dunlap 	case IDM_STATUS_SUSPENDED:
972a6d42e7dSPeter Dunlap 		break;