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