1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25#include <sys/cpuvar.h>
26#include <sys/types.h>
27#include <sys/conf.h>
28#include <sys/stat.h>
29#include <sys/file.h>
30#include <sys/ddi.h>
31#include <sys/sunddi.h>
32#include <sys/modctl.h>
33#include <sys/sysmacros.h>
34#include <sys/socket.h>
35#include <sys/strsubr.h>
36#include <sys/nvpair.h>
37
38#include <sys/stmf.h>
39#include <sys/stmf_ioctl.h>
40#include <sys/portif.h>
41#include <sys/idm/idm.h>
42#include <sys/idm/idm_conn_sm.h>
43
44#include "iscsit_isns.h"
45#include "iscsit.h"
46
47#define	ISCSIT_VERSION		BUILD_DATE "-1.18dev"
48#define	ISCSIT_NAME_VERSION	"COMSTAR ISCSIT v" ISCSIT_VERSION
49
50/*
51 * DDI entry points.
52 */
53static int iscsit_drv_attach(dev_info_t *, ddi_attach_cmd_t);
54static int iscsit_drv_detach(dev_info_t *, ddi_detach_cmd_t);
55static int iscsit_drv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
56static int iscsit_drv_open(dev_t *, int, int, cred_t *);
57static int iscsit_drv_close(dev_t, int, int, cred_t *);
58static boolean_t iscsit_drv_busy(void);
59static int iscsit_drv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
60
61extern struct mod_ops mod_miscops;
62
63
64static struct cb_ops iscsit_cb_ops = {
65	iscsit_drv_open,	/* cb_open */
66	iscsit_drv_close,	/* cb_close */
67	nodev,			/* cb_strategy */
68	nodev,			/* cb_print */
69	nodev,			/* cb_dump */
70	nodev,			/* cb_read */
71	nodev,			/* cb_write */
72	iscsit_drv_ioctl,	/* cb_ioctl */
73	nodev,			/* cb_devmap */
74	nodev,			/* cb_mmap */
75	nodev,			/* cb_segmap */
76	nochpoll,		/* cb_chpoll */
77	ddi_prop_op,		/* cb_prop_op */
78	NULL,			/* cb_streamtab */
79	D_MP,			/* cb_flag */
80	CB_REV,			/* cb_rev */
81	nodev,			/* cb_aread */
82	nodev,			/* cb_awrite */
83};
84
85static struct dev_ops iscsit_dev_ops = {
86	DEVO_REV,		/* devo_rev */
87	0,			/* devo_refcnt */
88	iscsit_drv_getinfo,	/* devo_getinfo */
89	nulldev,		/* devo_identify */
90	nulldev,		/* devo_probe */
91	iscsit_drv_attach,	/* devo_attach */
92	iscsit_drv_detach,	/* devo_detach */
93	nodev,			/* devo_reset */
94	&iscsit_cb_ops,		/* devo_cb_ops */
95	NULL,			/* devo_bus_ops */
96	NULL,			/* devo_power */
97	ddi_quiesce_not_needed,	/* quiesce */
98};
99
100static struct modldrv modldrv = {
101	&mod_driverops,
102	"iSCSI Target",
103	&iscsit_dev_ops,
104};
105
106static struct modlinkage modlinkage = {
107	MODREV_1,
108	&modldrv,
109	NULL,
110};
111
112
113iscsit_global_t iscsit_global;
114
115kmem_cache_t	*iscsit_status_pdu_cache;
116
117boolean_t	iscsit_sm_logging = B_FALSE;
118
119kmutex_t	login_sm_session_mutex;
120
121static idm_status_t iscsit_init(dev_info_t *dip);
122static idm_status_t iscsit_enable_svc(iscsit_hostinfo_t *hostinfo);
123static void iscsit_disable_svc(void);
124
125static int
126iscsit_check_cmdsn_and_queue(idm_pdu_t *rx_pdu);
127
128static void
129iscsit_add_pdu_to_queue(iscsit_sess_t *ist, idm_pdu_t *rx_pdu);
130
131static idm_pdu_t *
132iscsit_remove_pdu_from_queue(iscsit_sess_t *ist, uint32_t cmdsn);
133
134static void
135iscsit_process_pdu_in_queue(iscsit_sess_t *ist);
136
137static void
138iscsit_rxpdu_queue_monitor_session(iscsit_sess_t *ist);
139
140static void
141iscsit_rxpdu_queue_monitor(void *arg);
142
143static void
144iscsit_post_staged_pdu(idm_pdu_t *rx_pdu);
145
146static void
147iscsit_post_scsi_cmd(idm_conn_t *ic, idm_pdu_t *rx_pdu);
148
149static void
150iscsit_op_scsi_task_mgmt(iscsit_conn_t *ict, idm_pdu_t *rx_pdu);
151
152static void
153iscsit_pdu_op_noop(iscsit_conn_t *ict, idm_pdu_t *rx_pdu);
154
155static void
156iscsit_pdu_op_login_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu);
157
158void
159iscsit_pdu_op_text_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu);
160
161static void
162iscsit_pdu_op_logout_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu);
163
164int iscsit_cmd_window();
165
166static  int
167iscsit_sna_lt(uint32_t sn1, uint32_t sn2);
168
169void
170iscsit_set_cmdsn(iscsit_conn_t *ict, idm_pdu_t *rx_pdu);
171
172static void
173iscsit_deferred_dispatch(idm_pdu_t *rx_pdu);
174
175static void
176iscsit_deferred(void *rx_pdu_void);
177
178static idm_status_t
179iscsit_conn_accept(idm_conn_t *ic);
180
181static idm_status_t
182iscsit_ffp_enabled(idm_conn_t *ic);
183
184static idm_status_t
185iscsit_ffp_disabled(idm_conn_t *ic, idm_ffp_disable_t disable_class);
186
187static idm_status_t
188iscsit_conn_lost(idm_conn_t *ic);
189
190static idm_status_t
191iscsit_conn_destroy(idm_conn_t *ic);
192
193static stmf_data_buf_t *
194iscsit_dbuf_alloc(scsi_task_t *task, uint32_t size, uint32_t *pminsize,
195    uint32_t flags);
196
197static void
198iscsit_dbuf_free(stmf_dbuf_store_t *ds, stmf_data_buf_t *dbuf);
199
200static void
201iscsit_buf_xfer_cb(idm_buf_t *idb, idm_status_t status);
202
203static void
204iscsit_send_good_status_done(idm_pdu_t *pdu, idm_status_t status);
205
206static void
207iscsit_send_status_done(idm_pdu_t *pdu, idm_status_t status);
208
209static stmf_status_t
210iscsit_idm_to_stmf(idm_status_t idmrc);
211
212static iscsit_task_t *
213iscsit_task_alloc(iscsit_conn_t *ict);
214
215static void
216iscsit_task_free(iscsit_task_t *itask);
217
218static iscsit_task_t *
219iscsit_tm_task_alloc(iscsit_conn_t *ict);
220
221static void
222iscsit_tm_task_free(iscsit_task_t *itask);
223
224static idm_status_t
225iscsit_task_start(iscsit_task_t *itask);
226
227static void
228iscsit_task_done(iscsit_task_t *itask);
229
230static int
231iscsit_status_pdu_constructor(void *pdu_void, void *arg, int flags);
232
233static void
234iscsit_pp_cb(struct stmf_port_provider *pp, int cmd, void *arg, uint32_t flags);
235
236static it_cfg_status_t
237iscsit_config_merge(it_config_t *cfg);
238
239static idm_status_t
240iscsit_login_fail(idm_conn_t *ic);
241
242static boolean_t iscsit_cmdsn_in_window(iscsit_conn_t *ict, uint32_t cmdsn);
243static void iscsit_send_direct_scsi_resp(iscsit_conn_t *ict, idm_pdu_t *rx_pdu,
244    uint8_t response, uint8_t cmd_status);
245static void iscsit_send_task_mgmt_resp(idm_pdu_t *tm_resp_pdu,
246    uint8_t tm_status);
247
248/*
249 * MC/S: Out-of-order commands are staged on a session-wide wait
250 * queue until a system-tunable threshold is reached. A separate
251 * thread is used to scan the staging queue on all the session,
252 * If a delayed PDU does not arrive within a timeout, the target
253 * will advance to the staged PDU that is next in sequence, skipping
254 * over the missing PDU(s) to go past a hole in the sequence.
255 */
256volatile int rxpdu_queue_threshold = ISCSIT_RXPDU_QUEUE_THRESHOLD;
257
258static kmutex_t		iscsit_rxpdu_queue_monitor_mutex;
259kthread_t		*iscsit_rxpdu_queue_monitor_thr_id;
260static kt_did_t		iscsit_rxpdu_queue_monitor_thr_did;
261static boolean_t	iscsit_rxpdu_queue_monitor_thr_running;
262static kcondvar_t	iscsit_rxpdu_queue_monitor_cv;
263
264int
265_init(void)
266{
267	int rc;
268
269	rw_init(&iscsit_global.global_rwlock, NULL, RW_DRIVER, NULL);
270	mutex_init(&iscsit_global.global_state_mutex, NULL,
271	    MUTEX_DRIVER, NULL);
272	iscsit_global.global_svc_state = ISE_DETACHED;
273
274	mutex_init(&iscsit_rxpdu_queue_monitor_mutex, NULL,
275	    MUTEX_DRIVER, NULL);
276	mutex_init(&login_sm_session_mutex, NULL, MUTEX_DRIVER, NULL);
277	iscsit_rxpdu_queue_monitor_thr_id = NULL;
278	iscsit_rxpdu_queue_monitor_thr_running = B_FALSE;
279	cv_init(&iscsit_rxpdu_queue_monitor_cv, NULL, CV_DEFAULT, NULL);
280
281	if ((rc = mod_install(&modlinkage)) != 0) {
282		mutex_destroy(&iscsit_global.global_state_mutex);
283		rw_destroy(&iscsit_global.global_rwlock);
284		return (rc);
285	}
286
287	return (rc);
288}
289
290int
291_info(struct modinfo *modinfop)
292{
293	return (mod_info(&modlinkage, modinfop));
294}
295
296int
297_fini(void)
298{
299	int rc;
300
301	rc = mod_remove(&modlinkage);
302
303	if (rc == 0) {
304		mutex_destroy(&iscsit_rxpdu_queue_monitor_mutex);
305		mutex_destroy(&login_sm_session_mutex);
306		cv_destroy(&iscsit_rxpdu_queue_monitor_cv);
307		mutex_destroy(&iscsit_global.global_state_mutex);
308		rw_destroy(&iscsit_global.global_rwlock);
309	}
310
311	return (rc);
312}
313
314/*
315 * DDI entry points.
316 */
317
318/* ARGSUSED */
319static int
320iscsit_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
321    void **result)
322{
323	ulong_t instance = getminor((dev_t)arg);
324
325	switch (cmd) {
326	case DDI_INFO_DEVT2DEVINFO:
327		*result = iscsit_global.global_dip;
328		return (DDI_SUCCESS);
329
330	case DDI_INFO_DEVT2INSTANCE:
331		*result = (void *)instance;
332		return (DDI_SUCCESS);
333
334	default:
335		break;
336	}
337
338	return (DDI_FAILURE);
339}
340
341static int
342iscsit_drv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
343{
344	if (cmd != DDI_ATTACH) {
345		return (DDI_FAILURE);
346	}
347
348	if (ddi_get_instance(dip) != 0) {
349		/* we only allow instance 0 to attach */
350		return (DDI_FAILURE);
351	}
352
353	/* create the minor node */
354	if (ddi_create_minor_node(dip, ISCSIT_MODNAME, S_IFCHR, 0,
355	    DDI_PSEUDO, 0) != DDI_SUCCESS) {
356		cmn_err(CE_WARN, "iscsit_drv_attach: "
357		    "failed creating minor node");
358		return (DDI_FAILURE);
359	}
360
361	if (iscsit_init(dip) != IDM_STATUS_SUCCESS) {
362		cmn_err(CE_WARN, "iscsit_drv_attach: "
363		    "failed to initialize");
364		ddi_remove_minor_node(dip, NULL);
365		return (DDI_FAILURE);
366	}
367
368	iscsit_global.global_svc_state = ISE_DISABLED;
369	iscsit_global.global_dip = dip;
370
371	return (DDI_SUCCESS);
372}
373
374/*ARGSUSED*/
375static int
376iscsit_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
377{
378	if (cmd != DDI_DETACH)
379		return (DDI_FAILURE);
380
381	/*
382	 * drv_detach is called in a context that owns the
383	 * device node for the /dev/pseudo device.  If this thread blocks
384	 * for any resource, other threads that need the /dev/pseudo device
385	 * may end up in a deadlock with this thread.Hence, we use a
386	 * separate lock just for the structures that drv_detach needs
387	 * to access.
388	 */
389	mutex_enter(&iscsit_global.global_state_mutex);
390	if (iscsit_drv_busy()) {
391		mutex_exit(&iscsit_global.global_state_mutex);
392		return (EBUSY);
393	}
394
395	iscsit_global.global_dip = NULL;
396	ddi_remove_minor_node(dip, NULL);
397
398	ldi_ident_release(iscsit_global.global_li);
399	iscsit_global.global_svc_state = ISE_DETACHED;
400
401	mutex_exit(&iscsit_global.global_state_mutex);
402
403	return (DDI_SUCCESS);
404}
405
406/*ARGSUSED*/
407static int
408iscsit_drv_open(dev_t *devp, int flag, int otyp, cred_t *credp)
409{
410	return (0);
411}
412
413/* ARGSUSED */
414static int
415iscsit_drv_close(dev_t dev, int flag, int otyp, cred_t *credp)
416{
417	return (0);
418}
419
420static boolean_t
421iscsit_drv_busy(void)
422{
423	ASSERT(MUTEX_HELD(&iscsit_global.global_state_mutex));
424
425	switch (iscsit_global.global_svc_state) {
426	case ISE_DISABLED:
427	case ISE_DETACHED:
428		return (B_FALSE);
429	default:
430		return (B_TRUE);
431	}
432	/* NOTREACHED */
433}
434
435/* ARGSUSED */
436static int
437iscsit_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flag, cred_t *cred,
438    int *retval)
439{
440	iscsit_ioc_set_config_t		setcfg;
441	iscsit_ioc_set_config32_t	setcfg32;
442	char				*cfg_pnvlist = NULL;
443	nvlist_t			*cfg_nvlist = NULL;
444	it_config_t			*cfg = NULL;
445	idm_status_t			idmrc;
446	int				rc = 0;
447
448	if (drv_priv(cred) != 0) {
449		return (EPERM);
450	}
451
452	mutex_enter(&iscsit_global.global_state_mutex);
453
454	/*
455	 * Validate ioctl requests against global service state
456	 */
457	switch (iscsit_global.global_svc_state) {
458	case ISE_ENABLED:
459		if (cmd == ISCSIT_IOC_DISABLE_SVC) {
460			iscsit_global.global_svc_state = ISE_DISABLING;
461		} else if (cmd == ISCSIT_IOC_ENABLE_SVC) {
462			/* Already enabled */
463			mutex_exit(&iscsit_global.global_state_mutex);
464			return (0);
465		} else {
466			iscsit_global.global_svc_state = ISE_BUSY;
467		}
468		break;
469	case ISE_DISABLED:
470		if (cmd == ISCSIT_IOC_ENABLE_SVC) {
471			iscsit_global.global_svc_state = ISE_ENABLING;
472		} else if (cmd == ISCSIT_IOC_DISABLE_SVC) {
473			/* Already disabled */
474			mutex_exit(&iscsit_global.global_state_mutex);
475			return (0);
476		} else {
477			rc = EFAULT;
478		}
479		break;
480	case ISE_BUSY:
481	case ISE_ENABLING:
482	case ISE_DISABLING:
483		rc = EAGAIN;
484		break;
485	case ISE_DETACHED:
486	default:
487		rc = EFAULT;
488		break;
489	}
490
491	mutex_exit(&iscsit_global.global_state_mutex);
492	if (rc != 0)
493		return (rc);
494
495	/* Handle ioctl request (enable/disable have already been handled) */
496	switch (cmd) {
497	case ISCSIT_IOC_SET_CONFIG:
498		/* Any errors must set state back to ISE_ENABLED */
499		switch (ddi_model_convert_from(flag & FMODELS)) {
500		case DDI_MODEL_ILP32:
501			if (ddi_copyin((void *)argp, &setcfg32,
502			    sizeof (iscsit_ioc_set_config32_t), flag) != 0) {
503				rc = EFAULT;
504				goto cleanup;
505			}
506
507			setcfg.set_cfg_pnvlist =
508			    (char *)((uintptr_t)setcfg32.set_cfg_pnvlist);
509			setcfg.set_cfg_vers = setcfg32.set_cfg_vers;
510			setcfg.set_cfg_pnvlist_len =
511			    setcfg32.set_cfg_pnvlist_len;
512			break;
513		case DDI_MODEL_NONE:
514			if (ddi_copyin((void *)argp, &setcfg,
515			    sizeof (iscsit_ioc_set_config_t), flag) != 0) {
516				rc = EFAULT;
517				goto cleanup;
518			}
519			break;
520		default:
521			rc = EFAULT;
522			goto cleanup;
523		}
524
525		/* Check API version */
526		if (setcfg.set_cfg_vers != ISCSIT_API_VERS0) {
527			rc = EINVAL;
528			goto cleanup;
529		}
530
531		/* Config is in packed nvlist format so unpack it */
532		cfg_pnvlist = kmem_alloc(setcfg.set_cfg_pnvlist_len,
533		    KM_SLEEP);
534		ASSERT(cfg_pnvlist != NULL);
535
536		if (ddi_copyin(setcfg.set_cfg_pnvlist, cfg_pnvlist,
537		    setcfg.set_cfg_pnvlist_len, flag) != 0) {
538			rc = EFAULT;
539			goto cleanup;
540		}
541
542		rc = nvlist_unpack(cfg_pnvlist, setcfg.set_cfg_pnvlist_len,
543		    &cfg_nvlist, KM_SLEEP);
544		if (rc != 0) {
545			goto cleanup;
546		}
547
548		/* Translate nvlist */
549		rc = it_nv_to_config(cfg_nvlist, &cfg);
550		if (rc != 0) {
551			cmn_err(CE_WARN, "Configuration is invalid");
552			goto cleanup;
553		}
554
555		/* Update config */
556		rc = iscsit_config_merge(cfg);
557		/* FALLTHROUGH */
558
559cleanup:
560		if (cfg)
561			it_config_free_cmn(cfg);
562		if (cfg_pnvlist)
563			kmem_free(cfg_pnvlist, setcfg.set_cfg_pnvlist_len);
564		if (cfg_nvlist)
565			nvlist_free(cfg_nvlist);
566
567		/*
568		 * Now that the reconfig is complete set our state back to
569		 * enabled.
570		 */
571		mutex_enter(&iscsit_global.global_state_mutex);
572		iscsit_global.global_svc_state = ISE_ENABLED;
573		mutex_exit(&iscsit_global.global_state_mutex);
574		break;
575	case ISCSIT_IOC_ENABLE_SVC: {
576		iscsit_hostinfo_t hostinfo;
577
578		if (ddi_copyin((void *)argp, &hostinfo.length,
579		    sizeof (hostinfo.length), flag) != 0) {
580			mutex_enter(&iscsit_global.global_state_mutex);
581			iscsit_global.global_svc_state = ISE_DISABLED;
582			mutex_exit(&iscsit_global.global_state_mutex);
583			return (EFAULT);
584		}
585
586		if (hostinfo.length > sizeof (hostinfo.fqhn))
587			hostinfo.length = sizeof (hostinfo.fqhn);
588
589		if (ddi_copyin((void *)((caddr_t)argp +
590		    sizeof (hostinfo.length)), &hostinfo.fqhn,
591		    hostinfo.length, flag) != 0) {
592			mutex_enter(&iscsit_global.global_state_mutex);
593			iscsit_global.global_svc_state = ISE_DISABLED;
594			mutex_exit(&iscsit_global.global_state_mutex);
595			return (EFAULT);
596		}
597
598		idmrc = iscsit_enable_svc(&hostinfo);
599		mutex_enter(&iscsit_global.global_state_mutex);
600		if (idmrc == IDM_STATUS_SUCCESS) {
601			iscsit_global.global_svc_state = ISE_ENABLED;
602		} else {
603			rc = EIO;
604			iscsit_global.global_svc_state = ISE_DISABLED;
605		}
606		mutex_exit(&iscsit_global.global_state_mutex);
607		break;
608	}
609	case ISCSIT_IOC_DISABLE_SVC:
610		iscsit_disable_svc();
611		mutex_enter(&iscsit_global.global_state_mutex);
612		iscsit_global.global_svc_state = ISE_DISABLED;
613		mutex_exit(&iscsit_global.global_state_mutex);
614		break;
615
616	default:
617		rc = EINVAL;
618		mutex_enter(&iscsit_global.global_state_mutex);
619		iscsit_global.global_svc_state = ISE_ENABLED;
620		mutex_exit(&iscsit_global.global_state_mutex);
621	}
622
623	return (rc);
624}
625
626static idm_status_t
627iscsit_init(dev_info_t *dip)
628{
629	int			rc;
630
631	rc = ldi_ident_from_dip(dip, &iscsit_global.global_li);
632	ASSERT(rc == 0);  /* Failure indicates invalid argument */
633
634	iscsit_global.global_svc_state = ISE_DISABLED;
635
636	return (IDM_STATUS_SUCCESS);
637}
638
639/*
640 * iscsit_enable_svc
641 *
642 * registers all the configured targets and target portals with STMF
643 */
644static idm_status_t
645iscsit_enable_svc(iscsit_hostinfo_t *hostinfo)
646{
647	stmf_port_provider_t	*pp;
648	stmf_dbuf_store_t	*dbuf_store;
649	boolean_t		did_iscsit_isns_init;
650	idm_status_t		retval = IDM_STATUS_SUCCESS;
651
652	ASSERT(iscsit_global.global_svc_state == ISE_ENABLING);
653
654	/*
655	 * Make sure that can tell if we have partially allocated
656	 * in case we need to exit and tear down anything allocated.
657	 */
658	iscsit_global.global_tsih_pool = NULL;
659	iscsit_global.global_dbuf_store = NULL;
660	iscsit_status_pdu_cache = NULL;
661	pp = NULL;
662	iscsit_global.global_pp = NULL;
663	iscsit_global.global_default_tpg = NULL;
664	did_iscsit_isns_init = B_FALSE;
665	iscsit_global.global_dispatch_taskq = NULL;
666
667	/* Setup remaining fields in iscsit_global_t */
668	idm_refcnt_init(&iscsit_global.global_refcnt,
669	    &iscsit_global);
670
671	avl_create(&iscsit_global.global_discovery_sessions,
672	    iscsit_sess_avl_compare, sizeof (iscsit_sess_t),
673	    offsetof(iscsit_sess_t, ist_tgt_ln));
674
675	avl_create(&iscsit_global.global_target_list,
676	    iscsit_tgt_avl_compare, sizeof (iscsit_tgt_t),
677	    offsetof(iscsit_tgt_t, target_global_ln));
678
679	list_create(&iscsit_global.global_deleted_target_list,
680	    sizeof (iscsit_tgt_t),
681	    offsetof(iscsit_tgt_t, target_global_deleted_ln));
682
683	avl_create(&iscsit_global.global_tpg_list,
684	    iscsit_tpg_avl_compare, sizeof (iscsit_tpg_t),
685	    offsetof(iscsit_tpg_t, tpg_global_ln));
686
687	avl_create(&iscsit_global.global_ini_list,
688	    iscsit_ini_avl_compare, sizeof (iscsit_ini_t),
689	    offsetof(iscsit_ini_t, ini_global_ln));
690
691	iscsit_global.global_tsih_pool = vmem_create("iscsit_tsih_pool",
692	    (void *)1, ISCSI_MAX_TSIH, 1, NULL, NULL, NULL, 0,
693	    VM_SLEEP | VMC_IDENTIFIER);
694
695	/*
696	 * Setup STMF dbuf store.  Our buffers are bound to a specific
697	 * connection so we really can't let STMF cache buffers for us.
698	 * Consequently we'll just allocate one global buffer store.
699	 */
700	dbuf_store = stmf_alloc(STMF_STRUCT_DBUF_STORE, 0, 0);
701	if (dbuf_store == NULL) {
702		retval = IDM_STATUS_FAIL;
703		goto tear_down_and_return;
704	}
705	dbuf_store->ds_alloc_data_buf = iscsit_dbuf_alloc;
706	dbuf_store->ds_free_data_buf = iscsit_dbuf_free;
707	dbuf_store->ds_port_private = NULL;
708	iscsit_global.global_dbuf_store = dbuf_store;
709
710	/* Status PDU cache */
711	iscsit_status_pdu_cache = kmem_cache_create("iscsit_status_pdu_cache",
712	    sizeof (idm_pdu_t) + sizeof (iscsi_scsi_rsp_hdr_t), 8,
713	    &iscsit_status_pdu_constructor,
714	    NULL, NULL, NULL, NULL, KM_SLEEP);
715
716	/* Default TPG and portal */
717	iscsit_global.global_default_tpg = iscsit_tpg_createdefault();
718	if (iscsit_global.global_default_tpg == NULL) {
719		retval = IDM_STATUS_FAIL;
720		goto tear_down_and_return;
721	}
722
723	/* initialize isns client */
724	(void) iscsit_isns_init(hostinfo);
725	did_iscsit_isns_init = B_TRUE;
726
727	/* Register port provider */
728	pp = stmf_alloc(STMF_STRUCT_PORT_PROVIDER, 0, 0);
729	if (pp == NULL) {
730		retval = IDM_STATUS_FAIL;
731		goto tear_down_and_return;
732	}
733
734	pp->pp_portif_rev = PORTIF_REV_1;
735	pp->pp_instance = 0;
736	pp->pp_name = ISCSIT_MODNAME;
737	pp->pp_cb = iscsit_pp_cb;
738
739	iscsit_global.global_pp = pp;
740
741
742	if (stmf_register_port_provider(pp) != STMF_SUCCESS) {
743		retval = IDM_STATUS_FAIL;
744		goto tear_down_and_return;
745	}
746
747	iscsit_global.global_dispatch_taskq = taskq_create("iscsit_dispatch",
748	    1, minclsyspri, 16, 16, TASKQ_PREPOPULATE);
749
750	/* Scan staged PDUs, meaningful in MC/S situations */
751	iscsit_rxpdu_queue_monitor_start();
752
753	return (IDM_STATUS_SUCCESS);
754
755tear_down_and_return:
756
757	if (iscsit_global.global_dispatch_taskq) {
758		taskq_destroy(iscsit_global.global_dispatch_taskq);
759		iscsit_global.global_dispatch_taskq = NULL;
760	}
761
762	if (did_iscsit_isns_init)
763		iscsit_isns_fini();
764
765	if (iscsit_global.global_default_tpg) {
766		iscsit_tpg_destroydefault(iscsit_global.global_default_tpg);
767		iscsit_global.global_default_tpg = NULL;
768	}
769
770	if (iscsit_global.global_pp)
771		iscsit_global.global_pp = NULL;
772
773	if (pp)
774		stmf_free(pp);
775
776	if (iscsit_status_pdu_cache) {
777		kmem_cache_destroy(iscsit_status_pdu_cache);
778		iscsit_status_pdu_cache = NULL;
779	}
780
781	if (iscsit_global.global_dbuf_store) {
782		stmf_free(iscsit_global.global_dbuf_store);
783		iscsit_global.global_dbuf_store = NULL;
784	}
785
786	if (iscsit_global.global_tsih_pool) {
787		vmem_destroy(iscsit_global.global_tsih_pool);
788		iscsit_global.global_tsih_pool = NULL;
789	}
790
791	avl_destroy(&iscsit_global.global_ini_list);
792	avl_destroy(&iscsit_global.global_tpg_list);
793	list_destroy(&iscsit_global.global_deleted_target_list);
794	avl_destroy(&iscsit_global.global_target_list);
795	avl_destroy(&iscsit_global.global_discovery_sessions);
796
797	idm_refcnt_destroy(&iscsit_global.global_refcnt);
798
799	return (retval);
800}
801
802/*
803 * iscsit_disable_svc
804 *
805 * clean up all existing connections and deregister targets from STMF
806 */
807static void
808iscsit_disable_svc(void)
809{
810	iscsit_sess_t	*sess;
811
812	ASSERT(iscsit_global.global_svc_state == ISE_DISABLING);
813
814	iscsit_rxpdu_queue_monitor_stop();
815
816	/* tear down discovery sessions */
817	for (sess = avl_first(&iscsit_global.global_discovery_sessions);
818	    sess != NULL;
819	    sess = AVL_NEXT(&iscsit_global.global_discovery_sessions, sess))
820		iscsit_sess_close(sess);
821
822	/*
823	 * Passing NULL to iscsit_config_merge tells it to go to an empty
824	 * config.
825	 */
826	(void) iscsit_config_merge(NULL);
827
828	/*
829	 * Wait until there are no more global references
830	 */
831	idm_refcnt_wait_ref(&iscsit_global.global_refcnt);
832	idm_refcnt_destroy(&iscsit_global.global_refcnt);
833
834	/*
835	 * Default TPG must be destroyed after global_refcnt is 0.
836	 */
837	iscsit_tpg_destroydefault(iscsit_global.global_default_tpg);
838
839	avl_destroy(&iscsit_global.global_discovery_sessions);
840	list_destroy(&iscsit_global.global_deleted_target_list);
841	avl_destroy(&iscsit_global.global_target_list);
842	avl_destroy(&iscsit_global.global_tpg_list);
843	avl_destroy(&iscsit_global.global_ini_list);
844
845	taskq_destroy(iscsit_global.global_dispatch_taskq);
846
847	iscsit_isns_fini();
848
849	stmf_free(iscsit_global.global_dbuf_store);
850	iscsit_global.global_dbuf_store = NULL;
851
852	(void) stmf_deregister_port_provider(iscsit_global.global_pp);
853	stmf_free(iscsit_global.global_pp);
854	iscsit_global.global_pp = NULL;
855
856	kmem_cache_destroy(iscsit_status_pdu_cache);
857	iscsit_status_pdu_cache = NULL;
858
859	vmem_destroy(iscsit_global.global_tsih_pool);
860	iscsit_global.global_tsih_pool = NULL;
861}
862
863void
864iscsit_global_hold()
865{
866	/*
867	 * To take out a global hold, we must either own the global
868	 * state mutex or we must be running inside of an ioctl that
869	 * has set the global state to ISE_BUSY, ISE_DISABLING, or
870	 * ISE_ENABLING.  We don't track the "owner" for these flags,
871	 * so just checking if they are set is enough for now.
872	 */
873	ASSERT((iscsit_global.global_svc_state == ISE_ENABLING) ||
874	    (iscsit_global.global_svc_state == ISE_DISABLING) ||
875	    (iscsit_global.global_svc_state == ISE_BUSY) ||
876	    MUTEX_HELD(&iscsit_global.global_state_mutex));
877
878	idm_refcnt_hold(&iscsit_global.global_refcnt);
879}
880
881void
882iscsit_global_rele()
883{
884	idm_refcnt_rele(&iscsit_global.global_refcnt);
885}
886
887void
888iscsit_global_wait_ref()
889{
890	idm_refcnt_wait_ref(&iscsit_global.global_refcnt);
891}
892
893/*
894 * IDM callbacks
895 */
896
897/*ARGSUSED*/
898void
899iscsit_rx_pdu(idm_conn_t *ic, idm_pdu_t *rx_pdu)
900{
901	iscsit_conn_t *ict = ic->ic_handle;
902	switch (IDM_PDU_OPCODE(rx_pdu)) {
903	case ISCSI_OP_SCSI_CMD:
904		ASSERT(0); /* Shouldn't happen */
905		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
906		break;
907	case ISCSI_OP_SNACK_CMD:
908		/*
909		 * We'll need to handle this when we support ERL1/2.  For
910		 * now we treat it as a protocol error.
911		 */
912		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
913		idm_conn_event(ic, CE_TRANSPORT_FAIL, NULL);
914		break;
915	case ISCSI_OP_SCSI_TASK_MGT_MSG:
916		if (iscsit_check_cmdsn_and_queue(rx_pdu)) {
917			iscsit_set_cmdsn(ict, rx_pdu);
918			iscsit_op_scsi_task_mgmt(ict, rx_pdu);
919		}
920		break;
921	case ISCSI_OP_NOOP_OUT:
922	case ISCSI_OP_LOGIN_CMD:
923	case ISCSI_OP_TEXT_CMD:
924	case ISCSI_OP_LOGOUT_CMD:
925		/*
926		 * If/when we switch to userland processing these PDU's
927		 * will be handled by iscsitd.
928		 */
929		iscsit_deferred_dispatch(rx_pdu);
930		break;
931	default:
932		/* Protocol error */
933		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
934		idm_conn_event(ic, CE_TRANSPORT_FAIL, NULL);
935		break;
936	}
937}
938
939/*ARGSUSED*/
940void
941iscsit_rx_pdu_error(idm_conn_t *ic, idm_pdu_t *rx_pdu, idm_status_t status)
942{
943	idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
944}
945
946void
947iscsit_task_aborted(idm_task_t *idt, idm_status_t status)
948{
949	iscsit_task_t *itask = idt->idt_private;
950
951	switch (status) {
952	case IDM_STATUS_SUSPENDED:
953		break;
954	case IDM_STATUS_ABORTED:
955		mutex_enter(&itask->it_mutex);
956		itask->it_aborted = B_TRUE;
957		/*
958		 * We rely on the fact that STMF tracks outstanding
959		 * buffer transfers and will free all of our buffers
960		 * before freeing the task so we don't need to
961		 * explicitly free the buffers from iscsit/idm
962		 */
963		if (itask->it_stmf_abort) {
964			mutex_exit(&itask->it_mutex);
965			/*
966			 * Task is no longer active
967			 */
968			iscsit_task_done(itask);
969
970			/*
971			 * STMF has already asked for this task to be aborted
972			 *
973			 * STMF specification is wrong... says to return
974			 * STMF_ABORTED, the code actually looks for
975			 * STMF_ABORT_SUCCESS.
976			 */
977			stmf_task_lport_aborted(itask->it_stmf_task,
978			    STMF_ABORT_SUCCESS, STMF_IOF_LPORT_DONE);
979			return;
980		} else {
981			mutex_exit(&itask->it_mutex);
982			/*
983			 * Tell STMF to stop processing the task.
984			 */
985			stmf_abort(STMF_QUEUE_TASK_ABORT, itask->it_stmf_task,
986			    STMF_ABORTED, NULL);
987			return;
988		}
989		/*NOTREACHED*/
990	default:
991		ASSERT(0);
992	}
993}
994
995/*ARGSUSED*/
996idm_status_t
997iscsit_client_notify(idm_conn_t *ic, idm_client_notify_t icn,
998    uintptr_t data)
999{
1000	idm_status_t rc = IDM_STATUS_SUCCESS;
1001
1002	/*
1003	 * IDM client notifications will never occur at interrupt level
1004	 * since they are generated from the connection state machine which
1005	 * running on taskq threads.
1006	 *
1007	 */
1008	switch (icn) {
1009	case CN_CONNECT_ACCEPT:
1010		rc = iscsit_conn_accept(ic); /* No data */
1011		break;
1012	case CN_FFP_ENABLED:
1013		rc = iscsit_ffp_enabled(ic); /* No data */
1014		break;
1015	case CN_FFP_DISABLED:
1016		/*
1017		 * Data indicates whether this was the result of an
1018		 * explicit logout request.
1019		 */
1020		rc = iscsit_ffp_disabled(ic, (idm_ffp_disable_t)data);
1021		break;
1022	case CN_CONNECT_LOST:
1023		rc = iscsit_conn_lost(ic);
1024		break;
1025	case CN_CONNECT_DESTROY:
1026		rc = iscsit_conn_destroy(ic);
1027		break;
1028	case CN_LOGIN_FAIL:
1029		/*
1030		 * Force the login state machine to completion
1031		 */
1032		rc = iscsit_login_fail(ic);
1033		break;
1034	default:
1035		rc = IDM_STATUS_REJECT;
1036		break;
1037	}
1038
1039	return (rc);
1040}
1041
1042/*
1043 * iscsit_update_statsn is invoked for all the PDUs which have the StatSN
1044 * field in the header. The StatSN is incremented if the IDM_PDU_ADVANCE_STATSN
1045 * flag is set in the pdu flags field. The StatSN is connection-wide and is
1046 * protected by the mutex ict_statsn_mutex. For Data-In PDUs, if the flag
1047 * IDM_TASK_PHASECOLLAPSE_REQ is set, the status (phase-collapse) is also filled
1048 */
1049void
1050iscsit_update_statsn(idm_task_t *idm_task, idm_pdu_t *pdu)
1051{
1052	iscsi_scsi_rsp_hdr_t *rsp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr;
1053	iscsit_conn_t *ict = (iscsit_conn_t *)pdu->isp_ic->ic_handle;
1054	iscsit_task_t *itask = NULL;
1055	scsi_task_t *task = NULL;
1056
1057	mutex_enter(&ict->ict_statsn_mutex);
1058	rsp->statsn = htonl(ict->ict_statsn);
1059	if (pdu->isp_flags & IDM_PDU_ADVANCE_STATSN)
1060		ict->ict_statsn++;
1061	mutex_exit(&ict->ict_statsn_mutex);
1062
1063	/*
1064	 * The last SCSI Data PDU passed for a command may also contain the
1065	 * status if the status indicates termination with no expections, i.e.
1066	 * no sense data or response involved. If the command completes with
1067	 * an error, then the response and sense data will be sent in a
1068	 * separate iSCSI Response PDU.
1069	 */
1070	if ((idm_task) && (idm_task->idt_flags & IDM_TASK_PHASECOLLAPSE_REQ)) {
1071		itask = idm_task->idt_private;
1072		task = itask->it_stmf_task;
1073
1074		rsp->cmd_status = task->task_scsi_status;
1075		rsp->flags	|= ISCSI_FLAG_DATA_STATUS;
1076		if (task->task_status_ctrl & TASK_SCTRL_OVER) {
1077			rsp->flags |= ISCSI_FLAG_CMD_OVERFLOW;
1078		} else if (task->task_status_ctrl & TASK_SCTRL_UNDER) {
1079			rsp->flags |= ISCSI_FLAG_CMD_UNDERFLOW;
1080		}
1081		rsp->residual_count = htonl(task->task_resid);
1082
1083		/*
1084		 * Removing the task from the session task list
1085		 * just before the status is sent in the last
1086		 * Data PDU transfer
1087		 */
1088		iscsit_task_done(itask);
1089	}
1090}
1091
1092void
1093iscsit_build_hdr(idm_task_t *idm_task, idm_pdu_t *pdu, uint8_t opcode)
1094{
1095	iscsit_task_t *itask = idm_task->idt_private;
1096	iscsi_data_rsp_hdr_t *dh = (iscsi_data_rsp_hdr_t *)pdu->isp_hdr;
1097
1098	/*
1099	 * We acquired iscsit_sess_t.ist_sn_mutex in iscsit_xfer_scsi_data
1100	 */
1101	ASSERT(MUTEX_HELD(&itask->it_ict->ict_sess->ist_sn_mutex));
1102	/*
1103	 * On incoming data, the target transfer tag and Lun is only
1104	 * provided by the target if the A bit is set, Since the target
1105	 * does not currently support Error Recovery Level 1, the A
1106	 * bit is never set.
1107	 */
1108	dh->opcode = opcode;
1109	dh->itt = itask->it_itt;
1110	dh->ttt = ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_SCSI_DATA_RSP) ?
1111	    ISCSI_RSVD_TASK_TAG : itask->it_ttt;
1112
1113	dh->expcmdsn = htonl(itask->it_ict->ict_sess->ist_expcmdsn);
1114	dh->maxcmdsn = htonl(itask->it_ict->ict_sess->ist_maxcmdsn);
1115
1116	/*
1117	 * IDM must set:
1118	 *
1119	 * data.flags and rtt.flags
1120	 * data.dlength
1121	 * data.datasn
1122	 * data.offset
1123	 * statsn, residual_count and cmd_status (for phase collapse)
1124	 * rtt.rttsn
1125	 * rtt.data_offset
1126	 * rtt.data_length
1127	 */
1128}
1129
1130void
1131iscsit_keepalive(idm_conn_t *ic)
1132{
1133	idm_pdu_t		*nop_in_pdu;
1134	iscsi_nop_in_hdr_t	*nop_in;
1135	iscsit_conn_t		*ict = ic->ic_handle;
1136
1137	/*
1138	 * IDM noticed the connection has been idle for too long so it's
1139	 * time to provoke some activity.  Build and transmit an iSCSI
1140	 * nop-in PDU -- when the initiator responds it will be counted
1141	 * as "activity" and keep the connection alive.
1142	 *
1143	 * We don't actually care about the response here at the iscsit level
1144	 * so we will just throw it away without looking at it when it arrives.
1145	 */
1146	nop_in_pdu = idm_pdu_alloc(sizeof (*nop_in), 0);
1147	idm_pdu_init(nop_in_pdu, ic, NULL, NULL);
1148	nop_in = (iscsi_nop_in_hdr_t *)nop_in_pdu->isp_hdr;
1149	bzero(nop_in, sizeof (*nop_in));
1150	nop_in->opcode = ISCSI_OP_NOOP_IN;
1151	nop_in->flags = ISCSI_FLAG_FINAL;
1152	nop_in->itt = ISCSI_RSVD_TASK_TAG;
1153	/*
1154	 * When the target sends a NOP-In as a Ping, the target transfer tag
1155	 * is set to a valid (not reserved) value and the initiator task tag
1156	 * is set to ISCSI_RSVD_TASK_TAG (0xffffffff). In this case the StatSN
1157	 * will always contain the next sequence number but the StatSN for the
1158	 * connection is not advanced after this PDU is sent.
1159	 */
1160	nop_in_pdu->isp_flags |= IDM_PDU_SET_STATSN;
1161	/*
1162	 * This works because we don't currently allocate ttt's anywhere else
1163	 * in iscsit so as long as we stay out of IDM's range we are safe.
1164	 * If we need to allocate ttt's for other PDU's in the future this will
1165	 * need to be improved.
1166	 */
1167	mutex_enter(&ict->ict_mutex);
1168	nop_in->ttt = ict->ict_keepalive_ttt;
1169	ict->ict_keepalive_ttt++;
1170	if (ict->ict_keepalive_ttt == ISCSI_RSVD_TASK_TAG)
1171		ict->ict_keepalive_ttt = IDM_TASKIDS_MAX;
1172	mutex_exit(&ict->ict_mutex);
1173
1174	iscsit_pdu_tx(nop_in_pdu);
1175}
1176
1177static idm_status_t
1178iscsit_conn_accept(idm_conn_t *ic)
1179{
1180	iscsit_conn_t *ict;
1181
1182	/*
1183	 * We need to get a global hold here to ensure that the service
1184	 * doesn't get shutdown prior to establishing a session. This
1185	 * gets released in iscsit_conn_destroy().
1186	 */
1187	mutex_enter(&iscsit_global.global_state_mutex);
1188	if (iscsit_global.global_svc_state != ISE_ENABLED) {
1189		mutex_exit(&iscsit_global.global_state_mutex);
1190		return (IDM_STATUS_FAIL);
1191	}
1192	iscsit_global_hold();
1193	mutex_exit(&iscsit_global.global_state_mutex);
1194
1195	/*
1196	 * Allocate an associated iscsit structure to represent this
1197	 * connection.  We shouldn't really create a session until we
1198	 * get the first login PDU.
1199	 */
1200	ict = kmem_zalloc(sizeof (*ict), KM_SLEEP);
1201
1202	ict->ict_ic = ic;
1203	ict->ict_statsn = 1;
1204	ict->ict_keepalive_ttt = IDM_TASKIDS_MAX; /* Avoid IDM TT range */
1205	ic->ic_handle = ict;
1206	mutex_init(&ict->ict_mutex, NULL, MUTEX_DRIVER, NULL);
1207	mutex_init(&ict->ict_statsn_mutex, NULL, MUTEX_DRIVER, NULL);
1208	idm_refcnt_init(&ict->ict_refcnt, ict);
1209
1210	/*
1211	 * Initialize login state machine
1212	 */
1213	if (iscsit_login_sm_init(ict) != IDM_STATUS_SUCCESS) {
1214		iscsit_global_rele();
1215		/*
1216		 * Cleanup the ict after idm notifies us about this failure
1217		 */
1218		return (IDM_STATUS_FAIL);
1219	}
1220
1221	return (IDM_STATUS_SUCCESS);
1222}
1223
1224idm_status_t
1225iscsit_conn_reinstate(iscsit_conn_t *reinstate_ict, iscsit_conn_t *new_ict)
1226{
1227	idm_status_t	result;
1228
1229	/*
1230	 * Note in new connection state that this connection is
1231	 * reinstating an existing connection.
1232	 */
1233	new_ict->ict_reinstating = B_TRUE;
1234	new_ict->ict_reinstate_conn = reinstate_ict;
1235	new_ict->ict_statsn = reinstate_ict->ict_statsn;
1236
1237	/*
1238	 * Now generate connection state machine event to existing connection
1239	 * so that it starts the cleanup process.
1240	 */
1241	result = idm_conn_reinstate_event(reinstate_ict->ict_ic,
1242	    new_ict->ict_ic);
1243
1244	return (result);
1245}
1246
1247void
1248iscsit_conn_hold(iscsit_conn_t *ict)
1249{
1250	idm_refcnt_hold(&ict->ict_refcnt);
1251}
1252
1253void
1254iscsit_conn_rele(iscsit_conn_t *ict)
1255{
1256	idm_refcnt_rele(&ict->ict_refcnt);
1257}
1258
1259void
1260iscsit_conn_dispatch_hold(iscsit_conn_t *ict)
1261{
1262	idm_refcnt_hold(&ict->ict_dispatch_refcnt);
1263}
1264
1265void
1266iscsit_conn_dispatch_rele(iscsit_conn_t *ict)
1267{
1268	idm_refcnt_rele(&ict->ict_dispatch_refcnt);
1269}
1270
1271static idm_status_t
1272iscsit_login_fail(idm_conn_t *ic)
1273{
1274	iscsit_conn_t *ict = ic->ic_handle;
1275
1276	/* Generate login state machine event */
1277	iscsit_login_sm_event(ict, ILE_LOGIN_CONN_ERROR, NULL);
1278
1279	return (IDM_STATUS_SUCCESS);
1280}
1281
1282static idm_status_t
1283iscsit_ffp_enabled(idm_conn_t *ic)
1284{
1285	iscsit_conn_t *ict = ic->ic_handle;
1286
1287	/* Generate session state machine event */
1288	iscsit_sess_sm_event(ict->ict_sess, SE_CONN_LOGGED_IN, ict);
1289
1290	return (IDM_STATUS_SUCCESS);
1291}
1292
1293static idm_status_t
1294iscsit_ffp_disabled(idm_conn_t *ic, idm_ffp_disable_t disable_class)
1295{
1296	iscsit_conn_t *ict = ic->ic_handle;
1297
1298	/* Generate session state machine event */
1299	switch (disable_class) {
1300	case FD_CONN_FAIL:
1301		iscsit_sess_sm_event(ict->ict_sess, SE_CONN_FFP_FAIL, ict);
1302		break;
1303	case FD_CONN_LOGOUT:
1304		iscsit_sess_sm_event(ict->ict_sess, SE_CONN_FFP_DISABLE, ict);
1305		break;
1306	case FD_SESS_LOGOUT:
1307		iscsit_sess_sm_event(ict->ict_sess, SE_SESSION_CLOSE, ict);
1308		break;
1309	default:
1310		ASSERT(0);
1311	}
1312
1313	return (IDM_STATUS_SUCCESS);
1314}
1315
1316static idm_status_t
1317iscsit_conn_lost(idm_conn_t *ic)
1318{
1319	iscsit_conn_t	*ict	= ic->ic_handle;
1320	iscsit_sess_t	*ist	= ict->ict_sess;
1321	iscsit_cbuf_t	*cbuf;
1322	idm_pdu_t	*rx_pdu;
1323	int i;
1324
1325	mutex_enter(&ict->ict_mutex);
1326	ict->ict_lost = B_TRUE;
1327	mutex_exit(&ict->ict_mutex);
1328	/*
1329	 * scrub the staging queue for all PDUs on this connection
1330	 */
1331	if (ist != NULL) {
1332		mutex_enter(&ist->ist_sn_mutex);
1333		for (cbuf = ist->ist_rxpdu_queue, i = 0;
1334		    ((cbuf->cb_num_elems > 0) && (i < ISCSIT_RXPDU_QUEUE_LEN));
1335		    i++) {
1336			if (((rx_pdu = cbuf->cb_buffer[i]) != NULL) &&
1337			    (rx_pdu->isp_ic == ic)) {
1338				/* conn is lost, drop the pdu */
1339				DTRACE_PROBE3(scrubbing__staging__queue,
1340				    iscsit_sess_t *, ist, idm_conn_t *, ic,
1341				    idm_pdu_t *, rx_pdu);
1342				idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL);
1343				cbuf->cb_buffer[i] = NULL;
1344				cbuf->cb_num_elems--;
1345				iscsit_conn_dispatch_rele(ict);
1346			}
1347		}
1348		mutex_exit(&ist->ist_sn_mutex);
1349	}
1350	/*
1351	 * Make sure there aren't any PDU's transitioning from the receive
1352	 * handler to the dispatch taskq.
1353	 */
1354	idm_refcnt_wait_ref(&ict->ict_dispatch_refcnt);
1355
1356	return (IDM_STATUS_SUCCESS);
1357}
1358
1359static idm_status_t
1360iscsit_conn_destroy(idm_conn_t *ic)
1361{
1362	iscsit_conn_t *ict = ic->ic_handle;
1363
1364	mutex_enter(&ict->ict_mutex);
1365	ict->ict_destroyed = B_TRUE;
1366	mutex_exit(&ict->ict_mutex);
1367
1368	/* Generate session state machine event */
1369	if (ict->ict_sess != NULL) {
1370		/*
1371		 * Session state machine will call iscsit_conn_destroy_done()
1372		 * when it has removed references to this connection.
1373		 */
1374		iscsit_sess_sm_event(ict->ict_sess, SE_CONN_FAIL, ict);
1375	}
1376
1377	idm_refcnt_wait_ref(&ict->ict_refcnt);
1378	/*
1379	 * The session state machine does not need to post
1380	 * events to IDM any longer, so it is safe to set
1381	 * the idm connection reference to NULL
1382	 */
1383	ict->ict_ic = NULL;
1384
1385	/* Reap the login state machine */
1386	iscsit_login_sm_fini(ict);
1387
1388	/* Clean up any text command remnants */
1389	iscsit_text_cmd_fini(ict);
1390
1391	mutex_destroy(&ict->ict_mutex);
1392	idm_refcnt_destroy(&ict->ict_refcnt);
1393	kmem_free(ict, sizeof (*ict));
1394
1395	iscsit_global_rele();
1396
1397	return (IDM_STATUS_SUCCESS);
1398}
1399
1400void
1401iscsit_conn_logout(iscsit_conn_t *ict)
1402{
1403	/*
1404	 * If the iscsi connection is active, then
1405	 * logout the IDM connection by sending a
1406	 * CE_LOGOUT_SESSION_SUCCESS, else, no action
1407	 * needs to be taken because the connection
1408	 * is already in the teardown process.
1409	 */
1410	mutex_enter(&ict->ict_mutex);
1411	if (ict->ict_lost == B_FALSE && ict->ict_destroyed == B_FALSE) {
1412		idm_conn_event(ict->ict_ic, CE_LOGOUT_SESSION_SUCCESS, NULL);
1413	}
1414	mutex_exit(&ict->ict_mutex);
1415}
1416
1417/*
1418 * STMF-related functions
1419 *
1420 * iSCSI to STMF mapping
1421 *
1422 * Session == ?
1423 * Connection == bound to local port but not itself a local port
1424 * Target
1425 * Target portal (group?) == local port (really but we're not going to do this)
1426 *	iscsit needs to map connections to local ports (whatever we decide
1427 * 	they are)
1428 * Target == ?
1429 */
1430
1431/*ARGSUSED*/
1432static stmf_data_buf_t *
1433iscsit_dbuf_alloc(scsi_task_t *task, uint32_t size, uint32_t *pminsize,
1434    uint32_t flags)
1435{
1436	iscsit_task_t *itask = task->task_port_private;
1437	idm_buf_t *idm_buffer;
1438	iscsit_buf_t	*ibuf;
1439	stmf_data_buf_t *result;
1440	uint32_t	bsize;
1441
1442	/*
1443	 * If the requested size is larger than MaxBurstLength and the
1444	 * given pminsize is also larger than MaxBurstLength, then the
1445	 * allocation fails (dbuf = NULL) and pminsize is modified to
1446	 * be equal to MaxBurstLength. stmf/sbd then should re-invoke
1447	 * this function with the corrected values for transfer.
1448	 */
1449	ASSERT(pminsize);
1450	if (size <= itask->it_ict->ict_op.op_max_burst_length) {
1451		bsize = size;
1452	} else if (*pminsize <= itask->it_ict->ict_op.op_max_burst_length) {
1453		bsize = itask->it_ict->ict_op.op_max_burst_length;
1454	} else {
1455		*pminsize = itask->it_ict->ict_op.op_max_burst_length;
1456		return (NULL);
1457	}
1458
1459	/* Alloc buffer */
1460	idm_buffer = idm_buf_alloc(itask->it_ict->ict_ic, NULL, bsize);
1461	if (idm_buffer != NULL) {
1462		result = stmf_alloc(STMF_STRUCT_DATA_BUF,
1463		    sizeof (iscsit_buf_t), 0);
1464		if (result != NULL) {
1465			/* Fill in stmf_data_buf_t */
1466			ibuf = result->db_port_private;
1467			ibuf->ibuf_idm_buf = idm_buffer;
1468			ibuf->ibuf_stmf_buf = result;
1469			ibuf->ibuf_is_immed = B_FALSE;
1470			result->db_flags = DB_DONT_CACHE;
1471			result->db_buf_size = bsize;
1472			result->db_data_size = bsize;
1473			result->db_sglist_length = 1;
1474			result->db_sglist[0].seg_addr = idm_buffer->idb_buf;
1475			result->db_sglist[0].seg_length =
1476			    idm_buffer->idb_buflen;
1477			return (result);
1478		}
1479
1480		/* Couldn't get the stmf_data_buf_t so free the buffer */
1481		idm_buf_free(idm_buffer);
1482	}
1483
1484	return (NULL);
1485}
1486
1487/*ARGSUSED*/
1488static void
1489iscsit_dbuf_free(stmf_dbuf_store_t *ds, stmf_data_buf_t *dbuf)
1490{
1491	iscsit_buf_t *ibuf = dbuf->db_port_private;
1492
1493	if (ibuf->ibuf_is_immed) {
1494		/*
1495		 * The iscsit_buf_t structure itself will be freed with its
1496		 * associated task.  Here we just need to free the PDU that
1497		 * held the immediate data.
1498		 */
1499		idm_pdu_complete(ibuf->ibuf_immed_data_pdu, IDM_STATUS_SUCCESS);
1500		ibuf->ibuf_immed_data_pdu = 0;
1501	} else {
1502		idm_buf_free(ibuf->ibuf_idm_buf);
1503		stmf_free(dbuf);
1504	}
1505}
1506
1507/*ARGSUSED*/
1508stmf_status_t
1509iscsit_xfer_scsi_data(scsi_task_t *task, stmf_data_buf_t *dbuf,
1510    uint32_t ioflags)
1511{
1512	iscsit_task_t *iscsit_task = task->task_port_private;
1513	iscsit_sess_t *ict_sess = iscsit_task->it_ict->ict_sess;
1514	iscsit_buf_t *ibuf = dbuf->db_port_private;
1515	int idm_rc;
1516
1517	/*
1518	 * If we are aborting then we can ignore this request
1519	 */
1520	if (iscsit_task->it_stmf_abort) {
1521		return (STMF_SUCCESS);
1522	}
1523
1524	/*
1525	 * If it's not immediate data then start the transfer
1526	 */
1527	ASSERT(ibuf->ibuf_is_immed == B_FALSE);
1528	if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
1529		/*
1530		 * The DB_SEND_STATUS_GOOD flag in the STMF data buffer allows
1531		 * the port provider to phase-collapse, i.e. send the status
1532		 * along with the final data PDU for the command. The port
1533		 * provider passes this request to the transport layer by
1534		 * setting a flag IDM_TASK_PHASECOLLAPSE_REQ in the task.
1535		 */
1536		if (dbuf->db_flags & DB_SEND_STATUS_GOOD)
1537			iscsit_task->it_idm_task->idt_flags |=
1538			    IDM_TASK_PHASECOLLAPSE_REQ;
1539		/*
1540		 * IDM will call iscsit_build_hdr so lock now to serialize
1541		 * access to the SN values.  We need to lock here to enforce
1542		 * lock ordering
1543		 */
1544		mutex_enter(&ict_sess->ist_sn_mutex);
1545		idm_rc = idm_buf_tx_to_ini(iscsit_task->it_idm_task,
1546		    ibuf->ibuf_idm_buf, dbuf->db_relative_offset,
1547		    dbuf->db_data_size, &iscsit_buf_xfer_cb, dbuf);
1548		mutex_exit(&ict_sess->ist_sn_mutex);
1549
1550		return (iscsit_idm_to_stmf(idm_rc));
1551	} else if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT) {
1552		/* Grab the SN lock (see comment above) */
1553		mutex_enter(&ict_sess->ist_sn_mutex);
1554		idm_rc = idm_buf_rx_from_ini(iscsit_task->it_idm_task,
1555		    ibuf->ibuf_idm_buf, dbuf->db_relative_offset,
1556		    dbuf->db_data_size, &iscsit_buf_xfer_cb, dbuf);
1557		mutex_exit(&ict_sess->ist_sn_mutex);
1558
1559		return (iscsit_idm_to_stmf(idm_rc));
1560	}
1561
1562	/* What are we supposed to do if there is no direction? */
1563	return (STMF_INVALID_ARG);
1564}
1565
1566static void
1567iscsit_buf_xfer_cb(idm_buf_t *idb, idm_status_t status)
1568{
1569	iscsit_task_t *itask = idb->idb_task_binding->idt_private;
1570	stmf_data_buf_t *dbuf = idb->idb_cb_arg;
1571
1572	dbuf->db_xfer_status = iscsit_idm_to_stmf(status);
1573
1574	/*
1575	 * If the task has been aborted then we don't need to call STMF
1576	 */
1577	if (itask->it_stmf_abort) {
1578		return;
1579	}
1580
1581	/*
1582	 * For ISCSI over TCP (not iSER), the last SCSI Data PDU passed
1583	 * for a successful command contains the status as requested by
1584	 * by COMSTAR (via the DB_SEND_STATUS_GOOD flag). But the iSER
1585	 * transport does not support phase-collapse. So pretend we are
1586	 * COMSTAR and send the status in a separate PDU now.
1587	 */
1588	if (idb->idb_task_binding->idt_flags & IDM_TASK_PHASECOLLAPSE_SUCCESS) {
1589		/*
1590		 * Mark task complete and notify COMSTAR
1591		 * that the status has been sent.
1592		 */
1593		itask->it_idm_task->idt_state = TASK_COMPLETE;
1594		stmf_send_status_done(itask->it_stmf_task,
1595		    iscsit_idm_to_stmf(status), STMF_IOF_LPORT_DONE);
1596	} else if ((dbuf->db_flags & DB_SEND_STATUS_GOOD) &&
1597	    status == IDM_STATUS_SUCCESS) {
1598
1599		/*
1600		 * The iscsi target port provider - for iSER, emulates the
1601		 * DB_SEND_STATUS_GOOD optimization if requested by STMF;
1602		 * it sends the status in a separate PDU after the data
1603		 * transfer. In this case the port provider should first
1604		 * call stmf_data_xfer_done() to mark the transfer complete
1605		 * and then send the status. Although STMF will free the
1606		 * buffer at the time the task is freed, even if the transfer
1607		 * is not marked complete, this behavior makes statistics
1608		 * gathering and task state tracking more difficult than it
1609		 * needs to be.
1610		 */
1611		stmf_data_xfer_done(itask->it_stmf_task, dbuf, 0);
1612		if (iscsit_send_scsi_status(itask->it_stmf_task, 0)
1613		    != STMF_SUCCESS) {
1614			stmf_send_status_done(itask->it_stmf_task,
1615			    STMF_FAILURE, STMF_IOF_LPORT_DONE);
1616		}
1617	} else {
1618		stmf_data_xfer_done(itask->it_stmf_task, dbuf, 0);
1619		/* don't touch dbuf after stmf_data_xfer_done */
1620	}
1621}
1622
1623
1624/*ARGSUSED*/
1625stmf_status_t
1626iscsit_send_scsi_status(scsi_task_t *task, uint32_t ioflags)
1627{
1628	iscsit_task_t *itask = task->task_port_private;
1629	iscsi_scsi_rsp_hdr_t *rsp;
1630	idm_pdu_t *pdu;
1631	int resp_datalen;
1632
1633	/*
1634	 * If this task is aborted then we don't need to respond.
1635	 */
1636	if (itask->it_stmf_abort) {
1637		return (STMF_SUCCESS);
1638	}
1639
1640	/*
1641	 * If this is a task management status, handle it elsewhere.
1642	 */
1643	if (task->task_mgmt_function != TM_NONE) {
1644		/*
1645		 * Don't wait for the PDU completion to tell STMF
1646		 * the task is done -- it doesn't really matter and
1647		 * it makes life complicated if STMF later asks us to
1648		 * abort the request and we don't know whether the
1649		 * status has been sent or not.
1650		 */
1651		itask->it_tm_responded = B_TRUE;
1652		iscsit_send_task_mgmt_resp(itask->it_tm_pdu,
1653		    (task->task_completion_status == STMF_SUCCESS) ?
1654		    SCSI_TCP_TM_RESP_COMPLETE : SCSI_TCP_TM_RESP_FUNC_NOT_SUPP);
1655		stmf_send_status_done(task, STMF_SUCCESS,
1656		    STMF_IOF_LPORT_DONE);
1657		return (STMF_SUCCESS);
1658	}
1659
1660	/*
1661	 * Remove the task from the session task list
1662	 */
1663	iscsit_task_done(itask);
1664
1665	/*
1666	 * Send status
1667	 */
1668	mutex_enter(&itask->it_idm_task->idt_mutex);
1669	if ((itask->it_idm_task->idt_state == TASK_ACTIVE) &&
1670	    (task->task_completion_status == STMF_SUCCESS) &&
1671	    (task->task_sense_length == 0) &&
1672	    (task->task_resid == 0)) {
1673		itask->it_idm_task->idt_state = TASK_COMPLETE;
1674		/* PDU callback releases task hold */
1675		idm_task_hold(itask->it_idm_task);
1676		mutex_exit(&itask->it_idm_task->idt_mutex);
1677		/*
1678		 * Fast path.  Cached status PDU's are already
1679		 * initialized.  We just need to fill in
1680		 * connection and task information. StatSN is
1681		 * incremented by 1 for every status sent a
1682		 * connection.
1683		 */
1684		pdu = kmem_cache_alloc(iscsit_status_pdu_cache, KM_SLEEP);
1685		pdu->isp_ic = itask->it_ict->ict_ic;
1686		pdu->isp_private = itask;
1687		pdu->isp_flags |= IDM_PDU_SET_STATSN | IDM_PDU_ADVANCE_STATSN;
1688
1689		rsp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr;
1690		rsp->itt = itask->it_itt;
1691		/*
1692		 * ExpDataSN is the number of R2T and Data-In (read)
1693		 * PDUs the target has sent for the SCSI command.
1694		 *
1695		 * Since there is no support for bidirectional transfer
1696		 * yet, either idt_exp_datasn or idt_exp_rttsn, but not
1697		 * both is valid at any time
1698		 */
1699		rsp->expdatasn = (itask->it_idm_task->idt_exp_datasn != 0) ?
1700		    htonl(itask->it_idm_task->idt_exp_datasn):
1701		    htonl(itask->it_idm_task->idt_exp_rttsn);
1702		rsp->cmd_status = task->task_scsi_status;
1703		iscsit_pdu_tx(pdu);
1704		return (STMF_SUCCESS);
1705	} else {
1706		if (itask->it_idm_task->idt_state != TASK_ACTIVE) {
1707			mutex_exit(&itask->it_idm_task->idt_mutex);
1708			return (STMF_FAILURE);
1709		}
1710		itask->it_idm_task->idt_state = TASK_COMPLETE;
1711		/* PDU callback releases task hold */
1712		idm_task_hold(itask->it_idm_task);
1713		mutex_exit(&itask->it_idm_task->idt_mutex);
1714
1715		resp_datalen = (task->task_sense_length == 0) ? 0 :
1716		    (task->task_sense_length + sizeof (uint16_t));
1717
1718		pdu = idm_pdu_alloc(sizeof (iscsi_hdr_t), resp_datalen);
1719		idm_pdu_init(pdu, itask->it_ict->ict_ic, itask,
1720		    iscsit_send_status_done);
1721		pdu->isp_flags |= IDM_PDU_SET_STATSN | IDM_PDU_ADVANCE_STATSN;
1722
1723		rsp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr;
1724		bzero(rsp, sizeof (*rsp));
1725		rsp->opcode = ISCSI_OP_SCSI_RSP;
1726
1727		rsp->flags = ISCSI_FLAG_FINAL;
1728		if (task->task_status_ctrl & TASK_SCTRL_OVER) {
1729			rsp->flags |= ISCSI_FLAG_CMD_OVERFLOW;
1730		} else if (task->task_status_ctrl & TASK_SCTRL_UNDER) {
1731			rsp->flags |= ISCSI_FLAG_CMD_UNDERFLOW;
1732		}
1733
1734		rsp->bi_residual_count = 0;
1735		rsp->residual_count = htonl(task->task_resid);
1736		rsp->itt = itask->it_itt;
1737		rsp->response = ISCSI_STATUS_CMD_COMPLETED;
1738		rsp->expdatasn = (itask->it_idm_task->idt_exp_datasn != 0) ?
1739		    htonl(itask->it_idm_task->idt_exp_datasn):
1740		    htonl(itask->it_idm_task->idt_exp_rttsn);
1741		rsp->cmd_status = task->task_scsi_status;
1742		if (task->task_sense_length != 0) {
1743			/*
1744			 * Add a byte to provide the sense length in
1745			 * the response
1746			 */
1747			*(uint16_t *)((void *)pdu->isp_data) =
1748			    htons(task->task_sense_length);
1749			bcopy(task->task_sense_data,
1750			    (uint8_t *)pdu->isp_data +
1751			    sizeof (uint16_t),
1752			    task->task_sense_length);
1753			hton24(rsp->dlength, resp_datalen);
1754		}
1755
1756		DTRACE_PROBE5(iscsi__scsi__response,
1757		    iscsit_conn_t *, itask->it_ict,
1758		    uint8_t, rsp->response,
1759		    uint8_t, rsp->cmd_status,
1760		    idm_pdu_t *, pdu,
1761		    scsi_task_t *, task);
1762
1763		iscsit_pdu_tx(pdu);
1764
1765		return (STMF_SUCCESS);
1766	}
1767}
1768
1769/*ARGSUSED*/
1770static void
1771iscsit_send_good_status_done(idm_pdu_t *pdu, idm_status_t status)
1772{
1773	iscsit_task_t	*itask;
1774	boolean_t	aborted;
1775
1776	itask = pdu->isp_private;
1777	aborted = itask->it_stmf_abort;
1778
1779	/*
1780	 * After releasing the hold the task may be freed at any time so
1781	 * don't touch it.
1782	 */
1783	idm_task_rele(itask->it_idm_task);
1784	if (!aborted) {
1785		stmf_send_status_done(itask->it_stmf_task,
1786		    iscsit_idm_to_stmf(pdu->isp_status), STMF_IOF_LPORT_DONE);
1787	}
1788	kmem_cache_free(iscsit_status_pdu_cache, pdu);
1789}
1790
1791/*ARGSUSED*/
1792static void
1793iscsit_send_status_done(idm_pdu_t *pdu, idm_status_t status)
1794{
1795	iscsit_task_t	 *itask;
1796	boolean_t	aborted;
1797
1798	itask = pdu->isp_private;
1799	aborted = itask->it_stmf_abort;
1800
1801	/*
1802	 * After releasing the hold the task may be freed at any time so
1803	 * don't touch it.
1804	 */
1805	idm_task_rele(itask->it_idm_task);
1806	if (!aborted) {
1807		stmf_send_status_done(itask->it_stmf_task,
1808		    iscsit_idm_to_stmf(pdu->isp_status), STMF_IOF_LPORT_DONE);
1809	}
1810	idm_pdu_free(pdu);
1811}
1812
1813
1814void
1815iscsit_lport_task_free(scsi_task_t *task)
1816{
1817	iscsit_task_t *itask = task->task_port_private;
1818
1819	/* We only call idm_task_start for regular tasks, not task management */
1820	if (task->task_mgmt_function == TM_NONE) {
1821		idm_task_done(itask->it_idm_task);
1822		iscsit_task_free(itask);
1823		return;
1824	} else {
1825		iscsit_tm_task_free(itask);
1826	}
1827}
1828
1829/*ARGSUSED*/
1830stmf_status_t
1831iscsit_abort(stmf_local_port_t *lport, int abort_cmd, void *arg, uint32_t flags)
1832{
1833	scsi_task_t	*st = (scsi_task_t *)arg;
1834	iscsit_task_t	*iscsit_task;
1835	idm_task_t	*idt;
1836
1837	/*
1838	 * If this is a task management request then there's really not much to
1839	 * do.
1840	 */
1841	if (st->task_mgmt_function != TM_NONE) {
1842		return (STMF_ABORT_SUCCESS);
1843	}
1844
1845	/*
1846	 * Regular task, start cleaning up
1847	 */
1848	iscsit_task = st->task_port_private;
1849	idt = iscsit_task->it_idm_task;
1850	mutex_enter(&iscsit_task->it_mutex);
1851	iscsit_task->it_stmf_abort = B_TRUE;
1852	if (iscsit_task->it_aborted) {
1853		mutex_exit(&iscsit_task->it_mutex);
1854		/*
1855		 * Task is no longer active
1856		 */
1857		iscsit_task_done(iscsit_task);
1858
1859		/*
1860		 * STMF specification is wrong... says to return
1861		 * STMF_ABORTED, the code actually looks for
1862		 * STMF_ABORT_SUCCESS.
1863		 */
1864		return (STMF_ABORT_SUCCESS);
1865	} else {
1866		mutex_exit(&iscsit_task->it_mutex);
1867		/*
1868		 * Call IDM to abort the task.  Due to a variety of
1869		 * circumstances the task may already be in the process of
1870		 * aborting.
1871		 * We'll let IDM worry about rationalizing all that except
1872		 * for one particular instance.  If the state of the task
1873		 * is TASK_COMPLETE, we need to indicate to the framework
1874		 * that we are in fact done.  This typically happens with
1875		 * framework-initiated task management type requests
1876		 * (e.g. abort task).
1877		 */
1878		if (idt->idt_state == TASK_COMPLETE) {
1879			idm_refcnt_wait_ref(&idt->idt_refcnt);
1880			return (STMF_ABORT_SUCCESS);
1881		} else {
1882			idm_task_abort(idt->idt_ic, idt, AT_TASK_MGMT_ABORT);
1883			return (STMF_SUCCESS);
1884		}
1885	}
1886
1887	/*NOTREACHED*/
1888}
1889
1890/*ARGSUSED*/
1891void
1892iscsit_ctl(stmf_local_port_t *lport, int cmd, void *arg)
1893{
1894	iscsit_tgt_t		*iscsit_tgt;
1895
1896	ASSERT((cmd == STMF_CMD_LPORT_ONLINE) ||
1897	    (cmd == STMF_ACK_LPORT_ONLINE_COMPLETE) ||
1898	    (cmd == STMF_CMD_LPORT_OFFLINE) ||
1899	    (cmd == STMF_ACK_LPORT_OFFLINE_COMPLETE));
1900
1901	iscsit_tgt = (iscsit_tgt_t *)lport->lport_port_private;
1902
1903	switch (cmd) {
1904	case STMF_CMD_LPORT_ONLINE:
1905		iscsit_tgt_sm_event(iscsit_tgt, TE_STMF_ONLINE_REQ);
1906		break;
1907	case STMF_CMD_LPORT_OFFLINE:
1908		iscsit_tgt_sm_event(iscsit_tgt, TE_STMF_OFFLINE_REQ);
1909		break;
1910	case STMF_ACK_LPORT_ONLINE_COMPLETE:
1911		iscsit_tgt_sm_event(iscsit_tgt, TE_STMF_ONLINE_COMPLETE_ACK);
1912		break;
1913	case STMF_ACK_LPORT_OFFLINE_COMPLETE:
1914		iscsit_tgt_sm_event(iscsit_tgt, TE_STMF_OFFLINE_COMPLETE_ACK);
1915		break;
1916
1917	default:
1918		break;
1919	}
1920}
1921
1922static stmf_status_t
1923iscsit_idm_to_stmf(idm_status_t idmrc)
1924{
1925	switch (idmrc) {
1926	case IDM_STATUS_SUCCESS:
1927		return (STMF_SUCCESS);
1928	default:
1929		return (STMF_FAILURE);
1930	}
1931	/*NOTREACHED*/
1932}
1933
1934void
1935iscsit_op_scsi_cmd(idm_conn_t *ic, idm_pdu_t *rx_pdu)
1936{
1937	iscsit_conn_t		*ict = ic->ic_handle;
1938
1939	if (iscsit_check_cmdsn_and_queue(rx_pdu)) {
1940		iscsit_post_scsi_cmd(ic, rx_pdu);
1941	}
1942	iscsit_process_pdu_in_queue(ict->ict_sess);
1943}
1944
1945/*
1946 * ISCSI protocol
1947 */
1948
1949void
1950iscsit_post_scsi_cmd(idm_conn_t *ic, idm_pdu_t *rx_pdu)
1951{
1952	iscsit_conn_t		*ict;
1953	iscsit_task_t		*itask;
1954	scsi_task_t		*task;
1955	iscsit_buf_t		*ibuf;
1956	iscsi_scsi_cmd_hdr_t	*iscsi_scsi =
1957	    (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr;
1958	iscsi_addl_hdr_t	*ahs_hdr;
1959	uint16_t		addl_cdb_len = 0;
1960
1961	ict = ic->ic_handle;
1962
1963	itask = iscsit_task_alloc(ict);
1964	if (itask == NULL) {
1965		/* Finish processing request */
1966		iscsit_set_cmdsn(ict, rx_pdu);
1967
1968		iscsit_send_direct_scsi_resp(ict, rx_pdu,
1969		    ISCSI_STATUS_CMD_COMPLETED, STATUS_BUSY);
1970		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
1971		return;
1972	}
1973
1974	/*
1975	 * Note CmdSN and ITT in task.  IDM will have already validated this
1976	 * request against the connection state so we don't need to check
1977	 * that (the connection may have changed state in the meantime but
1978	 * we will catch that when we try to send a response)
1979	 */
1980	itask->it_cmdsn = ntohl(iscsi_scsi->cmdsn);
1981	itask->it_itt = iscsi_scsi->itt;
1982
1983	/*
1984	 * Check for extended CDB AHS
1985	 */
1986	if (iscsi_scsi->hlength > 0) {
1987		ahs_hdr = (iscsi_addl_hdr_t *)iscsi_scsi;
1988		addl_cdb_len = ((ahs_hdr->ahs_hlen_hi << 8) |
1989		    ahs_hdr->ahs_hlen_lo) - 1; /* Adjust for reserved byte */
1990		if (((addl_cdb_len + 4) / sizeof (uint32_t)) >
1991		    iscsi_scsi->hlength) {
1992			/* Mangled header info, drop it */
1993			idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
1994			return;
1995		}
1996	}
1997
1998	ict = rx_pdu->isp_ic->ic_handle; /* IDM client private */
1999
2000	/*
2001	 * Add task to session list.  This function will also check to
2002	 * ensure that the task does not already exist.
2003	 */
2004	if (iscsit_task_start(itask) != IDM_STATUS_SUCCESS) {
2005		/*
2006		 * Task exists, free all resources and reject.  Don't
2007		 * update expcmdsn in this case because RFC 3720 says
2008		 * "The CmdSN of the rejected command PDU (if it is a
2009		 * non-immediate command) MUST NOT be considered received
2010		 * by the target (i.e., a command sequence gap must be
2011		 * assumed for the CmdSN), even though the CmdSN of the
2012		 * rejected command PDU may be reliably ascertained.  Upon
2013		 * receiving the Reject, the initiator MUST plug the CmdSN
2014		 * gap in order to continue to use the session.  The gap
2015		 * may be plugged either by transmitting a command PDU
2016		 * with the same CmdSN, or by aborting the task (see section
2017		 * 6.9 on how an abort may plug a CmdSN gap)." (Section 6.3)
2018		 */
2019		iscsit_task_free(itask);
2020		iscsit_send_reject(ict, rx_pdu, ISCSI_REJECT_TASK_IN_PROGRESS);
2021		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
2022		return;
2023	}
2024
2025	/* Update sequence numbers */
2026	iscsit_set_cmdsn(ict, rx_pdu);
2027
2028	/*
2029	 * Allocate STMF task
2030	 */
2031	itask->it_stmf_task = stmf_task_alloc(
2032	    itask->it_ict->ict_sess->ist_lport,
2033	    itask->it_ict->ict_sess->ist_stmf_sess, iscsi_scsi->lun,
2034	    16 + addl_cdb_len, 0);
2035	if (itask->it_stmf_task == NULL) {
2036		/*
2037		 * Either stmf really couldn't get memory for a task or,
2038		 * more likely, the LU is currently in reset.  Either way
2039		 * we have no choice but to fail the request.
2040		 */
2041		iscsit_task_done(itask);
2042		iscsit_task_free(itask);
2043		iscsit_send_direct_scsi_resp(ict, rx_pdu,
2044		    ISCSI_STATUS_CMD_COMPLETED, STATUS_BUSY);
2045		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
2046		return;
2047	}
2048
2049	task = itask->it_stmf_task;
2050	task->task_port_private = itask;
2051
2052	bcopy(iscsi_scsi->lun, task->task_lun_no, sizeof (task->task_lun_no));
2053
2054	/*
2055	 * iSCSI and Comstar use the same values.  Should we rely on this
2056	 * or translate them bit-wise?
2057	 */
2058
2059	task->task_flags =
2060	    (((iscsi_scsi->flags & ISCSI_FLAG_CMD_READ) ? TF_READ_DATA : 0) |
2061	    ((iscsi_scsi->flags & ISCSI_FLAG_CMD_WRITE) ? TF_WRITE_DATA : 0) |
2062	    ((rx_pdu->isp_datalen == 0) ? 0 : TF_INITIAL_BURST));
2063
2064	switch (iscsi_scsi->flags & ISCSI_FLAG_CMD_ATTR_MASK) {
2065	case ISCSI_ATTR_UNTAGGED:
2066		break;
2067	case ISCSI_ATTR_SIMPLE:
2068		task->task_additional_flags |= TF_ATTR_SIMPLE_QUEUE;
2069		break;
2070	case ISCSI_ATTR_ORDERED:
2071		task->task_additional_flags |= TF_ATTR_ORDERED_QUEUE;
2072		break;
2073	case ISCSI_ATTR_HEAD_OF_QUEUE:
2074		task->task_additional_flags |= TF_ATTR_HEAD_OF_QUEUE;
2075		break;
2076	case ISCSI_ATTR_ACA:
2077		task->task_additional_flags |= TF_ATTR_ACA;
2078		break;
2079	default:
2080		/* Protocol error but just take it, treat as untagged */
2081		break;
2082	}
2083
2084
2085	task->task_additional_flags = 0;
2086	task->task_priority = 0;
2087	task->task_mgmt_function = TM_NONE;
2088
2089	/*
2090	 * This "task_max_nbufs" doesn't map well to BIDI.  We probably need
2091	 * parameter for each direction.  "MaxOutstandingR2T" may very well
2092	 * be set to one which could prevent us from doing simultaneous
2093	 * transfers in each direction.
2094	 */
2095	task->task_max_nbufs = (iscsi_scsi->flags & ISCSI_FLAG_CMD_WRITE) ?
2096	    ict->ict_op.op_max_outstanding_r2t : STMF_BUFS_MAX;
2097	task->task_cmd_seq_no = ntohl(iscsi_scsi->itt);
2098	task->task_expected_xfer_length = ntohl(iscsi_scsi->data_length);
2099
2100	/* Copy CDB */
2101	bcopy(iscsi_scsi->scb, task->task_cdb, 16);
2102	if (addl_cdb_len > 0) {
2103		bcopy(ahs_hdr->ahs_extscb, task->task_cdb + 16, addl_cdb_len);
2104	}
2105
2106	DTRACE_ISCSI_3(scsi__command, idm_conn_t *, ic,
2107	    iscsi_scsi_cmd_hdr_t *, (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr,
2108	    scsi_task_t *, task);
2109
2110	/*
2111	 * Copy the transport header into the task handle from the PDU
2112	 * handle. The transport header describes this task's remote tagged
2113	 * buffer.
2114	 */
2115	if (rx_pdu->isp_transport_hdrlen != 0) {
2116		bcopy(rx_pdu->isp_transport_hdr,
2117		    itask->it_idm_task->idt_transport_hdr,
2118		    rx_pdu->isp_transport_hdrlen);
2119	}
2120
2121	/*
2122	 * Tell IDM about our new active task
2123	 */
2124	idm_task_start(itask->it_idm_task, (uintptr_t)itask->it_itt);
2125
2126	/*
2127	 * If we have any immediate data then setup the immediate buffer
2128	 * context that comes with the task
2129	 */
2130	if (rx_pdu->isp_datalen) {
2131		ibuf = itask->it_immed_data;
2132		ibuf->ibuf_immed_data_pdu = rx_pdu;
2133		ibuf->ibuf_stmf_buf->db_data_size = rx_pdu->isp_datalen;
2134		ibuf->ibuf_stmf_buf->db_buf_size = rx_pdu->isp_datalen;
2135		ibuf->ibuf_stmf_buf->db_relative_offset = 0;
2136		ibuf->ibuf_stmf_buf->db_sglist[0].seg_length =
2137		    rx_pdu->isp_datalen;
2138		ibuf->ibuf_stmf_buf->db_sglist[0].seg_addr = rx_pdu->isp_data;
2139
2140		DTRACE_ISCSI_8(xfer__start, idm_conn_t *, ic,
2141		    uintptr_t, ibuf->ibuf_stmf_buf->db_sglist[0].seg_addr,
2142		    uint32_t, ibuf->ibuf_stmf_buf->db_relative_offset,
2143		    uint64_t, 0, uint32_t, 0, uint32_t, 0, /* no raddr */
2144		    uint32_t, rx_pdu->isp_datalen, int, XFER_BUF_TX_TO_INI);
2145
2146		/*
2147		 * For immediate data transfer, there is no callback from
2148		 * stmf to indicate that the initial burst of data is
2149		 * transferred successfully. In some cases, the task can
2150		 * get freed before execution returns from stmf_post_task.
2151		 * Although this xfer-start/done probe accurately tracks
2152		 * the size of the transfer, it does only provide a best
2153		 * effort on the timing of the transfer.
2154		 */
2155		DTRACE_ISCSI_8(xfer__done, idm_conn_t *, ic,
2156		    uintptr_t, ibuf->ibuf_stmf_buf->db_sglist[0].seg_addr,
2157		    uint32_t, ibuf->ibuf_stmf_buf->db_relative_offset,
2158		    uint64_t, 0, uint32_t, 0, uint32_t, 0, /* no raddr */
2159		    uint32_t, rx_pdu->isp_datalen, int, XFER_BUF_TX_TO_INI);
2160		stmf_post_task(task, ibuf->ibuf_stmf_buf);
2161	} else {
2162
2163		stmf_post_task(task, NULL);
2164		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
2165	}
2166}
2167
2168/*ARGSUSED*/
2169void
2170iscsit_deferred_dispatch(idm_pdu_t *rx_pdu)
2171{
2172	iscsit_conn_t *ict = rx_pdu->isp_ic->ic_handle;
2173
2174	/*
2175	 * If the connection has been lost then ignore new PDU's
2176	 */
2177	mutex_enter(&ict->ict_mutex);
2178	if (ict->ict_lost) {
2179		mutex_exit(&ict->ict_mutex);
2180		idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL);
2181		return;
2182	}
2183
2184	/*
2185	 * Grab a hold on the connection to prevent it from going away
2186	 * between now and when the taskq function is called.
2187	 */
2188	iscsit_conn_dispatch_hold(ict);
2189	mutex_exit(&ict->ict_mutex);
2190
2191	if (taskq_dispatch(iscsit_global.global_dispatch_taskq,
2192	    iscsit_deferred, rx_pdu, DDI_NOSLEEP) == NULL) {
2193		/*
2194		 * In the unlikely scenario that we couldn't get the resources
2195		 * to dispatch the PDU then just drop it.
2196		 */
2197		idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL);
2198		idm_conn_event(ict->ict_ic, CE_TRANSPORT_FAIL, NULL);
2199		iscsit_conn_dispatch_rele(ict);
2200	}
2201}
2202
2203static void
2204iscsit_deferred(void *rx_pdu_void)
2205{
2206	idm_pdu_t		*rx_pdu = rx_pdu_void;
2207	idm_conn_t		*ic = rx_pdu->isp_ic;
2208	iscsit_conn_t		*ict = ic->ic_handle;
2209
2210	/*
2211	 * NOP and Task Management Commands can be marked for immediate
2212	 * delivery. Commands marked as 'Immediate' are to be considered
2213	 * for execution as soon as they arrive on the target. So these
2214	 * should not be checked for sequence order and put in a queue.
2215	 * The CmdSN is not advanced for Immediate Commands.
2216	 */
2217	switch (IDM_PDU_OPCODE(rx_pdu)) {
2218	case ISCSI_OP_NOOP_OUT:
2219		if (iscsit_check_cmdsn_and_queue(rx_pdu)) {
2220			iscsit_set_cmdsn(ict, rx_pdu);
2221			iscsit_pdu_op_noop(ict, rx_pdu);
2222		}
2223		break;
2224	case ISCSI_OP_LOGIN_CMD:
2225		iscsit_pdu_op_login_cmd(ict, rx_pdu);
2226		iscsit_conn_dispatch_rele(ict);
2227		return;
2228	case ISCSI_OP_TEXT_CMD:
2229		if (iscsit_check_cmdsn_and_queue(rx_pdu)) {
2230			iscsit_set_cmdsn(ict, rx_pdu);
2231			iscsit_pdu_op_text_cmd(ict, rx_pdu);
2232		}
2233		break;
2234	case ISCSI_OP_LOGOUT_CMD:
2235		if (iscsit_check_cmdsn_and_queue(rx_pdu)) {
2236			iscsit_set_cmdsn(ict, rx_pdu);
2237			iscsit_pdu_op_logout_cmd(ict, rx_pdu);
2238		}
2239		break;
2240	default:
2241		/* Protocol error.  IDM should have caught this */
2242		idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL);
2243		ASSERT(0);
2244		break;
2245	}
2246	/*
2247	 * Check if there are other PDUs in the session staging queue
2248	 * waiting to be posted to SCSI layer.
2249	 */
2250	iscsit_process_pdu_in_queue(ict->ict_sess);
2251
2252	iscsit_conn_dispatch_rele(ict);
2253}
2254
2255static void
2256iscsit_send_direct_scsi_resp(iscsit_conn_t *ict, idm_pdu_t *rx_pdu,
2257    uint8_t response, uint8_t cmd_status)
2258{
2259	idm_pdu_t			*rsp_pdu;
2260	idm_conn_t			*ic;
2261	iscsi_scsi_rsp_hdr_t		*resp;
2262	iscsi_scsi_cmd_hdr_t		*req =
2263	    (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr;
2264
2265	ic = ict->ict_ic;
2266
2267	rsp_pdu = idm_pdu_alloc(sizeof (iscsi_scsi_rsp_hdr_t), 0);
2268	idm_pdu_init(rsp_pdu, ic, NULL, NULL);
2269	/*
2270	 * StatSN is incremented by 1 for every response sent on
2271	 * a connection except for responses sent as a result of
2272	 * a retry or SNACK
2273	 */
2274	rsp_pdu->isp_flags |= IDM_PDU_SET_STATSN | IDM_PDU_ADVANCE_STATSN;
2275
2276	resp = (iscsi_scsi_rsp_hdr_t *)rsp_pdu->isp_hdr;
2277
2278	resp->opcode = ISCSI_OP_SCSI_RSP;
2279	resp->flags = ISCSI_FLAG_FINAL;
2280	resp->response = response;
2281	resp->cmd_status = cmd_status;
2282	resp->itt = req->itt;
2283	if ((response == ISCSI_STATUS_CMD_COMPLETED) &&
2284	    (req->data_length != 0) &&
2285	    ((req->flags & ISCSI_FLAG_CMD_READ) ||
2286	    (req->flags & ISCSI_FLAG_CMD_WRITE))) {
2287		resp->flags |= ISCSI_FLAG_CMD_UNDERFLOW;
2288		resp->residual_count = req->data_length;
2289	}
2290
2291	DTRACE_PROBE4(iscsi__scsi__direct__response,
2292	    iscsit_conn_t *, ict,
2293	    uint8_t, resp->response,
2294	    uint8_t, resp->cmd_status,
2295	    idm_pdu_t *, rsp_pdu);
2296
2297	iscsit_pdu_tx(rsp_pdu);
2298}
2299
2300void
2301iscsit_send_task_mgmt_resp(idm_pdu_t *tm_resp_pdu, uint8_t tm_status)
2302{
2303	iscsi_scsi_task_mgt_rsp_hdr_t	*tm_resp;
2304
2305	/*
2306	 * The target must take note of the last-sent StatSN.
2307	 * The StatSN is to be incremented after sending a
2308	 * task management response. Digest recovery can only
2309	 * work if StatSN is incremented.
2310	 */
2311	tm_resp_pdu->isp_flags |= IDM_PDU_SET_STATSN | IDM_PDU_ADVANCE_STATSN;
2312	tm_resp = (iscsi_scsi_task_mgt_rsp_hdr_t *)tm_resp_pdu->isp_hdr;
2313	tm_resp->response = tm_status;
2314
2315	DTRACE_PROBE3(iscsi__scsi__tm__response,
2316	    iscsit_conn_t *, tm_resp_pdu->isp_ic->ic_handle,
2317	    uint8_t, tm_resp->response,
2318	    idm_pdu_t *, tm_resp_pdu);
2319	iscsit_pdu_tx(tm_resp_pdu);
2320}
2321
2322void
2323iscsit_op_scsi_task_mgmt(iscsit_conn_t *ict, idm_pdu_t *rx_pdu)
2324{
2325	idm_pdu_t			*tm_resp_pdu;
2326	iscsit_task_t			*itask;
2327	iscsit_task_t			*tm_itask;
2328	scsi_task_t			*task;
2329	iscsi_scsi_task_mgt_hdr_t 	*iscsi_tm =
2330	    (iscsi_scsi_task_mgt_hdr_t *)rx_pdu->isp_hdr;
2331	iscsi_scsi_task_mgt_rsp_hdr_t 	*iscsi_tm_rsp =
2332	    (iscsi_scsi_task_mgt_rsp_hdr_t *)rx_pdu->isp_hdr;
2333	uint32_t			rtt, cmdsn, refcmdsn;
2334	uint8_t				tm_func;
2335
2336	/*
2337	 * Setup response PDU (response field will get filled in later)
2338	 */
2339	tm_resp_pdu = idm_pdu_alloc(sizeof (iscsi_scsi_task_mgt_rsp_hdr_t), 0);
2340	if (tm_resp_pdu == NULL) {
2341		/* Can't respond, just drop it */
2342		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
2343		return;
2344	}
2345	idm_pdu_init(tm_resp_pdu, ict->ict_ic, NULL, NULL);
2346	iscsi_tm_rsp = (iscsi_scsi_task_mgt_rsp_hdr_t *)tm_resp_pdu->isp_hdr;
2347	bzero(iscsi_tm_rsp, sizeof (iscsi_scsi_task_mgt_rsp_hdr_t));
2348	iscsi_tm_rsp->opcode = ISCSI_OP_SCSI_TASK_MGT_RSP;
2349	iscsi_tm_rsp->flags = ISCSI_FLAG_FINAL;
2350	iscsi_tm_rsp->itt = rx_pdu->isp_hdr->itt;
2351
2352	/*
2353	 * Figure out what we're being asked to do.
2354	 */
2355	DTRACE_PROBE4(iscsi__scsi__tm__request,
2356	    iscsit_conn_t *, ict,
2357	    uint8_t, (iscsi_tm->function & ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK),
2358	    uint32_t, iscsi_tm->rtt,
2359	    idm_pdu_t *, rx_pdu);
2360	switch (iscsi_tm->function & ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK) {
2361	case ISCSI_TM_FUNC_ABORT_TASK:
2362		/*
2363		 * STMF doesn't currently support the "abort task" task
2364		 * management command although it does support aborting
2365		 * an individual task.  We'll get STMF to abort the task
2366		 * for us but handle the details of the task management
2367		 * command ourselves.
2368		 *
2369		 * Find the task associated with the referenced task tag.
2370		 */
2371		rtt = iscsi_tm->rtt;
2372		itask = (iscsit_task_t *)idm_task_find_by_handle(ict->ict_ic,
2373		    (uintptr_t)rtt);
2374
2375		if (itask == NULL) {
2376			cmdsn = ntohl(iscsi_tm->cmdsn);
2377			refcmdsn = ntohl(iscsi_tm->refcmdsn);
2378
2379			/*
2380			 * Task was not found. But the SCSI command could be
2381			 * on the rxpdu wait queue. If RefCmdSN is within
2382			 * the CmdSN window and less than CmdSN of the TM
2383			 * function, return "Function Complete". Otherwise,
2384			 * return "Task Does Not Exist".
2385			 */
2386
2387			if (iscsit_cmdsn_in_window(ict, refcmdsn) &&
2388			    iscsit_sna_lt(refcmdsn, cmdsn)) {
2389				mutex_enter(&ict->ict_sess->ist_sn_mutex);
2390				(void) iscsit_remove_pdu_from_queue(
2391				    ict->ict_sess, refcmdsn);
2392				iscsit_conn_dispatch_rele(ict);
2393				mutex_exit(&ict->ict_sess->ist_sn_mutex);
2394				iscsit_send_task_mgmt_resp(tm_resp_pdu,
2395				    SCSI_TCP_TM_RESP_COMPLETE);
2396			} else {
2397				iscsit_send_task_mgmt_resp(tm_resp_pdu,
2398				    SCSI_TCP_TM_RESP_NO_TASK);
2399			}
2400		} else {
2401
2402			/*
2403			 * Tell STMF to abort the task.  This will do no harm
2404			 * if the task is already complete.
2405			 */
2406			stmf_abort(STMF_QUEUE_TASK_ABORT, itask->it_stmf_task,
2407			    STMF_ABORTED, NULL);
2408
2409			/*
2410			 * Make sure the task hasn't already completed
2411			 */
2412			mutex_enter(&itask->it_idm_task->idt_mutex);
2413			if ((itask->it_idm_task->idt_state == TASK_COMPLETE) ||
2414			    (itask->it_idm_task->idt_state == TASK_IDLE)) {
2415				/*
2416				 * Task is complete, return "Task Does Not
2417				 * Exist"
2418				 */
2419				mutex_exit(&itask->it_idm_task->idt_mutex);
2420				iscsit_send_task_mgmt_resp(tm_resp_pdu,
2421				    SCSI_TCP_TM_RESP_NO_TASK);
2422			} else {
2423				/*
2424				 * STMF is now aborting the task, return
2425				 * "Function Complete"
2426				 */
2427				mutex_exit(&itask->it_idm_task->idt_mutex);
2428				iscsit_send_task_mgmt_resp(tm_resp_pdu,
2429				    SCSI_TCP_TM_RESP_COMPLETE);
2430			}
2431			idm_task_rele(itask->it_idm_task);
2432		}
2433		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
2434		return;
2435
2436	case ISCSI_TM_FUNC_ABORT_TASK_SET:
2437		tm_func = TM_ABORT_TASK_SET;
2438		break;
2439
2440	case ISCSI_TM_FUNC_CLEAR_ACA:
2441		tm_func = TM_CLEAR_ACA;
2442		break;
2443
2444	case ISCSI_TM_FUNC_CLEAR_TASK_SET:
2445		tm_func = TM_CLEAR_TASK_SET;
2446		break;
2447
2448	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
2449		tm_func = TM_LUN_RESET;
2450		break;
2451
2452	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
2453		tm_func = TM_TARGET_WARM_RESET;
2454		break;
2455
2456	case ISCSI_TM_FUNC_TARGET_COLD_RESET:
2457		tm_func = TM_TARGET_COLD_RESET;
2458		break;
2459
2460	case ISCSI_TM_FUNC_TASK_REASSIGN:
2461		/*
2462		 * We do not currently support allegiance reassignment.  When
2463		 * we start supporting ERL1+, we will need to.
2464		 */
2465		iscsit_send_task_mgmt_resp(tm_resp_pdu,
2466		    SCSI_TCP_TM_RESP_NO_ALLG_REASSN);
2467		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
2468		return;
2469
2470	default:
2471		iscsit_send_task_mgmt_resp(tm_resp_pdu,
2472		    SCSI_TCP_TM_RESP_REJECTED);
2473		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
2474		return;
2475	}
2476
2477	tm_itask = iscsit_tm_task_alloc(ict);
2478	if (tm_itask == NULL) {
2479		iscsit_send_task_mgmt_resp(tm_resp_pdu,
2480		    SCSI_TCP_TM_RESP_REJECTED);
2481		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
2482		return;
2483	}
2484
2485
2486	task = stmf_task_alloc(ict->ict_sess->ist_lport,
2487	    ict->ict_sess->ist_stmf_sess, iscsi_tm->lun,
2488	    0, STMF_TASK_EXT_NONE);
2489	if (task == NULL) {
2490		/*
2491		 * If this happens, either the LU is in reset, couldn't
2492		 * get memory, or some other condition in which we simply
2493		 * can't complete this request.  It would be nice to return
2494		 * an error code like "busy" but the closest we have is
2495		 * "rejected".
2496		 */
2497		iscsit_send_task_mgmt_resp(tm_resp_pdu,
2498		    SCSI_TCP_TM_RESP_REJECTED);
2499		iscsit_tm_task_free(tm_itask);
2500		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
2501		return;
2502	}
2503
2504	tm_itask->it_tm_pdu = tm_resp_pdu;
2505	tm_itask->it_stmf_task = task;
2506	task->task_port_private = tm_itask;
2507	task->task_mgmt_function = tm_func;
2508	task->task_additional_flags = TASK_AF_NO_EXPECTED_XFER_LENGTH;
2509	task->task_priority = 0;
2510	task->task_max_nbufs = STMF_BUFS_MAX;
2511	task->task_cmd_seq_no = iscsi_tm->itt;
2512	task->task_expected_xfer_length = 0;
2513
2514	stmf_post_task(task, NULL);
2515	idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
2516}
2517
2518static void
2519iscsit_pdu_op_noop(iscsit_conn_t *ict, idm_pdu_t *rx_pdu)
2520{
2521	iscsi_nop_out_hdr_t *out = (iscsi_nop_out_hdr_t *)rx_pdu->isp_hdr;
2522	iscsi_nop_in_hdr_t *in;
2523	int resp_datalen;
2524	idm_pdu_t *resp;
2525
2526	/* Ignore the response from initiator */
2527	if ((out->itt == ISCSI_RSVD_TASK_TAG) ||
2528	    (out->ttt != ISCSI_RSVD_TASK_TAG)) {
2529		idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
2530		return;
2531	}
2532
2533	/* Allocate a PDU to respond */
2534	resp_datalen = ntoh24(out->dlength);
2535	resp = idm_pdu_alloc(sizeof (iscsi_hdr_t), resp_datalen);
2536	idm_pdu_init(resp, ict->ict_ic, NULL, NULL);
2537	if (resp_datalen > 0) {
2538		bcopy(rx_pdu->isp_data, resp->isp_data, resp_datalen);
2539	}
2540
2541	/*
2542	 * When sending a NOP-In as a response to a NOP-Out from the initiator,
2543	 * the target must respond with the same initiator task tag that was
2544	 * provided in the NOP-Out request, the target transfer tag must be
2545	 * ISCSI_RSVD_TASK_TAG (0xffffffff) and StatSN will contain the next
2546	 * status sequence number. The StatSN for the connection is advanced
2547	 * after this PDU is sent.
2548	 */
2549	in = (iscsi_nop_in_hdr_t *)resp->isp_hdr;
2550	bzero(in, sizeof (*in));
2551	in->opcode = ISCSI_OP_NOOP_IN;
2552	in->flags = ISCSI_FLAG_FINAL;
2553	bcopy(out->lun, in->lun, 8);
2554	in->itt		= out->itt;
2555	in->ttt		= ISCSI_RSVD_TASK_TAG;
2556	hton24(in->dlength, resp_datalen);
2557	resp->isp_flags |= IDM_PDU_SET_STATSN | IDM_PDU_ADVANCE_STATSN;
2558	/* Any other field in resp to be set? */
2559	iscsit_pdu_tx(resp);
2560	idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
2561}
2562
2563static void
2564iscsit_pdu_op_login_cmd(iscsit_conn_t	*ict, idm_pdu_t *rx_pdu)
2565{
2566
2567	/*
2568	 * Submit PDU to login state machine.  State machine will free the
2569	 * PDU.
2570	 */
2571	iscsit_login_sm_event(ict, ILE_LOGIN_RCV, rx_pdu);
2572}
2573
2574void
2575iscsit_pdu_op_logout_cmd(iscsit_conn_t	*ict, idm_pdu_t *rx_pdu)
2576{
2577	iscsi_logout_hdr_t 	*logout_req =
2578	    (iscsi_logout_hdr_t *)rx_pdu->isp_hdr;
2579	iscsi_logout_rsp_hdr_t	*logout_rsp;
2580	idm_pdu_t *resp;
2581
2582	/* Allocate a PDU to respond */
2583	resp = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0);
2584	idm_pdu_init(resp, ict->ict_ic, NULL, NULL);
2585	/*
2586	 * The StatSN is to be sent to the initiator,
2587	 * it is not required to increment the number
2588	 * as the connection is terminating.
2589	 */
2590	resp->isp_flags |= IDM_PDU_SET_STATSN;
2591	/*
2592	 * Logout results in the immediate termination of all tasks except
2593	 * if the logout reason is ISCSI_LOGOUT_REASON_RECOVERY.  The
2594	 * connection state machine will drive this task cleanup automatically
2595	 * so we don't need to handle that here.
2596	 */
2597	logout_rsp = (iscsi_logout_rsp_hdr_t *)resp->isp_hdr;
2598	bzero(logout_rsp, sizeof (*logout_rsp));
2599	logout_rsp->opcode = ISCSI_OP_LOGOUT_RSP;
2600	logout_rsp->flags = ISCSI_FLAG_FINAL;
2601	logout_rsp->itt = logout_req->itt;
2602	if ((logout_req->flags & ISCSI_FLAG_LOGOUT_REASON_MASK) >
2603	    ISCSI_LOGOUT_REASON_RECOVERY) {
2604		logout_rsp->response = ISCSI_LOGOUT_RECOVERY_UNSUPPORTED;
2605	} else {
2606		logout_rsp->response = ISCSI_LOGOUT_SUCCESS;
2607	}
2608
2609	iscsit_pdu_tx(resp);
2610	idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
2611}
2612
2613/*
2614 * Calculate the number of outstanding commands we can process
2615 */
2616int
2617iscsit_cmd_window()
2618{
2619	/*
2620	 * Instead of using a pre-defined constant for the command window,
2621	 * it should be made confiurable and dynamic. With MC/S, sequence
2622	 * numbers will be used up at a much faster rate than with SC/S.
2623	 */
2624	return	(ISCSIT_MAX_WINDOW);
2625}
2626
2627/*
2628 * Set local registers based on incoming PDU
2629 */
2630void
2631iscsit_set_cmdsn(iscsit_conn_t *ict, idm_pdu_t *rx_pdu)
2632{
2633	iscsit_sess_t *ist;
2634	iscsi_scsi_cmd_hdr_t *req;
2635
2636	ist = ict->ict_sess;
2637
2638	req = (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr;
2639	if (req->opcode & ISCSI_OP_IMMEDIATE) {
2640		/* no cmdsn increment for immediate PDUs */
2641		return;
2642	}
2643
2644	/* Ensure that the ExpCmdSN advances in an orderly manner */
2645	mutex_enter(&ist->ist_sn_mutex);
2646	ist->ist_expcmdsn = ntohl(req->cmdsn) + 1;
2647	ist->ist_maxcmdsn = ntohl(req->cmdsn) + iscsit_cmd_window();
2648	mutex_exit(&ist->ist_sn_mutex);
2649}
2650
2651/*
2652 * Wrapper funtion, calls iscsi_calc_rspsn and idm_pdu_tx
2653 */
2654void
2655iscsit_pdu_tx(idm_pdu_t *pdu)
2656{
2657	iscsit_conn_t *ict = pdu->isp_ic->ic_handle;
2658	iscsi_scsi_rsp_hdr_t *rsp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr;
2659	iscsit_sess_t *ist = ict->ict_sess;
2660
2661	/*
2662	 * The command sequence numbers are session-wide and must stay
2663	 * consistent across the transfer, so protect the cmdsn with a
2664	 * mutex lock on the session. The status sequence number will
2665	 * be updated just before the transport layer transmits the PDU.
2666	 */
2667
2668	mutex_enter(&ict->ict_sess->ist_sn_mutex);
2669	/* Set ExpCmdSN and MaxCmdSN */
2670	rsp->maxcmdsn = htonl(ist->ist_maxcmdsn);
2671	rsp->expcmdsn = htonl(ist->ist_expcmdsn);
2672	idm_pdu_tx(pdu);
2673	mutex_exit(&ict->ict_sess->ist_sn_mutex);
2674}
2675
2676/*
2677 * Internal functions
2678 */
2679
2680void
2681iscsit_send_async_event(iscsit_conn_t *ict, uint8_t event)
2682{
2683	idm_pdu_t		*abt;
2684	iscsi_async_evt_hdr_t	*async_abt;
2685
2686	/*
2687	 * Get a PDU to build the abort request.
2688	 */
2689	abt = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0);
2690	if (abt == NULL) {
2691		idm_conn_event(ict->ict_ic, CE_TRANSPORT_FAIL, NULL);
2692		return;
2693	}
2694
2695	/*
2696	 * A asynchronous message is sent by the target to request a logout.
2697	 * The StatSN for the connection is advanced after the PDU is sent
2698	 * to allow for initiator and target state synchronization.
2699	 */
2700	idm_pdu_init(abt, ict->ict_ic, NULL, NULL);
2701	abt->isp_datalen = 0;
2702	abt->isp_flags |= IDM_PDU_SET_STATSN | IDM_PDU_ADVANCE_STATSN;
2703
2704	async_abt = (iscsi_async_evt_hdr_t *)abt->isp_hdr;
2705	bzero(async_abt, sizeof (*async_abt));
2706	async_abt->opcode = ISCSI_OP_ASYNC_EVENT;
2707	async_abt->async_event = event;
2708	async_abt->flags = ISCSI_FLAG_FINAL;
2709	async_abt->rsvd4[0] = 0xff;
2710	async_abt->rsvd4[1] = 0xff;
2711	async_abt->rsvd4[2] = 0xff;
2712	async_abt->rsvd4[3] = 0xff;
2713
2714	switch (event) {
2715	case ISCSI_ASYNC_EVENT_REQUEST_LOGOUT:
2716		async_abt->param3 = htons(IDM_LOGOUT_SECONDS);
2717		break;
2718	case ISCSI_ASYNC_EVENT_SCSI_EVENT:
2719	case ISCSI_ASYNC_EVENT_DROPPING_CONNECTION:
2720	case ISCSI_ASYNC_EVENT_DROPPING_ALL_CONNECTIONS:
2721	case ISCSI_ASYNC_EVENT_PARAM_NEGOTIATION:
2722	default:
2723		ASSERT(0);
2724	}
2725
2726	iscsit_pdu_tx(abt);
2727}
2728
2729void
2730iscsit_send_reject(iscsit_conn_t *ict, idm_pdu_t *rejected_pdu, uint8_t reason)
2731{
2732	idm_pdu_t		*reject_pdu;
2733	iscsi_reject_rsp_hdr_t	*reject;
2734
2735	/*
2736	 * Get a PDU to build the abort request.
2737	 */
2738	reject_pdu = idm_pdu_alloc(sizeof (iscsi_hdr_t),
2739	    rejected_pdu->isp_hdrlen);
2740	if (reject_pdu == NULL) {
2741		idm_conn_event(ict->ict_ic, CE_TRANSPORT_FAIL, NULL);
2742		return;
2743	}
2744	idm_pdu_init(reject_pdu, ict->ict_ic, NULL, NULL);
2745	/* StatSN is advanced after a Reject PDU */
2746	reject_pdu->isp_flags |= IDM_PDU_SET_STATSN | IDM_PDU_ADVANCE_STATSN;
2747	reject_pdu->isp_datalen = rejected_pdu->isp_hdrlen;
2748	bcopy(rejected_pdu->isp_hdr, reject_pdu->isp_data,
2749	    rejected_pdu->isp_hdrlen);
2750
2751	reject = (iscsi_reject_rsp_hdr_t *)reject_pdu->isp_hdr;
2752	bzero(reject, sizeof (*reject));
2753	reject->opcode = ISCSI_OP_REJECT_MSG;
2754	reject->reason = reason;
2755	reject->flags = ISCSI_FLAG_FINAL;
2756	hton24(reject->dlength, rejected_pdu->isp_hdrlen);
2757	reject->must_be_ff[0] = 0xff;
2758	reject->must_be_ff[1] = 0xff;
2759	reject->must_be_ff[2] = 0xff;
2760	reject->must_be_ff[3] = 0xff;
2761
2762	iscsit_pdu_tx(reject_pdu);
2763}
2764
2765
2766static iscsit_task_t *
2767iscsit_task_alloc(iscsit_conn_t *ict)
2768{
2769	iscsit_task_t *itask;
2770	iscsit_buf_t *immed_ibuf;
2771
2772	/*
2773	 * Possible items to pre-alloc if we cache iscsit_task_t's:
2774	 *
2775	 * Status PDU w/ sense buffer
2776	 * stmf_data_buf_t for immediate data
2777	 */
2778	itask = kmem_alloc(sizeof (iscsit_task_t) + sizeof (iscsit_buf_t) +
2779	    sizeof (stmf_data_buf_t), KM_NOSLEEP);
2780	if (itask != NULL) {
2781		mutex_init(&itask->it_mutex, NULL, MUTEX_DRIVER, NULL);
2782		itask->it_aborted = itask->it_stmf_abort =
2783		    itask->it_tm_task = 0;
2784
2785		immed_ibuf = (iscsit_buf_t *)(itask + 1);
2786		bzero(immed_ibuf, sizeof (*immed_ibuf));
2787		immed_ibuf->ibuf_is_immed = B_TRUE;
2788		immed_ibuf->ibuf_stmf_buf = (stmf_data_buf_t *)(immed_ibuf + 1);
2789
2790		bzero(immed_ibuf->ibuf_stmf_buf, sizeof (stmf_data_buf_t));
2791		immed_ibuf->ibuf_stmf_buf->db_port_private = immed_ibuf;
2792		immed_ibuf->ibuf_stmf_buf->db_sglist_length = 1;
2793		immed_ibuf->ibuf_stmf_buf->db_flags = DB_DIRECTION_FROM_RPORT |
2794		    DB_DONT_CACHE;
2795		itask->it_immed_data = immed_ibuf;
2796		itask->it_idm_task = idm_task_alloc(ict->ict_ic);
2797		if (itask->it_idm_task != NULL) {
2798			itask->it_idm_task->idt_private = itask;
2799			itask->it_ict = ict;
2800			itask->it_ttt = itask->it_idm_task->idt_tt;
2801			return (itask);
2802		} else {
2803			kmem_free(itask, sizeof (iscsit_task_t) +
2804			    sizeof (iscsit_buf_t) + sizeof (stmf_data_buf_t));
2805		}
2806	}
2807
2808	return (NULL);
2809}
2810
2811static void
2812iscsit_task_free(iscsit_task_t *itask)
2813{
2814	idm_task_free(itask->it_idm_task);
2815	mutex_destroy(&itask->it_mutex);
2816	kmem_free(itask, sizeof (iscsit_task_t) +
2817	    sizeof (iscsit_buf_t) + sizeof (stmf_data_buf_t));
2818}
2819
2820static iscsit_task_t *
2821iscsit_tm_task_alloc(iscsit_conn_t *ict)
2822{
2823	iscsit_task_t *itask;
2824
2825	itask = kmem_zalloc(sizeof (iscsit_task_t), KM_NOSLEEP);
2826	if (itask != NULL) {
2827		idm_conn_hold(ict->ict_ic);
2828		mutex_init(&itask->it_mutex, NULL, MUTEX_DRIVER, NULL);
2829		itask->it_aborted = itask->it_stmf_abort =
2830		    itask->it_tm_responded = 0;
2831		itask->it_tm_pdu = NULL;
2832		itask->it_tm_task = 1;
2833		itask->it_ict = ict;
2834	}
2835
2836	return (itask);
2837}
2838
2839static void
2840iscsit_tm_task_free(iscsit_task_t *itask)
2841{
2842	/*
2843	 * If we responded then the call to idm_pdu_complete will free the
2844	 * PDU.  Otherwise we got aborted before the TM function could
2845	 * complete and we need to free the PDU explicitly.
2846	 */
2847	if (itask->it_tm_pdu != NULL && !itask->it_tm_responded)
2848		idm_pdu_free(itask->it_tm_pdu);
2849	idm_conn_rele(itask->it_ict->ict_ic);
2850	mutex_destroy(&itask->it_mutex);
2851	kmem_free(itask, sizeof (iscsit_task_t));
2852}
2853
2854static idm_status_t
2855iscsit_task_start(iscsit_task_t *itask)
2856{
2857	iscsit_sess_t *ist = itask->it_ict->ict_sess;
2858	avl_index_t		where;
2859
2860	/*
2861	 * Sanity check the ITT and ensure that this task does not already
2862	 * exist.  If not then add the task to the session task list.
2863	 */
2864	mutex_enter(&ist->ist_mutex);
2865	mutex_enter(&itask->it_mutex);
2866	itask->it_active = 1;
2867	if (avl_find(&ist->ist_task_list, itask, &where) == NULL) {
2868		/* New task, add to AVL */
2869		avl_insert(&ist->ist_task_list, itask, where);
2870		mutex_exit(&itask->it_mutex);
2871		mutex_exit(&ist->ist_mutex);
2872		return (IDM_STATUS_SUCCESS);
2873	}
2874	mutex_exit(&itask->it_mutex);
2875	mutex_exit(&ist->ist_mutex);
2876
2877	return (IDM_STATUS_REJECT);
2878}
2879
2880static void
2881iscsit_task_done(iscsit_task_t *itask)
2882{
2883	iscsit_sess_t *ist = itask->it_ict->ict_sess;
2884
2885	mutex_enter(&ist->ist_mutex);
2886	mutex_enter(&itask->it_mutex);
2887	if (itask->it_active) {
2888		avl_remove(&ist->ist_task_list, itask);
2889		itask->it_active = 0;
2890	}
2891	mutex_exit(&itask->it_mutex);
2892	mutex_exit(&ist->ist_mutex);
2893}
2894
2895/*
2896 * iscsit status PDU cache
2897 */
2898
2899/*ARGSUSED*/
2900static int
2901iscsit_status_pdu_constructor(void *pdu_void, void *arg, int flags)
2902{
2903	idm_pdu_t *pdu = pdu_void;
2904	iscsi_scsi_rsp_hdr_t *rsp;
2905
2906	bzero(pdu, sizeof (idm_pdu_t));
2907	pdu->isp_callback = iscsit_send_good_status_done;
2908	pdu->isp_magic = IDM_PDU_MAGIC;
2909	pdu->isp_hdr = (iscsi_hdr_t *)(pdu + 1); /* Ptr arithmetic */
2910	pdu->isp_hdrlen = sizeof (iscsi_hdr_t);
2911
2912	/* Setup status response */
2913	rsp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr;
2914	bzero(rsp, sizeof (*rsp));
2915	rsp->opcode = ISCSI_OP_SCSI_RSP;
2916	rsp->flags = ISCSI_FLAG_FINAL;
2917	rsp->response = ISCSI_STATUS_CMD_COMPLETED;
2918
2919	return (0);
2920}
2921
2922/*
2923 * iscsit private data handler
2924 */
2925
2926/*ARGSUSED*/
2927static void
2928iscsit_pp_cb(struct stmf_port_provider *pp, int cmd, void *arg, uint32_t flags)
2929{
2930	it_config_t		*cfg;
2931	nvlist_t		*nvl;
2932	iscsit_service_enabled_t	old_state;
2933
2934	if ((cmd != STMF_PROVIDER_DATA_UPDATED) || (arg == NULL)) {
2935		return;
2936	}
2937
2938	nvl = (nvlist_t *)arg;
2939
2940	/* Translate nvlist */
2941	if (it_nv_to_config(nvl, &cfg) != 0) {
2942		cmn_err(CE_WARN, "Configuration is invalid");
2943		return;
2944	}
2945
2946	/* Check that no iSCSI ioctl is currently running */
2947	mutex_enter(&iscsit_global.global_state_mutex);
2948	old_state = iscsit_global.global_svc_state;
2949	switch (iscsit_global.global_svc_state) {
2950	case ISE_ENABLED:
2951	case ISE_DISABLED:
2952		iscsit_global.global_svc_state = ISE_BUSY;
2953		break;
2954	case ISE_ENABLING:
2955		/*
2956		 * It is OK for the iscsit_pp_cb to be called from inside of
2957		 * an iSCSI ioctl only if we are currently executing inside
2958		 * of stmf_register_port_provider.
2959		 */
2960		ASSERT((flags & STMF_PCB_PREG_COMPLETE) != 0);
2961		break;
2962	default:
2963		cmn_err(CE_WARN, "iscsit_pp_cb called when global_svc_state"
2964		    " is not ENABLED(0x%x) -- ignoring",
2965		    iscsit_global.global_svc_state);
2966		mutex_exit(&iscsit_global.global_state_mutex);
2967		it_config_free_cmn(cfg);
2968		return;
2969	}
2970	mutex_exit(&iscsit_global.global_state_mutex);
2971
2972	/* Update config */
2973	(void) iscsit_config_merge(cfg);
2974
2975	it_config_free_cmn(cfg);
2976
2977	/* Restore old iSCSI driver global state */
2978	mutex_enter(&iscsit_global.global_state_mutex);
2979	ASSERT(iscsit_global.global_svc_state == ISE_BUSY ||
2980	    iscsit_global.global_svc_state == ISE_ENABLING);
2981	iscsit_global.global_svc_state = old_state;
2982	mutex_exit(&iscsit_global.global_state_mutex);
2983}
2984
2985
2986static it_cfg_status_t
2987iscsit_config_merge(it_config_t *in_cfg)
2988{
2989	it_cfg_status_t	status;
2990	it_config_t	*cfg;
2991	it_config_t	tmp_cfg;
2992	list_t		tpg_del_list;
2993
2994	if (in_cfg) {
2995		cfg = in_cfg;
2996	} else {
2997		/* Make empty config */
2998		bzero(&tmp_cfg, sizeof (tmp_cfg));
2999		cfg = &tmp_cfg;
3000	}
3001
3002	list_create(&tpg_del_list,  sizeof (iscsit_tpg_t),
3003	    offsetof(iscsit_tpg_t, tpg_delete_ln));
3004
3005	/*
3006	 * Update targets, initiator contexts, target portal groups,
3007	 * and iSNS client
3008	 */
3009	ISCSIT_GLOBAL_LOCK(RW_WRITER);
3010	if (((status = iscsit_config_merge_tpg(cfg, &tpg_del_list))
3011	    != 0) ||
3012	    ((status = iscsit_config_merge_tgt(cfg)) != 0) ||
3013	    ((status = iscsit_config_merge_ini(cfg)) != 0) ||
3014	    ((status = isnst_config_merge(cfg)) != 0)) {
3015		ISCSIT_GLOBAL_UNLOCK();
3016		return (status);
3017	}
3018
3019	/* Update other global config parameters */
3020	if (iscsit_global.global_props) {
3021		nvlist_free(iscsit_global.global_props);
3022		iscsit_global.global_props = NULL;
3023	}
3024	if (in_cfg) {
3025		(void) nvlist_dup(cfg->config_global_properties,
3026		    &iscsit_global.global_props, KM_SLEEP);
3027	}
3028	ISCSIT_GLOBAL_UNLOCK();
3029
3030	iscsit_config_destroy_tpgs(&tpg_del_list);
3031
3032	list_destroy(&tpg_del_list);
3033
3034	return (ITCFG_SUCCESS);
3035}
3036
3037/*
3038 * iscsit_sna_lt[e]
3039 *
3040 * Compare serial numbers using serial number arithmetic as defined in
3041 * RFC 1982.
3042 *
3043 * NOTE: This code is duplicated in the isns server. It ought to be common.
3044 */
3045
3046static int
3047iscsit_sna_lt(uint32_t sn1, uint32_t sn2)
3048{
3049	return ((sn1 != sn2) &&
3050	    (((sn1 < sn2) && ((sn2 - sn1) < ISCSIT_SNA32_CHECK)) ||
3051	    ((sn1 > sn2) && ((sn1 - sn2) > ISCSIT_SNA32_CHECK))));
3052}
3053
3054static int
3055iscsit_sna_lte(uint32_t sn1, uint32_t sn2)
3056{
3057	return ((sn1 == sn2) ||
3058	    (((sn1 < sn2) && ((sn2 - sn1) < ISCSIT_SNA32_CHECK)) ||
3059	    ((sn1 > sn2) && ((sn1 - sn2) > ISCSIT_SNA32_CHECK))));
3060}
3061
3062
3063static boolean_t
3064iscsit_cmdsn_in_window(iscsit_conn_t *ict, uint32_t cmdsn)
3065{
3066	iscsit_sess_t	*ist = ict->ict_sess;
3067	int		rval = B_TRUE;
3068
3069	ist = ict->ict_sess;
3070
3071	mutex_enter(&ist->ist_sn_mutex);
3072
3073	/*
3074	 * If cmdsn is less than ist_expcmdsn - iscsit_cmd_window() or
3075	 * greater than ist_expcmdsn, it's not in the window.
3076	 */
3077
3078	if (iscsit_sna_lt(cmdsn, (ist->ist_expcmdsn - iscsit_cmd_window())) ||
3079	    !iscsit_sna_lte(cmdsn, ist->ist_expcmdsn)) {
3080		rval = B_FALSE;
3081	}
3082
3083	mutex_exit(&ist->ist_sn_mutex);
3084
3085	return (rval);
3086}
3087
3088/*
3089 * iscsit_check_cmdsn_and_queue
3090 *
3091 * Independent of the order in which the iSCSI target receives non-immediate
3092 * command PDU across the entire session and any multiple connections within
3093 * the session, the target must deliver the commands to the SCSI layer in
3094 * CmdSN order. So out-of-order non-immediate commands are queued up on a
3095 * session-wide wait queue. Duplicate commands are ignored.
3096 *
3097 */
3098static int
3099iscsit_check_cmdsn_and_queue(idm_pdu_t *rx_pdu)
3100{
3101	idm_conn_t		*ic = rx_pdu->isp_ic;
3102	iscsit_conn_t		*ict = ic->ic_handle;
3103	iscsit_sess_t		*ist = ict->ict_sess;
3104	iscsi_scsi_cmd_hdr_t	*hdr = (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr;
3105
3106	mutex_enter(&ist->ist_sn_mutex);
3107	if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
3108		/* do not queue, handle it immediately */
3109		DTRACE_PROBE2(immediate__cmd, iscsit_sess_t *, ist,
3110		    idm_pdu_t *, rx_pdu);
3111		mutex_exit(&ist->ist_sn_mutex);
3112		return (ISCSIT_CMDSN_EQ_EXPCMDSN);
3113	}
3114	if (iscsit_sna_lt(ist->ist_expcmdsn, ntohl(hdr->cmdsn))) {
3115		/*
3116		 * Out-of-order commands (cmdSN higher than ExpCmdSN)
3117		 * are staged on a fixed-size circular buffer until
3118		 * the missing command is delivered to the SCSI layer.
3119		 * Irrespective of the order of insertion into the
3120		 * staging queue, the commands are processed out of the
3121		 * queue in cmdSN order only.
3122		 */
3123		rx_pdu->isp_queue_time = ddi_get_time();
3124		iscsit_add_pdu_to_queue(ist, rx_pdu);
3125		mutex_exit(&ist->ist_sn_mutex);
3126		return (ISCSIT_CMDSN_GT_EXPCMDSN);
3127	} else if (iscsit_sna_lt(ntohl(hdr->cmdsn), ist->ist_expcmdsn)) {
3128		DTRACE_PROBE3(cmdsn__lt__expcmdsn, iscsit_sess_t *, ist,
3129		    iscsit_conn_t *, ict, idm_pdu_t *, rx_pdu);
3130		mutex_exit(&ist->ist_sn_mutex);
3131		return (ISCSIT_CMDSN_LT_EXPCMDSN);
3132	} else {
3133		mutex_exit(&ist->ist_sn_mutex);
3134		return (ISCSIT_CMDSN_EQ_EXPCMDSN);
3135	}
3136}
3137
3138/*
3139 * iscsit_add_pdu_to_queue() adds PDUs into the array indexed by
3140 * their cmdsn value. The length of the array is kept above the
3141 * maximum window size. The window keeps the cmdsn within a range
3142 * such that there are no collisons. e.g. the assumption is that
3143 * the windowing checks make it impossible to receive PDUs that
3144 * index into the same location in the array.
3145 */
3146static void
3147iscsit_add_pdu_to_queue(iscsit_sess_t *ist, idm_pdu_t *rx_pdu)
3148{
3149	iscsit_cbuf_t	*cbuf	= ist->ist_rxpdu_queue;
3150	iscsit_conn_t	*ict 	= rx_pdu->isp_ic->ic_handle;
3151	uint32_t	cmdsn	=
3152	    ((iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr)->cmdsn;
3153	uint32_t	index;
3154
3155	ASSERT(MUTEX_HELD(&ist->ist_sn_mutex));
3156	/*
3157	 * If the connection is being torn down, then
3158	 * don't add the PDU to the staging queue
3159	 */
3160	mutex_enter(&ict->ict_mutex);
3161	if (ict->ict_lost) {
3162		mutex_exit(&ict->ict_mutex);
3163		idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL);
3164		return;
3165	}
3166	iscsit_conn_dispatch_hold(ict);
3167	mutex_exit(&ict->ict_mutex);
3168
3169	index = ntohl(cmdsn) % ISCSIT_RXPDU_QUEUE_LEN;
3170	ASSERT(cbuf->cb_buffer[index] == NULL);
3171	cbuf->cb_buffer[index] = rx_pdu;
3172	cbuf->cb_num_elems++;
3173}
3174
3175static idm_pdu_t *
3176iscsit_remove_pdu_from_queue(iscsit_sess_t *ist, uint32_t cmdsn)
3177{
3178	iscsit_cbuf_t	*cbuf	= ist->ist_rxpdu_queue;
3179	idm_pdu_t	*pdu	= NULL;
3180	uint32_t	index;
3181
3182	ASSERT(MUTEX_HELD(&ist->ist_sn_mutex));
3183	index = cmdsn % ISCSIT_RXPDU_QUEUE_LEN;
3184	if ((pdu = cbuf->cb_buffer[index]) != NULL) {
3185		ASSERT(cmdsn ==
3186		    ntohl(((iscsi_scsi_cmd_hdr_t *)pdu->isp_hdr)->cmdsn));
3187		cbuf->cb_buffer[index] = NULL;
3188		cbuf->cb_num_elems--;
3189		return (pdu);
3190	}
3191	return (NULL);
3192}
3193
3194/*
3195 * iscsit_process_pdu_in_queue() finds the next pdu in sequence
3196 * and posts it to the SCSI layer
3197 */
3198static void
3199iscsit_process_pdu_in_queue(iscsit_sess_t *ist)
3200{
3201	iscsit_cbuf_t	*cbuf	= ist->ist_rxpdu_queue;
3202	idm_pdu_t	*pdu = NULL;
3203	uint32_t	expcmdsn;
3204
3205	for (;;) {
3206		mutex_enter(&ist->ist_sn_mutex);
3207		if (cbuf->cb_num_elems == 0) {
3208			mutex_exit(&ist->ist_sn_mutex);
3209			break;
3210		}
3211		expcmdsn = ist->ist_expcmdsn;
3212		if ((pdu = iscsit_remove_pdu_from_queue(ist, expcmdsn))
3213		    == NULL) {
3214			mutex_exit(&ist->ist_sn_mutex);
3215			break;
3216		}
3217		mutex_exit(&ist->ist_sn_mutex);
3218		iscsit_post_staged_pdu(pdu);
3219	}
3220}
3221
3222static void
3223iscsit_post_staged_pdu(idm_pdu_t *rx_pdu)
3224{
3225	iscsit_conn_t	*ict	= rx_pdu->isp_ic->ic_handle;
3226
3227	/* Post the PDU to the SCSI layer */
3228	switch (IDM_PDU_OPCODE(rx_pdu)) {
3229	case ISCSI_OP_NOOP_OUT:
3230		iscsit_set_cmdsn(ict, rx_pdu);
3231		iscsit_pdu_op_noop(ict, rx_pdu);
3232		break;
3233	case ISCSI_OP_TEXT_CMD:
3234		iscsit_set_cmdsn(ict, rx_pdu);
3235		iscsit_pdu_op_text_cmd(ict, rx_pdu);
3236		break;
3237	case ISCSI_OP_SCSI_TASK_MGT_MSG:
3238		iscsit_set_cmdsn(ict, rx_pdu);
3239		iscsit_op_scsi_task_mgmt(ict, rx_pdu);
3240		break;
3241	case ISCSI_OP_SCSI_CMD:
3242		/* cmdSN will be incremented after creating itask */
3243		iscsit_post_scsi_cmd(rx_pdu->isp_ic, rx_pdu);
3244		break;
3245	case ISCSI_OP_LOGOUT_CMD:
3246		iscsit_set_cmdsn(ict, rx_pdu);
3247		iscsit_pdu_op_logout_cmd(ict, rx_pdu);
3248		break;
3249	default:
3250		/* No other PDUs should be placed on the queue */
3251		ASSERT(0);
3252	}
3253	iscsit_conn_dispatch_rele(ict); /* release hold on the conn */
3254}
3255
3256/* ARGSUSED */
3257void
3258iscsit_rxpdu_queue_monitor_start(void)
3259{
3260	mutex_enter(&iscsit_rxpdu_queue_monitor_mutex);
3261	if (iscsit_rxpdu_queue_monitor_thr_running) {
3262		mutex_exit(&iscsit_rxpdu_queue_monitor_mutex);
3263		return;
3264	}
3265	iscsit_rxpdu_queue_monitor_thr_id =
3266	    thread_create(NULL, 0, iscsit_rxpdu_queue_monitor, NULL,
3267	    0, &p0, TS_RUN, minclsyspri);
3268	while (!iscsit_rxpdu_queue_monitor_thr_running) {
3269		cv_wait(&iscsit_rxpdu_queue_monitor_cv,
3270		    &iscsit_rxpdu_queue_monitor_mutex);
3271	}
3272	mutex_exit(&iscsit_rxpdu_queue_monitor_mutex);
3273
3274}
3275
3276/* ARGSUSED */
3277void
3278iscsit_rxpdu_queue_monitor_stop(void)
3279{
3280	mutex_enter(&iscsit_rxpdu_queue_monitor_mutex);
3281	if (iscsit_rxpdu_queue_monitor_thr_running) {
3282		iscsit_rxpdu_queue_monitor_thr_running = B_FALSE;
3283		cv_signal(&iscsit_rxpdu_queue_monitor_cv);
3284		mutex_exit(&iscsit_rxpdu_queue_monitor_mutex);
3285
3286		thread_join(iscsit_rxpdu_queue_monitor_thr_did);
3287		return;
3288	}
3289	mutex_exit(&iscsit_rxpdu_queue_monitor_mutex);
3290}
3291
3292/*
3293 * A separate thread is used to scan the staging queue on all the
3294 * sessions, If a delayed PDU does not arrive within a timeout, the
3295 * target will advance to the staged PDU that is next in sequence
3296 * and exceeded the threshold wait time. It is up to the initiator
3297 * to note that the target has not acknowledged a particular cmdsn
3298 * and take appropriate action.
3299 */
3300/* ARGSUSED */
3301static void
3302iscsit_rxpdu_queue_monitor(void *arg)
3303{
3304	iscsit_tgt_t	*tgt;
3305	iscsit_sess_t	*ist;
3306
3307	mutex_enter(&iscsit_rxpdu_queue_monitor_mutex);
3308	iscsit_rxpdu_queue_monitor_thr_did = curthread->t_did;
3309	iscsit_rxpdu_queue_monitor_thr_running = B_TRUE;
3310	cv_signal(&iscsit_rxpdu_queue_monitor_cv);
3311
3312	while (iscsit_rxpdu_queue_monitor_thr_running) {
3313		ISCSIT_GLOBAL_LOCK(RW_READER);
3314		for (tgt = avl_first(&iscsit_global.global_target_list);
3315		    tgt != NULL;
3316		    tgt = AVL_NEXT(&iscsit_global.global_target_list, tgt)) {
3317			mutex_enter(&tgt->target_mutex);
3318			for (ist = avl_first(&tgt->target_sess_list);
3319			    ist != NULL;
3320			    ist = AVL_NEXT(&tgt->target_sess_list, ist)) {
3321
3322				iscsit_rxpdu_queue_monitor_session(ist);
3323			}
3324			mutex_exit(&tgt->target_mutex);
3325		}
3326		ISCSIT_GLOBAL_UNLOCK();
3327		if (iscsit_rxpdu_queue_monitor_thr_running == B_FALSE) {
3328			break;
3329		}
3330		(void) cv_reltimedwait(&iscsit_rxpdu_queue_monitor_cv,
3331		    &iscsit_rxpdu_queue_monitor_mutex,
3332		    ISCSIT_RXPDU_QUEUE_MONITOR_INTERVAL * drv_usectohz(1000000),
3333		    TR_CLOCK_TICK);
3334	}
3335	mutex_exit(&iscsit_rxpdu_queue_monitor_mutex);
3336	thread_exit();
3337}
3338
3339static void
3340iscsit_rxpdu_queue_monitor_session(iscsit_sess_t *ist)
3341{
3342	iscsit_cbuf_t	*cbuf	= ist->ist_rxpdu_queue;
3343	idm_pdu_t	*next_pdu = NULL;
3344	uint32_t	index, next_cmdsn, i;
3345
3346	/*
3347	 * Assume that all PDUs in the staging queue have a cmdsn >= expcmdsn.
3348	 * Starting with the expcmdsn, iterate over the staged PDUs to find
3349	 * the next PDU with a wait time greater than the threshold. If found
3350	 * advance the staged PDU to the SCSI layer, skipping over the missing
3351	 * PDU(s) to get past the hole in the command sequence. It is up to
3352	 * the initiator to note that the target has not acknowledged a cmdsn
3353	 * and take appropriate action.
3354	 *
3355	 * Since the PDU(s) arrive in any random order, it is possible that
3356	 * that the actual wait time for a particular PDU is much longer than
3357	 * the defined threshold. e.g. Consider a case where commands are sent
3358	 * over 4 different connections, and cmdsn = 1004 arrives first, then
3359	 * 1003, and 1002 and 1001 are lost due to a connection failure.
3360	 * So now 1003 is waiting for 1002 to be delivered, and although the
3361	 * wait time of 1004 > wait time of 1003, only 1003 will be considered
3362	 * by the monitor thread. 1004 will be automatically processed by
3363	 * iscsit_process_pdu_in_queue() once the scan is complete and the
3364	 * expcmdsn becomes current.
3365	 */
3366	mutex_enter(&ist->ist_sn_mutex);
3367	cbuf = ist->ist_rxpdu_queue;
3368	if (cbuf->cb_num_elems == 0) {
3369		mutex_exit(&ist->ist_sn_mutex);
3370		return;
3371	}
3372	for (next_pdu = NULL, i = 0; ; i++) {
3373		next_cmdsn = ist->ist_expcmdsn + i; /* start at expcmdsn */
3374		index = next_cmdsn % ISCSIT_RXPDU_QUEUE_LEN;
3375		if ((next_pdu = cbuf->cb_buffer[index]) != NULL) {
3376			/*
3377			 * If the PDU wait time has not exceeded threshold
3378			 * stop scanning the staging queue until the timer
3379			 * fires again
3380			 */
3381			if ((ddi_get_time() - next_pdu->isp_queue_time)
3382			    < rxpdu_queue_threshold) {
3383				mutex_exit(&ist->ist_sn_mutex);
3384				return;
3385			}
3386			/*
3387			 * Remove the next PDU from the queue and post it
3388			 * to the SCSI layer, skipping over the missing
3389			 * PDU. Stop scanning the staging queue until
3390			 * the monitor timer fires again
3391			 */
3392			(void) iscsit_remove_pdu_from_queue(ist, next_cmdsn);
3393			mutex_exit(&ist->ist_sn_mutex);
3394			DTRACE_PROBE3(advanced__to__blocked__cmdsn,
3395			    iscsit_sess_t *, ist, idm_pdu_t *, next_pdu,
3396			    uint32_t, next_cmdsn);
3397			iscsit_post_staged_pdu(next_pdu);
3398			/* Deliver any subsequent PDUs immediately */
3399			iscsit_process_pdu_in_queue(ist);
3400			return;
3401		}
3402		/*
3403		 * Skipping over i PDUs, e.g. a case where commands 1001 and
3404		 * 1002 are lost in the network, skip over both and post 1003
3405		 * expcmdsn then becomes 1004 at the end of the scan.
3406		 */
3407		DTRACE_PROBE2(skipping__over__cmdsn, iscsit_sess_t *, ist,
3408		    uint32_t, next_cmdsn);
3409	}
3410	/*
3411	 * following the assumption, staged cmdsn >= expcmdsn, this statement
3412	 * is never reached.
3413	 */
3414}
3415