xref: /titanic_41/usr/src/uts/common/io/comstar/stmf/stmf.c (revision 32c22d57860198538fb6b8f261cb76ab26318d34)
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/conf.h>
26 #include <sys/file.h>
27 #include <sys/ddi.h>
28 #include <sys/sunddi.h>
29 #include <sys/modctl.h>
30 #include <sys/scsi/scsi.h>
31 #include <sys/scsi/impl/scsi_reset_notify.h>
32 #include <sys/disp.h>
33 #include <sys/byteorder.h>
34 #include <sys/atomic.h>
35 #include <sys/ethernet.h>
36 #include <sys/sdt.h>
37 #include <sys/nvpair.h>
38 #include <sys/zone.h>
39 #include <sys/id_space.h>
40 
41 #include <sys/stmf.h>
42 #include <sys/lpif.h>
43 #include <sys/portif.h>
44 #include <sys/stmf_ioctl.h>
45 #include <sys/pppt_ic_if.h>
46 
47 #include "stmf_impl.h"
48 #include "lun_map.h"
49 #include "stmf_state.h"
50 #include "stmf_stats.h"
51 
52 /*
53  * Lock order:
54  * stmf_state_lock --> ilport_lock/iss_lockp --> ilu_task_lock
55  */
56 
57 static uint64_t stmf_session_counter = 0;
58 static uint16_t stmf_rtpid_counter = 0;
59 /* start messages at 1 */
60 static uint64_t stmf_proxy_msg_id = 1;
61 #define	MSG_ID_TM_BIT	0x8000000000000000
62 
63 static int stmf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
64 static int stmf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
65 static int stmf_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
66 	void **result);
67 static int stmf_open(dev_t *devp, int flag, int otype, cred_t *credp);
68 static int stmf_close(dev_t dev, int flag, int otype, cred_t *credp);
69 static int stmf_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
70 	cred_t *credp, int *rval);
71 static int stmf_get_stmf_state(stmf_state_desc_t *std);
72 static int stmf_set_stmf_state(stmf_state_desc_t *std);
73 static void stmf_abort_task_offline(scsi_task_t *task, int offline_lu,
74     char *info);
75 static int stmf_set_alua_state(stmf_alua_state_desc_t *alua_state);
76 static void stmf_get_alua_state(stmf_alua_state_desc_t *alua_state);
77 
78 static void stmf_task_audit(stmf_i_scsi_task_t *itask,
79     task_audit_event_t te, uint32_t cmd_or_iof, stmf_data_buf_t *dbuf);
80 
81 stmf_xfer_data_t *stmf_prepare_tpgs_data(uint8_t ilu_alua);
82 void stmf_svc_init();
83 stmf_status_t stmf_svc_fini();
84 void stmf_svc(void *arg);
85 void stmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info);
86 void stmf_check_freetask();
87 void stmf_abort_target_reset(scsi_task_t *task);
88 stmf_status_t stmf_lun_reset_poll(stmf_lu_t *lu, struct scsi_task *task,
89 							int target_reset);
90 void stmf_target_reset_poll(struct scsi_task *task);
91 void stmf_handle_lun_reset(scsi_task_t *task);
92 void stmf_handle_target_reset(scsi_task_t *task);
93 void stmf_xd_to_dbuf(stmf_data_buf_t *dbuf, int set_rel_off);
94 int stmf_load_ppd_ioctl(stmf_ppioctl_data_t *ppi, uint64_t *ppi_token,
95     uint32_t *err_ret);
96 int stmf_delete_ppd_ioctl(stmf_ppioctl_data_t *ppi);
97 int stmf_get_ppd_ioctl(stmf_ppioctl_data_t *ppi, stmf_ppioctl_data_t *ppi_out,
98     uint32_t *err_ret);
99 void stmf_delete_ppd(stmf_pp_data_t *ppd);
100 void stmf_delete_all_ppds();
101 void stmf_trace_clear();
102 void stmf_worker_init();
103 stmf_status_t stmf_worker_fini();
104 void stmf_worker_mgmt();
105 void stmf_worker_task(void *arg);
106 static void stmf_task_lu_free(scsi_task_t *task, stmf_i_scsi_session_t *iss);
107 static stmf_status_t stmf_ic_lu_reg(stmf_ic_reg_dereg_lun_msg_t *msg,
108     uint32_t type);
109 static stmf_status_t stmf_ic_lu_dereg(stmf_ic_reg_dereg_lun_msg_t *msg);
110 static stmf_status_t stmf_ic_rx_scsi_status(stmf_ic_scsi_status_msg_t *msg);
111 static stmf_status_t stmf_ic_rx_status(stmf_ic_status_msg_t *msg);
112 static stmf_status_t stmf_ic_rx_scsi_data(stmf_ic_scsi_data_msg_t *msg);
113 void stmf_task_lu_killall(stmf_lu_t *lu, scsi_task_t *tm_task, stmf_status_t s);
114 
115 /* pppt modhandle */
116 ddi_modhandle_t pppt_mod;
117 
118 /* pppt modload imported functions */
119 stmf_ic_reg_port_msg_alloc_func_t ic_reg_port_msg_alloc;
120 stmf_ic_dereg_port_msg_alloc_func_t ic_dereg_port_msg_alloc;
121 stmf_ic_reg_lun_msg_alloc_func_t ic_reg_lun_msg_alloc;
122 stmf_ic_dereg_lun_msg_alloc_func_t ic_dereg_lun_msg_alloc;
123 stmf_ic_lun_active_msg_alloc_func_t ic_lun_active_msg_alloc;
124 stmf_ic_scsi_cmd_msg_alloc_func_t ic_scsi_cmd_msg_alloc;
125 stmf_ic_scsi_data_xfer_done_msg_alloc_func_t ic_scsi_data_xfer_done_msg_alloc;
126 stmf_ic_session_create_msg_alloc_func_t ic_session_reg_msg_alloc;
127 stmf_ic_session_destroy_msg_alloc_func_t ic_session_dereg_msg_alloc;
128 stmf_ic_tx_msg_func_t ic_tx_msg;
129 stmf_ic_msg_free_func_t ic_msg_free;
130 
131 static void stmf_itl_task_start(stmf_i_scsi_task_t *itask);
132 static void stmf_itl_lu_new_task(stmf_i_scsi_task_t *itask);
133 static void stmf_itl_task_done(stmf_i_scsi_task_t *itask);
134 
135 static void stmf_lport_xfer_start(stmf_i_scsi_task_t *itask,
136     stmf_data_buf_t *dbuf);
137 static void stmf_lport_xfer_done(stmf_i_scsi_task_t *itask,
138     stmf_data_buf_t *dbuf);
139 
140 static void stmf_update_kstat_lu_q(scsi_task_t *, void());
141 static void stmf_update_kstat_lport_q(scsi_task_t *, void());
142 static void stmf_update_kstat_lu_io(scsi_task_t *, stmf_data_buf_t *);
143 static void stmf_update_kstat_lport_io(scsi_task_t *, stmf_data_buf_t *);
144 
145 static int stmf_irport_compare(const void *void_irport1,
146     const void *void_irport2);
147 static stmf_i_remote_port_t *stmf_irport_create(scsi_devid_desc_t *rport_devid);
148 static void stmf_irport_destroy(stmf_i_remote_port_t *irport);
149 static stmf_i_remote_port_t *stmf_irport_register(
150     scsi_devid_desc_t *rport_devid);
151 static stmf_i_remote_port_t *stmf_irport_lookup_locked(
152     scsi_devid_desc_t *rport_devid);
153 static void stmf_irport_deregister(stmf_i_remote_port_t *irport);
154 
155 static void stmf_teardown_itl_kstats(stmf_i_itl_kstat_t *ks);
156 static void stmf_delete_itl_kstat_by_lport(char *);
157 static void stmf_delete_itl_kstat_by_guid(char *);
158 static int stmf_itl_kstat_compare(const void*, const void*);
159 static stmf_i_itl_kstat_t *stmf_itl_kstat_lookup(char *kstat_nm);
160 static stmf_i_itl_kstat_t *stmf_itl_kstat_create(stmf_itl_data_t *itl,
161     char *nm, scsi_devid_desc_t *lport, scsi_devid_desc_t *lun);
162 
163 extern struct mod_ops mod_driverops;
164 
165 /* =====[ Tunables ]===== */
166 /* Internal tracing */
167 volatile int	stmf_trace_on = 1;
168 volatile int	stmf_trace_buf_size = (1 * 1024 * 1024);
169 /*
170  * The reason default task timeout is 75 is because we want the
171  * host to timeout 1st and mostly host timeout is 60 seconds.
172  */
173 volatile int	stmf_default_task_timeout = 75;
174 /*
175  * Setting this to one means, you are responsible for config load and keeping
176  * things in sync with persistent database.
177  */
178 volatile int	stmf_allow_modunload = 0;
179 
180 volatile int stmf_max_nworkers = 256;
181 volatile int stmf_min_nworkers = 4;
182 volatile int stmf_worker_scale_down_delay = 20;
183 
184 /* === [ Debugging and fault injection ] === */
185 #ifdef	DEBUG
186 volatile int stmf_drop_task_counter = 0;
187 volatile int stmf_drop_buf_counter = 0;
188 
189 #endif
190 
191 stmf_state_t		stmf_state;
192 static stmf_lu_t	*dlun0;
193 
194 static uint8_t stmf_first_zero[] =
195 	{ 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 0xff };
196 static uint8_t stmf_first_one[] =
197 	{ 0xff, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
198 
199 static kmutex_t	trace_buf_lock;
200 static int	trace_buf_size;
201 static int	trace_buf_curndx;
202 caddr_t	stmf_trace_buf;
203 
204 static enum {
205 	STMF_WORKERS_DISABLED = 0,
206 	STMF_WORKERS_ENABLING,
207 	STMF_WORKERS_ENABLED
208 } stmf_workers_state = STMF_WORKERS_DISABLED;
209 static int stmf_i_max_nworkers;
210 static int stmf_i_min_nworkers;
211 static int stmf_nworkers_cur;		/* # of workers currently running */
212 static int stmf_nworkers_needed;	/* # of workers need to be running */
213 static int stmf_worker_sel_counter = 0;
214 static uint32_t stmf_cur_ntasks = 0;
215 static clock_t stmf_wm_last = 0;
216 /*
217  * This is equal to stmf_nworkers_cur while we are increasing # workers and
218  * stmf_nworkers_needed while we are decreasing the worker count.
219  */
220 static int stmf_nworkers_accepting_cmds;
221 static stmf_worker_t *stmf_workers = NULL;
222 static clock_t stmf_worker_mgmt_delay = 2;
223 static clock_t stmf_worker_scale_down_timer = 0;
224 static int stmf_worker_scale_down_qd = 0;
225 
226 static struct cb_ops stmf_cb_ops = {
227 	stmf_open,			/* open */
228 	stmf_close,			/* close */
229 	nodev,				/* strategy */
230 	nodev,				/* print */
231 	nodev,				/* dump */
232 	nodev,				/* read */
233 	nodev,				/* write */
234 	stmf_ioctl,			/* ioctl */
235 	nodev,				/* devmap */
236 	nodev,				/* mmap */
237 	nodev,				/* segmap */
238 	nochpoll,			/* chpoll */
239 	ddi_prop_op,			/* cb_prop_op */
240 	0,				/* streamtab */
241 	D_NEW | D_MP,			/* cb_flag */
242 	CB_REV,				/* rev */
243 	nodev,				/* aread */
244 	nodev				/* awrite */
245 };
246 
247 static struct dev_ops stmf_ops = {
248 	DEVO_REV,
249 	0,
250 	stmf_getinfo,
251 	nulldev,		/* identify */
252 	nulldev,		/* probe */
253 	stmf_attach,
254 	stmf_detach,
255 	nodev,			/* reset */
256 	&stmf_cb_ops,
257 	NULL,			/* bus_ops */
258 	NULL			/* power */
259 };
260 
261 #define	STMF_NAME		"COMSTAR STMF"
262 #define	STMF_MODULE_NAME	"stmf"
263 
264 static struct modldrv modldrv = {
265 	&mod_driverops,
266 	STMF_NAME,
267 	&stmf_ops
268 };
269 
270 static struct modlinkage modlinkage = {
271 	MODREV_1,
272 	&modldrv,
273 	NULL
274 };
275 
276 int
277 _init(void)
278 {
279 	int ret;
280 
281 	ret = mod_install(&modlinkage);
282 	if (ret)
283 		return (ret);
284 	stmf_trace_buf = kmem_zalloc(stmf_trace_buf_size, KM_SLEEP);
285 	trace_buf_size = stmf_trace_buf_size;
286 	trace_buf_curndx = 0;
287 	mutex_init(&trace_buf_lock, NULL, MUTEX_DRIVER, 0);
288 	bzero(&stmf_state, sizeof (stmf_state_t));
289 	/* STMF service is off by default */
290 	stmf_state.stmf_service_running = 0;
291 	mutex_init(&stmf_state.stmf_lock, NULL, MUTEX_DRIVER, NULL);
292 	cv_init(&stmf_state.stmf_cv, NULL, CV_DRIVER, NULL);
293 	stmf_session_counter = (uint64_t)ddi_get_lbolt();
294 	avl_create(&stmf_state.stmf_irportlist,
295 	    stmf_irport_compare, sizeof (stmf_i_remote_port_t),
296 	    offsetof(stmf_i_remote_port_t, irport_ln));
297 	stmf_state.stmf_ilport_inst_space =
298 	    id_space_create("lport-instances", 0, MAX_ILPORT);
299 	stmf_state.stmf_irport_inst_space =
300 	    id_space_create("rport-instances", 0, MAX_IRPORT);
301 	avl_create(&stmf_state.stmf_itl_kstat_list,
302 	    stmf_itl_kstat_compare, sizeof (stmf_i_itl_kstat_t),
303 	    offsetof(stmf_i_itl_kstat_t, iitl_kstat_ln));
304 	stmf_view_init();
305 	stmf_svc_init();
306 	stmf_dlun_init();
307 	return (ret);
308 }
309 
310 int
311 _fini(void)
312 {
313 	int ret;
314 	stmf_i_remote_port_t	*irport;
315 	stmf_i_itl_kstat_t	*ks_itl;
316 	void			*avl_dest_cookie = NULL;
317 
318 	if (stmf_state.stmf_service_running)
319 		return (EBUSY);
320 	if ((!stmf_allow_modunload) &&
321 	    (stmf_state.stmf_config_state != STMF_CONFIG_NONE)) {
322 		return (EBUSY);
323 	}
324 	if (stmf_state.stmf_nlps || stmf_state.stmf_npps) {
325 		return (EBUSY);
326 	}
327 	if (stmf_dlun_fini() != STMF_SUCCESS)
328 		return (EBUSY);
329 	if (stmf_worker_fini() != STMF_SUCCESS) {
330 		stmf_dlun_init();
331 		return (EBUSY);
332 	}
333 	if (stmf_svc_fini() != STMF_SUCCESS) {
334 		stmf_dlun_init();
335 		stmf_worker_init();
336 		return (EBUSY);
337 	}
338 
339 	ret = mod_remove(&modlinkage);
340 	if (ret) {
341 		stmf_svc_init();
342 		stmf_dlun_init();
343 		stmf_worker_init();
344 		return (ret);
345 	}
346 
347 	stmf_view_clear_config();
348 
349 	while ((irport = avl_destroy_nodes(&stmf_state.stmf_irportlist,
350 	    &avl_dest_cookie)) != NULL)
351 		stmf_irport_destroy(irport);
352 	avl_destroy(&stmf_state.stmf_irportlist);
353 	id_space_destroy(stmf_state.stmf_ilport_inst_space);
354 	id_space_destroy(stmf_state.stmf_irport_inst_space);
355 
356 	avl_dest_cookie = NULL;
357 	while ((ks_itl = avl_destroy_nodes(&stmf_state.stmf_itl_kstat_list,
358 	    &avl_dest_cookie)) != NULL) {
359 		stmf_teardown_itl_kstats(ks_itl);
360 		kmem_free(ks_itl, sizeof (ks_itl));
361 	}
362 	avl_destroy(&stmf_state.stmf_itl_kstat_list);
363 
364 	kmem_free(stmf_trace_buf, stmf_trace_buf_size);
365 	mutex_destroy(&trace_buf_lock);
366 	mutex_destroy(&stmf_state.stmf_lock);
367 	cv_destroy(&stmf_state.stmf_cv);
368 	return (ret);
369 }
370 
371 int
372 _info(struct modinfo *modinfop)
373 {
374 	return (mod_info(&modlinkage, modinfop));
375 }
376 
377 /* ARGSUSED */
378 static int
379 stmf_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
380 {
381 	switch (cmd) {
382 	case DDI_INFO_DEVT2DEVINFO:
383 		*result = stmf_state.stmf_dip;
384 		break;
385 	case DDI_INFO_DEVT2INSTANCE:
386 		*result =
387 		    (void *)(uintptr_t)ddi_get_instance(stmf_state.stmf_dip);
388 		break;
389 	default:
390 		return (DDI_FAILURE);
391 	}
392 
393 	return (DDI_SUCCESS);
394 }
395 
396 static int
397 stmf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
398 {
399 	switch (cmd) {
400 	case DDI_ATTACH:
401 		stmf_state.stmf_dip = dip;
402 
403 		if (ddi_create_minor_node(dip, "admin", S_IFCHR, 0,
404 		    DDI_NT_STMF, 0) != DDI_SUCCESS) {
405 			break;
406 		}
407 		ddi_report_dev(dip);
408 		return (DDI_SUCCESS);
409 	}
410 
411 	return (DDI_FAILURE);
412 }
413 
414 static int
415 stmf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
416 {
417 	switch (cmd) {
418 	case DDI_DETACH:
419 		ddi_remove_minor_node(dip, 0);
420 		return (DDI_SUCCESS);
421 	}
422 
423 	return (DDI_FAILURE);
424 }
425 
426 /* ARGSUSED */
427 static int
428 stmf_open(dev_t *devp, int flag, int otype, cred_t *credp)
429 {
430 	mutex_enter(&stmf_state.stmf_lock);
431 	if (stmf_state.stmf_exclusive_open) {
432 		mutex_exit(&stmf_state.stmf_lock);
433 		return (EBUSY);
434 	}
435 	if (flag & FEXCL) {
436 		if (stmf_state.stmf_opened) {
437 			mutex_exit(&stmf_state.stmf_lock);
438 			return (EBUSY);
439 		}
440 		stmf_state.stmf_exclusive_open = 1;
441 	}
442 	stmf_state.stmf_opened = 1;
443 	mutex_exit(&stmf_state.stmf_lock);
444 	return (0);
445 }
446 
447 /* ARGSUSED */
448 static int
449 stmf_close(dev_t dev, int flag, int otype, cred_t *credp)
450 {
451 	mutex_enter(&stmf_state.stmf_lock);
452 	stmf_state.stmf_opened = 0;
453 	if (stmf_state.stmf_exclusive_open &&
454 	    (stmf_state.stmf_config_state != STMF_CONFIG_INIT_DONE)) {
455 		stmf_state.stmf_config_state = STMF_CONFIG_NONE;
456 		stmf_delete_all_ppds();
457 		stmf_view_clear_config();
458 		stmf_view_init();
459 	}
460 	stmf_state.stmf_exclusive_open = 0;
461 	mutex_exit(&stmf_state.stmf_lock);
462 	return (0);
463 }
464 
465 int
466 stmf_copyin_iocdata(intptr_t data, int mode, stmf_iocdata_t **iocd,
467 						void **ibuf, void **obuf)
468 {
469 	int ret;
470 
471 	*ibuf = NULL;
472 	*obuf = NULL;
473 	*iocd = kmem_zalloc(sizeof (stmf_iocdata_t), KM_SLEEP);
474 
475 	ret = ddi_copyin((void *)data, *iocd, sizeof (stmf_iocdata_t), mode);
476 	if (ret)
477 		return (EFAULT);
478 	if ((*iocd)->stmf_version != STMF_VERSION_1) {
479 		ret = EINVAL;
480 		goto copyin_iocdata_done;
481 	}
482 	if ((*iocd)->stmf_ibuf_size) {
483 		*ibuf = kmem_zalloc((*iocd)->stmf_ibuf_size, KM_SLEEP);
484 		ret = ddi_copyin((void *)((unsigned long)(*iocd)->stmf_ibuf),
485 		    *ibuf, (*iocd)->stmf_ibuf_size, mode);
486 	}
487 	if ((*iocd)->stmf_obuf_size)
488 		*obuf = kmem_zalloc((*iocd)->stmf_obuf_size, KM_SLEEP);
489 
490 	if (ret == 0)
491 		return (0);
492 	ret = EFAULT;
493 copyin_iocdata_done:;
494 	if (*obuf) {
495 		kmem_free(*obuf, (*iocd)->stmf_obuf_size);
496 		*obuf = NULL;
497 	}
498 	if (*ibuf) {
499 		kmem_free(*ibuf, (*iocd)->stmf_ibuf_size);
500 		*ibuf = NULL;
501 	}
502 	kmem_free(*iocd, sizeof (stmf_iocdata_t));
503 	return (ret);
504 }
505 
506 int
507 stmf_copyout_iocdata(intptr_t data, int mode, stmf_iocdata_t *iocd, void *obuf)
508 {
509 	int ret;
510 
511 	if (iocd->stmf_obuf_size) {
512 		ret = ddi_copyout(obuf, (void *)(unsigned long)iocd->stmf_obuf,
513 		    iocd->stmf_obuf_size, mode);
514 		if (ret)
515 			return (EFAULT);
516 	}
517 	ret = ddi_copyout(iocd, (void *)data, sizeof (stmf_iocdata_t), mode);
518 	if (ret)
519 		return (EFAULT);
520 	return (0);
521 }
522 
523 /* ARGSUSED */
524 static int
525 stmf_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
526 	cred_t *credp, int *rval)
527 {
528 	stmf_iocdata_t *iocd;
529 	void *ibuf = NULL, *obuf = NULL;
530 	slist_lu_t *luid_list;
531 	slist_target_port_t *lportid_list;
532 	stmf_i_lu_t *ilu;
533 	stmf_i_local_port_t *ilport;
534 	stmf_i_scsi_session_t *iss;
535 	slist_scsi_session_t *iss_list;
536 	sioc_lu_props_t *lup;
537 	sioc_target_port_props_t *lportp;
538 	stmf_ppioctl_data_t *ppi, *ppi_out = NULL;
539 	uint64_t *ppi_token = NULL;
540 	uint8_t *p_id, *id;
541 	stmf_state_desc_t *std;
542 	stmf_status_t ctl_ret;
543 	stmf_state_change_info_t ssi;
544 	int ret = 0;
545 	uint32_t n;
546 	int i;
547 	stmf_group_op_data_t *grp_entry;
548 	stmf_group_name_t *grpname;
549 	stmf_view_op_entry_t *ve;
550 	stmf_id_type_t idtype;
551 	stmf_id_data_t *id_entry;
552 	stmf_id_list_t	*id_list;
553 	stmf_view_entry_t *view_entry;
554 	uint32_t	veid;
555 
556 	if ((cmd & 0xff000000) != STMF_IOCTL) {
557 		return (ENOTTY);
558 	}
559 
560 	if (drv_priv(credp) != 0) {
561 		return (EPERM);
562 	}
563 
564 	ret = stmf_copyin_iocdata(data, mode, &iocd, &ibuf, &obuf);
565 	if (ret)
566 		return (ret);
567 	iocd->stmf_error = 0;
568 
569 	switch (cmd) {
570 	case STMF_IOCTL_LU_LIST:
571 		/* retrieves both registered/unregistered */
572 		mutex_enter(&stmf_state.stmf_lock);
573 		id_list = &stmf_state.stmf_luid_list;
574 		n = min(id_list->id_count,
575 		    (iocd->stmf_obuf_size)/sizeof (slist_lu_t));
576 		iocd->stmf_obuf_max_nentries = id_list->id_count;
577 		luid_list = (slist_lu_t *)obuf;
578 		id_entry = id_list->idl_head;
579 		for (i = 0; i < n; i++) {
580 			bcopy(id_entry->id_data, luid_list[i].lu_guid, 16);
581 			id_entry = id_entry->id_next;
582 		}
583 
584 		n = iocd->stmf_obuf_size/sizeof (slist_lu_t);
585 		for (ilu = stmf_state.stmf_ilulist; ilu; ilu = ilu->ilu_next) {
586 			id = (uint8_t *)ilu->ilu_lu->lu_id;
587 			if (stmf_lookup_id(id_list, 16, id + 4) == NULL) {
588 				iocd->stmf_obuf_max_nentries++;
589 				if (i < n) {
590 					bcopy(id + 4, luid_list[i].lu_guid,
591 					    sizeof (slist_lu_t));
592 					i++;
593 				}
594 			}
595 		}
596 		iocd->stmf_obuf_nentries = i;
597 		mutex_exit(&stmf_state.stmf_lock);
598 		break;
599 
600 	case STMF_IOCTL_REG_LU_LIST:
601 		mutex_enter(&stmf_state.stmf_lock);
602 		iocd->stmf_obuf_max_nentries = stmf_state.stmf_nlus;
603 		n = min(stmf_state.stmf_nlus,
604 		    (iocd->stmf_obuf_size)/sizeof (slist_lu_t));
605 		iocd->stmf_obuf_nentries = n;
606 		ilu = stmf_state.stmf_ilulist;
607 		luid_list = (slist_lu_t *)obuf;
608 		for (i = 0; i < n; i++) {
609 			uint8_t *id;
610 			id = (uint8_t *)ilu->ilu_lu->lu_id;
611 			bcopy(id + 4, luid_list[i].lu_guid, 16);
612 			ilu = ilu->ilu_next;
613 		}
614 		mutex_exit(&stmf_state.stmf_lock);
615 		break;
616 
617 	case STMF_IOCTL_VE_LU_LIST:
618 		mutex_enter(&stmf_state.stmf_lock);
619 		id_list = &stmf_state.stmf_luid_list;
620 		n = min(id_list->id_count,
621 		    (iocd->stmf_obuf_size)/sizeof (slist_lu_t));
622 		iocd->stmf_obuf_max_nentries = id_list->id_count;
623 		iocd->stmf_obuf_nentries = n;
624 		luid_list = (slist_lu_t *)obuf;
625 		id_entry = id_list->idl_head;
626 		for (i = 0; i < n; i++) {
627 			bcopy(id_entry->id_data, luid_list[i].lu_guid, 16);
628 			id_entry = id_entry->id_next;
629 		}
630 		mutex_exit(&stmf_state.stmf_lock);
631 		break;
632 
633 	case STMF_IOCTL_TARGET_PORT_LIST:
634 		mutex_enter(&stmf_state.stmf_lock);
635 		iocd->stmf_obuf_max_nentries = stmf_state.stmf_nlports;
636 		n = min(stmf_state.stmf_nlports,
637 		    (iocd->stmf_obuf_size)/sizeof (slist_target_port_t));
638 		iocd->stmf_obuf_nentries = n;
639 		ilport = stmf_state.stmf_ilportlist;
640 		lportid_list = (slist_target_port_t *)obuf;
641 		for (i = 0; i < n; i++) {
642 			uint8_t *id;
643 			id = (uint8_t *)ilport->ilport_lport->lport_id;
644 			bcopy(id, lportid_list[i].target, id[3] + 4);
645 			ilport = ilport->ilport_next;
646 		}
647 		mutex_exit(&stmf_state.stmf_lock);
648 		break;
649 
650 	case STMF_IOCTL_SESSION_LIST:
651 		p_id = (uint8_t *)ibuf;
652 		if ((p_id == NULL) || (iocd->stmf_ibuf_size < 4) ||
653 		    (iocd->stmf_ibuf_size < (p_id[3] + 4))) {
654 			ret = EINVAL;
655 			break;
656 		}
657 		mutex_enter(&stmf_state.stmf_lock);
658 		for (ilport = stmf_state.stmf_ilportlist; ilport; ilport =
659 		    ilport->ilport_next) {
660 			uint8_t *id;
661 			id = (uint8_t *)ilport->ilport_lport->lport_id;
662 			if ((p_id[3] == id[3]) &&
663 			    (bcmp(p_id + 4, id + 4, id[3]) == 0)) {
664 				break;
665 			}
666 		}
667 		if (ilport == NULL) {
668 			mutex_exit(&stmf_state.stmf_lock);
669 			ret = ENOENT;
670 			break;
671 		}
672 		iocd->stmf_obuf_max_nentries = ilport->ilport_nsessions;
673 		n = min(ilport->ilport_nsessions,
674 		    (iocd->stmf_obuf_size)/sizeof (slist_scsi_session_t));
675 		iocd->stmf_obuf_nentries = n;
676 		iss = ilport->ilport_ss_list;
677 		iss_list = (slist_scsi_session_t *)obuf;
678 		for (i = 0; i < n; i++) {
679 			uint8_t *id;
680 			id = (uint8_t *)iss->iss_ss->ss_rport_id;
681 			bcopy(id, iss_list[i].initiator, id[3] + 4);
682 			iss_list[i].creation_time = (uint32_t)
683 			    iss->iss_creation_time;
684 			if (iss->iss_ss->ss_rport_alias) {
685 				(void) strncpy(iss_list[i].alias,
686 				    iss->iss_ss->ss_rport_alias, 255);
687 				iss_list[i].alias[255] = 0;
688 			} else {
689 				iss_list[i].alias[0] = 0;
690 			}
691 			iss = iss->iss_next;
692 		}
693 		mutex_exit(&stmf_state.stmf_lock);
694 		break;
695 
696 	case STMF_IOCTL_GET_LU_PROPERTIES:
697 		p_id = (uint8_t *)ibuf;
698 		if ((iocd->stmf_ibuf_size < 16) ||
699 		    (iocd->stmf_obuf_size < sizeof (sioc_lu_props_t)) ||
700 		    (p_id[0] == 0)) {
701 			ret = EINVAL;
702 			break;
703 		}
704 		mutex_enter(&stmf_state.stmf_lock);
705 		for (ilu = stmf_state.stmf_ilulist; ilu; ilu = ilu->ilu_next) {
706 			if (bcmp(p_id, ilu->ilu_lu->lu_id->ident, 16) == 0)
707 				break;
708 		}
709 		if (ilu == NULL) {
710 			mutex_exit(&stmf_state.stmf_lock);
711 			ret = ENOENT;
712 			break;
713 		}
714 		lup = (sioc_lu_props_t *)obuf;
715 		bcopy(ilu->ilu_lu->lu_id->ident, lup->lu_guid, 16);
716 		lup->lu_state = ilu->ilu_state & 0x0f;
717 		lup->lu_present = 1; /* XXX */
718 		(void) strncpy(lup->lu_provider_name,
719 		    ilu->ilu_lu->lu_lp->lp_name, 255);
720 		lup->lu_provider_name[254] = 0;
721 		if (ilu->ilu_lu->lu_alias) {
722 			(void) strncpy(lup->lu_alias,
723 			    ilu->ilu_lu->lu_alias, 255);
724 			lup->lu_alias[255] = 0;
725 		} else {
726 			lup->lu_alias[0] = 0;
727 		}
728 		mutex_exit(&stmf_state.stmf_lock);
729 		break;
730 
731 	case STMF_IOCTL_GET_TARGET_PORT_PROPERTIES:
732 		p_id = (uint8_t *)ibuf;
733 		if ((p_id == NULL) ||
734 		    (iocd->stmf_ibuf_size < (p_id[3] + 4)) ||
735 		    (iocd->stmf_obuf_size <
736 		    sizeof (sioc_target_port_props_t))) {
737 			ret = EINVAL;
738 			break;
739 		}
740 		mutex_enter(&stmf_state.stmf_lock);
741 		for (ilport = stmf_state.stmf_ilportlist; ilport;
742 		    ilport = ilport->ilport_next) {
743 			uint8_t *id;
744 			id = (uint8_t *)ilport->ilport_lport->lport_id;
745 			if ((p_id[3] == id[3]) &&
746 			    (bcmp(p_id+4, id+4, id[3]) == 0))
747 				break;
748 		}
749 		if (ilport == NULL) {
750 			mutex_exit(&stmf_state.stmf_lock);
751 			ret = ENOENT;
752 			break;
753 		}
754 		lportp = (sioc_target_port_props_t *)obuf;
755 		bcopy(ilport->ilport_lport->lport_id, lportp->tgt_id,
756 		    ilport->ilport_lport->lport_id->ident_length + 4);
757 		lportp->tgt_state = ilport->ilport_state & 0x0f;
758 		lportp->tgt_present = 1; /* XXX */
759 		(void) strncpy(lportp->tgt_provider_name,
760 		    ilport->ilport_lport->lport_pp->pp_name, 255);
761 		lportp->tgt_provider_name[254] = 0;
762 		if (ilport->ilport_lport->lport_alias) {
763 			(void) strncpy(lportp->tgt_alias,
764 			    ilport->ilport_lport->lport_alias, 255);
765 			lportp->tgt_alias[255] = 0;
766 		} else {
767 			lportp->tgt_alias[0] = 0;
768 		}
769 		mutex_exit(&stmf_state.stmf_lock);
770 		break;
771 
772 	case STMF_IOCTL_SET_STMF_STATE:
773 		if ((ibuf == NULL) ||
774 		    (iocd->stmf_ibuf_size < sizeof (stmf_state_desc_t))) {
775 			ret = EINVAL;
776 			break;
777 		}
778 		ret = stmf_set_stmf_state((stmf_state_desc_t *)ibuf);
779 		break;
780 
781 	case STMF_IOCTL_GET_STMF_STATE:
782 		if ((obuf == NULL) ||
783 		    (iocd->stmf_obuf_size < sizeof (stmf_state_desc_t))) {
784 			ret = EINVAL;
785 			break;
786 		}
787 		ret = stmf_get_stmf_state((stmf_state_desc_t *)obuf);
788 		break;
789 
790 	case STMF_IOCTL_SET_ALUA_STATE:
791 		if ((ibuf == NULL) ||
792 		    (iocd->stmf_ibuf_size < sizeof (stmf_alua_state_desc_t))) {
793 			ret = EINVAL;
794 			break;
795 		}
796 		ret = stmf_set_alua_state((stmf_alua_state_desc_t *)ibuf);
797 		break;
798 
799 	case STMF_IOCTL_GET_ALUA_STATE:
800 		if ((obuf == NULL) ||
801 		    (iocd->stmf_obuf_size < sizeof (stmf_alua_state_desc_t))) {
802 			ret = EINVAL;
803 			break;
804 		}
805 		stmf_get_alua_state((stmf_alua_state_desc_t *)obuf);
806 		break;
807 
808 	case STMF_IOCTL_SET_LU_STATE:
809 		ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
810 		ssi.st_additional_info = NULL;
811 		std = (stmf_state_desc_t *)ibuf;
812 		if ((ibuf == NULL) ||
813 		    (iocd->stmf_ibuf_size < sizeof (stmf_state_desc_t))) {
814 			ret = EINVAL;
815 			break;
816 		}
817 		p_id = std->ident;
818 		mutex_enter(&stmf_state.stmf_lock);
819 		if (stmf_state.stmf_inventory_locked) {
820 			mutex_exit(&stmf_state.stmf_lock);
821 			ret = EBUSY;
822 			break;
823 		}
824 		for (ilu = stmf_state.stmf_ilulist; ilu; ilu = ilu->ilu_next) {
825 			if (bcmp(p_id, ilu->ilu_lu->lu_id->ident, 16) == 0)
826 				break;
827 		}
828 		if (ilu == NULL) {
829 			mutex_exit(&stmf_state.stmf_lock);
830 			ret = ENOENT;
831 			break;
832 		}
833 		stmf_state.stmf_inventory_locked = 1;
834 		mutex_exit(&stmf_state.stmf_lock);
835 		cmd = (std->state == STMF_STATE_ONLINE) ? STMF_CMD_LU_ONLINE :
836 		    STMF_CMD_LU_OFFLINE;
837 		ctl_ret = stmf_ctl(cmd, (void *)ilu->ilu_lu, &ssi);
838 		if (ctl_ret == STMF_ALREADY)
839 			ret = 0;
840 		else if (ctl_ret == STMF_BUSY)
841 			ret = EBUSY;
842 		else if (ctl_ret != STMF_SUCCESS)
843 			ret = EIO;
844 		mutex_enter(&stmf_state.stmf_lock);
845 		stmf_state.stmf_inventory_locked = 0;
846 		mutex_exit(&stmf_state.stmf_lock);
847 		break;
848 
849 	case STMF_IOCTL_SET_TARGET_PORT_STATE:
850 		ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
851 		ssi.st_additional_info = NULL;
852 		std = (stmf_state_desc_t *)ibuf;
853 		if ((ibuf == NULL) ||
854 		    (iocd->stmf_ibuf_size < sizeof (stmf_state_desc_t))) {
855 			ret = EINVAL;
856 			break;
857 		}
858 		p_id = std->ident;
859 		mutex_enter(&stmf_state.stmf_lock);
860 		if (stmf_state.stmf_inventory_locked) {
861 			mutex_exit(&stmf_state.stmf_lock);
862 			ret = EBUSY;
863 			break;
864 		}
865 		for (ilport = stmf_state.stmf_ilportlist; ilport;
866 		    ilport = ilport->ilport_next) {
867 			uint8_t *id;
868 			id = (uint8_t *)ilport->ilport_lport->lport_id;
869 			if ((id[3] == p_id[3]) &&
870 			    (bcmp(id+4, p_id+4, id[3]) == 0)) {
871 				break;
872 			}
873 		}
874 		if (ilport == NULL) {
875 			mutex_exit(&stmf_state.stmf_lock);
876 			ret = ENOENT;
877 			break;
878 		}
879 		stmf_state.stmf_inventory_locked = 1;
880 		mutex_exit(&stmf_state.stmf_lock);
881 		cmd = (std->state == STMF_STATE_ONLINE) ?
882 		    STMF_CMD_LPORT_ONLINE : STMF_CMD_LPORT_OFFLINE;
883 		ctl_ret = stmf_ctl(cmd, (void *)ilport->ilport_lport, &ssi);
884 		if (ctl_ret == STMF_ALREADY)
885 			ret = 0;
886 		else if (ctl_ret == STMF_BUSY)
887 			ret = EBUSY;
888 		else if (ctl_ret != STMF_SUCCESS)
889 			ret = EIO;
890 		mutex_enter(&stmf_state.stmf_lock);
891 		stmf_state.stmf_inventory_locked = 0;
892 		mutex_exit(&stmf_state.stmf_lock);
893 		break;
894 
895 	case STMF_IOCTL_ADD_HG_ENTRY:
896 		idtype = STMF_ID_TYPE_HOST;
897 		/* FALLTHROUGH */
898 	case STMF_IOCTL_ADD_TG_ENTRY:
899 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
900 			ret = EACCES;
901 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
902 			break;
903 		}
904 		if (cmd == STMF_IOCTL_ADD_TG_ENTRY) {
905 			idtype = STMF_ID_TYPE_TARGET;
906 		}
907 		grp_entry = (stmf_group_op_data_t *)ibuf;
908 		if ((ibuf == NULL) ||
909 		    (iocd->stmf_ibuf_size < sizeof (stmf_group_op_data_t))) {
910 			ret = EINVAL;
911 			break;
912 		}
913 		if (grp_entry->group.name[0] == '*') {
914 			ret = EINVAL;
915 			break; /* not allowed */
916 		}
917 		mutex_enter(&stmf_state.stmf_lock);
918 		ret = stmf_add_group_member(grp_entry->group.name,
919 		    grp_entry->group.name_size,
920 		    grp_entry->ident + 4,
921 		    grp_entry->ident[3],
922 		    idtype,
923 		    &iocd->stmf_error);
924 		mutex_exit(&stmf_state.stmf_lock);
925 		break;
926 	case STMF_IOCTL_REMOVE_HG_ENTRY:
927 		idtype = STMF_ID_TYPE_HOST;
928 		/* FALLTHROUGH */
929 	case STMF_IOCTL_REMOVE_TG_ENTRY:
930 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
931 			ret = EACCES;
932 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
933 			break;
934 		}
935 		if (cmd == STMF_IOCTL_REMOVE_TG_ENTRY) {
936 			idtype = STMF_ID_TYPE_TARGET;
937 		}
938 		grp_entry = (stmf_group_op_data_t *)ibuf;
939 		if ((ibuf == NULL) ||
940 		    (iocd->stmf_ibuf_size < sizeof (stmf_group_op_data_t))) {
941 			ret = EINVAL;
942 			break;
943 		}
944 		if (grp_entry->group.name[0] == '*') {
945 			ret = EINVAL;
946 			break; /* not allowed */
947 		}
948 		mutex_enter(&stmf_state.stmf_lock);
949 		ret = stmf_remove_group_member(grp_entry->group.name,
950 		    grp_entry->group.name_size,
951 		    grp_entry->ident + 4,
952 		    grp_entry->ident[3],
953 		    idtype,
954 		    &iocd->stmf_error);
955 		mutex_exit(&stmf_state.stmf_lock);
956 		break;
957 	case STMF_IOCTL_CREATE_HOST_GROUP:
958 		idtype = STMF_ID_TYPE_HOST_GROUP;
959 		/* FALLTHROUGH */
960 	case STMF_IOCTL_CREATE_TARGET_GROUP:
961 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
962 			ret = EACCES;
963 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
964 			break;
965 		}
966 		grpname = (stmf_group_name_t *)ibuf;
967 
968 		if (cmd == STMF_IOCTL_CREATE_TARGET_GROUP)
969 			idtype = STMF_ID_TYPE_TARGET_GROUP;
970 		if ((ibuf == NULL) ||
971 		    (iocd->stmf_ibuf_size < sizeof (stmf_group_name_t))) {
972 			ret = EINVAL;
973 			break;
974 		}
975 		if (grpname->name[0] == '*') {
976 			ret = EINVAL;
977 			break; /* not allowed */
978 		}
979 		mutex_enter(&stmf_state.stmf_lock);
980 		ret = stmf_add_group(grpname->name,
981 		    grpname->name_size, idtype, &iocd->stmf_error);
982 		mutex_exit(&stmf_state.stmf_lock);
983 		break;
984 	case STMF_IOCTL_REMOVE_HOST_GROUP:
985 		idtype = STMF_ID_TYPE_HOST_GROUP;
986 		/* FALLTHROUGH */
987 	case STMF_IOCTL_REMOVE_TARGET_GROUP:
988 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
989 			ret = EACCES;
990 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
991 			break;
992 		}
993 		grpname = (stmf_group_name_t *)ibuf;
994 		if (cmd == STMF_IOCTL_REMOVE_TARGET_GROUP)
995 			idtype = STMF_ID_TYPE_TARGET_GROUP;
996 		if ((ibuf == NULL) ||
997 		    (iocd->stmf_ibuf_size < sizeof (stmf_group_name_t))) {
998 			ret = EINVAL;
999 			break;
1000 		}
1001 		if (grpname->name[0] == '*') {
1002 			ret = EINVAL;
1003 			break; /* not allowed */
1004 		}
1005 		mutex_enter(&stmf_state.stmf_lock);
1006 		ret = stmf_remove_group(grpname->name,
1007 		    grpname->name_size, idtype, &iocd->stmf_error);
1008 		mutex_exit(&stmf_state.stmf_lock);
1009 		break;
1010 	case STMF_IOCTL_VALIDATE_VIEW:
1011 	case STMF_IOCTL_ADD_VIEW_ENTRY:
1012 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1013 			ret = EACCES;
1014 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1015 			break;
1016 		}
1017 		ve = (stmf_view_op_entry_t *)ibuf;
1018 		if ((ibuf == NULL) ||
1019 		    (iocd->stmf_ibuf_size < sizeof (stmf_view_op_entry_t))) {
1020 			ret = EINVAL;
1021 			break;
1022 		}
1023 		if (!ve->ve_lu_number_valid)
1024 			ve->ve_lu_nbr[2] = 0xFF;
1025 		if (ve->ve_all_hosts) {
1026 			ve->ve_host_group.name[0] = '*';
1027 			ve->ve_host_group.name_size = 1;
1028 		}
1029 		if (ve->ve_all_targets) {
1030 			ve->ve_target_group.name[0] = '*';
1031 			ve->ve_target_group.name_size = 1;
1032 		}
1033 		if (ve->ve_ndx_valid)
1034 			veid = ve->ve_ndx;
1035 		else
1036 			veid = 0xffffffff;
1037 		mutex_enter(&stmf_state.stmf_lock);
1038 		if (cmd == STMF_IOCTL_ADD_VIEW_ENTRY) {
1039 			ret = stmf_add_ve(ve->ve_host_group.name,
1040 			    ve->ve_host_group.name_size,
1041 			    ve->ve_target_group.name,
1042 			    ve->ve_target_group.name_size,
1043 			    ve->ve_guid,
1044 			    &veid,
1045 			    ve->ve_lu_nbr,
1046 			    &iocd->stmf_error);
1047 		} else {  /* STMF_IOCTL_VALIDATE_VIEW */
1048 			ret = stmf_validate_lun_ve(ve->ve_host_group.name,
1049 			    ve->ve_host_group.name_size,
1050 			    ve->ve_target_group.name,
1051 			    ve->ve_target_group.name_size,
1052 			    ve->ve_lu_nbr,
1053 			    &iocd->stmf_error);
1054 		}
1055 		mutex_exit(&stmf_state.stmf_lock);
1056 		if (ret == 0 &&
1057 		    (!ve->ve_ndx_valid || !ve->ve_lu_number_valid) &&
1058 		    iocd->stmf_obuf_size >= sizeof (stmf_view_op_entry_t)) {
1059 			stmf_view_op_entry_t *ve_ret =
1060 			    (stmf_view_op_entry_t *)obuf;
1061 			iocd->stmf_obuf_nentries = 1;
1062 			iocd->stmf_obuf_max_nentries = 1;
1063 			if (!ve->ve_ndx_valid) {
1064 				ve_ret->ve_ndx = veid;
1065 				ve_ret->ve_ndx_valid = 1;
1066 			}
1067 			if (!ve->ve_lu_number_valid) {
1068 				ve_ret->ve_lu_number_valid = 1;
1069 				bcopy(ve->ve_lu_nbr, ve_ret->ve_lu_nbr, 8);
1070 			}
1071 		}
1072 		break;
1073 	case STMF_IOCTL_REMOVE_VIEW_ENTRY:
1074 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1075 			ret = EACCES;
1076 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1077 			break;
1078 		}
1079 		ve = (stmf_view_op_entry_t *)ibuf;
1080 		if ((ibuf == NULL) ||
1081 		    (iocd->stmf_ibuf_size < sizeof (stmf_view_op_entry_t))) {
1082 			ret = EINVAL;
1083 			break;
1084 		}
1085 		if (!ve->ve_ndx_valid) {
1086 			ret = EINVAL;
1087 			break;
1088 		}
1089 		mutex_enter(&stmf_state.stmf_lock);
1090 		ret = stmf_remove_ve_by_id(ve->ve_guid, ve->ve_ndx,
1091 		    &iocd->stmf_error);
1092 		mutex_exit(&stmf_state.stmf_lock);
1093 		break;
1094 	case STMF_IOCTL_GET_HG_LIST:
1095 		id_list = &stmf_state.stmf_hg_list;
1096 		/* FALLTHROUGH */
1097 	case STMF_IOCTL_GET_TG_LIST:
1098 		if (cmd == STMF_IOCTL_GET_TG_LIST)
1099 			id_list = &stmf_state.stmf_tg_list;
1100 		mutex_enter(&stmf_state.stmf_lock);
1101 		iocd->stmf_obuf_max_nentries = id_list->id_count;
1102 		n = min(id_list->id_count,
1103 		    (iocd->stmf_obuf_size)/sizeof (stmf_group_name_t));
1104 		iocd->stmf_obuf_nentries = n;
1105 		id_entry = id_list->idl_head;
1106 		grpname = (stmf_group_name_t *)obuf;
1107 		for (i = 0; i < n; i++) {
1108 			if (id_entry->id_data[0] == '*') {
1109 				if (iocd->stmf_obuf_nentries > 0) {
1110 					iocd->stmf_obuf_nentries--;
1111 				}
1112 				id_entry = id_entry->id_next;
1113 				continue;
1114 			}
1115 			grpname->name_size = id_entry->id_data_size;
1116 			bcopy(id_entry->id_data, grpname->name,
1117 			    id_entry->id_data_size);
1118 			grpname++;
1119 			id_entry = id_entry->id_next;
1120 		}
1121 		mutex_exit(&stmf_state.stmf_lock);
1122 		break;
1123 	case STMF_IOCTL_GET_HG_ENTRIES:
1124 		id_list = &stmf_state.stmf_hg_list;
1125 		/* FALLTHROUGH */
1126 	case STMF_IOCTL_GET_TG_ENTRIES:
1127 		grpname = (stmf_group_name_t *)ibuf;
1128 		if ((ibuf == NULL) ||
1129 		    (iocd->stmf_ibuf_size < sizeof (stmf_group_name_t))) {
1130 			ret = EINVAL;
1131 			break;
1132 		}
1133 		if (cmd == STMF_IOCTL_GET_TG_ENTRIES) {
1134 			id_list = &stmf_state.stmf_tg_list;
1135 		}
1136 		mutex_enter(&stmf_state.stmf_lock);
1137 		id_entry = stmf_lookup_id(id_list, grpname->name_size,
1138 		    grpname->name);
1139 		if (!id_entry)
1140 			ret = ENODEV;
1141 		else {
1142 			stmf_ge_ident_t *grp_entry;
1143 			id_list = (stmf_id_list_t *)id_entry->id_impl_specific;
1144 			iocd->stmf_obuf_max_nentries = id_list->id_count;
1145 			n = min(id_list->id_count,
1146 			    iocd->stmf_obuf_size/sizeof (stmf_ge_ident_t));
1147 			iocd->stmf_obuf_nentries = n;
1148 			id_entry = id_list->idl_head;
1149 			grp_entry = (stmf_ge_ident_t *)obuf;
1150 			for (i = 0; i < n; i++) {
1151 				bcopy(id_entry->id_data, grp_entry->ident,
1152 				    id_entry->id_data_size);
1153 				grp_entry->ident_size = id_entry->id_data_size;
1154 				id_entry = id_entry->id_next;
1155 				grp_entry++;
1156 			}
1157 		}
1158 		mutex_exit(&stmf_state.stmf_lock);
1159 		break;
1160 
1161 	case STMF_IOCTL_GET_VE_LIST:
1162 		n = iocd->stmf_obuf_size/sizeof (stmf_view_op_entry_t);
1163 		mutex_enter(&stmf_state.stmf_lock);
1164 		ve = (stmf_view_op_entry_t *)obuf;
1165 		for (id_entry = stmf_state.stmf_luid_list.idl_head;
1166 		    id_entry; id_entry = id_entry->id_next) {
1167 			for (view_entry = (stmf_view_entry_t *)
1168 			    id_entry->id_impl_specific; view_entry;
1169 			    view_entry = view_entry->ve_next) {
1170 				iocd->stmf_obuf_max_nentries++;
1171 				if (iocd->stmf_obuf_nentries >= n)
1172 					continue;
1173 				ve->ve_ndx_valid = 1;
1174 				ve->ve_ndx = view_entry->ve_id;
1175 				ve->ve_lu_number_valid = 1;
1176 				bcopy(view_entry->ve_lun, ve->ve_lu_nbr, 8);
1177 				bcopy(view_entry->ve_luid->id_data, ve->ve_guid,
1178 				    view_entry->ve_luid->id_data_size);
1179 				if (view_entry->ve_hg->id_data[0] == '*') {
1180 					ve->ve_all_hosts = 1;
1181 				} else {
1182 					bcopy(view_entry->ve_hg->id_data,
1183 					    ve->ve_host_group.name,
1184 					    view_entry->ve_hg->id_data_size);
1185 					ve->ve_host_group.name_size =
1186 					    view_entry->ve_hg->id_data_size;
1187 				}
1188 
1189 				if (view_entry->ve_tg->id_data[0] == '*') {
1190 					ve->ve_all_targets = 1;
1191 				} else {
1192 					bcopy(view_entry->ve_tg->id_data,
1193 					    ve->ve_target_group.name,
1194 					    view_entry->ve_tg->id_data_size);
1195 					ve->ve_target_group.name_size =
1196 					    view_entry->ve_tg->id_data_size;
1197 				}
1198 				ve++;
1199 				iocd->stmf_obuf_nentries++;
1200 			}
1201 		}
1202 		mutex_exit(&stmf_state.stmf_lock);
1203 		break;
1204 
1205 	case STMF_IOCTL_LU_VE_LIST:
1206 		p_id = (uint8_t *)ibuf;
1207 		if ((iocd->stmf_ibuf_size != 16) ||
1208 		    (iocd->stmf_obuf_size < sizeof (stmf_view_op_entry_t))) {
1209 			ret = EINVAL;
1210 			break;
1211 		}
1212 
1213 		n = iocd->stmf_obuf_size/sizeof (stmf_view_op_entry_t);
1214 		mutex_enter(&stmf_state.stmf_lock);
1215 		ve = (stmf_view_op_entry_t *)obuf;
1216 		for (id_entry = stmf_state.stmf_luid_list.idl_head;
1217 		    id_entry; id_entry = id_entry->id_next) {
1218 			if (bcmp(id_entry->id_data, p_id, 16) != 0)
1219 				continue;
1220 			for (view_entry = (stmf_view_entry_t *)
1221 			    id_entry->id_impl_specific; view_entry;
1222 			    view_entry = view_entry->ve_next) {
1223 				iocd->stmf_obuf_max_nentries++;
1224 				if (iocd->stmf_obuf_nentries >= n)
1225 					continue;
1226 				ve->ve_ndx_valid = 1;
1227 				ve->ve_ndx = view_entry->ve_id;
1228 				ve->ve_lu_number_valid = 1;
1229 				bcopy(view_entry->ve_lun, ve->ve_lu_nbr, 8);
1230 				bcopy(view_entry->ve_luid->id_data, ve->ve_guid,
1231 				    view_entry->ve_luid->id_data_size);
1232 				if (view_entry->ve_hg->id_data[0] == '*') {
1233 					ve->ve_all_hosts = 1;
1234 				} else {
1235 					bcopy(view_entry->ve_hg->id_data,
1236 					    ve->ve_host_group.name,
1237 					    view_entry->ve_hg->id_data_size);
1238 					ve->ve_host_group.name_size =
1239 					    view_entry->ve_hg->id_data_size;
1240 				}
1241 
1242 				if (view_entry->ve_tg->id_data[0] == '*') {
1243 					ve->ve_all_targets = 1;
1244 				} else {
1245 					bcopy(view_entry->ve_tg->id_data,
1246 					    ve->ve_target_group.name,
1247 					    view_entry->ve_tg->id_data_size);
1248 					ve->ve_target_group.name_size =
1249 					    view_entry->ve_tg->id_data_size;
1250 				}
1251 				ve++;
1252 				iocd->stmf_obuf_nentries++;
1253 			}
1254 			break;
1255 		}
1256 		mutex_exit(&stmf_state.stmf_lock);
1257 		break;
1258 
1259 	case STMF_IOCTL_LOAD_PP_DATA:
1260 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1261 			ret = EACCES;
1262 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1263 			break;
1264 		}
1265 		ppi = (stmf_ppioctl_data_t *)ibuf;
1266 		if ((ppi == NULL) ||
1267 		    (iocd->stmf_ibuf_size < sizeof (stmf_ppioctl_data_t))) {
1268 			ret = EINVAL;
1269 			break;
1270 		}
1271 		/* returned token */
1272 		ppi_token = (uint64_t *)obuf;
1273 		if ((ppi_token == NULL) ||
1274 		    (iocd->stmf_obuf_size < sizeof (uint64_t))) {
1275 			ret = EINVAL;
1276 			break;
1277 		}
1278 		ret = stmf_load_ppd_ioctl(ppi, ppi_token, &iocd->stmf_error);
1279 		break;
1280 
1281 	case STMF_IOCTL_GET_PP_DATA:
1282 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1283 			ret = EACCES;
1284 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1285 			break;
1286 		}
1287 		ppi = (stmf_ppioctl_data_t *)ibuf;
1288 		if (ppi == NULL ||
1289 		    (iocd->stmf_ibuf_size < sizeof (stmf_ppioctl_data_t))) {
1290 			ret = EINVAL;
1291 			break;
1292 		}
1293 		ppi_out = (stmf_ppioctl_data_t *)obuf;
1294 		if ((ppi_out == NULL) ||
1295 		    (iocd->stmf_obuf_size < sizeof (stmf_ppioctl_data_t))) {
1296 			ret = EINVAL;
1297 			break;
1298 		}
1299 		ret = stmf_get_ppd_ioctl(ppi, ppi_out, &iocd->stmf_error);
1300 		break;
1301 
1302 	case STMF_IOCTL_CLEAR_PP_DATA:
1303 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1304 			ret = EACCES;
1305 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1306 			break;
1307 		}
1308 		ppi = (stmf_ppioctl_data_t *)ibuf;
1309 		if ((ppi == NULL) ||
1310 		    (iocd->stmf_ibuf_size < sizeof (stmf_ppioctl_data_t))) {
1311 			ret = EINVAL;
1312 			break;
1313 		}
1314 		ret = stmf_delete_ppd_ioctl(ppi);
1315 		break;
1316 
1317 	case STMF_IOCTL_CLEAR_TRACE:
1318 		stmf_trace_clear();
1319 		break;
1320 
1321 	case STMF_IOCTL_ADD_TRACE:
1322 		if (iocd->stmf_ibuf_size && ibuf) {
1323 			((uint8_t *)ibuf)[iocd->stmf_ibuf_size - 1] = 0;
1324 			stmf_trace("\nstradm", "%s\n", ibuf);
1325 		}
1326 		break;
1327 
1328 	case STMF_IOCTL_GET_TRACE_POSITION:
1329 		if (obuf && (iocd->stmf_obuf_size > 3)) {
1330 			mutex_enter(&trace_buf_lock);
1331 			*((int *)obuf) = trace_buf_curndx;
1332 			mutex_exit(&trace_buf_lock);
1333 		} else {
1334 			ret = EINVAL;
1335 		}
1336 		break;
1337 
1338 	case STMF_IOCTL_GET_TRACE:
1339 		if ((iocd->stmf_obuf_size == 0) || (iocd->stmf_ibuf_size < 4)) {
1340 			ret = EINVAL;
1341 			break;
1342 		}
1343 		i = *((int *)ibuf);
1344 		if ((i > trace_buf_size) || ((i + iocd->stmf_obuf_size) >
1345 		    trace_buf_size)) {
1346 			ret = EINVAL;
1347 			break;
1348 		}
1349 		mutex_enter(&trace_buf_lock);
1350 		bcopy(stmf_trace_buf + i, obuf, iocd->stmf_obuf_size);
1351 		mutex_exit(&trace_buf_lock);
1352 		break;
1353 
1354 	default:
1355 		ret = ENOTTY;
1356 	}
1357 
1358 	if (ret == 0) {
1359 		ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
1360 	} else if (iocd->stmf_error) {
1361 		(void) stmf_copyout_iocdata(data, mode, iocd, obuf);
1362 	}
1363 	if (obuf) {
1364 		kmem_free(obuf, iocd->stmf_obuf_size);
1365 		obuf = NULL;
1366 	}
1367 	if (ibuf) {
1368 		kmem_free(ibuf, iocd->stmf_ibuf_size);
1369 		ibuf = NULL;
1370 	}
1371 	kmem_free(iocd, sizeof (stmf_iocdata_t));
1372 	return (ret);
1373 }
1374 
1375 static int
1376 stmf_get_service_state()
1377 {
1378 	stmf_i_local_port_t *ilport;
1379 	stmf_i_lu_t *ilu;
1380 	int online = 0;
1381 	int offline = 0;
1382 	int onlining = 0;
1383 	int offlining = 0;
1384 
1385 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
1386 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
1387 	    ilport = ilport->ilport_next) {
1388 		if (ilport->ilport_state == STMF_STATE_OFFLINE)
1389 			offline++;
1390 		else if (ilport->ilport_state == STMF_STATE_ONLINE)
1391 			online++;
1392 		else if (ilport->ilport_state == STMF_STATE_ONLINING)
1393 			onlining++;
1394 		else if (ilport->ilport_state == STMF_STATE_OFFLINING)
1395 			offlining++;
1396 	}
1397 
1398 	for (ilu = stmf_state.stmf_ilulist; ilu != NULL;
1399 	    ilu = ilu->ilu_next) {
1400 		if (ilu->ilu_state == STMF_STATE_OFFLINE)
1401 			offline++;
1402 		else if (ilu->ilu_state == STMF_STATE_ONLINE)
1403 			online++;
1404 		else if (ilu->ilu_state == STMF_STATE_ONLINING)
1405 			onlining++;
1406 		else if (ilu->ilu_state == STMF_STATE_OFFLINING)
1407 			offlining++;
1408 	}
1409 
1410 	if (stmf_state.stmf_service_running) {
1411 		if (onlining)
1412 			return (STMF_STATE_ONLINING);
1413 		else
1414 			return (STMF_STATE_ONLINE);
1415 	}
1416 
1417 	if (offlining) {
1418 		return (STMF_STATE_OFFLINING);
1419 	}
1420 
1421 	return (STMF_STATE_OFFLINE);
1422 }
1423 
1424 static int
1425 stmf_set_stmf_state(stmf_state_desc_t *std)
1426 {
1427 	stmf_i_local_port_t *ilport;
1428 	stmf_i_lu_t *ilu;
1429 	stmf_state_change_info_t ssi;
1430 	int svc_state;
1431 
1432 	ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
1433 	ssi.st_additional_info = NULL;
1434 
1435 	mutex_enter(&stmf_state.stmf_lock);
1436 	if (!stmf_state.stmf_exclusive_open) {
1437 		mutex_exit(&stmf_state.stmf_lock);
1438 		return (EACCES);
1439 	}
1440 
1441 	if (stmf_state.stmf_inventory_locked) {
1442 		mutex_exit(&stmf_state.stmf_lock);
1443 		return (EBUSY);
1444 	}
1445 
1446 	if ((std->state != STMF_STATE_ONLINE) &&
1447 	    (std->state != STMF_STATE_OFFLINE)) {
1448 		mutex_exit(&stmf_state.stmf_lock);
1449 		return (EINVAL);
1450 	}
1451 
1452 	svc_state = stmf_get_service_state();
1453 	if ((svc_state == STMF_STATE_OFFLINING) ||
1454 	    (svc_state == STMF_STATE_ONLINING)) {
1455 		mutex_exit(&stmf_state.stmf_lock);
1456 		return (EBUSY);
1457 	}
1458 
1459 	if (svc_state == STMF_STATE_OFFLINE) {
1460 		if (std->config_state == STMF_CONFIG_INIT) {
1461 			if (std->state != STMF_STATE_OFFLINE) {
1462 				mutex_exit(&stmf_state.stmf_lock);
1463 				return (EINVAL);
1464 			}
1465 			stmf_state.stmf_config_state = STMF_CONFIG_INIT;
1466 			stmf_delete_all_ppds();
1467 			stmf_view_clear_config();
1468 			stmf_view_init();
1469 			mutex_exit(&stmf_state.stmf_lock);
1470 			return (0);
1471 		}
1472 		if ((stmf_state.stmf_config_state == STMF_CONFIG_INIT) ||
1473 		    (stmf_state.stmf_config_state == STMF_CONFIG_NONE)) {
1474 			if (std->config_state != STMF_CONFIG_INIT_DONE) {
1475 				mutex_exit(&stmf_state.stmf_lock);
1476 				return (EINVAL);
1477 			}
1478 			stmf_state.stmf_config_state = STMF_CONFIG_INIT_DONE;
1479 		}
1480 		if (std->state == STMF_STATE_OFFLINE) {
1481 			mutex_exit(&stmf_state.stmf_lock);
1482 			return (0);
1483 		}
1484 		if (stmf_state.stmf_config_state == STMF_CONFIG_INIT) {
1485 			mutex_exit(&stmf_state.stmf_lock);
1486 			return (EINVAL);
1487 		}
1488 		stmf_state.stmf_inventory_locked = 1;
1489 		stmf_state.stmf_service_running = 1;
1490 		mutex_exit(&stmf_state.stmf_lock);
1491 
1492 		for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
1493 		    ilport = ilport->ilport_next) {
1494 			if (ilport->ilport_prev_state != STMF_STATE_ONLINE)
1495 				continue;
1496 			(void) stmf_ctl(STMF_CMD_LPORT_ONLINE,
1497 			    ilport->ilport_lport, &ssi);
1498 		}
1499 
1500 		for (ilu = stmf_state.stmf_ilulist; ilu != NULL;
1501 		    ilu = ilu->ilu_next) {
1502 			if (ilu->ilu_prev_state != STMF_STATE_ONLINE)
1503 				continue;
1504 			(void) stmf_ctl(STMF_CMD_LU_ONLINE, ilu->ilu_lu, &ssi);
1505 		}
1506 		mutex_enter(&stmf_state.stmf_lock);
1507 		stmf_state.stmf_inventory_locked = 0;
1508 		mutex_exit(&stmf_state.stmf_lock);
1509 		return (0);
1510 	}
1511 
1512 	/* svc_state is STMF_STATE_ONLINE here */
1513 	if ((std->state != STMF_STATE_OFFLINE) ||
1514 	    (std->config_state == STMF_CONFIG_INIT)) {
1515 		mutex_exit(&stmf_state.stmf_lock);
1516 		return (EACCES);
1517 	}
1518 
1519 	stmf_state.stmf_inventory_locked = 1;
1520 	stmf_state.stmf_service_running = 0;
1521 
1522 	mutex_exit(&stmf_state.stmf_lock);
1523 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
1524 	    ilport = ilport->ilport_next) {
1525 		if (ilport->ilport_state != STMF_STATE_ONLINE)
1526 			continue;
1527 		(void) stmf_ctl(STMF_CMD_LPORT_OFFLINE,
1528 		    ilport->ilport_lport, &ssi);
1529 	}
1530 
1531 	for (ilu = stmf_state.stmf_ilulist; ilu != NULL;
1532 	    ilu = ilu->ilu_next) {
1533 		if (ilu->ilu_state != STMF_STATE_ONLINE)
1534 			continue;
1535 		(void) stmf_ctl(STMF_CMD_LU_OFFLINE, ilu->ilu_lu, &ssi);
1536 	}
1537 	mutex_enter(&stmf_state.stmf_lock);
1538 	stmf_state.stmf_inventory_locked = 0;
1539 	mutex_exit(&stmf_state.stmf_lock);
1540 	return (0);
1541 }
1542 
1543 static int
1544 stmf_get_stmf_state(stmf_state_desc_t *std)
1545 {
1546 	mutex_enter(&stmf_state.stmf_lock);
1547 	std->state = stmf_get_service_state();
1548 	std->config_state = stmf_state.stmf_config_state;
1549 	mutex_exit(&stmf_state.stmf_lock);
1550 
1551 	return (0);
1552 }
1553 
1554 /*
1555  * handles registration message from pppt for a logical unit
1556  */
1557 stmf_status_t
1558 stmf_ic_lu_reg(stmf_ic_reg_dereg_lun_msg_t *msg, uint32_t type)
1559 {
1560 	stmf_i_lu_provider_t	*ilp;
1561 	stmf_lu_provider_t	*lp;
1562 	mutex_enter(&stmf_state.stmf_lock);
1563 	for (ilp = stmf_state.stmf_ilplist; ilp != NULL; ilp = ilp->ilp_next) {
1564 		if (strcmp(msg->icrl_lu_provider_name,
1565 		    ilp->ilp_lp->lp_name) == 0) {
1566 			lp = ilp->ilp_lp;
1567 			mutex_exit(&stmf_state.stmf_lock);
1568 			lp->lp_proxy_msg(msg->icrl_lun_id, msg->icrl_cb_arg,
1569 			    msg->icrl_cb_arg_len, type);
1570 			return (STMF_SUCCESS);
1571 		}
1572 	}
1573 	mutex_exit(&stmf_state.stmf_lock);
1574 	return (STMF_SUCCESS);
1575 }
1576 
1577 /*
1578  * handles de-registration message from pppt for a logical unit
1579  */
1580 stmf_status_t
1581 stmf_ic_lu_dereg(stmf_ic_reg_dereg_lun_msg_t *msg)
1582 {
1583 	stmf_i_lu_provider_t	*ilp;
1584 	stmf_lu_provider_t	*lp;
1585 	mutex_enter(&stmf_state.stmf_lock);
1586 	for (ilp = stmf_state.stmf_ilplist; ilp != NULL; ilp = ilp->ilp_next) {
1587 		if (strcmp(msg->icrl_lu_provider_name,
1588 		    ilp->ilp_lp->lp_name) == 0) {
1589 			lp = ilp->ilp_lp;
1590 			mutex_exit(&stmf_state.stmf_lock);
1591 			lp->lp_proxy_msg(msg->icrl_lun_id, NULL, 0,
1592 			    STMF_MSG_LU_DEREGISTER);
1593 			return (STMF_SUCCESS);
1594 		}
1595 	}
1596 	mutex_exit(&stmf_state.stmf_lock);
1597 	return (STMF_SUCCESS);
1598 }
1599 
1600 /*
1601  * helper function to find a task that matches a task_msgid
1602  */
1603 scsi_task_t *
1604 find_task_from_msgid(uint8_t *lu_id, stmf_ic_msgid_t task_msgid)
1605 {
1606 	stmf_i_lu_t *ilu;
1607 	stmf_i_scsi_task_t *itask;
1608 
1609 	mutex_enter(&stmf_state.stmf_lock);
1610 	for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) {
1611 		if (bcmp(lu_id, ilu->ilu_lu->lu_id->ident, 16) == 0) {
1612 			break;
1613 		}
1614 	}
1615 
1616 	if (ilu == NULL) {
1617 		mutex_exit(&stmf_state.stmf_lock);
1618 		return (NULL);
1619 	}
1620 
1621 	mutex_enter(&ilu->ilu_task_lock);
1622 	for (itask = ilu->ilu_tasks; itask != NULL;
1623 	    itask = itask->itask_lu_next) {
1624 		if (itask->itask_flags & (ITASK_IN_FREE_LIST |
1625 		    ITASK_BEING_ABORTED)) {
1626 			continue;
1627 		}
1628 		if (itask->itask_proxy_msg_id == task_msgid) {
1629 			break;
1630 		}
1631 	}
1632 	mutex_exit(&ilu->ilu_task_lock);
1633 	mutex_exit(&stmf_state.stmf_lock);
1634 
1635 	if (itask != NULL) {
1636 		return (itask->itask_task);
1637 	} else {
1638 		/* task not found. Likely already aborted. */
1639 		return (NULL);
1640 	}
1641 }
1642 
1643 /*
1644  * message received from pppt/ic
1645  */
1646 stmf_status_t
1647 stmf_msg_rx(stmf_ic_msg_t *msg)
1648 {
1649 	mutex_enter(&stmf_state.stmf_lock);
1650 	if (stmf_state.stmf_alua_state != 1) {
1651 		mutex_exit(&stmf_state.stmf_lock);
1652 		cmn_err(CE_WARN, "stmf alua state is disabled");
1653 		ic_msg_free(msg);
1654 		return (STMF_FAILURE);
1655 	}
1656 	mutex_exit(&stmf_state.stmf_lock);
1657 
1658 	switch (msg->icm_msg_type) {
1659 		case STMF_ICM_REGISTER_LUN:
1660 			(void) stmf_ic_lu_reg(
1661 			    (stmf_ic_reg_dereg_lun_msg_t *)msg->icm_msg,
1662 			    STMF_MSG_LU_REGISTER);
1663 			break;
1664 		case STMF_ICM_LUN_ACTIVE:
1665 			(void) stmf_ic_lu_reg(
1666 			    (stmf_ic_reg_dereg_lun_msg_t *)msg->icm_msg,
1667 			    STMF_MSG_LU_ACTIVE);
1668 			break;
1669 		case STMF_ICM_DEREGISTER_LUN:
1670 			(void) stmf_ic_lu_dereg(
1671 			    (stmf_ic_reg_dereg_lun_msg_t *)msg->icm_msg);
1672 			break;
1673 		case STMF_ICM_SCSI_DATA:
1674 			(void) stmf_ic_rx_scsi_data(
1675 			    (stmf_ic_scsi_data_msg_t *)msg->icm_msg);
1676 			break;
1677 		case STMF_ICM_SCSI_STATUS:
1678 			(void) stmf_ic_rx_scsi_status(
1679 			    (stmf_ic_scsi_status_msg_t *)msg->icm_msg);
1680 			break;
1681 		case STMF_ICM_STATUS:
1682 			(void) stmf_ic_rx_status(
1683 			    (stmf_ic_status_msg_t *)msg->icm_msg);
1684 			break;
1685 		default:
1686 			cmn_err(CE_WARN, "unknown message received %d",
1687 			    msg->icm_msg_type);
1688 			ic_msg_free(msg);
1689 			return (STMF_FAILURE);
1690 	}
1691 	ic_msg_free(msg);
1692 	return (STMF_SUCCESS);
1693 }
1694 
1695 stmf_status_t
1696 stmf_ic_rx_status(stmf_ic_status_msg_t *msg)
1697 {
1698 	stmf_i_local_port_t *ilport;
1699 
1700 	if (msg->ics_msg_type != STMF_ICM_REGISTER_PROXY_PORT) {
1701 		/* for now, ignore other message status */
1702 		return (STMF_SUCCESS);
1703 	}
1704 
1705 	if (msg->ics_status != STMF_SUCCESS) {
1706 		return (STMF_SUCCESS);
1707 	}
1708 
1709 	mutex_enter(&stmf_state.stmf_lock);
1710 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
1711 	    ilport = ilport->ilport_next) {
1712 		if (msg->ics_msgid == ilport->ilport_reg_msgid) {
1713 			ilport->ilport_proxy_registered = 1;
1714 			break;
1715 		}
1716 	}
1717 	mutex_exit(&stmf_state.stmf_lock);
1718 	return (STMF_SUCCESS);
1719 }
1720 
1721 /*
1722  * handles scsi status message from pppt
1723  */
1724 stmf_status_t
1725 stmf_ic_rx_scsi_status(stmf_ic_scsi_status_msg_t *msg)
1726 {
1727 	scsi_task_t *task;
1728 
1729 	/* is this a task management command */
1730 	if (msg->icss_task_msgid & MSG_ID_TM_BIT) {
1731 		return (STMF_SUCCESS);
1732 	}
1733 
1734 	task = find_task_from_msgid(msg->icss_lun_id, msg->icss_task_msgid);
1735 
1736 	if (task == NULL) {
1737 		return (STMF_SUCCESS);
1738 	}
1739 
1740 	task->task_scsi_status = msg->icss_status;
1741 	task->task_sense_data = msg->icss_sense;
1742 	task->task_sense_length = msg->icss_sense_len;
1743 	(void) stmf_send_scsi_status(task, STMF_IOF_LU_DONE);
1744 
1745 	return (STMF_SUCCESS);
1746 }
1747 
1748 /*
1749  * handles scsi data message from pppt
1750  */
1751 stmf_status_t
1752 stmf_ic_rx_scsi_data(stmf_ic_scsi_data_msg_t *msg)
1753 {
1754 	stmf_i_scsi_task_t *itask;
1755 	scsi_task_t *task;
1756 	stmf_xfer_data_t *xd = NULL;
1757 	stmf_data_buf_t *dbuf;
1758 	uint32_t sz, minsz, xd_sz, asz;
1759 
1760 	/* is this a task management command */
1761 	if (msg->icsd_task_msgid & MSG_ID_TM_BIT) {
1762 		return (STMF_SUCCESS);
1763 	}
1764 
1765 	task = find_task_from_msgid(msg->icsd_lun_id, msg->icsd_task_msgid);
1766 	if (task == NULL) {
1767 		stmf_ic_msg_t *ic_xfer_done_msg = NULL;
1768 		static uint64_t data_msg_id;
1769 		stmf_status_t ic_ret = STMF_FAILURE;
1770 		mutex_enter(&stmf_state.stmf_lock);
1771 		data_msg_id = stmf_proxy_msg_id++;
1772 		mutex_exit(&stmf_state.stmf_lock);
1773 		/*
1774 		 * send xfer done status to pppt
1775 		 * for now, set the session id to 0 as we cannot
1776 		 * ascertain it since we cannot find the task
1777 		 */
1778 		ic_xfer_done_msg = ic_scsi_data_xfer_done_msg_alloc(
1779 		    msg->icsd_task_msgid, 0, STMF_FAILURE, data_msg_id);
1780 		if (ic_xfer_done_msg) {
1781 			ic_ret = ic_tx_msg(ic_xfer_done_msg);
1782 			if (ic_ret != STMF_IC_MSG_SUCCESS) {
1783 				cmn_err(CE_WARN, "unable to xmit proxy msg");
1784 			}
1785 		}
1786 		return (STMF_FAILURE);
1787 	}
1788 
1789 	itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
1790 	dbuf = itask->itask_proxy_dbuf;
1791 
1792 	task->task_cmd_xfer_length += msg->icsd_data_len;
1793 
1794 	if (task->task_additional_flags &
1795 	    TASK_AF_NO_EXPECTED_XFER_LENGTH) {
1796 		task->task_expected_xfer_length =
1797 		    task->task_cmd_xfer_length;
1798 	}
1799 
1800 	sz = min(task->task_expected_xfer_length,
1801 	    task->task_cmd_xfer_length);
1802 
1803 	xd_sz = msg->icsd_data_len;
1804 	asz = xd_sz + sizeof (*xd) - 4;
1805 	xd = (stmf_xfer_data_t *)kmem_zalloc(asz, KM_NOSLEEP);
1806 
1807 	if (xd == NULL) {
1808 		stmf_abort(STMF_QUEUE_TASK_ABORT, task,
1809 		    STMF_ALLOC_FAILURE, NULL);
1810 		return (STMF_FAILURE);
1811 	}
1812 
1813 	xd->alloc_size = asz;
1814 	xd->size_left = xd_sz;
1815 	bcopy(msg->icsd_data, xd->buf, xd_sz);
1816 
1817 	sz = min(sz, xd->size_left);
1818 	xd->size_left = sz;
1819 	minsz = min(512, sz);
1820 
1821 	if (dbuf == NULL)
1822 		dbuf = stmf_alloc_dbuf(task, sz, &minsz, 0);
1823 	if (dbuf == NULL) {
1824 		kmem_free(xd, xd->alloc_size);
1825 		stmf_abort(STMF_QUEUE_TASK_ABORT, task,
1826 		    STMF_ALLOC_FAILURE, NULL);
1827 		return (STMF_FAILURE);
1828 	}
1829 	dbuf->db_lu_private = xd;
1830 	dbuf->db_relative_offset = task->task_nbytes_transferred;
1831 	stmf_xd_to_dbuf(dbuf, 0);
1832 
1833 	dbuf->db_flags = DB_DIRECTION_TO_RPORT;
1834 	(void) stmf_xfer_data(task, dbuf, 0);
1835 	return (STMF_SUCCESS);
1836 }
1837 
1838 stmf_status_t
1839 stmf_proxy_scsi_cmd(scsi_task_t *task, stmf_data_buf_t *dbuf)
1840 {
1841 	stmf_i_scsi_task_t *itask =
1842 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
1843 	stmf_i_local_port_t *ilport =
1844 	    (stmf_i_local_port_t *)task->task_lport->lport_stmf_private;
1845 	stmf_ic_msg_t *ic_cmd_msg;
1846 	stmf_ic_msg_status_t ic_ret;
1847 	stmf_status_t ret = STMF_FAILURE;
1848 
1849 	if (stmf_state.stmf_alua_state != 1) {
1850 		cmn_err(CE_WARN, "stmf alua state is disabled");
1851 		return (STMF_FAILURE);
1852 	}
1853 
1854 	if (ilport->ilport_proxy_registered == 0) {
1855 		return (STMF_FAILURE);
1856 	}
1857 
1858 	mutex_enter(&stmf_state.stmf_lock);
1859 	itask->itask_proxy_msg_id = stmf_proxy_msg_id++;
1860 	mutex_exit(&stmf_state.stmf_lock);
1861 	itask->itask_proxy_dbuf = dbuf;
1862 
1863 	/*
1864 	 * stmf will now take over the task handling for this task
1865 	 * but it still needs to be treated differently from other
1866 	 * default handled tasks, hence the ITASK_PROXY_TASK.
1867 	 * If this is a task management function, we're really just
1868 	 * duping the command to the peer. Set the TM bit so that
1869 	 * we can recognize this on return since we won't be completing
1870 	 * the proxied task in that case.
1871 	 */
1872 	if (task->task_mgmt_function) {
1873 		itask->itask_proxy_msg_id |= MSG_ID_TM_BIT;
1874 	} else {
1875 		uint32_t new, old;
1876 		do {
1877 			new = old = itask->itask_flags;
1878 			if (new & ITASK_BEING_ABORTED)
1879 				return (STMF_FAILURE);
1880 			new |= ITASK_DEFAULT_HANDLING | ITASK_PROXY_TASK;
1881 		} while (atomic_cas_32(&itask->itask_flags, old, new) != old);
1882 	}
1883 	if (dbuf) {
1884 		ic_cmd_msg = ic_scsi_cmd_msg_alloc(itask->itask_proxy_msg_id,
1885 		    task, dbuf->db_data_size, dbuf->db_sglist[0].seg_addr,
1886 		    itask->itask_proxy_msg_id);
1887 	} else {
1888 		ic_cmd_msg = ic_scsi_cmd_msg_alloc(itask->itask_proxy_msg_id,
1889 		    task, 0, NULL, itask->itask_proxy_msg_id);
1890 	}
1891 	if (ic_cmd_msg) {
1892 		ic_ret = ic_tx_msg(ic_cmd_msg);
1893 		if (ic_ret == STMF_IC_MSG_SUCCESS) {
1894 			ret = STMF_SUCCESS;
1895 		}
1896 	}
1897 	return (ret);
1898 }
1899 
1900 
1901 stmf_status_t
1902 pppt_modload()
1903 {
1904 	int error;
1905 
1906 	if (pppt_mod == NULL && ((pppt_mod =
1907 	    ddi_modopen("drv/pppt", KRTLD_MODE_FIRST, &error)) == NULL)) {
1908 		cmn_err(CE_WARN, "Unable to load pppt");
1909 		return (STMF_FAILURE);
1910 	}
1911 
1912 	if (ic_reg_port_msg_alloc == NULL && ((ic_reg_port_msg_alloc =
1913 	    (stmf_ic_reg_port_msg_alloc_func_t)
1914 	    ddi_modsym(pppt_mod, "stmf_ic_reg_port_msg_alloc",
1915 	    &error)) == NULL)) {
1916 		cmn_err(CE_WARN,
1917 		    "Unable to find symbol - stmf_ic_reg_port_msg_alloc");
1918 		return (STMF_FAILURE);
1919 	}
1920 
1921 
1922 	if (ic_dereg_port_msg_alloc == NULL && ((ic_dereg_port_msg_alloc =
1923 	    (stmf_ic_dereg_port_msg_alloc_func_t)
1924 	    ddi_modsym(pppt_mod, "stmf_ic_dereg_port_msg_alloc",
1925 	    &error)) == NULL)) {
1926 		cmn_err(CE_WARN,
1927 		    "Unable to find symbol - stmf_ic_dereg_port_msg_alloc");
1928 		return (STMF_FAILURE);
1929 	}
1930 
1931 	if (ic_reg_lun_msg_alloc == NULL && ((ic_reg_lun_msg_alloc =
1932 	    (stmf_ic_reg_lun_msg_alloc_func_t)
1933 	    ddi_modsym(pppt_mod, "stmf_ic_reg_lun_msg_alloc",
1934 	    &error)) == NULL)) {
1935 		cmn_err(CE_WARN,
1936 		    "Unable to find symbol - stmf_ic_reg_lun_msg_alloc");
1937 		return (STMF_FAILURE);
1938 	}
1939 
1940 	if (ic_lun_active_msg_alloc == NULL && ((ic_lun_active_msg_alloc =
1941 	    (stmf_ic_lun_active_msg_alloc_func_t)
1942 	    ddi_modsym(pppt_mod, "stmf_ic_lun_active_msg_alloc",
1943 	    &error)) == NULL)) {
1944 		cmn_err(CE_WARN,
1945 		    "Unable to find symbol - stmf_ic_lun_active_msg_alloc");
1946 		return (STMF_FAILURE);
1947 	}
1948 
1949 	if (ic_dereg_lun_msg_alloc == NULL && ((ic_dereg_lun_msg_alloc =
1950 	    (stmf_ic_dereg_lun_msg_alloc_func_t)
1951 	    ddi_modsym(pppt_mod, "stmf_ic_dereg_lun_msg_alloc",
1952 	    &error)) == NULL)) {
1953 		cmn_err(CE_WARN,
1954 		    "Unable to find symbol - stmf_ic_dereg_lun_msg_alloc");
1955 		return (STMF_FAILURE);
1956 	}
1957 
1958 	if (ic_scsi_cmd_msg_alloc == NULL && ((ic_scsi_cmd_msg_alloc =
1959 	    (stmf_ic_scsi_cmd_msg_alloc_func_t)
1960 	    ddi_modsym(pppt_mod, "stmf_ic_scsi_cmd_msg_alloc",
1961 	    &error)) == NULL)) {
1962 		cmn_err(CE_WARN,
1963 		    "Unable to find symbol - stmf_ic_scsi_cmd_msg_alloc");
1964 		return (STMF_FAILURE);
1965 	}
1966 
1967 	if (ic_scsi_data_xfer_done_msg_alloc == NULL &&
1968 	    ((ic_scsi_data_xfer_done_msg_alloc =
1969 	    (stmf_ic_scsi_data_xfer_done_msg_alloc_func_t)
1970 	    ddi_modsym(pppt_mod, "stmf_ic_scsi_data_xfer_done_msg_alloc",
1971 	    &error)) == NULL)) {
1972 		cmn_err(CE_WARN,
1973 		    "Unable to find symbol -"
1974 		    "stmf_ic_scsi_data_xfer_done_msg_alloc");
1975 		return (STMF_FAILURE);
1976 	}
1977 
1978 	if (ic_session_reg_msg_alloc == NULL &&
1979 	    ((ic_session_reg_msg_alloc =
1980 	    (stmf_ic_session_create_msg_alloc_func_t)
1981 	    ddi_modsym(pppt_mod, "stmf_ic_session_create_msg_alloc",
1982 	    &error)) == NULL)) {
1983 		cmn_err(CE_WARN,
1984 		    "Unable to find symbol -"
1985 		    "stmf_ic_session_create_msg_alloc");
1986 		return (STMF_FAILURE);
1987 	}
1988 
1989 	if (ic_session_dereg_msg_alloc == NULL &&
1990 	    ((ic_session_dereg_msg_alloc =
1991 	    (stmf_ic_session_destroy_msg_alloc_func_t)
1992 	    ddi_modsym(pppt_mod, "stmf_ic_session_destroy_msg_alloc",
1993 	    &error)) == NULL)) {
1994 		cmn_err(CE_WARN,
1995 		    "Unable to find symbol -"
1996 		    "stmf_ic_session_destroy_msg_alloc");
1997 		return (STMF_FAILURE);
1998 	}
1999 
2000 	if (ic_tx_msg == NULL && ((ic_tx_msg =
2001 	    (stmf_ic_tx_msg_func_t)ddi_modsym(pppt_mod, "stmf_ic_tx_msg",
2002 	    &error)) == NULL)) {
2003 		cmn_err(CE_WARN, "Unable to find symbol - stmf_ic_tx_msg");
2004 		return (STMF_FAILURE);
2005 	}
2006 
2007 	if (ic_msg_free == NULL && ((ic_msg_free =
2008 	    (stmf_ic_msg_free_func_t)ddi_modsym(pppt_mod, "stmf_ic_msg_free",
2009 	    &error)) == NULL)) {
2010 		cmn_err(CE_WARN, "Unable to find symbol - stmf_ic_msg_free");
2011 		return (STMF_FAILURE);
2012 	}
2013 	return (STMF_SUCCESS);
2014 }
2015 
2016 static void
2017 stmf_get_alua_state(stmf_alua_state_desc_t *alua_state)
2018 {
2019 	mutex_enter(&stmf_state.stmf_lock);
2020 	alua_state->alua_node = stmf_state.stmf_alua_node;
2021 	alua_state->alua_state = stmf_state.stmf_alua_state;
2022 	mutex_exit(&stmf_state.stmf_lock);
2023 }
2024 
2025 
2026 static int
2027 stmf_set_alua_state(stmf_alua_state_desc_t *alua_state)
2028 {
2029 	stmf_i_local_port_t *ilport;
2030 	stmf_i_lu_t *ilu;
2031 	stmf_lu_t *lu;
2032 	stmf_ic_msg_status_t ic_ret;
2033 	stmf_ic_msg_t *ic_reg_lun, *ic_reg_port;
2034 	stmf_local_port_t *lport;
2035 	int ret = 0;
2036 
2037 	if (alua_state->alua_state > 1 || alua_state->alua_node > 1) {
2038 		return (EINVAL);
2039 	}
2040 
2041 	mutex_enter(&stmf_state.stmf_lock);
2042 	if (alua_state->alua_state == 1) {
2043 		if (pppt_modload() == STMF_FAILURE) {
2044 			ret = EIO;
2045 			goto err;
2046 		}
2047 		if (alua_state->alua_node != 0) {
2048 			/* reset existing rtpids to new base */
2049 			stmf_rtpid_counter = 255;
2050 		}
2051 		stmf_state.stmf_alua_node = alua_state->alua_node;
2052 		stmf_state.stmf_alua_state = 1;
2053 		/* register existing local ports with ppp */
2054 		for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
2055 		    ilport = ilport->ilport_next) {
2056 			/* skip standby ports and non-alua participants */
2057 			if (ilport->ilport_standby == 1 ||
2058 			    ilport->ilport_alua == 0) {
2059 				continue;
2060 			}
2061 			if (alua_state->alua_node != 0) {
2062 				ilport->ilport_rtpid =
2063 				    atomic_add_16_nv(&stmf_rtpid_counter, 1);
2064 			}
2065 			lport = ilport->ilport_lport;
2066 			ic_reg_port = ic_reg_port_msg_alloc(
2067 			    lport->lport_id, ilport->ilport_rtpid,
2068 			    0, NULL, stmf_proxy_msg_id);
2069 			if (ic_reg_port) {
2070 				ic_ret = ic_tx_msg(ic_reg_port);
2071 				if (ic_ret == STMF_IC_MSG_SUCCESS) {
2072 					ilport->ilport_reg_msgid =
2073 					    stmf_proxy_msg_id++;
2074 				} else {
2075 					cmn_err(CE_WARN,
2076 					    "error on port registration "
2077 					    "port - %s",
2078 					    ilport->ilport_kstat_tgt_name);
2079 				}
2080 			}
2081 		}
2082 		/* register existing logical units */
2083 		for (ilu = stmf_state.stmf_ilulist; ilu != NULL;
2084 		    ilu = ilu->ilu_next) {
2085 			if (ilu->ilu_access != STMF_LU_ACTIVE) {
2086 				continue;
2087 			}
2088 			/* register with proxy module */
2089 			lu = ilu->ilu_lu;
2090 			if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 &&
2091 			    lu->lu_lp->lp_alua_support) {
2092 				ilu->ilu_alua = 1;
2093 				/* allocate the register message */
2094 				ic_reg_lun = ic_reg_lun_msg_alloc(
2095 				    lu->lu_id->ident, lu->lu_lp->lp_name,
2096 				    lu->lu_proxy_reg_arg_len,
2097 				    (uint8_t *)lu->lu_proxy_reg_arg,
2098 				    stmf_proxy_msg_id);
2099 				/* send the message */
2100 				if (ic_reg_lun) {
2101 					ic_ret = ic_tx_msg(ic_reg_lun);
2102 					if (ic_ret == STMF_IC_MSG_SUCCESS) {
2103 						stmf_proxy_msg_id++;
2104 					}
2105 				}
2106 			}
2107 		}
2108 	} else {
2109 		stmf_state.stmf_alua_state = 0;
2110 	}
2111 
2112 err:
2113 	mutex_exit(&stmf_state.stmf_lock);
2114 	return (ret);
2115 }
2116 
2117 
2118 typedef struct {
2119 	void	*bp;	/* back pointer from internal struct to main struct */
2120 	int	alloc_size;
2121 } __istmf_t;
2122 
2123 typedef struct {
2124 	__istmf_t	*fp;	/* Framework private */
2125 	void		*cp;	/* Caller private */
2126 	void		*ss;	/* struct specific */
2127 } __stmf_t;
2128 
2129 static struct {
2130 	int shared;
2131 	int fw_private;
2132 } stmf_sizes[] = { { 0, 0 },
2133 	{ GET_STRUCT_SIZE(stmf_lu_provider_t),
2134 		GET_STRUCT_SIZE(stmf_i_lu_provider_t) },
2135 	{ GET_STRUCT_SIZE(stmf_port_provider_t),
2136 		GET_STRUCT_SIZE(stmf_i_port_provider_t) },
2137 	{ GET_STRUCT_SIZE(stmf_local_port_t),
2138 		GET_STRUCT_SIZE(stmf_i_local_port_t) },
2139 	{ GET_STRUCT_SIZE(stmf_lu_t),
2140 		GET_STRUCT_SIZE(stmf_i_lu_t) },
2141 	{ GET_STRUCT_SIZE(stmf_scsi_session_t),
2142 		GET_STRUCT_SIZE(stmf_i_scsi_session_t) },
2143 	{ GET_STRUCT_SIZE(scsi_task_t),
2144 		GET_STRUCT_SIZE(stmf_i_scsi_task_t) },
2145 	{ GET_STRUCT_SIZE(stmf_data_buf_t),
2146 		GET_STRUCT_SIZE(__istmf_t) },
2147 	{ GET_STRUCT_SIZE(stmf_dbuf_store_t),
2148 		GET_STRUCT_SIZE(__istmf_t) }
2149 
2150 };
2151 
2152 void *
2153 stmf_alloc(stmf_struct_id_t struct_id, int additional_size, int flags)
2154 {
2155 	int stmf_size;
2156 	int kmem_flag;
2157 	__stmf_t *sh;
2158 
2159 	if ((struct_id == 0) || (struct_id >= STMF_MAX_STRUCT_IDS))
2160 		return (NULL);
2161 
2162 	if ((curthread->t_flag & T_INTR_THREAD) || (flags & AF_FORCE_NOSLEEP)) {
2163 		kmem_flag = KM_NOSLEEP;
2164 	} else {
2165 		kmem_flag = KM_SLEEP;
2166 	}
2167 
2168 	additional_size = (additional_size + 7) & (~7);
2169 	stmf_size = stmf_sizes[struct_id].shared +
2170 	    stmf_sizes[struct_id].fw_private + additional_size;
2171 
2172 	if (flags & AF_DONTZERO)
2173 		sh = (__stmf_t *)kmem_alloc(stmf_size, kmem_flag);
2174 	else
2175 		sh = (__stmf_t *)kmem_zalloc(stmf_size, kmem_flag);
2176 
2177 	if (sh == NULL)
2178 		return (NULL);
2179 
2180 	/*
2181 	 * In principle, the implementation inside stmf_alloc should not
2182 	 * be changed anyway. But the original order of framework private
2183 	 * data and caller private data does not support sglist in the caller
2184 	 * private data.
2185 	 * To work around this, the memory segments of framework private
2186 	 * data and caller private data are re-ordered here.
2187 	 * A better solution is to provide a specific interface to allocate
2188 	 * the sglist, then we will not need this workaround any more.
2189 	 * But before the new interface is available, the memory segment
2190 	 * ordering should be kept as is.
2191 	 */
2192 	sh->cp = GET_BYTE_OFFSET(sh, stmf_sizes[struct_id].shared);
2193 	sh->fp = (__istmf_t *)GET_BYTE_OFFSET(sh,
2194 	    stmf_sizes[struct_id].shared + additional_size);
2195 
2196 	sh->fp->bp = sh;
2197 	/* Just store the total size instead of storing additional size */
2198 	sh->fp->alloc_size = stmf_size;
2199 
2200 	return (sh);
2201 }
2202 
2203 void
2204 stmf_free(void *ptr)
2205 {
2206 	__stmf_t *sh = (__stmf_t *)ptr;
2207 
2208 	/*
2209 	 * So far we dont need any struct specific processing. If such
2210 	 * a need ever arises, then store the struct id in the framework
2211 	 * private section and get it here as sh->fp->struct_id.
2212 	 */
2213 	kmem_free(ptr, sh->fp->alloc_size);
2214 }
2215 
2216 /*
2217  * Given a pointer to stmf_lu_t, verifies if this lu is registered with the
2218  * framework and returns a pointer to framework private data for the lu.
2219  * Returns NULL if the lu was not found.
2220  */
2221 stmf_i_lu_t *
2222 stmf_lookup_lu(stmf_lu_t *lu)
2223 {
2224 	stmf_i_lu_t *ilu;
2225 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
2226 
2227 	for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) {
2228 		if (ilu->ilu_lu == lu)
2229 			return (ilu);
2230 	}
2231 	return (NULL);
2232 }
2233 
2234 /*
2235  * Given a pointer to stmf_local_port_t, verifies if this lport is registered
2236  * with the framework and returns a pointer to framework private data for
2237  * the lport.
2238  * Returns NULL if the lport was not found.
2239  */
2240 stmf_i_local_port_t *
2241 stmf_lookup_lport(stmf_local_port_t *lport)
2242 {
2243 	stmf_i_local_port_t *ilport;
2244 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
2245 
2246 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
2247 	    ilport = ilport->ilport_next) {
2248 		if (ilport->ilport_lport == lport)
2249 			return (ilport);
2250 	}
2251 	return (NULL);
2252 }
2253 
2254 stmf_status_t
2255 stmf_register_lu_provider(stmf_lu_provider_t *lp)
2256 {
2257 	stmf_i_lu_provider_t *ilp = (stmf_i_lu_provider_t *)lp->lp_stmf_private;
2258 	stmf_pp_data_t *ppd;
2259 	uint32_t cb_flags;
2260 
2261 	if (lp->lp_lpif_rev != LPIF_REV_1 && lp->lp_lpif_rev != LPIF_REV_2)
2262 		return (STMF_FAILURE);
2263 
2264 	mutex_enter(&stmf_state.stmf_lock);
2265 	ilp->ilp_next = stmf_state.stmf_ilplist;
2266 	stmf_state.stmf_ilplist = ilp;
2267 	stmf_state.stmf_nlps++;
2268 
2269 	/* See if we need to do a callback */
2270 	for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
2271 		if (strcmp(ppd->ppd_name, lp->lp_name) == 0) {
2272 			break;
2273 		}
2274 	}
2275 	if ((ppd == NULL) || (ppd->ppd_nv == NULL)) {
2276 		goto rlp_bail_out;
2277 	}
2278 	ilp->ilp_ppd = ppd;
2279 	ppd->ppd_provider = ilp;
2280 	if (lp->lp_cb == NULL)
2281 		goto rlp_bail_out;
2282 	ilp->ilp_cb_in_progress = 1;
2283 	cb_flags = STMF_PCB_PREG_COMPLETE;
2284 	if (stmf_state.stmf_config_state == STMF_CONFIG_INIT)
2285 		cb_flags |= STMF_PCB_STMF_ONLINING;
2286 	mutex_exit(&stmf_state.stmf_lock);
2287 	lp->lp_cb(lp, STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
2288 	mutex_enter(&stmf_state.stmf_lock);
2289 	ilp->ilp_cb_in_progress = 0;
2290 
2291 rlp_bail_out:
2292 	mutex_exit(&stmf_state.stmf_lock);
2293 
2294 	return (STMF_SUCCESS);
2295 }
2296 
2297 stmf_status_t
2298 stmf_deregister_lu_provider(stmf_lu_provider_t *lp)
2299 {
2300 	stmf_i_lu_provider_t	**ppilp;
2301 	stmf_i_lu_provider_t *ilp = (stmf_i_lu_provider_t *)lp->lp_stmf_private;
2302 
2303 	mutex_enter(&stmf_state.stmf_lock);
2304 	if (ilp->ilp_nlus || ilp->ilp_cb_in_progress) {
2305 		mutex_exit(&stmf_state.stmf_lock);
2306 		return (STMF_BUSY);
2307 	}
2308 	for (ppilp = &stmf_state.stmf_ilplist; *ppilp != NULL;
2309 	    ppilp = &((*ppilp)->ilp_next)) {
2310 		if (*ppilp == ilp) {
2311 			*ppilp = ilp->ilp_next;
2312 			stmf_state.stmf_nlps--;
2313 			if (ilp->ilp_ppd) {
2314 				ilp->ilp_ppd->ppd_provider = NULL;
2315 				ilp->ilp_ppd = NULL;
2316 			}
2317 			mutex_exit(&stmf_state.stmf_lock);
2318 			return (STMF_SUCCESS);
2319 		}
2320 	}
2321 	mutex_exit(&stmf_state.stmf_lock);
2322 	return (STMF_NOT_FOUND);
2323 }
2324 
2325 stmf_status_t
2326 stmf_register_port_provider(stmf_port_provider_t *pp)
2327 {
2328 	stmf_i_port_provider_t *ipp =
2329 	    (stmf_i_port_provider_t *)pp->pp_stmf_private;
2330 	stmf_pp_data_t *ppd;
2331 	uint32_t cb_flags;
2332 
2333 	if (pp->pp_portif_rev != PORTIF_REV_1)
2334 		return (STMF_FAILURE);
2335 
2336 	mutex_enter(&stmf_state.stmf_lock);
2337 	ipp->ipp_next = stmf_state.stmf_ipplist;
2338 	stmf_state.stmf_ipplist = ipp;
2339 	stmf_state.stmf_npps++;
2340 	/* See if we need to do a callback */
2341 	for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
2342 		if (strcmp(ppd->ppd_name, pp->pp_name) == 0) {
2343 			break;
2344 		}
2345 	}
2346 	if ((ppd == NULL) || (ppd->ppd_nv == NULL)) {
2347 		goto rpp_bail_out;
2348 	}
2349 	ipp->ipp_ppd = ppd;
2350 	ppd->ppd_provider = ipp;
2351 	if (pp->pp_cb == NULL)
2352 		goto rpp_bail_out;
2353 	ipp->ipp_cb_in_progress = 1;
2354 	cb_flags = STMF_PCB_PREG_COMPLETE;
2355 	if (stmf_state.stmf_config_state == STMF_CONFIG_INIT)
2356 		cb_flags |= STMF_PCB_STMF_ONLINING;
2357 	mutex_exit(&stmf_state.stmf_lock);
2358 	pp->pp_cb(pp, STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
2359 	mutex_enter(&stmf_state.stmf_lock);
2360 	ipp->ipp_cb_in_progress = 0;
2361 
2362 rpp_bail_out:
2363 	mutex_exit(&stmf_state.stmf_lock);
2364 
2365 	return (STMF_SUCCESS);
2366 }
2367 
2368 stmf_status_t
2369 stmf_deregister_port_provider(stmf_port_provider_t *pp)
2370 {
2371 	stmf_i_port_provider_t *ipp =
2372 	    (stmf_i_port_provider_t *)pp->pp_stmf_private;
2373 	stmf_i_port_provider_t **ppipp;
2374 
2375 	mutex_enter(&stmf_state.stmf_lock);
2376 	if (ipp->ipp_npps || ipp->ipp_cb_in_progress) {
2377 		mutex_exit(&stmf_state.stmf_lock);
2378 		return (STMF_BUSY);
2379 	}
2380 	for (ppipp = &stmf_state.stmf_ipplist; *ppipp != NULL;
2381 	    ppipp = &((*ppipp)->ipp_next)) {
2382 		if (*ppipp == ipp) {
2383 			*ppipp = ipp->ipp_next;
2384 			stmf_state.stmf_npps--;
2385 			if (ipp->ipp_ppd) {
2386 				ipp->ipp_ppd->ppd_provider = NULL;
2387 				ipp->ipp_ppd = NULL;
2388 			}
2389 			mutex_exit(&stmf_state.stmf_lock);
2390 			return (STMF_SUCCESS);
2391 		}
2392 	}
2393 	mutex_exit(&stmf_state.stmf_lock);
2394 	return (STMF_NOT_FOUND);
2395 }
2396 
2397 int
2398 stmf_load_ppd_ioctl(stmf_ppioctl_data_t *ppi, uint64_t *ppi_token,
2399     uint32_t *err_ret)
2400 {
2401 	stmf_i_port_provider_t		*ipp;
2402 	stmf_i_lu_provider_t		*ilp;
2403 	stmf_pp_data_t			*ppd;
2404 	nvlist_t			*nv;
2405 	int				s;
2406 	int				ret;
2407 
2408 	*err_ret = 0;
2409 
2410 	if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) {
2411 		return (EINVAL);
2412 	}
2413 
2414 	mutex_enter(&stmf_state.stmf_lock);
2415 	for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
2416 		if (ppi->ppi_lu_provider) {
2417 			if (!ppd->ppd_lu_provider)
2418 				continue;
2419 		} else if (ppi->ppi_port_provider) {
2420 			if (!ppd->ppd_port_provider)
2421 				continue;
2422 		}
2423 		if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0)
2424 			break;
2425 	}
2426 
2427 	if (ppd == NULL) {
2428 		/* New provider */
2429 		s = strlen(ppi->ppi_name);
2430 		if (s > 254) {
2431 			mutex_exit(&stmf_state.stmf_lock);
2432 			return (EINVAL);
2433 		}
2434 		s += sizeof (stmf_pp_data_t) - 7;
2435 
2436 		ppd = kmem_zalloc(s, KM_NOSLEEP);
2437 		if (ppd == NULL) {
2438 			mutex_exit(&stmf_state.stmf_lock);
2439 			return (ENOMEM);
2440 		}
2441 		ppd->ppd_alloc_size = s;
2442 		(void) strcpy(ppd->ppd_name, ppi->ppi_name);
2443 
2444 		/* See if this provider already exists */
2445 		if (ppi->ppi_lu_provider) {
2446 			ppd->ppd_lu_provider = 1;
2447 			for (ilp = stmf_state.stmf_ilplist; ilp != NULL;
2448 			    ilp = ilp->ilp_next) {
2449 				if (strcmp(ppi->ppi_name,
2450 				    ilp->ilp_lp->lp_name) == 0) {
2451 					ppd->ppd_provider = ilp;
2452 					ilp->ilp_ppd = ppd;
2453 					break;
2454 				}
2455 			}
2456 		} else {
2457 			ppd->ppd_port_provider = 1;
2458 			for (ipp = stmf_state.stmf_ipplist; ipp != NULL;
2459 			    ipp = ipp->ipp_next) {
2460 				if (strcmp(ppi->ppi_name,
2461 				    ipp->ipp_pp->pp_name) == 0) {
2462 					ppd->ppd_provider = ipp;
2463 					ipp->ipp_ppd = ppd;
2464 					break;
2465 				}
2466 			}
2467 		}
2468 
2469 		/* Link this ppd in */
2470 		ppd->ppd_next = stmf_state.stmf_ppdlist;
2471 		stmf_state.stmf_ppdlist = ppd;
2472 	}
2473 
2474 	/*
2475 	 * User is requesting that the token be checked.
2476 	 * If there was another set after the user's get
2477 	 * it's an error
2478 	 */
2479 	if (ppi->ppi_token_valid) {
2480 		if (ppi->ppi_token != ppd->ppd_token) {
2481 			*err_ret = STMF_IOCERR_PPD_UPDATED;
2482 			mutex_exit(&stmf_state.stmf_lock);
2483 			return (EINVAL);
2484 		}
2485 	}
2486 
2487 	if ((ret = nvlist_unpack((char *)ppi->ppi_data,
2488 	    (size_t)ppi->ppi_data_size, &nv, KM_NOSLEEP)) != 0) {
2489 		mutex_exit(&stmf_state.stmf_lock);
2490 		return (ret);
2491 	}
2492 
2493 	/* Free any existing lists and add this one to the ppd */
2494 	if (ppd->ppd_nv)
2495 		nvlist_free(ppd->ppd_nv);
2496 	ppd->ppd_nv = nv;
2497 
2498 	/* set the token for writes */
2499 	ppd->ppd_token++;
2500 	/* return token to caller */
2501 	if (ppi_token) {
2502 		*ppi_token = ppd->ppd_token;
2503 	}
2504 
2505 	/* If there is a provider registered, do the notifications */
2506 	if (ppd->ppd_provider) {
2507 		uint32_t cb_flags = 0;
2508 
2509 		if (stmf_state.stmf_config_state == STMF_CONFIG_INIT)
2510 			cb_flags |= STMF_PCB_STMF_ONLINING;
2511 		if (ppi->ppi_lu_provider) {
2512 			ilp = (stmf_i_lu_provider_t *)ppd->ppd_provider;
2513 			if (ilp->ilp_lp->lp_cb == NULL)
2514 				goto bail_out;
2515 			ilp->ilp_cb_in_progress = 1;
2516 			mutex_exit(&stmf_state.stmf_lock);
2517 			ilp->ilp_lp->lp_cb(ilp->ilp_lp,
2518 			    STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
2519 			mutex_enter(&stmf_state.stmf_lock);
2520 			ilp->ilp_cb_in_progress = 0;
2521 		} else {
2522 			ipp = (stmf_i_port_provider_t *)ppd->ppd_provider;
2523 			if (ipp->ipp_pp->pp_cb == NULL)
2524 				goto bail_out;
2525 			ipp->ipp_cb_in_progress = 1;
2526 			mutex_exit(&stmf_state.stmf_lock);
2527 			ipp->ipp_pp->pp_cb(ipp->ipp_pp,
2528 			    STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
2529 			mutex_enter(&stmf_state.stmf_lock);
2530 			ipp->ipp_cb_in_progress = 0;
2531 		}
2532 	}
2533 
2534 bail_out:
2535 	mutex_exit(&stmf_state.stmf_lock);
2536 
2537 	return (0);
2538 }
2539 
2540 void
2541 stmf_delete_ppd(stmf_pp_data_t *ppd)
2542 {
2543 	stmf_pp_data_t **pppd;
2544 
2545 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
2546 	if (ppd->ppd_provider) {
2547 		if (ppd->ppd_lu_provider) {
2548 			((stmf_i_lu_provider_t *)
2549 			    ppd->ppd_provider)->ilp_ppd = NULL;
2550 		} else {
2551 			((stmf_i_port_provider_t *)
2552 			    ppd->ppd_provider)->ipp_ppd = NULL;
2553 		}
2554 		ppd->ppd_provider = NULL;
2555 	}
2556 
2557 	for (pppd = &stmf_state.stmf_ppdlist; *pppd != NULL;
2558 	    pppd = &((*pppd)->ppd_next)) {
2559 		if (*pppd == ppd)
2560 			break;
2561 	}
2562 
2563 	if (*pppd == NULL)
2564 		return;
2565 
2566 	*pppd = ppd->ppd_next;
2567 	if (ppd->ppd_nv)
2568 		nvlist_free(ppd->ppd_nv);
2569 
2570 	kmem_free(ppd, ppd->ppd_alloc_size);
2571 }
2572 
2573 int
2574 stmf_delete_ppd_ioctl(stmf_ppioctl_data_t *ppi)
2575 {
2576 	stmf_pp_data_t *ppd;
2577 	int ret = ENOENT;
2578 
2579 	if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) {
2580 		return (EINVAL);
2581 	}
2582 
2583 	mutex_enter(&stmf_state.stmf_lock);
2584 
2585 	for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
2586 		if (ppi->ppi_lu_provider) {
2587 			if (!ppd->ppd_lu_provider)
2588 				continue;
2589 		} else if (ppi->ppi_port_provider) {
2590 			if (!ppd->ppd_port_provider)
2591 				continue;
2592 		}
2593 		if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0)
2594 			break;
2595 	}
2596 
2597 	if (ppd) {
2598 		ret = 0;
2599 		stmf_delete_ppd(ppd);
2600 	}
2601 	mutex_exit(&stmf_state.stmf_lock);
2602 
2603 	return (ret);
2604 }
2605 
2606 int
2607 stmf_get_ppd_ioctl(stmf_ppioctl_data_t *ppi, stmf_ppioctl_data_t *ppi_out,
2608     uint32_t *err_ret)
2609 {
2610 	stmf_pp_data_t *ppd;
2611 	size_t req_size;
2612 	int ret = ENOENT;
2613 	char *bufp = (char *)ppi_out->ppi_data;
2614 
2615 	if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) {
2616 		return (EINVAL);
2617 	}
2618 
2619 	mutex_enter(&stmf_state.stmf_lock);
2620 
2621 	for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
2622 		if (ppi->ppi_lu_provider) {
2623 			if (!ppd->ppd_lu_provider)
2624 				continue;
2625 		} else if (ppi->ppi_port_provider) {
2626 			if (!ppd->ppd_port_provider)
2627 				continue;
2628 		}
2629 		if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0)
2630 			break;
2631 	}
2632 
2633 	if (ppd && ppd->ppd_nv) {
2634 		ppi_out->ppi_token = ppd->ppd_token;
2635 		if ((ret = nvlist_size(ppd->ppd_nv, &req_size,
2636 		    NV_ENCODE_XDR)) != 0) {
2637 			goto done;
2638 		}
2639 		ppi_out->ppi_data_size = req_size;
2640 		if (req_size > ppi->ppi_data_size) {
2641 			*err_ret = STMF_IOCERR_INSUFFICIENT_BUF;
2642 			ret = EINVAL;
2643 			goto done;
2644 		}
2645 
2646 		if ((ret = nvlist_pack(ppd->ppd_nv, &bufp, &req_size,
2647 		    NV_ENCODE_XDR, 0)) != 0) {
2648 			goto done;
2649 		}
2650 		ret = 0;
2651 	}
2652 
2653 done:
2654 	mutex_exit(&stmf_state.stmf_lock);
2655 
2656 	return (ret);
2657 }
2658 
2659 void
2660 stmf_delete_all_ppds()
2661 {
2662 	stmf_pp_data_t *ppd, *nppd;
2663 
2664 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
2665 	for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = nppd) {
2666 		nppd = ppd->ppd_next;
2667 		stmf_delete_ppd(ppd);
2668 	}
2669 }
2670 
2671 /*
2672  * 16 is the max string length of a protocol_ident, increase
2673  * the size if needed.
2674  */
2675 #define	STMF_KSTAT_LU_SZ	(STMF_GUID_INPUT + 1 + 256)
2676 #define	STMF_KSTAT_TGT_SZ	(256 * 2 + 16)
2677 
2678 /*
2679  * This array matches the Protocol Identifier in stmf_ioctl.h
2680  */
2681 #define	MAX_PROTO_STR_LEN	32
2682 
2683 char *protocol_ident[PROTOCOL_ANY] = {
2684 	"Fibre Channel",
2685 	"Parallel SCSI",
2686 	"SSA",
2687 	"IEEE_1394",
2688 	"SRP",
2689 	"iSCSI",
2690 	"SAS",
2691 	"ADT",
2692 	"ATAPI",
2693 	"UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"
2694 };
2695 
2696 /*
2697  * Update the lun wait/run queue count
2698  */
2699 static void
2700 stmf_update_kstat_lu_q(scsi_task_t *task, void func())
2701 {
2702 	stmf_i_lu_t		*ilu;
2703 	kstat_io_t		*kip;
2704 
2705 	if (task->task_lu == dlun0)
2706 		return;
2707 	ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
2708 	if (ilu != NULL && ilu->ilu_kstat_io != NULL) {
2709 		kip = KSTAT_IO_PTR(ilu->ilu_kstat_io);
2710 		if (kip != NULL) {
2711 			func(kip);
2712 		}
2713 	}
2714 }
2715 
2716 /*
2717  * Update the target(lport) wait/run queue count
2718  */
2719 static void
2720 stmf_update_kstat_lport_q(scsi_task_t *task, void func())
2721 {
2722 	stmf_i_local_port_t	*ilp;
2723 	kstat_io_t		*kip;
2724 
2725 	ilp = (stmf_i_local_port_t *)task->task_lport->lport_stmf_private;
2726 	if (ilp != NULL && ilp->ilport_kstat_io != NULL) {
2727 		kip = KSTAT_IO_PTR(ilp->ilport_kstat_io);
2728 		if (kip != NULL) {
2729 			mutex_enter(ilp->ilport_kstat_io->ks_lock);
2730 			func(kip);
2731 			mutex_exit(ilp->ilport_kstat_io->ks_lock);
2732 		}
2733 	}
2734 }
2735 
2736 static void
2737 stmf_update_kstat_lport_io(scsi_task_t *task, stmf_data_buf_t *dbuf)
2738 {
2739 	stmf_i_local_port_t	*ilp;
2740 	kstat_io_t		*kip;
2741 
2742 	ilp = (stmf_i_local_port_t *)task->task_lport->lport_stmf_private;
2743 	if (ilp != NULL && ilp->ilport_kstat_io != NULL) {
2744 		kip = KSTAT_IO_PTR(ilp->ilport_kstat_io);
2745 		if (kip != NULL) {
2746 			mutex_enter(ilp->ilport_kstat_io->ks_lock);
2747 			STMF_UPDATE_KSTAT_IO(kip, dbuf);
2748 			mutex_exit(ilp->ilport_kstat_io->ks_lock);
2749 		}
2750 	}
2751 }
2752 
2753 static void
2754 stmf_update_kstat_lu_io(scsi_task_t *task, stmf_data_buf_t *dbuf)
2755 {
2756 	stmf_i_lu_t		*ilu;
2757 	kstat_io_t		*kip;
2758 
2759 	ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
2760 	if (ilu != NULL && ilu->ilu_kstat_io != NULL) {
2761 		kip = KSTAT_IO_PTR(ilu->ilu_kstat_io);
2762 		if (kip != NULL) {
2763 			mutex_enter(ilu->ilu_kstat_io->ks_lock);
2764 			STMF_UPDATE_KSTAT_IO(kip, dbuf);
2765 			mutex_exit(ilu->ilu_kstat_io->ks_lock);
2766 		}
2767 	}
2768 }
2769 
2770 static void
2771 stmf_create_kstat_lu(stmf_i_lu_t *ilu)
2772 {
2773 	char				ks_nm[KSTAT_STRLEN];
2774 	stmf_kstat_lu_info_t		*ks_lu;
2775 
2776 	/* create kstat lun info */
2777 	ks_lu = (stmf_kstat_lu_info_t *)kmem_zalloc(STMF_KSTAT_LU_SZ,
2778 	    KM_NOSLEEP);
2779 	if (ks_lu == NULL) {
2780 		cmn_err(CE_WARN, "STMF: kmem_zalloc failed");
2781 		return;
2782 	}
2783 
2784 	bzero(ks_nm, sizeof (ks_nm));
2785 	(void) sprintf(ks_nm, "stmf_lu_%"PRIxPTR"", (uintptr_t)ilu);
2786 	if ((ilu->ilu_kstat_info = kstat_create(STMF_MODULE_NAME, 0,
2787 	    ks_nm, "misc", KSTAT_TYPE_NAMED,
2788 	    sizeof (stmf_kstat_lu_info_t) / sizeof (kstat_named_t),
2789 	    KSTAT_FLAG_VIRTUAL)) == NULL) {
2790 		kmem_free(ks_lu, STMF_KSTAT_LU_SZ);
2791 		cmn_err(CE_WARN, "STMF: kstat_create lu failed");
2792 		return;
2793 	}
2794 
2795 	ilu->ilu_kstat_info->ks_data_size = STMF_KSTAT_LU_SZ;
2796 	ilu->ilu_kstat_info->ks_data = ks_lu;
2797 
2798 	kstat_named_init(&ks_lu->i_lun_guid, "lun-guid",
2799 	    KSTAT_DATA_STRING);
2800 	kstat_named_init(&ks_lu->i_lun_alias, "lun-alias",
2801 	    KSTAT_DATA_STRING);
2802 
2803 	/* convert guid to hex string */
2804 	int		i;
2805 	uint8_t		*p = ilu->ilu_lu->lu_id->ident;
2806 	bzero(ilu->ilu_ascii_hex_guid, sizeof (ilu->ilu_ascii_hex_guid));
2807 	for (i = 0; i < STMF_GUID_INPUT / 2; i++) {
2808 		(void) sprintf(&ilu->ilu_ascii_hex_guid[i * 2], "%02x", p[i]);
2809 	}
2810 	kstat_named_setstr(&ks_lu->i_lun_guid,
2811 	    (const char *)ilu->ilu_ascii_hex_guid);
2812 	kstat_named_setstr(&ks_lu->i_lun_alias,
2813 	    (const char *)ilu->ilu_lu->lu_alias);
2814 	kstat_install(ilu->ilu_kstat_info);
2815 
2816 	/* create kstat lun io */
2817 	bzero(ks_nm, sizeof (ks_nm));
2818 	(void) sprintf(ks_nm, "stmf_lu_io_%"PRIxPTR"", (uintptr_t)ilu);
2819 	if ((ilu->ilu_kstat_io = kstat_create(STMF_MODULE_NAME, 0,
2820 	    ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) {
2821 		cmn_err(CE_WARN, "STMF: kstat_create lu_io failed");
2822 		return;
2823 	}
2824 	mutex_init(&ilu->ilu_kstat_lock, NULL, MUTEX_DRIVER, 0);
2825 	ilu->ilu_kstat_io->ks_lock = &ilu->ilu_kstat_lock;
2826 	kstat_install(ilu->ilu_kstat_io);
2827 }
2828 
2829 static void
2830 stmf_create_kstat_lport(stmf_i_local_port_t *ilport)
2831 {
2832 	char				ks_nm[KSTAT_STRLEN];
2833 	stmf_kstat_tgt_info_t		*ks_tgt;
2834 	int				id, len;
2835 
2836 	/* create kstat lport info */
2837 	ks_tgt = (stmf_kstat_tgt_info_t *)kmem_zalloc(STMF_KSTAT_TGT_SZ,
2838 	    KM_NOSLEEP);
2839 	if (ks_tgt == NULL) {
2840 		cmn_err(CE_WARN, "STMF: kmem_zalloc failed");
2841 		return;
2842 	}
2843 
2844 	bzero(ks_nm, sizeof (ks_nm));
2845 	(void) sprintf(ks_nm, "stmf_tgt_%"PRIxPTR"", (uintptr_t)ilport);
2846 	if ((ilport->ilport_kstat_info = kstat_create(STMF_MODULE_NAME,
2847 	    0, ks_nm, "misc", KSTAT_TYPE_NAMED,
2848 	    sizeof (stmf_kstat_tgt_info_t) / sizeof (kstat_named_t),
2849 	    KSTAT_FLAG_VIRTUAL)) == NULL) {
2850 		kmem_free(ks_tgt, STMF_KSTAT_TGT_SZ);
2851 		cmn_err(CE_WARN, "STMF: kstat_create target failed");
2852 		return;
2853 	}
2854 
2855 	ilport->ilport_kstat_info->ks_data_size = STMF_KSTAT_TGT_SZ;
2856 	ilport->ilport_kstat_info->ks_data = ks_tgt;
2857 
2858 	kstat_named_init(&ks_tgt->i_tgt_name, "target-name",
2859 	    KSTAT_DATA_STRING);
2860 	kstat_named_init(&ks_tgt->i_tgt_alias, "target-alias",
2861 	    KSTAT_DATA_STRING);
2862 	kstat_named_init(&ks_tgt->i_protocol, "protocol",
2863 	    KSTAT_DATA_STRING);
2864 
2865 	/* ident might not be null terminated */
2866 	len = ilport->ilport_lport->lport_id->ident_length;
2867 	bcopy(ilport->ilport_lport->lport_id->ident,
2868 	    ilport->ilport_kstat_tgt_name, len);
2869 	ilport->ilport_kstat_tgt_name[len + 1] = NULL;
2870 	kstat_named_setstr(&ks_tgt->i_tgt_name,
2871 	    (const char *)ilport->ilport_kstat_tgt_name);
2872 	kstat_named_setstr(&ks_tgt->i_tgt_alias,
2873 	    (const char *)ilport->ilport_lport->lport_alias);
2874 	/* protocol */
2875 	if ((id = ilport->ilport_lport->lport_id->protocol_id) > PROTOCOL_ANY) {
2876 		cmn_err(CE_WARN, "STMF: protocol_id out of bound");
2877 		id = PROTOCOL_ANY;
2878 	}
2879 	kstat_named_setstr(&ks_tgt->i_protocol, protocol_ident[id]);
2880 	kstat_install(ilport->ilport_kstat_info);
2881 
2882 	/* create kstat lport io */
2883 	bzero(ks_nm, sizeof (ks_nm));
2884 	(void) sprintf(ks_nm, "stmf_tgt_io_%"PRIxPTR"", (uintptr_t)ilport);
2885 	if ((ilport->ilport_kstat_io = kstat_create(STMF_MODULE_NAME, 0,
2886 	    ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) {
2887 		cmn_err(CE_WARN, "STMF: kstat_create target_io failed");
2888 		return;
2889 	}
2890 	mutex_init(&ilport->ilport_kstat_lock, NULL, MUTEX_DRIVER, 0);
2891 	ilport->ilport_kstat_io->ks_lock = &ilport->ilport_kstat_lock;
2892 	kstat_install(ilport->ilport_kstat_io);
2893 }
2894 
2895 /*
2896  * set the asymmetric access state for a logical unit
2897  * caller is responsible for establishing SCSI unit attention on
2898  * state change
2899  */
2900 stmf_status_t
2901 stmf_set_lu_access(stmf_lu_t *lu, uint8_t access_state)
2902 {
2903 	stmf_i_lu_t *ilu;
2904 	uint8_t *p1, *p2;
2905 
2906 	if ((access_state != STMF_LU_STANDBY) &&
2907 	    (access_state != STMF_LU_ACTIVE)) {
2908 		return (STMF_INVALID_ARG);
2909 	}
2910 
2911 	p1 = &lu->lu_id->ident[0];
2912 	mutex_enter(&stmf_state.stmf_lock);
2913 	if (stmf_state.stmf_inventory_locked) {
2914 		mutex_exit(&stmf_state.stmf_lock);
2915 		return (STMF_BUSY);
2916 	}
2917 
2918 	for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) {
2919 		p2 = &ilu->ilu_lu->lu_id->ident[0];
2920 		if (bcmp(p1, p2, 16) == 0) {
2921 			break;
2922 		}
2923 	}
2924 
2925 	if (!ilu) {
2926 		ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
2927 	} else {
2928 		/*
2929 		 * We're changing access state on an existing logical unit
2930 		 * Send the proxy registration message for this logical unit
2931 		 * if we're in alua mode.
2932 		 * If the requested state is STMF_LU_ACTIVE, we want to register
2933 		 * this logical unit.
2934 		 * If the requested state is STMF_LU_STANDBY, we're going to
2935 		 * abort all tasks for this logical unit.
2936 		 */
2937 		if (stmf_state.stmf_alua_state == 1 &&
2938 		    access_state == STMF_LU_ACTIVE) {
2939 			stmf_ic_msg_status_t ic_ret = STMF_IC_MSG_SUCCESS;
2940 			stmf_ic_msg_t *ic_reg_lun;
2941 			if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 &&
2942 			    lu->lu_lp->lp_alua_support) {
2943 				ilu->ilu_alua = 1;
2944 				/* allocate the register message */
2945 				ic_reg_lun = ic_lun_active_msg_alloc(p1,
2946 				    lu->lu_lp->lp_name,
2947 				    lu->lu_proxy_reg_arg_len,
2948 				    (uint8_t *)lu->lu_proxy_reg_arg,
2949 				    stmf_proxy_msg_id);
2950 				/* send the message */
2951 				if (ic_reg_lun) {
2952 					ic_ret = ic_tx_msg(ic_reg_lun);
2953 					if (ic_ret == STMF_IC_MSG_SUCCESS) {
2954 						stmf_proxy_msg_id++;
2955 					}
2956 				}
2957 			}
2958 		} else if (stmf_state.stmf_alua_state == 1 &&
2959 		    access_state == STMF_LU_STANDBY) {
2960 			/* abort all tasks for this lu */
2961 			stmf_task_lu_killall(lu, NULL, STMF_ABORTED);
2962 		}
2963 	}
2964 
2965 	ilu->ilu_access = access_state;
2966 
2967 	mutex_exit(&stmf_state.stmf_lock);
2968 	return (STMF_SUCCESS);
2969 }
2970 
2971 
2972 stmf_status_t
2973 stmf_register_lu(stmf_lu_t *lu)
2974 {
2975 	stmf_i_lu_t *ilu;
2976 	uint8_t *p1, *p2;
2977 	stmf_state_change_info_t ssci;
2978 	stmf_id_data_t *luid;
2979 
2980 	if ((lu->lu_id->ident_type != ID_TYPE_NAA) ||
2981 	    (lu->lu_id->ident_length != 16) ||
2982 	    ((lu->lu_id->ident[0] & 0xf0) != 0x60)) {
2983 		return (STMF_INVALID_ARG);
2984 	}
2985 	p1 = &lu->lu_id->ident[0];
2986 	mutex_enter(&stmf_state.stmf_lock);
2987 	if (stmf_state.stmf_inventory_locked) {
2988 		mutex_exit(&stmf_state.stmf_lock);
2989 		return (STMF_BUSY);
2990 	}
2991 
2992 	for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) {
2993 		p2 = &ilu->ilu_lu->lu_id->ident[0];
2994 		if (bcmp(p1, p2, 16) == 0) {
2995 			mutex_exit(&stmf_state.stmf_lock);
2996 			return (STMF_ALREADY);
2997 		}
2998 	}
2999 
3000 	ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
3001 	luid = stmf_lookup_id(&stmf_state.stmf_luid_list,
3002 	    lu->lu_id->ident_length, lu->lu_id->ident);
3003 	if (luid) {
3004 		luid->id_pt_to_object = (void *)ilu;
3005 		ilu->ilu_luid = luid;
3006 	}
3007 	ilu->ilu_alias = NULL;
3008 
3009 	ilu->ilu_next = stmf_state.stmf_ilulist;
3010 	ilu->ilu_prev = NULL;
3011 	if (ilu->ilu_next)
3012 		ilu->ilu_next->ilu_prev = ilu;
3013 	stmf_state.stmf_ilulist = ilu;
3014 	stmf_state.stmf_nlus++;
3015 	if (lu->lu_lp) {
3016 		((stmf_i_lu_provider_t *)
3017 		    (lu->lu_lp->lp_stmf_private))->ilp_nlus++;
3018 	}
3019 	ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1;
3020 	STMF_EVENT_ALLOC_HANDLE(ilu->ilu_event_hdl);
3021 	stmf_create_kstat_lu(ilu);
3022 	/*
3023 	 * register with proxy module if available and logical unit
3024 	 * is in active state
3025 	 */
3026 	if (stmf_state.stmf_alua_state == 1 &&
3027 	    ilu->ilu_access == STMF_LU_ACTIVE) {
3028 		stmf_ic_msg_status_t ic_ret = STMF_IC_MSG_SUCCESS;
3029 		stmf_ic_msg_t *ic_reg_lun;
3030 		if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 &&
3031 		    lu->lu_lp->lp_alua_support) {
3032 			ilu->ilu_alua = 1;
3033 			/* allocate the register message */
3034 			ic_reg_lun = ic_reg_lun_msg_alloc(p1,
3035 			    lu->lu_lp->lp_name, lu->lu_proxy_reg_arg_len,
3036 			    (uint8_t *)lu->lu_proxy_reg_arg, stmf_proxy_msg_id);
3037 			/* send the message */
3038 			if (ic_reg_lun) {
3039 				ic_ret = ic_tx_msg(ic_reg_lun);
3040 				if (ic_ret == STMF_IC_MSG_SUCCESS) {
3041 					stmf_proxy_msg_id++;
3042 				}
3043 			}
3044 		}
3045 	}
3046 	mutex_exit(&stmf_state.stmf_lock);
3047 
3048 	/* XXX we should probably check if this lu can be brought online */
3049 	ilu->ilu_prev_state = STMF_STATE_ONLINE;
3050 	if (stmf_state.stmf_service_running) {
3051 		ssci.st_rflags = 0;
3052 		ssci.st_additional_info = NULL;
3053 		(void) stmf_ctl(STMF_CMD_LU_ONLINE, lu, &ssci);
3054 	}
3055 
3056 	/* XXX: Generate event */
3057 	return (STMF_SUCCESS);
3058 }
3059 
3060 stmf_status_t
3061 stmf_deregister_lu(stmf_lu_t *lu)
3062 {
3063 	stmf_i_lu_t *ilu;
3064 
3065 	mutex_enter(&stmf_state.stmf_lock);
3066 	if (stmf_state.stmf_inventory_locked) {
3067 		mutex_exit(&stmf_state.stmf_lock);
3068 		return (STMF_BUSY);
3069 	}
3070 	ilu = stmf_lookup_lu(lu);
3071 	if (ilu == NULL) {
3072 		mutex_exit(&stmf_state.stmf_lock);
3073 		return (STMF_INVALID_ARG);
3074 	}
3075 	if (ilu->ilu_state == STMF_STATE_OFFLINE) {
3076 		ASSERT(ilu->ilu_ntasks == ilu->ilu_ntasks_free);
3077 		while (ilu->ilu_flags & ILU_STALL_DEREGISTER) {
3078 			cv_wait(&stmf_state.stmf_cv, &stmf_state.stmf_lock);
3079 		}
3080 		if (ilu->ilu_ntasks) {
3081 			stmf_i_scsi_task_t *itask, *nitask;
3082 
3083 			nitask = ilu->ilu_tasks;
3084 			do {
3085 				itask = nitask;
3086 				nitask = itask->itask_lu_next;
3087 				lu->lu_task_free(itask->itask_task);
3088 				stmf_free(itask->itask_task);
3089 			} while (nitask != NULL);
3090 
3091 			ilu->ilu_tasks = ilu->ilu_free_tasks = NULL;
3092 			ilu->ilu_ntasks = ilu->ilu_ntasks_free = 0;
3093 		}
3094 		/* de-register with proxy if available */
3095 		if (ilu->ilu_access == STMF_LU_ACTIVE &&
3096 		    stmf_state.stmf_alua_state == 1) {
3097 			/* de-register with proxy module */
3098 			stmf_ic_msg_status_t ic_ret = STMF_IC_MSG_SUCCESS;
3099 			stmf_ic_msg_t *ic_dereg_lun;
3100 			if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 &&
3101 			    lu->lu_lp->lp_alua_support) {
3102 				ilu->ilu_alua = 1;
3103 				/* allocate the de-register message */
3104 				ic_dereg_lun = ic_dereg_lun_msg_alloc(
3105 				    lu->lu_id->ident, lu->lu_lp->lp_name, 0,
3106 				    NULL, stmf_proxy_msg_id);
3107 				/* send the message */
3108 				if (ic_dereg_lun) {
3109 					ic_ret = ic_tx_msg(ic_dereg_lun);
3110 					if (ic_ret == STMF_IC_MSG_SUCCESS) {
3111 						stmf_proxy_msg_id++;
3112 					}
3113 				}
3114 			}
3115 		}
3116 
3117 		if (ilu->ilu_next)
3118 			ilu->ilu_next->ilu_prev = ilu->ilu_prev;
3119 		if (ilu->ilu_prev)
3120 			ilu->ilu_prev->ilu_next = ilu->ilu_next;
3121 		else
3122 			stmf_state.stmf_ilulist = ilu->ilu_next;
3123 		stmf_state.stmf_nlus--;
3124 
3125 		if (ilu == stmf_state.stmf_svc_ilu_draining) {
3126 			stmf_state.stmf_svc_ilu_draining = ilu->ilu_next;
3127 		}
3128 		if (ilu == stmf_state.stmf_svc_ilu_timing) {
3129 			stmf_state.stmf_svc_ilu_timing = ilu->ilu_next;
3130 		}
3131 		if (lu->lu_lp) {
3132 			((stmf_i_lu_provider_t *)
3133 			    (lu->lu_lp->lp_stmf_private))->ilp_nlus--;
3134 		}
3135 		if (ilu->ilu_luid) {
3136 			((stmf_id_data_t *)ilu->ilu_luid)->id_pt_to_object =
3137 			    NULL;
3138 			ilu->ilu_luid = NULL;
3139 		}
3140 		STMF_EVENT_FREE_HANDLE(ilu->ilu_event_hdl);
3141 	} else {
3142 		mutex_exit(&stmf_state.stmf_lock);
3143 		return (STMF_BUSY);
3144 	}
3145 	if (ilu->ilu_kstat_info) {
3146 		kmem_free(ilu->ilu_kstat_info->ks_data,
3147 		    ilu->ilu_kstat_info->ks_data_size);
3148 		kstat_delete(ilu->ilu_kstat_info);
3149 	}
3150 	if (ilu->ilu_kstat_io) {
3151 		kstat_delete(ilu->ilu_kstat_io);
3152 		mutex_destroy(&ilu->ilu_kstat_lock);
3153 	}
3154 	stmf_delete_itl_kstat_by_guid(ilu->ilu_ascii_hex_guid);
3155 	mutex_exit(&stmf_state.stmf_lock);
3156 	return (STMF_SUCCESS);
3157 }
3158 
3159 void
3160 stmf_set_port_standby(stmf_local_port_t *lport, uint16_t rtpid)
3161 {
3162 	stmf_i_local_port_t *ilport =
3163 	    (stmf_i_local_port_t *)lport->lport_stmf_private;
3164 	ilport->ilport_rtpid = rtpid;
3165 	ilport->ilport_standby = 1;
3166 }
3167 
3168 void
3169 stmf_set_port_alua(stmf_local_port_t *lport)
3170 {
3171 	stmf_i_local_port_t *ilport =
3172 	    (stmf_i_local_port_t *)lport->lport_stmf_private;
3173 	ilport->ilport_alua = 1;
3174 }
3175 
3176 stmf_status_t
3177 stmf_register_local_port(stmf_local_port_t *lport)
3178 {
3179 	stmf_i_local_port_t *ilport;
3180 	stmf_state_change_info_t ssci;
3181 	int start_workers = 0;
3182 
3183 	mutex_enter(&stmf_state.stmf_lock);
3184 	if (stmf_state.stmf_inventory_locked) {
3185 		mutex_exit(&stmf_state.stmf_lock);
3186 		return (STMF_BUSY);
3187 	}
3188 	ilport = (stmf_i_local_port_t *)lport->lport_stmf_private;
3189 	rw_init(&ilport->ilport_lock, NULL, RW_DRIVER, NULL);
3190 
3191 	ilport->ilport_instance =
3192 	    id_alloc_nosleep(stmf_state.stmf_ilport_inst_space);
3193 	if (ilport->ilport_instance == -1) {
3194 		mutex_exit(&stmf_state.stmf_lock);
3195 		return (STMF_FAILURE);
3196 	}
3197 	ilport->ilport_next = stmf_state.stmf_ilportlist;
3198 	ilport->ilport_prev = NULL;
3199 	if (ilport->ilport_next)
3200 		ilport->ilport_next->ilport_prev = ilport;
3201 	stmf_state.stmf_ilportlist = ilport;
3202 	stmf_state.stmf_nlports++;
3203 	if (lport->lport_pp) {
3204 		((stmf_i_port_provider_t *)
3205 		    (lport->lport_pp->pp_stmf_private))->ipp_npps++;
3206 	}
3207 	ilport->ilport_tg =
3208 	    stmf_lookup_group_for_target(lport->lport_id->ident,
3209 	    lport->lport_id->ident_length);
3210 
3211 	/*
3212 	 * rtpid will/must be set if this is a standby port
3213 	 * only register ports that are not standby (proxy) ports
3214 	 * and ports that are alua participants (ilport_alua == 1)
3215 	 */
3216 	if (ilport->ilport_standby == 0) {
3217 		ilport->ilport_rtpid = atomic_add_16_nv(&stmf_rtpid_counter, 1);
3218 	}
3219 
3220 	if (stmf_state.stmf_alua_state == 1 &&
3221 	    ilport->ilport_standby == 0 &&
3222 	    ilport->ilport_alua == 1) {
3223 		stmf_ic_msg_t *ic_reg_port;
3224 		stmf_ic_msg_status_t ic_ret;
3225 		stmf_local_port_t *lport;
3226 		lport = ilport->ilport_lport;
3227 		ic_reg_port = ic_reg_port_msg_alloc(
3228 		    lport->lport_id, ilport->ilport_rtpid,
3229 		    0, NULL, stmf_proxy_msg_id);
3230 		if (ic_reg_port) {
3231 			ic_ret = ic_tx_msg(ic_reg_port);
3232 			if (ic_ret == STMF_IC_MSG_SUCCESS) {
3233 				ilport->ilport_reg_msgid = stmf_proxy_msg_id++;
3234 			} else {
3235 				cmn_err(CE_WARN, "error on port registration "
3236 				"port - %s", ilport->ilport_kstat_tgt_name);
3237 			}
3238 		}
3239 	}
3240 	STMF_EVENT_ALLOC_HANDLE(ilport->ilport_event_hdl);
3241 	stmf_create_kstat_lport(ilport);
3242 	if (stmf_workers_state == STMF_WORKERS_DISABLED) {
3243 		stmf_workers_state = STMF_WORKERS_ENABLING;
3244 		start_workers = 1;
3245 	}
3246 	mutex_exit(&stmf_state.stmf_lock);
3247 
3248 	if (start_workers)
3249 		stmf_worker_init();
3250 
3251 	/* XXX we should probably check if this lport can be brought online */
3252 	ilport->ilport_prev_state = STMF_STATE_ONLINE;
3253 	if (stmf_state.stmf_service_running) {
3254 		ssci.st_rflags = 0;
3255 		ssci.st_additional_info = NULL;
3256 		(void) stmf_ctl(STMF_CMD_LPORT_ONLINE, lport, &ssci);
3257 	}
3258 
3259 	/* XXX: Generate event */
3260 	return (STMF_SUCCESS);
3261 }
3262 
3263 stmf_status_t
3264 stmf_deregister_local_port(stmf_local_port_t *lport)
3265 {
3266 	stmf_i_local_port_t *ilport;
3267 
3268 	mutex_enter(&stmf_state.stmf_lock);
3269 	if (stmf_state.stmf_inventory_locked) {
3270 		mutex_exit(&stmf_state.stmf_lock);
3271 		return (STMF_BUSY);
3272 	}
3273 
3274 	ilport = (stmf_i_local_port_t *)lport->lport_stmf_private;
3275 
3276 	/*
3277 	 * deregister ports that are not standby (proxy)
3278 	 */
3279 	if (stmf_state.stmf_alua_state == 1 &&
3280 	    ilport->ilport_standby == 0 &&
3281 	    ilport->ilport_alua == 1) {
3282 		stmf_ic_msg_t *ic_dereg_port;
3283 		stmf_ic_msg_status_t ic_ret;
3284 		ic_dereg_port = ic_dereg_port_msg_alloc(
3285 		    lport->lport_id, 0, NULL, stmf_proxy_msg_id);
3286 		if (ic_dereg_port) {
3287 			ic_ret = ic_tx_msg(ic_dereg_port);
3288 			if (ic_ret == STMF_IC_MSG_SUCCESS) {
3289 				stmf_proxy_msg_id++;
3290 			}
3291 		}
3292 	}
3293 
3294 	if (ilport->ilport_nsessions == 0) {
3295 		if (ilport->ilport_next)
3296 			ilport->ilport_next->ilport_prev = ilport->ilport_prev;
3297 		if (ilport->ilport_prev)
3298 			ilport->ilport_prev->ilport_next = ilport->ilport_next;
3299 		else
3300 			stmf_state.stmf_ilportlist = ilport->ilport_next;
3301 		id_free(stmf_state.stmf_ilport_inst_space,
3302 		    ilport->ilport_instance);
3303 		rw_destroy(&ilport->ilport_lock);
3304 		stmf_state.stmf_nlports--;
3305 		if (lport->lport_pp) {
3306 			((stmf_i_port_provider_t *)
3307 			    (lport->lport_pp->pp_stmf_private))->ipp_npps--;
3308 		}
3309 		ilport->ilport_tg = NULL;
3310 		STMF_EVENT_FREE_HANDLE(ilport->ilport_event_hdl);
3311 	} else {
3312 		mutex_exit(&stmf_state.stmf_lock);
3313 		return (STMF_BUSY);
3314 	}
3315 	if (ilport->ilport_kstat_info) {
3316 		kmem_free(ilport->ilport_kstat_info->ks_data,
3317 		    ilport->ilport_kstat_info->ks_data_size);
3318 		kstat_delete(ilport->ilport_kstat_info);
3319 	}
3320 	if (ilport->ilport_kstat_io) {
3321 		kstat_delete(ilport->ilport_kstat_io);
3322 		mutex_destroy(&ilport->ilport_kstat_lock);
3323 	}
3324 	stmf_delete_itl_kstat_by_lport(ilport->ilport_kstat_tgt_name);
3325 	mutex_exit(&stmf_state.stmf_lock);
3326 	return (STMF_SUCCESS);
3327 }
3328 
3329 /*
3330  * Rport id/instance mappings remain valid until STMF is unloaded
3331  */
3332 static int
3333 stmf_irport_compare(const void *void_irport1, const void *void_irport2)
3334 {
3335 	const	stmf_i_remote_port_t	*irport1 = void_irport1;
3336 	const	stmf_i_remote_port_t	*irport2 = void_irport2;
3337 	int			result;
3338 
3339 	/* Sort by code set then ident */
3340 	if (irport1->irport_id->code_set <
3341 	    irport2->irport_id->code_set) {
3342 		return (-1);
3343 	} else if (irport1->irport_id->code_set >
3344 	    irport2->irport_id->code_set) {
3345 		return (1);
3346 	}
3347 
3348 	/* Next by ident length */
3349 	if (irport1->irport_id->ident_length <
3350 	    irport2->irport_id->ident_length) {
3351 		return (-1);
3352 	} else if (irport1->irport_id->ident_length >
3353 	    irport2->irport_id->ident_length) {
3354 		return (1);
3355 	}
3356 
3357 	/* Code set and ident length both match, now compare idents */
3358 	result = memcmp(irport1->irport_id->ident,
3359 	    irport2->irport_id->ident,
3360 	    irport1->irport_id->ident_length);
3361 
3362 	if (result < 0) {
3363 		return (-1);
3364 	} else if (result > 0) {
3365 		return (1);
3366 	}
3367 
3368 	return (0);
3369 }
3370 
3371 static stmf_i_remote_port_t *
3372 stmf_irport_create(scsi_devid_desc_t *rport_devid)
3373 {
3374 	int			alloc_len;
3375 	stmf_i_remote_port_t	*irport;
3376 
3377 	/*
3378 	 * Lookup will bump the refcnt if there's an existing rport
3379 	 * context for this identifier.
3380 	 */
3381 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
3382 
3383 	alloc_len = sizeof (*irport) + sizeof (scsi_devid_desc_t) +
3384 	    rport_devid->ident_length - 1;
3385 	irport = kmem_zalloc(alloc_len, KM_NOSLEEP);
3386 	if (irport == NULL) {
3387 		return (NULL);
3388 	}
3389 
3390 	irport->irport_instance =
3391 	    id_alloc_nosleep(stmf_state.stmf_irport_inst_space);
3392 	if (irport->irport_instance == -1) {
3393 		kmem_free(irport, alloc_len);
3394 		return (NULL);
3395 	}
3396 
3397 	irport->irport_id =
3398 	    (struct scsi_devid_desc *)(irport + 1); /* Ptr. Arith. */
3399 	bcopy(rport_devid, irport->irport_id,
3400 	    sizeof (scsi_devid_desc_t) + rport_devid->ident_length - 1);
3401 	irport->irport_refcnt = 1;
3402 	mutex_init(&irport->irport_mutex, NULL, MUTEX_DEFAULT, NULL);
3403 
3404 	return (irport);
3405 }
3406 
3407 static void
3408 stmf_irport_destroy(stmf_i_remote_port_t *irport)
3409 {
3410 	id_free(stmf_state.stmf_irport_inst_space, irport->irport_instance);
3411 	mutex_destroy(&irport->irport_mutex);
3412 	kmem_free(irport, sizeof (*irport) + sizeof (scsi_devid_desc_t) +
3413 	    irport->irport_id->ident_length - 1);
3414 }
3415 
3416 static stmf_i_remote_port_t *
3417 stmf_irport_register(scsi_devid_desc_t *rport_devid)
3418 {
3419 	stmf_i_remote_port_t	*irport;
3420 
3421 	mutex_enter(&stmf_state.stmf_lock);
3422 
3423 	/*
3424 	 * Lookup will bump the refcnt if there's an existing rport
3425 	 * context for this identifier.
3426 	 */
3427 	if ((irport = stmf_irport_lookup_locked(rport_devid)) != NULL) {
3428 		mutex_exit(&stmf_state.stmf_lock);
3429 		return (irport);
3430 	}
3431 
3432 	irport = stmf_irport_create(rport_devid);
3433 	if (irport == NULL) {
3434 		mutex_exit(&stmf_state.stmf_lock);
3435 		return (NULL);
3436 	}
3437 
3438 	avl_add(&stmf_state.stmf_irportlist, irport);
3439 	mutex_exit(&stmf_state.stmf_lock);
3440 
3441 	return (irport);
3442 }
3443 
3444 static stmf_i_remote_port_t *
3445 stmf_irport_lookup_locked(scsi_devid_desc_t *rport_devid)
3446 {
3447 	stmf_i_remote_port_t	*irport;
3448 	stmf_i_remote_port_t	tmp_irport;
3449 
3450 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
3451 	tmp_irport.irport_id = rport_devid;
3452 	irport = avl_find(&stmf_state.stmf_irportlist, &tmp_irport, NULL);
3453 	if (irport != NULL) {
3454 		mutex_enter(&irport->irport_mutex);
3455 		irport->irport_refcnt++;
3456 		mutex_exit(&irport->irport_mutex);
3457 	}
3458 
3459 	return (irport);
3460 }
3461 
3462 static void
3463 stmf_irport_deregister(stmf_i_remote_port_t *irport)
3464 {
3465 	/*
3466 	 * If we were actually going to remove unreferenced remote ports
3467 	 * we would want to acquire stmf_state.stmf_lock before getting
3468 	 * the irport mutex.
3469 	 *
3470 	 * Instead we're just going to leave it there even if unreferenced.
3471 	 */
3472 	mutex_enter(&irport->irport_mutex);
3473 	irport->irport_refcnt--;
3474 	mutex_exit(&irport->irport_mutex);
3475 }
3476 
3477 /*
3478  * Port provider has to make sure that register/deregister session and
3479  * port are serialized calls.
3480  */
3481 stmf_status_t
3482 stmf_register_scsi_session(stmf_local_port_t *lport, stmf_scsi_session_t *ss)
3483 {
3484 	stmf_i_scsi_session_t *iss;
3485 	stmf_i_local_port_t *ilport = (stmf_i_local_port_t *)
3486 	    lport->lport_stmf_private;
3487 	uint8_t		lun[8];
3488 
3489 	/*
3490 	 * Port state has to be online to register a scsi session. It is
3491 	 * possible that we started an offline operation and a new SCSI
3492 	 * session started at the same time (in that case also we are going
3493 	 * to fail the registeration). But any other state is simply
3494 	 * a bad port provider implementation.
3495 	 */
3496 	if (ilport->ilport_state != STMF_STATE_ONLINE) {
3497 		if (ilport->ilport_state != STMF_STATE_OFFLINING) {
3498 			stmf_trace(lport->lport_alias, "Port is trying to "
3499 			    "register a session while the state is neither "
3500 			    "online nor offlining");
3501 		}
3502 		return (STMF_FAILURE);
3503 	}
3504 	bzero(lun, 8);
3505 	iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
3506 	if ((iss->iss_irport = stmf_irport_register(ss->ss_rport_id)) == NULL) {
3507 		stmf_trace(lport->lport_alias, "Could not register "
3508 		    "remote port during session registration");
3509 		return (STMF_FAILURE);
3510 	}
3511 
3512 	iss->iss_flags |= ISS_BEING_CREATED;
3513 
3514 	/* sessions use the ilport_lock. No separate lock is required */
3515 	iss->iss_lockp = &ilport->ilport_lock;
3516 
3517 	if (iss->iss_sm != NULL)
3518 		cmn_err(CE_PANIC, "create lun map called with non NULL map");
3519 	iss->iss_sm = (stmf_lun_map_t *)kmem_zalloc(sizeof (stmf_lun_map_t),
3520 	    KM_SLEEP);
3521 
3522 	mutex_enter(&stmf_state.stmf_lock);
3523 	rw_enter(&ilport->ilport_lock, RW_WRITER);
3524 	(void) stmf_session_create_lun_map(ilport, iss);
3525 	ilport->ilport_nsessions++;
3526 	iss->iss_next = ilport->ilport_ss_list;
3527 	ilport->ilport_ss_list = iss;
3528 	rw_exit(&ilport->ilport_lock);
3529 	mutex_exit(&stmf_state.stmf_lock);
3530 
3531 	iss->iss_creation_time = ddi_get_time();
3532 	ss->ss_session_id = atomic_add_64_nv(&stmf_session_counter, 1);
3533 	iss->iss_flags &= ~ISS_BEING_CREATED;
3534 	/* XXX should we remove ISS_LUN_INVENTORY_CHANGED on new session? */
3535 	iss->iss_flags &= ~ISS_LUN_INVENTORY_CHANGED;
3536 	DTRACE_PROBE2(session__online, stmf_local_port_t *, lport,
3537 	    stmf_scsi_session_t *, ss);
3538 	return (STMF_SUCCESS);
3539 }
3540 
3541 void
3542 stmf_deregister_scsi_session(stmf_local_port_t *lport, stmf_scsi_session_t *ss)
3543 {
3544 	stmf_i_local_port_t *ilport = (stmf_i_local_port_t *)
3545 	    lport->lport_stmf_private;
3546 	stmf_i_scsi_session_t *iss, **ppss;
3547 	int found = 0;
3548 	stmf_ic_msg_t *ic_session_dereg;
3549 	stmf_status_t ic_ret = STMF_FAILURE;
3550 
3551 	DTRACE_PROBE2(session__offline, stmf_local_port_t *, lport,
3552 	    stmf_scsi_session_t *, ss);
3553 
3554 	iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
3555 	if (ss->ss_rport_alias) {
3556 		ss->ss_rport_alias = NULL;
3557 	}
3558 
3559 try_dereg_ss_again:
3560 	mutex_enter(&stmf_state.stmf_lock);
3561 	atomic_and_32(&iss->iss_flags,
3562 	    ~(ISS_LUN_INVENTORY_CHANGED | ISS_GOT_INITIAL_LUNS));
3563 	if (iss->iss_flags & ISS_EVENT_ACTIVE) {
3564 		mutex_exit(&stmf_state.stmf_lock);
3565 		delay(1);
3566 		goto try_dereg_ss_again;
3567 	}
3568 
3569 	/* dereg proxy session if not standby port */
3570 	if (stmf_state.stmf_alua_state == 1 &&
3571 	    ilport->ilport_standby == 0 &&
3572 	    ilport->ilport_alua == 1) {
3573 		ic_session_dereg = ic_session_dereg_msg_alloc(
3574 		    ss, stmf_proxy_msg_id);
3575 		if (ic_session_dereg) {
3576 			ic_ret = ic_tx_msg(ic_session_dereg);
3577 			if (ic_ret == STMF_IC_MSG_SUCCESS) {
3578 				stmf_proxy_msg_id++;
3579 			}
3580 		}
3581 	}
3582 
3583 	rw_enter(&ilport->ilport_lock, RW_WRITER);
3584 	for (ppss = &ilport->ilport_ss_list; *ppss != NULL;
3585 	    ppss = &((*ppss)->iss_next)) {
3586 		if (iss == (*ppss)) {
3587 			*ppss = (*ppss)->iss_next;
3588 			found = 1;
3589 			break;
3590 		}
3591 	}
3592 	if (!found) {
3593 		cmn_err(CE_PANIC, "Deregister session called for non existent"
3594 		    " session");
3595 	}
3596 	ilport->ilport_nsessions--;
3597 
3598 	stmf_irport_deregister(iss->iss_irport);
3599 	(void) stmf_session_destroy_lun_map(ilport, iss);
3600 	rw_exit(&ilport->ilport_lock);
3601 	mutex_exit(&stmf_state.stmf_lock);
3602 }
3603 
3604 stmf_i_scsi_session_t *
3605 stmf_session_id_to_issptr(uint64_t session_id, int stay_locked)
3606 {
3607 	stmf_i_local_port_t *ilport;
3608 	stmf_i_scsi_session_t *iss;
3609 
3610 	mutex_enter(&stmf_state.stmf_lock);
3611 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
3612 	    ilport = ilport->ilport_next) {
3613 		rw_enter(&ilport->ilport_lock, RW_WRITER);
3614 		for (iss = ilport->ilport_ss_list; iss != NULL;
3615 		    iss = iss->iss_next) {
3616 			if (iss->iss_ss->ss_session_id == session_id) {
3617 				if (!stay_locked)
3618 					rw_exit(&ilport->ilport_lock);
3619 				mutex_exit(&stmf_state.stmf_lock);
3620 				return (iss);
3621 			}
3622 		}
3623 		rw_exit(&ilport->ilport_lock);
3624 	}
3625 	mutex_exit(&stmf_state.stmf_lock);
3626 	return (NULL);
3627 }
3628 
3629 #define	MAX_ALIAS		128
3630 
3631 static int
3632 stmf_itl_kstat_compare(const void *itl_kstat_1, const void *itl_kstat_2)
3633 {
3634 	const	stmf_i_itl_kstat_t	*kstat_nm1 = itl_kstat_1;
3635 	const	stmf_i_itl_kstat_t	*kstat_nm2 = itl_kstat_2;
3636 	int	ret;
3637 
3638 	ret = strcmp(kstat_nm1->iitl_kstat_nm, kstat_nm2->iitl_kstat_nm);
3639 	if (ret < 0) {
3640 		return (-1);
3641 	} else if (ret > 0) {
3642 		return (1);
3643 	}
3644 	return (0);
3645 }
3646 
3647 static stmf_i_itl_kstat_t *
3648 stmf_itl_kstat_lookup(char *kstat_nm)
3649 {
3650 	stmf_i_itl_kstat_t	tmp;
3651 	stmf_i_itl_kstat_t	*itl_kstat;
3652 
3653 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
3654 	(void) strcpy(tmp.iitl_kstat_nm, kstat_nm);
3655 	itl_kstat = avl_find(&stmf_state.stmf_itl_kstat_list, &tmp, NULL);
3656 	return (itl_kstat);
3657 }
3658 
3659 static void
3660 stmf_delete_itl_kstat_by_lport(char *tgt)
3661 {
3662 	stmf_i_itl_kstat_t	*ks_itl, *next;
3663 
3664 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
3665 	ks_itl = avl_first(&stmf_state.stmf_itl_kstat_list);
3666 	for (; ks_itl != NULL; ks_itl = next) {
3667 		next = AVL_NEXT(&stmf_state.stmf_itl_kstat_list, ks_itl);
3668 		if (strcmp(ks_itl->iitl_kstat_lport, tgt) == 0) {
3669 			stmf_teardown_itl_kstats(ks_itl);
3670 			avl_remove(&stmf_state.stmf_itl_kstat_list, ks_itl);
3671 			kmem_free(ks_itl, sizeof (stmf_i_itl_kstat_t));
3672 		}
3673 	}
3674 }
3675 
3676 static void
3677 stmf_delete_itl_kstat_by_guid(char *guid)
3678 {
3679 	stmf_i_itl_kstat_t	*ks_itl, *next;
3680 
3681 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
3682 	ks_itl = avl_first(&stmf_state.stmf_itl_kstat_list);
3683 	for (; ks_itl != NULL; ks_itl = next) {
3684 		next = AVL_NEXT(&stmf_state.stmf_itl_kstat_list, ks_itl);
3685 		if (strcmp(ks_itl->iitl_kstat_guid, guid) == 0) {
3686 			stmf_teardown_itl_kstats(ks_itl);
3687 			avl_remove(&stmf_state.stmf_itl_kstat_list, ks_itl);
3688 			kmem_free(ks_itl, sizeof (stmf_i_itl_kstat_t));
3689 		}
3690 	}
3691 }
3692 
3693 static stmf_i_itl_kstat_t *
3694 stmf_itl_kstat_create(stmf_itl_data_t *itl, char *nm,
3695     scsi_devid_desc_t *lport, scsi_devid_desc_t *lun)
3696 {
3697 	stmf_i_itl_kstat_t	*ks_itl;
3698 	int			i, len;
3699 
3700 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
3701 	if ((ks_itl = stmf_itl_kstat_lookup(nm)) != NULL)
3702 		return (ks_itl);
3703 
3704 	len = sizeof (stmf_i_itl_kstat_t);
3705 	ks_itl = kmem_zalloc(len, KM_NOSLEEP);
3706 	if (ks_itl == NULL)
3707 		return (NULL);
3708 
3709 	(void) strcpy(ks_itl->iitl_kstat_nm, nm);
3710 	bcopy(lport->ident, ks_itl->iitl_kstat_lport, lport->ident_length);
3711 	ks_itl->iitl_kstat_lport[lport->ident_length] = '\0';
3712 	for (i = 0; i < STMF_GUID_INPUT / 2; i++) {
3713 		(void) sprintf(&ks_itl->iitl_kstat_guid[i * 2], "%02x",
3714 		    lun->ident[i]);
3715 	}
3716 	ks_itl->iitl_kstat_strbuf = itl->itl_kstat_strbuf;
3717 	ks_itl->iitl_kstat_strbuflen = itl->itl_kstat_strbuflen;
3718 	ks_itl->iitl_kstat_info = itl->itl_kstat_info;
3719 	ks_itl->iitl_kstat_taskq = itl->itl_kstat_taskq;
3720 	ks_itl->iitl_kstat_lu_xfer = itl->itl_kstat_lu_xfer;
3721 	ks_itl->iitl_kstat_lport_xfer = itl->itl_kstat_lport_xfer;
3722 	avl_add(&stmf_state.stmf_itl_kstat_list, ks_itl);
3723 
3724 	return (ks_itl);
3725 }
3726 
3727 stmf_status_t
3728 stmf_setup_itl_kstats(stmf_itl_data_t *itl)
3729 {
3730 	char				ks_itl_id[32];
3731 	char				ks_nm[KSTAT_STRLEN];
3732 	char				ks_itl_nm[KSTAT_STRLEN];
3733 	stmf_kstat_itl_info_t		*ks_itl;
3734 	stmf_scsi_session_t		*ss;
3735 	stmf_i_scsi_session_t		*iss;
3736 	stmf_i_local_port_t		*ilport;
3737 	char				*strbuf;
3738 	int				id, len, i;
3739 	char				*rport_alias;
3740 	char				*lport_alias;
3741 	char				*lu_alias;
3742 	stmf_i_itl_kstat_t		*tmp_kstat;
3743 
3744 	/*
3745 	 * Allocate enough memory in the ITL to hold the relevant
3746 	 * identifiers.
3747 	 * rport and lport identifiers come from the stmf_scsi_session_t.
3748 	 * ident might not be null terminated.
3749 	 */
3750 	ss = itl->itl_session->iss_ss;
3751 	iss = ss->ss_stmf_private;
3752 	ilport = ss->ss_lport->lport_stmf_private;
3753 	(void) snprintf(ks_itl_id, 32, "%d.%d.%d",
3754 	    iss->iss_irport->irport_instance, ilport->ilport_instance,
3755 	    itl->itl_lun);
3756 
3757 	(void) snprintf(ks_itl_nm, KSTAT_STRLEN, "itl_%s", ks_itl_id);
3758 	/*
3759 	 * let's verify this itl_kstat already exist
3760 	 */
3761 	if ((tmp_kstat = stmf_itl_kstat_lookup(ks_itl_nm)) != NULL) {
3762 		itl->itl_kstat_strbuf = tmp_kstat->iitl_kstat_strbuf;
3763 		itl->itl_kstat_strbuflen = tmp_kstat->iitl_kstat_strbuflen;
3764 		itl->itl_kstat_info = tmp_kstat->iitl_kstat_info;
3765 		itl->itl_kstat_taskq = tmp_kstat->iitl_kstat_taskq;
3766 		itl->itl_kstat_lu_xfer = tmp_kstat->iitl_kstat_lu_xfer;
3767 		itl->itl_kstat_lport_xfer = tmp_kstat->iitl_kstat_lport_xfer;
3768 		return (STMF_SUCCESS);
3769 	}
3770 
3771 	/* New itl_kstat */
3772 	rport_alias = (ss->ss_rport_alias == NULL) ?
3773 	    "" : ss->ss_rport_alias;
3774 	lport_alias = (ss->ss_lport->lport_alias == NULL) ?
3775 	    "" : ss->ss_lport->lport_alias;
3776 	lu_alias = (itl->itl_ilu->ilu_lu->lu_alias == NULL) ?
3777 	    "" : itl->itl_ilu->ilu_lu->lu_alias;
3778 
3779 	itl->itl_kstat_strbuflen = (ss->ss_rport_id->ident_length + 1) +
3780 	    (strnlen(rport_alias, MAX_ALIAS) + 1) +
3781 	    (ss->ss_lport->lport_id->ident_length + 1) +
3782 	    (strnlen(lport_alias, MAX_ALIAS) + 1) +
3783 	    (STMF_GUID_INPUT + 1) +
3784 	    (strnlen(lu_alias, MAX_ALIAS) + 1) +
3785 	    MAX_PROTO_STR_LEN;
3786 	itl->itl_kstat_strbuf = kmem_zalloc(itl->itl_kstat_strbuflen,
3787 	    KM_NOSLEEP);
3788 	if (itl->itl_kstat_strbuf == NULL) {
3789 		return (STMF_ALLOC_FAILURE);
3790 	}
3791 
3792 	ks_itl = (stmf_kstat_itl_info_t *)kmem_zalloc(sizeof (*ks_itl),
3793 	    KM_NOSLEEP);
3794 	if (ks_itl == NULL) {
3795 		kmem_free(itl->itl_kstat_strbuf, itl->itl_kstat_strbuflen);
3796 		return (STMF_ALLOC_FAILURE);
3797 	}
3798 
3799 	if ((itl->itl_kstat_info = kstat_create(STMF_MODULE_NAME,
3800 	    0, ks_itl_nm, "misc", KSTAT_TYPE_NAMED,
3801 	    sizeof (stmf_kstat_itl_info_t) / sizeof (kstat_named_t),
3802 	    KSTAT_FLAG_VIRTUAL)) == NULL) {
3803 		goto itl_kstat_cleanup;
3804 	}
3805 
3806 	itl->itl_kstat_info->ks_data_size += itl->itl_kstat_strbuflen;
3807 	itl->itl_kstat_info->ks_data = ks_itl;
3808 
3809 	kstat_named_init(&ks_itl->i_rport_name, "rport-name",
3810 	    KSTAT_DATA_STRING);
3811 	kstat_named_init(&ks_itl->i_rport_alias, "rport-alias",
3812 	    KSTAT_DATA_STRING);
3813 	kstat_named_init(&ks_itl->i_lport_name, "lport-name",
3814 	    KSTAT_DATA_STRING);
3815 	kstat_named_init(&ks_itl->i_lport_alias, "lport-alias",
3816 	    KSTAT_DATA_STRING);
3817 	kstat_named_init(&ks_itl->i_protocol, "protocol",
3818 	    KSTAT_DATA_STRING);
3819 	kstat_named_init(&ks_itl->i_lu_guid, "lu-guid",
3820 	    KSTAT_DATA_STRING);
3821 	kstat_named_init(&ks_itl->i_lu_alias, "lu-alias",
3822 	    KSTAT_DATA_STRING);
3823 	kstat_named_init(&ks_itl->i_lu_number, "lu-number",
3824 	    KSTAT_DATA_UINT64);
3825 	kstat_named_init(&ks_itl->i_task_waitq_elapsed, "task-waitq-elapsed",
3826 	    KSTAT_DATA_UINT64);
3827 	kstat_named_init(&ks_itl->i_task_read_elapsed, "task-read-elapsed",
3828 	    KSTAT_DATA_UINT64);
3829 	kstat_named_init(&ks_itl->i_task_write_elapsed, "task-write-elapsed",
3830 	    KSTAT_DATA_UINT64);
3831 	kstat_named_init(&ks_itl->i_lu_read_elapsed, "lu-read-elapsed",
3832 	    KSTAT_DATA_UINT64);
3833 	kstat_named_init(&ks_itl->i_lu_write_elapsed, "lu-write-elapsed",
3834 	    KSTAT_DATA_UINT64);
3835 	kstat_named_init(&ks_itl->i_lport_read_elapsed, "lport-read-elapsed",
3836 	    KSTAT_DATA_UINT64);
3837 	kstat_named_init(&ks_itl->i_lport_write_elapsed, "lport-write-elapsed",
3838 	    KSTAT_DATA_UINT64);
3839 
3840 	strbuf = itl->itl_kstat_strbuf;
3841 
3842 	/* Rport */
3843 	len = ss->ss_rport_id->ident_length;
3844 	bcopy(ss->ss_rport_id->ident, strbuf, len);
3845 	strbuf += len;
3846 	*strbuf = '\0';
3847 	kstat_named_setstr(&ks_itl->i_rport_name, strbuf - len);
3848 	strbuf++;
3849 
3850 	len = strnlen(rport_alias, MAX_ALIAS);
3851 	(void) strncpy(strbuf, rport_alias, len + 1);
3852 	kstat_named_setstr(&ks_itl->i_rport_alias, strbuf);
3853 	strbuf += len + 1;
3854 
3855 	/* Lport */
3856 	len = ss->ss_lport->lport_id->ident_length;
3857 	bcopy(ss->ss_lport->lport_id->ident, strbuf, len);
3858 	strbuf += len;
3859 	*strbuf = '\0';
3860 	kstat_named_setstr(&ks_itl->i_lport_name, strbuf - len);
3861 	strbuf++;
3862 
3863 	len = strnlen(lport_alias, MAX_ALIAS);
3864 	(void) strncpy(strbuf, lport_alias, len + 1);
3865 	kstat_named_setstr(&ks_itl->i_lport_alias, strbuf);
3866 	strbuf += len + 1;
3867 
3868 	id = (ss->ss_lport->lport_id->protocol_id > PROTOCOL_ANY) ?
3869 	    PROTOCOL_ANY : ss->ss_lport->lport_id->protocol_id;
3870 	kstat_named_setstr(&ks_itl->i_protocol, protocol_ident[id]);
3871 
3872 	/* LU */
3873 	for (i = 0; i < STMF_GUID_INPUT / 2; i++) {
3874 		(void) sprintf(&strbuf[i * 2], "%02x",
3875 		    itl->itl_ilu->ilu_lu->lu_id->ident[i]);
3876 	}
3877 	kstat_named_setstr(&ks_itl->i_lu_guid, strbuf);
3878 	strbuf += STMF_GUID_INPUT + 1;
3879 
3880 	len = strnlen(lu_alias, MAX_ALIAS);
3881 	(void) strncpy(strbuf, lu_alias, len + 1);
3882 	kstat_named_setstr(&ks_itl->i_lu_alias, strbuf);
3883 	strbuf += len + 1;
3884 
3885 	ks_itl->i_lu_number.value.ui64 = itl->itl_lun;
3886 
3887 	/* Now create the I/O kstats */
3888 	(void) snprintf(ks_nm, KSTAT_STRLEN, "itl_tasks_%s",  ks_itl_id);
3889 	if ((itl->itl_kstat_taskq = kstat_create(STMF_MODULE_NAME, 0,
3890 	    ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) {
3891 		goto itl_kstat_cleanup;
3892 	}
3893 
3894 	(void) snprintf(ks_nm, KSTAT_STRLEN, "itl_lu_%s",  ks_itl_id);
3895 	if ((itl->itl_kstat_lu_xfer = kstat_create(STMF_MODULE_NAME, 0,
3896 	    ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) {
3897 		goto itl_kstat_cleanup;
3898 	}
3899 
3900 	(void) snprintf(ks_nm, KSTAT_STRLEN, "itl_lport_%s",  ks_itl_id);
3901 	if ((itl->itl_kstat_lport_xfer = kstat_create(STMF_MODULE_NAME, 0,
3902 	    ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) {
3903 		goto itl_kstat_cleanup;
3904 	}
3905 
3906 	/* Install all the kstats */
3907 	kstat_install(itl->itl_kstat_info);
3908 	kstat_install(itl->itl_kstat_taskq);
3909 	kstat_install(itl->itl_kstat_lu_xfer);
3910 	kstat_install(itl->itl_kstat_lport_xfer);
3911 
3912 	/* Add new itl_kstat to stmf_itl_kstat_list */
3913 	if (stmf_itl_kstat_create(itl, ks_itl_nm, ss->ss_lport->lport_id,
3914 	    itl->itl_ilu->ilu_lu->lu_id) != NULL)
3915 		return (STMF_SUCCESS);
3916 
3917 itl_kstat_cleanup:
3918 	if (itl->itl_kstat_taskq)
3919 		kstat_delete(itl->itl_kstat_taskq);
3920 	if (itl->itl_kstat_lu_xfer)
3921 		kstat_delete(itl->itl_kstat_lu_xfer);
3922 	if (itl->itl_kstat_lport_xfer)
3923 		kstat_delete(itl->itl_kstat_lport_xfer);
3924 	if (itl->itl_kstat_info)
3925 		kstat_delete(itl->itl_kstat_info);
3926 	kmem_free(ks_itl, sizeof (*ks_itl));
3927 	kmem_free(itl->itl_kstat_strbuf, itl->itl_kstat_strbuflen);
3928 	cmn_err(CE_WARN, "STMF: kstat_create itl failed");
3929 	return (STMF_ALLOC_FAILURE);
3930 }
3931 
3932 static void
3933 stmf_teardown_itl_kstats(stmf_i_itl_kstat_t *ks)
3934 {
3935 	kstat_delete(ks->iitl_kstat_lport_xfer);
3936 	kstat_delete(ks->iitl_kstat_lu_xfer);
3937 	kstat_delete(ks->iitl_kstat_taskq);
3938 	kmem_free(ks->iitl_kstat_info->ks_data, sizeof (stmf_kstat_itl_info_t));
3939 	kstat_delete(ks->iitl_kstat_info);
3940 	kmem_free(ks->iitl_kstat_strbuf, ks->iitl_kstat_strbuflen);
3941 }
3942 
3943 void
3944 stmf_release_itl_handle(stmf_lu_t *lu, stmf_itl_data_t *itl)
3945 {
3946 	stmf_itl_data_t **itlpp;
3947 	stmf_i_lu_t *ilu;
3948 
3949 	ASSERT(itl->itl_flags & STMF_ITL_BEING_TERMINATED);
3950 
3951 	ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
3952 	mutex_enter(&ilu->ilu_task_lock);
3953 	for (itlpp = &ilu->ilu_itl_list; (*itlpp) != NULL;
3954 	    itlpp = &(*itlpp)->itl_next) {
3955 		if ((*itlpp) == itl)
3956 			break;
3957 	}
3958 	ASSERT((*itlpp) != NULL);
3959 	*itlpp = itl->itl_next;
3960 	mutex_exit(&ilu->ilu_task_lock);
3961 	lu->lu_abort(lu, STMF_LU_ITL_HANDLE_REMOVED, itl->itl_handle,
3962 	    (uint32_t)itl->itl_hdlrm_reason);
3963 
3964 	kmem_free(itl, sizeof (*itl));
3965 }
3966 
3967 stmf_status_t
3968 stmf_register_itl_handle(stmf_lu_t *lu, uint8_t *lun,
3969     stmf_scsi_session_t *ss, uint64_t session_id, void *itl_handle)
3970 {
3971 	stmf_itl_data_t *itl;
3972 	stmf_i_scsi_session_t *iss;
3973 	stmf_lun_map_ent_t *lun_map_ent;
3974 	stmf_i_lu_t *ilu;
3975 	uint16_t n;
3976 
3977 	ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
3978 	if (ss == NULL) {
3979 		iss = stmf_session_id_to_issptr(session_id, 1);
3980 		if (iss == NULL)
3981 			return (STMF_NOT_FOUND);
3982 	} else {
3983 		iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
3984 	}
3985 
3986 	/*
3987 	 * Acquire stmf_lock for stmf_itl_kstat_lookup.
3988 	 */
3989 	mutex_enter(&stmf_state.stmf_lock);
3990 	rw_enter(iss->iss_lockp, RW_WRITER);
3991 	n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
3992 	lun_map_ent = (stmf_lun_map_ent_t *)
3993 	    stmf_get_ent_from_map(iss->iss_sm, n);
3994 	if ((lun_map_ent == NULL) || (lun_map_ent->ent_lu != lu)) {
3995 		rw_exit(iss->iss_lockp);
3996 		mutex_exit(&stmf_state.stmf_lock);
3997 		return (STMF_NOT_FOUND);
3998 	}
3999 	if (lun_map_ent->ent_itl_datap != NULL) {
4000 		rw_exit(iss->iss_lockp);
4001 		mutex_exit(&stmf_state.stmf_lock);
4002 		return (STMF_ALREADY);
4003 	}
4004 
4005 	itl = (stmf_itl_data_t *)kmem_zalloc(sizeof (*itl), KM_NOSLEEP);
4006 	if (itl == NULL) {
4007 		rw_exit(iss->iss_lockp);
4008 		mutex_exit(&stmf_state.stmf_lock);
4009 		return (STMF_ALLOC_FAILURE);
4010 	}
4011 
4012 	itl->itl_ilu = ilu;
4013 	itl->itl_session = iss;
4014 	itl->itl_counter = 1;
4015 	itl->itl_lun = n;
4016 	itl->itl_handle = itl_handle;
4017 
4018 	if (stmf_setup_itl_kstats(itl) != STMF_SUCCESS) {
4019 		kmem_free(itl, sizeof (*itl));
4020 		rw_exit(iss->iss_lockp);
4021 		mutex_exit(&stmf_state.stmf_lock);
4022 		return (STMF_ALLOC_FAILURE);
4023 	}
4024 
4025 	mutex_enter(&ilu->ilu_task_lock);
4026 	itl->itl_next = ilu->ilu_itl_list;
4027 	ilu->ilu_itl_list = itl;
4028 	mutex_exit(&ilu->ilu_task_lock);
4029 	lun_map_ent->ent_itl_datap = itl;
4030 	rw_exit(iss->iss_lockp);
4031 	mutex_exit(&stmf_state.stmf_lock);
4032 
4033 	return (STMF_SUCCESS);
4034 }
4035 
4036 void
4037 stmf_do_itl_dereg(stmf_lu_t *lu, stmf_itl_data_t *itl, uint8_t hdlrm_reason)
4038 {
4039 	uint8_t old, new;
4040 
4041 	do {
4042 		old = new = itl->itl_flags;
4043 		if (old & STMF_ITL_BEING_TERMINATED)
4044 			return;
4045 		new |= STMF_ITL_BEING_TERMINATED;
4046 	} while (atomic_cas_8(&itl->itl_flags, old, new) != old);
4047 	itl->itl_hdlrm_reason = hdlrm_reason;
4048 
4049 	ASSERT(itl->itl_counter);
4050 
4051 	if (atomic_add_32_nv(&itl->itl_counter, -1))
4052 		return;
4053 
4054 	drv_usecwait(10);
4055 	if (itl->itl_counter)
4056 		return;
4057 
4058 	stmf_release_itl_handle(lu, itl);
4059 }
4060 
4061 stmf_status_t
4062 stmf_deregister_all_lu_itl_handles(stmf_lu_t *lu)
4063 {
4064 	stmf_i_lu_t *ilu;
4065 	stmf_i_local_port_t *ilport;
4066 	stmf_i_scsi_session_t *iss;
4067 	stmf_lun_map_t *lm;
4068 	stmf_lun_map_ent_t *ent;
4069 	uint32_t nmaps, nu;
4070 	stmf_itl_data_t **itl_list;
4071 	int i;
4072 
4073 	ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
4074 
4075 dereg_itl_start:;
4076 	nmaps = ilu->ilu_ref_cnt;
4077 	if (nmaps == 0)
4078 		return (STMF_NOT_FOUND);
4079 	itl_list = (stmf_itl_data_t **)kmem_zalloc(
4080 	    nmaps * sizeof (stmf_itl_data_t *), KM_SLEEP);
4081 	mutex_enter(&stmf_state.stmf_lock);
4082 	if (nmaps != ilu->ilu_ref_cnt) {
4083 		/* Something changed, start all over */
4084 		mutex_exit(&stmf_state.stmf_lock);
4085 		kmem_free(itl_list, nmaps * sizeof (stmf_itl_data_t *));
4086 		goto dereg_itl_start;
4087 	}
4088 	nu = 0;
4089 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
4090 	    ilport = ilport->ilport_next) {
4091 		rw_enter(&ilport->ilport_lock, RW_WRITER);
4092 		for (iss = ilport->ilport_ss_list; iss != NULL;
4093 		    iss = iss->iss_next) {
4094 			lm = iss->iss_sm;
4095 			if (!lm)
4096 				continue;
4097 			for (i = 0; i < lm->lm_nentries; i++) {
4098 				if (lm->lm_plus[i] == NULL)
4099 					continue;
4100 				ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
4101 				if ((ent->ent_lu == lu) &&
4102 				    (ent->ent_itl_datap)) {
4103 					itl_list[nu++] = ent->ent_itl_datap;
4104 					ent->ent_itl_datap = NULL;
4105 					if (nu == nmaps) {
4106 						rw_exit(&ilport->ilport_lock);
4107 						goto dai_scan_done;
4108 					}
4109 				}
4110 			} /* lun table for a session */
4111 		} /* sessions */
4112 		rw_exit(&ilport->ilport_lock);
4113 	} /* ports */
4114 
4115 dai_scan_done:
4116 	mutex_exit(&stmf_state.stmf_lock);
4117 
4118 	for (i = 0; i < nu; i++) {
4119 		stmf_do_itl_dereg(lu, itl_list[i],
4120 		    STMF_ITL_REASON_DEREG_REQUEST);
4121 	}
4122 	kmem_free(itl_list, nmaps * sizeof (stmf_itl_data_t *));
4123 
4124 	return (STMF_SUCCESS);
4125 }
4126 
4127 stmf_status_t
4128 stmf_deregister_itl_handle(stmf_lu_t *lu, uint8_t *lun,
4129     stmf_scsi_session_t *ss, uint64_t session_id, void *itl_handle)
4130 {
4131 	stmf_i_scsi_session_t *iss;
4132 	stmf_itl_data_t *itl;
4133 	stmf_lun_map_ent_t *ent;
4134 	stmf_lun_map_t *lm;
4135 	int i;
4136 	uint16_t n;
4137 
4138 	if (ss == NULL) {
4139 		if (session_id == STMF_SESSION_ID_NONE)
4140 			return (STMF_INVALID_ARG);
4141 		iss = stmf_session_id_to_issptr(session_id, 1);
4142 		if (iss == NULL)
4143 			return (STMF_NOT_FOUND);
4144 	} else {
4145 		iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
4146 		rw_enter(iss->iss_lockp, RW_WRITER);
4147 	}
4148 	lm = iss->iss_sm;
4149 	if (lm == NULL) {
4150 		rw_exit(iss->iss_lockp);
4151 		return (STMF_NOT_FOUND);
4152 	}
4153 
4154 	if (lun) {
4155 		n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
4156 		ent = (stmf_lun_map_ent_t *)
4157 		    stmf_get_ent_from_map(iss->iss_sm, n);
4158 	} else {
4159 		if (itl_handle == NULL) {
4160 			rw_exit(iss->iss_lockp);
4161 			return (STMF_INVALID_ARG);
4162 		}
4163 		ent = NULL;
4164 		for (i = 0; i < lm->lm_nentries; i++) {
4165 			if (lm->lm_plus[i] == NULL)
4166 				continue;
4167 			ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
4168 			if (ent->ent_itl_datap &&
4169 			    (ent->ent_itl_datap->itl_handle == itl_handle)) {
4170 				break;
4171 			}
4172 		}
4173 	}
4174 	if ((ent == NULL) || (ent->ent_lu != lu) ||
4175 	    (ent->ent_itl_datap == NULL)) {
4176 		rw_exit(iss->iss_lockp);
4177 		return (STMF_NOT_FOUND);
4178 	}
4179 	itl = ent->ent_itl_datap;
4180 	ent->ent_itl_datap = NULL;
4181 	rw_exit(iss->iss_lockp);
4182 	stmf_do_itl_dereg(lu, itl, STMF_ITL_REASON_DEREG_REQUEST);
4183 
4184 	return (STMF_SUCCESS);
4185 }
4186 
4187 stmf_status_t
4188 stmf_get_itl_handle(stmf_lu_t *lu, uint8_t *lun, stmf_scsi_session_t *ss,
4189     uint64_t session_id, void **itl_handle_retp)
4190 {
4191 	stmf_i_scsi_session_t *iss;
4192 	stmf_lun_map_ent_t *ent;
4193 	stmf_lun_map_t *lm;
4194 	stmf_status_t ret;
4195 	int i;
4196 	uint16_t n;
4197 
4198 	if (ss == NULL) {
4199 		iss = stmf_session_id_to_issptr(session_id, 1);
4200 		if (iss == NULL)
4201 			return (STMF_NOT_FOUND);
4202 	} else {
4203 		iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
4204 		rw_enter(iss->iss_lockp, RW_WRITER);
4205 	}
4206 
4207 	ent = NULL;
4208 	if (lun == NULL) {
4209 		lm = iss->iss_sm;
4210 		for (i = 0; i < lm->lm_nentries; i++) {
4211 			if (lm->lm_plus[i] == NULL)
4212 				continue;
4213 			ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
4214 			if (ent->ent_lu == lu)
4215 				break;
4216 		}
4217 	} else {
4218 		n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
4219 		ent = (stmf_lun_map_ent_t *)
4220 		    stmf_get_ent_from_map(iss->iss_sm, n);
4221 		if (lu && (ent->ent_lu != lu))
4222 			ent = NULL;
4223 	}
4224 	if (ent && ent->ent_itl_datap) {
4225 		*itl_handle_retp = ent->ent_itl_datap->itl_handle;
4226 		ret = STMF_SUCCESS;
4227 	} else {
4228 		ret = STMF_NOT_FOUND;
4229 	}
4230 
4231 	rw_exit(iss->iss_lockp);
4232 	return (ret);
4233 }
4234 
4235 stmf_data_buf_t *
4236 stmf_alloc_dbuf(scsi_task_t *task, uint32_t size, uint32_t *pminsize,
4237     uint32_t flags)
4238 {
4239 	stmf_i_scsi_task_t *itask =
4240 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
4241 	stmf_local_port_t *lport = task->task_lport;
4242 	stmf_data_buf_t *dbuf;
4243 	uint8_t ndx;
4244 
4245 	ndx = stmf_first_zero[itask->itask_allocated_buf_map];
4246 	if (ndx == 0xff)
4247 		return (NULL);
4248 	dbuf = itask->itask_dbufs[ndx] = lport->lport_ds->ds_alloc_data_buf(
4249 	    task, size, pminsize, flags);
4250 	if (dbuf) {
4251 		task->task_cur_nbufs++;
4252 		itask->itask_allocated_buf_map |= (1 << ndx);
4253 		dbuf->db_flags &= ~DB_LPORT_XFER_ACTIVE;
4254 		dbuf->db_handle = ndx;
4255 		return (dbuf);
4256 	}
4257 
4258 	return (NULL);
4259 }
4260 
4261 stmf_status_t
4262 stmf_setup_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf, uint32_t flags)
4263 {
4264 	stmf_i_scsi_task_t *itask =
4265 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
4266 	stmf_local_port_t *lport = task->task_lport;
4267 	uint8_t ndx;
4268 	stmf_status_t ret;
4269 
4270 	ASSERT(task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF);
4271 	ASSERT(lport->lport_ds->ds_setup_dbuf != NULL);
4272 	ASSERT(dbuf->db_flags & DB_LU_DATA_BUF);
4273 
4274 	if ((task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF) == 0)
4275 		return (STMF_FAILURE);
4276 	if (lport->lport_ds->ds_setup_dbuf == NULL)
4277 		return (STMF_FAILURE);
4278 
4279 	ndx = stmf_first_zero[itask->itask_allocated_buf_map];
4280 	if (ndx == 0xff)
4281 		return (STMF_FAILURE);
4282 	ret = lport->lport_ds->ds_setup_dbuf(task, dbuf, flags);
4283 	if (ret == STMF_FAILURE)
4284 		return (STMF_FAILURE);
4285 	itask->itask_dbufs[ndx] = dbuf;
4286 	task->task_cur_nbufs++;
4287 	itask->itask_allocated_buf_map |= (1 << ndx);
4288 	dbuf->db_handle = ndx;
4289 
4290 	return (STMF_SUCCESS);
4291 }
4292 
4293 void
4294 stmf_teardown_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf)
4295 {
4296 	stmf_i_scsi_task_t *itask =
4297 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
4298 	stmf_local_port_t *lport = task->task_lport;
4299 
4300 	ASSERT(task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF);
4301 	ASSERT(lport->lport_ds->ds_teardown_dbuf != NULL);
4302 	ASSERT(dbuf->db_flags & DB_LU_DATA_BUF);
4303 
4304 	itask->itask_allocated_buf_map &= ~(1 << dbuf->db_handle);
4305 	task->task_cur_nbufs--;
4306 	lport->lport_ds->ds_teardown_dbuf(lport->lport_ds, dbuf);
4307 }
4308 
4309 void
4310 stmf_free_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf)
4311 {
4312 	stmf_i_scsi_task_t *itask =
4313 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
4314 	stmf_local_port_t *lport = task->task_lport;
4315 
4316 	itask->itask_allocated_buf_map &= ~(1 << dbuf->db_handle);
4317 	task->task_cur_nbufs--;
4318 	lport->lport_ds->ds_free_data_buf(lport->lport_ds, dbuf);
4319 }
4320 
4321 stmf_data_buf_t *
4322 stmf_handle_to_buf(scsi_task_t *task, uint8_t h)
4323 {
4324 	stmf_i_scsi_task_t *itask;
4325 
4326 	itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
4327 	if (h > 3)
4328 		return (NULL);
4329 	return (itask->itask_dbufs[h]);
4330 }
4331 
4332 /* ARGSUSED */
4333 struct scsi_task *
4334 stmf_task_alloc(struct stmf_local_port *lport, stmf_scsi_session_t *ss,
4335 			uint8_t *lun, uint16_t cdb_length_in, uint16_t ext_id)
4336 {
4337 	stmf_lu_t *lu;
4338 	stmf_i_scsi_session_t *iss;
4339 	stmf_i_lu_t *ilu;
4340 	stmf_i_scsi_task_t *itask;
4341 	stmf_i_scsi_task_t **ppitask;
4342 	scsi_task_t *task;
4343 	uint8_t	*l;
4344 	stmf_lun_map_ent_t *lun_map_ent;
4345 	uint16_t cdb_length;
4346 	uint16_t luNbr;
4347 	uint8_t new_task = 0;
4348 
4349 	/*
4350 	 * We allocate 7 extra bytes for CDB to provide a cdb pointer which
4351 	 * is guaranteed to be 8 byte aligned. Some LU providers like OSD
4352 	 * depend upon this alignment.
4353 	 */
4354 	if (cdb_length_in >= 16)
4355 		cdb_length = cdb_length_in + 7;
4356 	else
4357 		cdb_length = 16 + 7;
4358 	iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
4359 	luNbr = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
4360 	rw_enter(iss->iss_lockp, RW_READER);
4361 	lun_map_ent =
4362 	    (stmf_lun_map_ent_t *)stmf_get_ent_from_map(iss->iss_sm, luNbr);
4363 	if (!lun_map_ent) {
4364 		lu = dlun0;
4365 	} else {
4366 		lu = lun_map_ent->ent_lu;
4367 	}
4368 	ilu = lu->lu_stmf_private;
4369 	if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
4370 		rw_exit(iss->iss_lockp);
4371 		return (NULL);
4372 	}
4373 	do {
4374 		if (ilu->ilu_free_tasks == NULL) {
4375 			new_task = 1;
4376 			break;
4377 		}
4378 		mutex_enter(&ilu->ilu_task_lock);
4379 		for (ppitask = &ilu->ilu_free_tasks; (*ppitask != NULL) &&
4380 		    ((*ppitask)->itask_cdb_buf_size < cdb_length);
4381 		    ppitask = &((*ppitask)->itask_lu_free_next))
4382 			;
4383 		if (*ppitask) {
4384 			itask = *ppitask;
4385 			*ppitask = (*ppitask)->itask_lu_free_next;
4386 			ilu->ilu_ntasks_free--;
4387 			if (ilu->ilu_ntasks_free < ilu->ilu_ntasks_min_free)
4388 				ilu->ilu_ntasks_min_free = ilu->ilu_ntasks_free;
4389 		} else {
4390 			new_task = 1;
4391 		}
4392 		mutex_exit(&ilu->ilu_task_lock);
4393 	/* CONSTCOND */
4394 	} while (0);
4395 
4396 	if (!new_task) {
4397 		/*
4398 		 * Save the task_cdb pointer and zero per cmd fields.
4399 		 * We know the task_cdb_length is large enough by task
4400 		 * selection process above.
4401 		 */
4402 		uint8_t *save_cdb;
4403 		uintptr_t t_start, t_end;
4404 
4405 		task = itask->itask_task;
4406 		save_cdb = task->task_cdb;	/* save */
4407 		t_start = (uintptr_t)&task->task_flags;
4408 		t_end = (uintptr_t)&task->task_extended_cmd;
4409 		bzero((void *)t_start, (size_t)(t_end - t_start));
4410 		task->task_cdb = save_cdb;	/* restore */
4411 		itask->itask_ncmds = 0;
4412 	} else {
4413 		task = (scsi_task_t *)stmf_alloc(STMF_STRUCT_SCSI_TASK,
4414 		    cdb_length, AF_FORCE_NOSLEEP);
4415 		if (task == NULL) {
4416 			rw_exit(iss->iss_lockp);
4417 			return (NULL);
4418 		}
4419 		task->task_lu = lu;
4420 		l = task->task_lun_no;
4421 		l[0] = lun[0];
4422 		l[1] = lun[1];
4423 		l[2] = lun[2];
4424 		l[3] = lun[3];
4425 		l[4] = lun[4];
4426 		l[5] = lun[5];
4427 		l[6] = lun[6];
4428 		l[7] = lun[7];
4429 		task->task_cdb = (uint8_t *)task->task_port_private;
4430 		if ((ulong_t)(task->task_cdb) & 7ul) {
4431 			task->task_cdb = (uint8_t *)(((ulong_t)
4432 			    (task->task_cdb) + 7ul) & ~(7ul));
4433 		}
4434 		itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
4435 		itask->itask_cdb_buf_size = cdb_length;
4436 		mutex_init(&itask->itask_audit_mutex, NULL, MUTEX_DRIVER, NULL);
4437 	}
4438 	task->task_session = ss;
4439 	task->task_lport = lport;
4440 	task->task_cdb_length = cdb_length_in;
4441 	itask->itask_flags = ITASK_IN_TRANSITION;
4442 	itask->itask_waitq_time = 0;
4443 	itask->itask_lu_read_time = itask->itask_lu_write_time = 0;
4444 	itask->itask_lport_read_time = itask->itask_lport_write_time = 0;
4445 	itask->itask_read_xfer = itask->itask_write_xfer = 0;
4446 	itask->itask_audit_index = 0;
4447 
4448 	if (new_task) {
4449 		if (lu->lu_task_alloc(task) != STMF_SUCCESS) {
4450 			rw_exit(iss->iss_lockp);
4451 			stmf_free(task);
4452 			return (NULL);
4453 		}
4454 		mutex_enter(&ilu->ilu_task_lock);
4455 		if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
4456 			mutex_exit(&ilu->ilu_task_lock);
4457 			rw_exit(iss->iss_lockp);
4458 			stmf_free(task);
4459 			return (NULL);
4460 		}
4461 		itask->itask_lu_next = ilu->ilu_tasks;
4462 		if (ilu->ilu_tasks)
4463 			ilu->ilu_tasks->itask_lu_prev = itask;
4464 		ilu->ilu_tasks = itask;
4465 		/* kmem_zalloc automatically makes itask->itask_lu_prev NULL */
4466 		ilu->ilu_ntasks++;
4467 		mutex_exit(&ilu->ilu_task_lock);
4468 	}
4469 
4470 	itask->itask_ilu_task_cntr = ilu->ilu_cur_task_cntr;
4471 	atomic_add_32(itask->itask_ilu_task_cntr, 1);
4472 	itask->itask_start_time = ddi_get_lbolt();
4473 
4474 	if ((lun_map_ent != NULL) && ((itask->itask_itl_datap =
4475 	    lun_map_ent->ent_itl_datap) != NULL)) {
4476 		atomic_add_32(&itask->itask_itl_datap->itl_counter, 1);
4477 		task->task_lu_itl_handle = itask->itask_itl_datap->itl_handle;
4478 	} else {
4479 		itask->itask_itl_datap = NULL;
4480 		task->task_lu_itl_handle = NULL;
4481 	}
4482 
4483 	rw_exit(iss->iss_lockp);
4484 	return (task);
4485 }
4486 
4487 static void
4488 stmf_task_lu_free(scsi_task_t *task, stmf_i_scsi_session_t *iss)
4489 {
4490 	stmf_i_scsi_task_t *itask =
4491 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
4492 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
4493 
4494 	ASSERT(rw_lock_held(iss->iss_lockp));
4495 	itask->itask_flags = ITASK_IN_FREE_LIST;
4496 	itask->itask_proxy_msg_id = 0;
4497 	mutex_enter(&ilu->ilu_task_lock);
4498 	itask->itask_lu_free_next = ilu->ilu_free_tasks;
4499 	ilu->ilu_free_tasks = itask;
4500 	ilu->ilu_ntasks_free++;
4501 	mutex_exit(&ilu->ilu_task_lock);
4502 	atomic_add_32(itask->itask_ilu_task_cntr, -1);
4503 }
4504 
4505 void
4506 stmf_task_lu_check_freelist(stmf_i_lu_t *ilu)
4507 {
4508 	uint32_t	num_to_release, ndx;
4509 	stmf_i_scsi_task_t *itask;
4510 	stmf_lu_t	*lu = ilu->ilu_lu;
4511 
4512 	ASSERT(ilu->ilu_ntasks_min_free <= ilu->ilu_ntasks_free);
4513 
4514 	/* free half of the minimal free of the free tasks */
4515 	num_to_release = (ilu->ilu_ntasks_min_free + 1) / 2;
4516 	if (!num_to_release) {
4517 		return;
4518 	}
4519 	for (ndx = 0; ndx < num_to_release; ndx++) {
4520 		mutex_enter(&ilu->ilu_task_lock);
4521 		itask = ilu->ilu_free_tasks;
4522 		if (itask == NULL) {
4523 			mutex_exit(&ilu->ilu_task_lock);
4524 			break;
4525 		}
4526 		ilu->ilu_free_tasks = itask->itask_lu_free_next;
4527 		ilu->ilu_ntasks_free--;
4528 		mutex_exit(&ilu->ilu_task_lock);
4529 
4530 		lu->lu_task_free(itask->itask_task);
4531 		mutex_enter(&ilu->ilu_task_lock);
4532 		if (itask->itask_lu_next)
4533 			itask->itask_lu_next->itask_lu_prev =
4534 			    itask->itask_lu_prev;
4535 		if (itask->itask_lu_prev)
4536 			itask->itask_lu_prev->itask_lu_next =
4537 			    itask->itask_lu_next;
4538 		else
4539 			ilu->ilu_tasks = itask->itask_lu_next;
4540 
4541 		ilu->ilu_ntasks--;
4542 		mutex_exit(&ilu->ilu_task_lock);
4543 		stmf_free(itask->itask_task);
4544 	}
4545 }
4546 
4547 /*
4548  * Called with stmf_lock held
4549  */
4550 void
4551 stmf_check_freetask()
4552 {
4553 	stmf_i_lu_t *ilu;
4554 	clock_t	endtime = ddi_get_lbolt() + drv_usectohz(10000);
4555 
4556 	/* stmf_svc_ilu_draining may get changed after stmf_lock is released */
4557 	while ((ilu = stmf_state.stmf_svc_ilu_draining) != NULL) {
4558 		stmf_state.stmf_svc_ilu_draining = ilu->ilu_next;
4559 		if (!ilu->ilu_ntasks_min_free) {
4560 			ilu->ilu_ntasks_min_free = ilu->ilu_ntasks_free;
4561 			continue;
4562 		}
4563 		ilu->ilu_flags |= ILU_STALL_DEREGISTER;
4564 		mutex_exit(&stmf_state.stmf_lock);
4565 		stmf_task_lu_check_freelist(ilu);
4566 		/*
4567 		 * we do not care about the accuracy of
4568 		 * ilu_ntasks_min_free, so we don't lock here
4569 		 */
4570 		ilu->ilu_ntasks_min_free = ilu->ilu_ntasks_free;
4571 		mutex_enter(&stmf_state.stmf_lock);
4572 		ilu->ilu_flags &= ~ILU_STALL_DEREGISTER;
4573 		cv_broadcast(&stmf_state.stmf_cv);
4574 		if (ddi_get_lbolt() >= endtime)
4575 			break;
4576 	}
4577 }
4578 
4579 void
4580 stmf_do_ilu_timeouts(stmf_i_lu_t *ilu)
4581 {
4582 	clock_t l = ddi_get_lbolt();
4583 	clock_t ps = drv_usectohz(1000000);
4584 	stmf_i_scsi_task_t *itask;
4585 	scsi_task_t *task;
4586 	uint32_t to;
4587 
4588 	mutex_enter(&ilu->ilu_task_lock);
4589 	for (itask = ilu->ilu_tasks; itask != NULL;
4590 	    itask = itask->itask_lu_next) {
4591 		if (itask->itask_flags & (ITASK_IN_FREE_LIST |
4592 		    ITASK_BEING_ABORTED)) {
4593 			continue;
4594 		}
4595 		task = itask->itask_task;
4596 		if (task->task_timeout == 0)
4597 			to = stmf_default_task_timeout;
4598 		else
4599 			to = task->task_timeout;
4600 		if ((itask->itask_start_time + (to * ps)) > l)
4601 			continue;
4602 		stmf_abort(STMF_QUEUE_TASK_ABORT, task,
4603 		    STMF_TIMEOUT, NULL);
4604 	}
4605 	mutex_exit(&ilu->ilu_task_lock);
4606 }
4607 
4608 /*
4609  * Called with stmf_lock held
4610  */
4611 void
4612 stmf_check_ilu_timing()
4613 {
4614 	stmf_i_lu_t *ilu;
4615 	clock_t	endtime = ddi_get_lbolt() + drv_usectohz(10000);
4616 
4617 	/* stmf_svc_ilu_timing may get changed after stmf_lock is released */
4618 	while ((ilu = stmf_state.stmf_svc_ilu_timing) != NULL) {
4619 		stmf_state.stmf_svc_ilu_timing = ilu->ilu_next;
4620 		if (ilu->ilu_cur_task_cntr == (&ilu->ilu_task_cntr1)) {
4621 			if (ilu->ilu_task_cntr2 == 0) {
4622 				ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr2;
4623 				continue;
4624 			}
4625 		} else {
4626 			if (ilu->ilu_task_cntr1 == 0) {
4627 				ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1;
4628 				continue;
4629 			}
4630 		}
4631 		/*
4632 		 * If we are here then it means that there is some slowdown
4633 		 * in tasks on this lu. We need to check.
4634 		 */
4635 		ilu->ilu_flags |= ILU_STALL_DEREGISTER;
4636 		mutex_exit(&stmf_state.stmf_lock);
4637 		stmf_do_ilu_timeouts(ilu);
4638 		mutex_enter(&stmf_state.stmf_lock);
4639 		ilu->ilu_flags &= ~ILU_STALL_DEREGISTER;
4640 		cv_broadcast(&stmf_state.stmf_cv);
4641 		if (ddi_get_lbolt() >= endtime)
4642 			break;
4643 	}
4644 }
4645 
4646 /*
4647  * Kills all tasks on a lu except tm_task
4648  */
4649 void
4650 stmf_task_lu_killall(stmf_lu_t *lu, scsi_task_t *tm_task, stmf_status_t s)
4651 {
4652 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
4653 	stmf_i_scsi_task_t *itask;
4654 
4655 	mutex_enter(&ilu->ilu_task_lock);
4656 
4657 	for (itask = ilu->ilu_tasks; itask != NULL;
4658 	    itask = itask->itask_lu_next) {
4659 		if (itask->itask_flags & ITASK_IN_FREE_LIST)
4660 			continue;
4661 		if (itask->itask_task == tm_task)
4662 			continue;
4663 		stmf_abort(STMF_QUEUE_TASK_ABORT, itask->itask_task, s, NULL);
4664 	}
4665 	mutex_exit(&ilu->ilu_task_lock);
4666 }
4667 
4668 void
4669 stmf_free_task_bufs(stmf_i_scsi_task_t *itask, stmf_local_port_t *lport)
4670 {
4671 	int i;
4672 	uint8_t map;
4673 
4674 	if ((map = itask->itask_allocated_buf_map) == 0)
4675 		return;
4676 	for (i = 0; i < 4; i++) {
4677 		if (map & 1) {
4678 			stmf_data_buf_t *dbuf;
4679 
4680 			dbuf = itask->itask_dbufs[i];
4681 			if (dbuf->db_xfer_start_timestamp) {
4682 				stmf_lport_xfer_done(itask, dbuf);
4683 			}
4684 			if (dbuf->db_flags & DB_LU_DATA_BUF) {
4685 				/*
4686 				 * LU needs to clean up buffer.
4687 				 * LU is required to free the buffer
4688 				 * in the xfer_done handler.
4689 				 */
4690 				scsi_task_t *task = itask->itask_task;
4691 				stmf_lu_t *lu = task->task_lu;
4692 
4693 				lu->lu_dbuf_free(task, dbuf);
4694 				ASSERT(((itask->itask_allocated_buf_map>>i)
4695 				    & 1) == 0); /* must be gone */
4696 			} else {
4697 				ASSERT(dbuf->db_lu_private == NULL);
4698 				dbuf->db_lu_private = NULL;
4699 				lport->lport_ds->ds_free_data_buf(
4700 				    lport->lport_ds, dbuf);
4701 			}
4702 		}
4703 		map >>= 1;
4704 	}
4705 	itask->itask_allocated_buf_map = 0;
4706 }
4707 
4708 void
4709 stmf_task_free(scsi_task_t *task)
4710 {
4711 	stmf_local_port_t *lport = task->task_lport;
4712 	stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
4713 	    task->task_stmf_private;
4714 	stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
4715 	    task->task_session->ss_stmf_private;
4716 
4717 	stmf_task_audit(itask, TE_TASK_FREE, CMD_OR_IOF_NA, NULL);
4718 
4719 	stmf_free_task_bufs(itask, lport);
4720 	stmf_itl_task_done(itask);
4721 	DTRACE_PROBE2(stmf__task__end, scsi_task_t *, task,
4722 	    hrtime_t,
4723 	    itask->itask_done_timestamp - itask->itask_start_timestamp);
4724 	if (itask->itask_itl_datap) {
4725 		if (atomic_add_32_nv(&itask->itask_itl_datap->itl_counter,
4726 		    -1) == 0) {
4727 			stmf_release_itl_handle(task->task_lu,
4728 			    itask->itask_itl_datap);
4729 		}
4730 	}
4731 
4732 	rw_enter(iss->iss_lockp, RW_READER);
4733 	lport->lport_task_free(task);
4734 	if (itask->itask_worker) {
4735 		atomic_add_32(&stmf_cur_ntasks, -1);
4736 		atomic_add_32(&itask->itask_worker->worker_ref_count, -1);
4737 	}
4738 	/*
4739 	 * After calling stmf_task_lu_free, the task pointer can no longer
4740 	 * be trusted.
4741 	 */
4742 	stmf_task_lu_free(task, iss);
4743 	rw_exit(iss->iss_lockp);
4744 }
4745 
4746 void
4747 stmf_post_task(scsi_task_t *task, stmf_data_buf_t *dbuf)
4748 {
4749 	stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
4750 	    task->task_stmf_private;
4751 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
4752 	int nv;
4753 	uint32_t old, new;
4754 	uint32_t ct;
4755 	stmf_worker_t *w, *w1;
4756 	uint8_t tm;
4757 
4758 	if (task->task_max_nbufs > 4)
4759 		task->task_max_nbufs = 4;
4760 	task->task_cur_nbufs = 0;
4761 	/* Latest value of currently running tasks */
4762 	ct = atomic_add_32_nv(&stmf_cur_ntasks, 1);
4763 
4764 	/* Select the next worker using round robin */
4765 	nv = (int)atomic_add_32_nv((uint32_t *)&stmf_worker_sel_counter, 1);
4766 	if (nv >= stmf_nworkers_accepting_cmds) {
4767 		int s = nv;
4768 		do {
4769 			nv -= stmf_nworkers_accepting_cmds;
4770 		} while (nv >= stmf_nworkers_accepting_cmds);
4771 		if (nv < 0)
4772 			nv = 0;
4773 		/* Its ok if this cas fails */
4774 		(void) atomic_cas_32((uint32_t *)&stmf_worker_sel_counter,
4775 		    s, nv);
4776 	}
4777 	w = &stmf_workers[nv];
4778 
4779 	/*
4780 	 * A worker can be pinned by interrupt. So select the next one
4781 	 * if it has lower load.
4782 	 */
4783 	if ((nv + 1) >= stmf_nworkers_accepting_cmds) {
4784 		w1 = stmf_workers;
4785 	} else {
4786 		w1 = &stmf_workers[nv + 1];
4787 	}
4788 	if (w1->worker_queue_depth < w->worker_queue_depth)
4789 		w = w1;
4790 
4791 	mutex_enter(&w->worker_lock);
4792 	if (((w->worker_flags & STMF_WORKER_STARTED) == 0) ||
4793 	    (w->worker_flags & STMF_WORKER_TERMINATE)) {
4794 		/*
4795 		 * Maybe we are in the middle of a change. Just go to
4796 		 * the 1st worker.
4797 		 */
4798 		mutex_exit(&w->worker_lock);
4799 		w = stmf_workers;
4800 		mutex_enter(&w->worker_lock);
4801 	}
4802 	itask->itask_worker = w;
4803 	/*
4804 	 * Track max system load inside the worker as we already have the
4805 	 * worker lock (no point implementing another lock). The service
4806 	 * thread will do the comparisons and figure out the max overall
4807 	 * system load.
4808 	 */
4809 	if (w->worker_max_sys_qdepth_pu < ct)
4810 		w->worker_max_sys_qdepth_pu = ct;
4811 
4812 	do {
4813 		old = new = itask->itask_flags;
4814 		new |= ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE;
4815 		if (task->task_mgmt_function) {
4816 			tm = task->task_mgmt_function;
4817 			if ((tm == TM_TARGET_RESET) ||
4818 			    (tm == TM_TARGET_COLD_RESET) ||
4819 			    (tm == TM_TARGET_WARM_RESET)) {
4820 				new |= ITASK_DEFAULT_HANDLING;
4821 			}
4822 		} else if (task->task_cdb[0] == SCMD_REPORT_LUNS) {
4823 			new |= ITASK_DEFAULT_HANDLING;
4824 		}
4825 		new &= ~ITASK_IN_TRANSITION;
4826 	} while (atomic_cas_32(&itask->itask_flags, old, new) != old);
4827 
4828 	stmf_itl_task_start(itask);
4829 
4830 	itask->itask_worker_next = NULL;
4831 	if (w->worker_task_tail) {
4832 		w->worker_task_tail->itask_worker_next = itask;
4833 	} else {
4834 		w->worker_task_head = itask;
4835 	}
4836 	w->worker_task_tail = itask;
4837 	if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
4838 		w->worker_max_qdepth_pu = w->worker_queue_depth;
4839 	}
4840 	/* Measure task waitq time */
4841 	itask->itask_waitq_enter_timestamp = gethrtime();
4842 	atomic_add_32(&w->worker_ref_count, 1);
4843 	itask->itask_cmd_stack[0] = ITASK_CMD_NEW_TASK;
4844 	itask->itask_ncmds = 1;
4845 	stmf_task_audit(itask, TE_TASK_START, CMD_OR_IOF_NA, dbuf);
4846 	if (dbuf) {
4847 		itask->itask_allocated_buf_map = 1;
4848 		itask->itask_dbufs[0] = dbuf;
4849 		dbuf->db_handle = 0;
4850 	} else {
4851 		itask->itask_allocated_buf_map = 0;
4852 		itask->itask_dbufs[0] = NULL;
4853 	}
4854 
4855 	if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0) {
4856 		w->worker_signal_timestamp = gethrtime();
4857 		DTRACE_PROBE2(worker__signal, stmf_worker_t *, w,
4858 		    scsi_task_t *, task);
4859 		cv_signal(&w->worker_cv);
4860 	}
4861 	mutex_exit(&w->worker_lock);
4862 
4863 	/*
4864 	 * This can only happen if during stmf_task_alloc(), ILU_RESET_ACTIVE
4865 	 * was set between checking of ILU_RESET_ACTIVE and clearing of the
4866 	 * ITASK_IN_FREE_LIST flag. Take care of these "sneaked-in" tasks here.
4867 	 */
4868 	if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
4869 		stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ABORTED, NULL);
4870 	}
4871 }
4872 
4873 static void
4874 stmf_task_audit(stmf_i_scsi_task_t *itask,
4875     task_audit_event_t te, uint32_t cmd_or_iof, stmf_data_buf_t *dbuf)
4876 {
4877 	stmf_task_audit_rec_t *ar;
4878 
4879 	mutex_enter(&itask->itask_audit_mutex);
4880 	ar = &itask->itask_audit_records[itask->itask_audit_index++];
4881 	itask->itask_audit_index &= (ITASK_TASK_AUDIT_DEPTH - 1);
4882 	ar->ta_event = te;
4883 	ar->ta_cmd_or_iof = cmd_or_iof;
4884 	ar->ta_itask_flags = itask->itask_flags;
4885 	ar->ta_dbuf = dbuf;
4886 	gethrestime(&ar->ta_timestamp);
4887 	mutex_exit(&itask->itask_audit_mutex);
4888 }
4889 
4890 
4891 /*
4892  * ++++++++++++++ ABORT LOGIC ++++++++++++++++++++
4893  * Once ITASK_BEING_ABORTED is set, ITASK_KNOWN_TO_LU can be reset already
4894  * i.e. before ITASK_BEING_ABORTED being set. But if it was not, it cannot
4895  * be reset until the LU explicitly calls stmf_task_lu_aborted(). Of course
4896  * the LU will make this call only if we call the LU's abort entry point.
4897  * we will only call that entry point if ITASK_KNOWN_TO_LU was set.
4898  *
4899  * Same logic applies for the port.
4900  *
4901  * Also ITASK_BEING_ABORTED will not be allowed to set if both KNOWN_TO_LU
4902  * and KNOWN_TO_TGT_PORT are reset.
4903  *
4904  * +++++++++++++++++++++++++++++++++++++++++++++++
4905  */
4906 
4907 stmf_status_t
4908 stmf_xfer_data(scsi_task_t *task, stmf_data_buf_t *dbuf, uint32_t ioflags)
4909 {
4910 	stmf_status_t ret = STMF_SUCCESS;
4911 
4912 	stmf_i_scsi_task_t *itask =
4913 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
4914 
4915 	stmf_task_audit(itask, TE_XFER_START, ioflags, dbuf);
4916 
4917 	if (ioflags & STMF_IOF_LU_DONE) {
4918 		uint32_t new, old;
4919 		do {
4920 			new = old = itask->itask_flags;
4921 			if (new & ITASK_BEING_ABORTED)
4922 				return (STMF_ABORTED);
4923 			new &= ~ITASK_KNOWN_TO_LU;
4924 		} while (atomic_cas_32(&itask->itask_flags, old, new) != old);
4925 	}
4926 	if (itask->itask_flags & ITASK_BEING_ABORTED)
4927 		return (STMF_ABORTED);
4928 #ifdef	DEBUG
4929 	if (!(ioflags & STMF_IOF_STATS_ONLY) && stmf_drop_buf_counter > 0) {
4930 		if (atomic_add_32_nv((uint32_t *)&stmf_drop_buf_counter, -1) ==
4931 		    1)
4932 			return (STMF_SUCCESS);
4933 	}
4934 #endif
4935 
4936 	stmf_update_kstat_lu_io(task, dbuf);
4937 	stmf_update_kstat_lport_io(task, dbuf);
4938 	stmf_lport_xfer_start(itask, dbuf);
4939 	if (ioflags & STMF_IOF_STATS_ONLY) {
4940 		stmf_lport_xfer_done(itask, dbuf);
4941 		return (STMF_SUCCESS);
4942 	}
4943 
4944 	dbuf->db_flags |= DB_LPORT_XFER_ACTIVE;
4945 	ret = task->task_lport->lport_xfer_data(task, dbuf, ioflags);
4946 
4947 	/*
4948 	 * Port provider may have already called the buffer callback in
4949 	 * which case dbuf->db_xfer_start_timestamp will be 0.
4950 	 */
4951 	if (ret != STMF_SUCCESS) {
4952 		dbuf->db_flags &= ~DB_LPORT_XFER_ACTIVE;
4953 		if (dbuf->db_xfer_start_timestamp != 0)
4954 			stmf_lport_xfer_done(itask, dbuf);
4955 	}
4956 
4957 	return (ret);
4958 }
4959 
4960 void
4961 stmf_data_xfer_done(scsi_task_t *task, stmf_data_buf_t *dbuf, uint32_t iof)
4962 {
4963 	stmf_i_scsi_task_t *itask =
4964 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
4965 	stmf_i_local_port_t *ilport;
4966 	stmf_worker_t *w = itask->itask_worker;
4967 	uint32_t new, old;
4968 	uint8_t update_queue_flags, free_it, queue_it;
4969 
4970 	stmf_lport_xfer_done(itask, dbuf);
4971 
4972 	stmf_task_audit(itask, TE_XFER_DONE, iof, dbuf);
4973 
4974 	/* Guard against unexpected completions from the lport */
4975 	if (dbuf->db_flags & DB_LPORT_XFER_ACTIVE) {
4976 		dbuf->db_flags &= ~DB_LPORT_XFER_ACTIVE;
4977 	} else {
4978 		/*
4979 		 * This should never happen.
4980 		 */
4981 		ilport = task->task_lport->lport_stmf_private;
4982 		ilport->ilport_unexpected_comp++;
4983 		cmn_err(CE_PANIC, "Unexpected xfer completion task %p dbuf %p",
4984 		    (void *)task, (void *)dbuf);
4985 		return;
4986 	}
4987 
4988 	mutex_enter(&w->worker_lock);
4989 	do {
4990 		new = old = itask->itask_flags;
4991 		if (old & ITASK_BEING_ABORTED) {
4992 			mutex_exit(&w->worker_lock);
4993 			return;
4994 		}
4995 		free_it = 0;
4996 		if (iof & STMF_IOF_LPORT_DONE) {
4997 			new &= ~ITASK_KNOWN_TO_TGT_PORT;
4998 			task->task_completion_status = dbuf->db_xfer_status;
4999 			free_it = 1;
5000 		}
5001 		/*
5002 		 * If the task is known to LU then queue it. But if
5003 		 * it is already queued (multiple completions) then
5004 		 * just update the buffer information by grabbing the
5005 		 * worker lock. If the task is not known to LU,
5006 		 * completed/aborted, then see if we need to
5007 		 * free this task.
5008 		 */
5009 		if (old & ITASK_KNOWN_TO_LU) {
5010 			free_it = 0;
5011 			update_queue_flags = 1;
5012 			if (old & ITASK_IN_WORKER_QUEUE) {
5013 				queue_it = 0;
5014 			} else {
5015 				queue_it = 1;
5016 				new |= ITASK_IN_WORKER_QUEUE;
5017 			}
5018 		} else {
5019 			update_queue_flags = 0;
5020 			queue_it = 0;
5021 		}
5022 	} while (atomic_cas_32(&itask->itask_flags, old, new) != old);
5023 
5024 	if (update_queue_flags) {
5025 		uint8_t cmd = (dbuf->db_handle << 5) | ITASK_CMD_DATA_XFER_DONE;
5026 
5027 		ASSERT(itask->itask_ncmds < ITASK_MAX_NCMDS);
5028 		itask->itask_cmd_stack[itask->itask_ncmds++] = cmd;
5029 		if (queue_it) {
5030 			itask->itask_worker_next = NULL;
5031 			if (w->worker_task_tail) {
5032 				w->worker_task_tail->itask_worker_next = itask;
5033 			} else {
5034 				w->worker_task_head = itask;
5035 			}
5036 			w->worker_task_tail = itask;
5037 			/* Measure task waitq time */
5038 			itask->itask_waitq_enter_timestamp = gethrtime();
5039 			if (++(w->worker_queue_depth) >
5040 			    w->worker_max_qdepth_pu) {
5041 				w->worker_max_qdepth_pu = w->worker_queue_depth;
5042 			}
5043 			if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0)
5044 				cv_signal(&w->worker_cv);
5045 		}
5046 	}
5047 	mutex_exit(&w->worker_lock);
5048 
5049 	if (free_it) {
5050 		if ((itask->itask_flags & (ITASK_KNOWN_TO_LU |
5051 		    ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE |
5052 		    ITASK_BEING_ABORTED)) == 0) {
5053 			stmf_task_free(task);
5054 		}
5055 	}
5056 }
5057 
5058 stmf_status_t
5059 stmf_send_scsi_status(scsi_task_t *task, uint32_t ioflags)
5060 {
5061 	DTRACE_PROBE1(scsi__send__status, scsi_task_t *, task);
5062 
5063 	stmf_i_scsi_task_t *itask =
5064 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
5065 
5066 	stmf_task_audit(itask, TE_SEND_STATUS, ioflags, NULL);
5067 
5068 	if (ioflags & STMF_IOF_LU_DONE) {
5069 		uint32_t new, old;
5070 		do {
5071 			new = old = itask->itask_flags;
5072 			if (new & ITASK_BEING_ABORTED)
5073 				return (STMF_ABORTED);
5074 			new &= ~ITASK_KNOWN_TO_LU;
5075 		} while (atomic_cas_32(&itask->itask_flags, old, new) != old);
5076 	}
5077 
5078 	if (!(itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT)) {
5079 		return (STMF_SUCCESS);
5080 	}
5081 
5082 	if (itask->itask_flags & ITASK_BEING_ABORTED)
5083 		return (STMF_ABORTED);
5084 
5085 	if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
5086 		task->task_status_ctrl = 0;
5087 		task->task_resid = 0;
5088 	} else if (task->task_cmd_xfer_length >
5089 	    task->task_expected_xfer_length) {
5090 		task->task_status_ctrl = TASK_SCTRL_OVER;
5091 		task->task_resid = task->task_cmd_xfer_length -
5092 		    task->task_expected_xfer_length;
5093 	} else if (task->task_nbytes_transferred <
5094 	    task->task_expected_xfer_length) {
5095 		task->task_status_ctrl = TASK_SCTRL_UNDER;
5096 		task->task_resid = task->task_expected_xfer_length -
5097 		    task->task_nbytes_transferred;
5098 	} else {
5099 		task->task_status_ctrl = 0;
5100 		task->task_resid = 0;
5101 	}
5102 	return (task->task_lport->lport_send_status(task, ioflags));
5103 }
5104 
5105 void
5106 stmf_send_status_done(scsi_task_t *task, stmf_status_t s, uint32_t iof)
5107 {
5108 	stmf_i_scsi_task_t *itask =
5109 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
5110 	stmf_worker_t *w = itask->itask_worker;
5111 	uint32_t new, old;
5112 	uint8_t free_it, queue_it;
5113 
5114 	stmf_task_audit(itask, TE_SEND_STATUS_DONE, iof, NULL);
5115 
5116 	mutex_enter(&w->worker_lock);
5117 	do {
5118 		new = old = itask->itask_flags;
5119 		if (old & ITASK_BEING_ABORTED) {
5120 			mutex_exit(&w->worker_lock);
5121 			return;
5122 		}
5123 		free_it = 0;
5124 		if (iof & STMF_IOF_LPORT_DONE) {
5125 			new &= ~ITASK_KNOWN_TO_TGT_PORT;
5126 			free_it = 1;
5127 		}
5128 		/*
5129 		 * If the task is known to LU then queue it. But if
5130 		 * it is already queued (multiple completions) then
5131 		 * just update the buffer information by grabbing the
5132 		 * worker lock. If the task is not known to LU,
5133 		 * completed/aborted, then see if we need to
5134 		 * free this task.
5135 		 */
5136 		if (old & ITASK_KNOWN_TO_LU) {
5137 			free_it = 0;
5138 			queue_it = 1;
5139 			if (old & ITASK_IN_WORKER_QUEUE) {
5140 				cmn_err(CE_PANIC, "status completion received"
5141 				    " when task is already in worker queue "
5142 				    " task = %p", (void *)task);
5143 			}
5144 			new |= ITASK_IN_WORKER_QUEUE;
5145 		} else {
5146 			queue_it = 0;
5147 		}
5148 	} while (atomic_cas_32(&itask->itask_flags, old, new) != old);
5149 	task->task_completion_status = s;
5150 
5151 
5152 	if (queue_it) {
5153 		ASSERT(itask->itask_ncmds < ITASK_MAX_NCMDS);
5154 		itask->itask_cmd_stack[itask->itask_ncmds++] =
5155 		    ITASK_CMD_STATUS_DONE;
5156 		itask->itask_worker_next = NULL;
5157 		if (w->worker_task_tail) {
5158 			w->worker_task_tail->itask_worker_next = itask;
5159 		} else {
5160 			w->worker_task_head = itask;
5161 		}
5162 		w->worker_task_tail = itask;
5163 		/* Measure task waitq time */
5164 		itask->itask_waitq_enter_timestamp = gethrtime();
5165 		if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
5166 			w->worker_max_qdepth_pu = w->worker_queue_depth;
5167 		}
5168 		if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0)
5169 			cv_signal(&w->worker_cv);
5170 	}
5171 	mutex_exit(&w->worker_lock);
5172 
5173 	if (free_it) {
5174 		if ((itask->itask_flags & (ITASK_KNOWN_TO_LU |
5175 		    ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE |
5176 		    ITASK_BEING_ABORTED)) == 0) {
5177 			stmf_task_free(task);
5178 		} else {
5179 			cmn_err(CE_PANIC, "LU is done with the task but LPORT "
5180 			    " is not done, itask %p itask_flags %x",
5181 			    (void *)itask, itask->itask_flags);
5182 		}
5183 	}
5184 }
5185 
5186 void
5187 stmf_task_lu_done(scsi_task_t *task)
5188 {
5189 	stmf_i_scsi_task_t *itask =
5190 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
5191 	stmf_worker_t *w = itask->itask_worker;
5192 	uint32_t new, old;
5193 
5194 	mutex_enter(&w->worker_lock);
5195 	do {
5196 		new = old = itask->itask_flags;
5197 		if (old & ITASK_BEING_ABORTED) {
5198 			mutex_exit(&w->worker_lock);
5199 			return;
5200 		}
5201 		if (old & ITASK_IN_WORKER_QUEUE) {
5202 			cmn_err(CE_PANIC, "task_lu_done received"
5203 			    " when task is in worker queue "
5204 			    " task = %p", (void *)task);
5205 		}
5206 		new &= ~ITASK_KNOWN_TO_LU;
5207 	} while (atomic_cas_32(&itask->itask_flags, old, new) != old);
5208 
5209 	mutex_exit(&w->worker_lock);
5210 
5211 	if ((itask->itask_flags & (ITASK_KNOWN_TO_LU |
5212 	    ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE |
5213 	    ITASK_BEING_ABORTED)) == 0) {
5214 		stmf_task_free(task);
5215 	} else {
5216 		cmn_err(CE_PANIC, "stmf_lu_done should be the last stage but "
5217 		    " the task is still not done, task = %p", (void *)task);
5218 	}
5219 }
5220 
5221 void
5222 stmf_queue_task_for_abort(scsi_task_t *task, stmf_status_t s)
5223 {
5224 	stmf_i_scsi_task_t *itask =
5225 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
5226 	stmf_worker_t *w;
5227 	uint32_t old, new;
5228 
5229 	stmf_task_audit(itask, TE_TASK_ABORT, CMD_OR_IOF_NA, NULL);
5230 
5231 	do {
5232 		old = new = itask->itask_flags;
5233 		if ((old & ITASK_BEING_ABORTED) ||
5234 		    ((old & (ITASK_KNOWN_TO_TGT_PORT |
5235 		    ITASK_KNOWN_TO_LU)) == 0)) {
5236 			return;
5237 		}
5238 		new |= ITASK_BEING_ABORTED;
5239 	} while (atomic_cas_32(&itask->itask_flags, old, new) != old);
5240 	task->task_completion_status = s;
5241 	itask->itask_start_time = ddi_get_lbolt();
5242 
5243 	if (((w = itask->itask_worker) == NULL) ||
5244 	    (itask->itask_flags & ITASK_IN_TRANSITION)) {
5245 		return;
5246 	}
5247 
5248 	/* Queue it and get out */
5249 	mutex_enter(&w->worker_lock);
5250 	if (itask->itask_flags & ITASK_IN_WORKER_QUEUE) {
5251 		mutex_exit(&w->worker_lock);
5252 		return;
5253 	}
5254 	atomic_or_32(&itask->itask_flags, ITASK_IN_WORKER_QUEUE);
5255 	itask->itask_worker_next = NULL;
5256 	if (w->worker_task_tail) {
5257 		w->worker_task_tail->itask_worker_next = itask;
5258 	} else {
5259 		w->worker_task_head = itask;
5260 	}
5261 	w->worker_task_tail = itask;
5262 	if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
5263 		w->worker_max_qdepth_pu = w->worker_queue_depth;
5264 	}
5265 	if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0)
5266 		cv_signal(&w->worker_cv);
5267 	mutex_exit(&w->worker_lock);
5268 }
5269 
5270 void
5271 stmf_abort(int abort_cmd, scsi_task_t *task, stmf_status_t s, void *arg)
5272 {
5273 	stmf_i_scsi_task_t *itask = NULL;
5274 	uint32_t old, new, f, rf;
5275 
5276 	DTRACE_PROBE2(scsi__task__abort, scsi_task_t *, task,
5277 	    stmf_status_t, s);
5278 
5279 	switch (abort_cmd) {
5280 	case STMF_QUEUE_ABORT_LU:
5281 		stmf_task_lu_killall((stmf_lu_t *)arg, task, s);
5282 		return;
5283 	case STMF_QUEUE_TASK_ABORT:
5284 		stmf_queue_task_for_abort(task, s);
5285 		return;
5286 	case STMF_REQUEUE_TASK_ABORT_LPORT:
5287 		rf = ITASK_TGT_PORT_ABORT_CALLED;
5288 		f = ITASK_KNOWN_TO_TGT_PORT;
5289 		break;
5290 	case STMF_REQUEUE_TASK_ABORT_LU:
5291 		rf = ITASK_LU_ABORT_CALLED;
5292 		f = ITASK_KNOWN_TO_LU;
5293 		break;
5294 	default:
5295 		return;
5296 	}
5297 	itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
5298 	f |= ITASK_BEING_ABORTED | rf;
5299 	do {
5300 		old = new = itask->itask_flags;
5301 		if ((old & f) != f) {
5302 			return;
5303 		}
5304 		new &= ~rf;
5305 	} while (atomic_cas_32(&itask->itask_flags, old, new) != old);
5306 }
5307 
5308 void
5309 stmf_task_lu_aborted(scsi_task_t *task, stmf_status_t s, uint32_t iof)
5310 {
5311 	char			 info[STMF_CHANGE_INFO_LEN];
5312 	stmf_i_scsi_task_t	*itask = TASK_TO_ITASK(task);
5313 	unsigned long long	st;
5314 
5315 	stmf_task_audit(itask, TE_TASK_LU_ABORTED, iof, NULL);
5316 
5317 	st = s;	/* gcc fix */
5318 	if ((s != STMF_ABORT_SUCCESS) && (s != STMF_NOT_FOUND)) {
5319 		(void) snprintf(info, sizeof (info),
5320 		    "task %p, lu failed to abort ret=%llx", (void *)task, st);
5321 	} else if ((iof & STMF_IOF_LU_DONE) == 0) {
5322 		(void) snprintf(info, sizeof (info),
5323 		    "Task aborted but LU is not finished, task ="
5324 		    "%p, s=%llx, iof=%x", (void *)task, st, iof);
5325 	} else {
5326 		/*
5327 		 * LU abort successfully
5328 		 */
5329 		atomic_and_32(&itask->itask_flags, ~ITASK_KNOWN_TO_LU);
5330 		return;
5331 	}
5332 
5333 	stmf_abort_task_offline(task, 1, info);
5334 }
5335 
5336 void
5337 stmf_task_lport_aborted(scsi_task_t *task, stmf_status_t s, uint32_t iof)
5338 {
5339 	char			info[STMF_CHANGE_INFO_LEN];
5340 	stmf_i_scsi_task_t	*itask = TASK_TO_ITASK(task);
5341 	unsigned long long	st;
5342 	uint32_t		old, new;
5343 
5344 	stmf_task_audit(itask, TE_TASK_LPORT_ABORTED, iof, NULL);
5345 
5346 	st = s;
5347 	if ((s != STMF_ABORT_SUCCESS) && (s != STMF_NOT_FOUND)) {
5348 		(void) snprintf(info, sizeof (info),
5349 		    "task %p, tgt port failed to abort ret=%llx", (void *)task,
5350 		    st);
5351 	} else if ((iof & STMF_IOF_LPORT_DONE) == 0) {
5352 		(void) snprintf(info, sizeof (info),
5353 		    "Task aborted but tgt port is not finished, "
5354 		    "task=%p, s=%llx, iof=%x", (void *)task, st, iof);
5355 	} else {
5356 		/*
5357 		 * LPORT abort successfully
5358 		 */
5359 		do {
5360 			old = new = itask->itask_flags;
5361 			if (!(old & ITASK_KNOWN_TO_TGT_PORT))
5362 				return;
5363 			new &= ~ITASK_KNOWN_TO_TGT_PORT;
5364 		} while (atomic_cas_32(&itask->itask_flags, old, new) != old);
5365 		return;
5366 	}
5367 
5368 	stmf_abort_task_offline(task, 0, info);
5369 }
5370 
5371 stmf_status_t
5372 stmf_task_poll_lu(scsi_task_t *task, uint32_t timeout)
5373 {
5374 	stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
5375 	    task->task_stmf_private;
5376 	stmf_worker_t *w = itask->itask_worker;
5377 	int i;
5378 
5379 	ASSERT(itask->itask_flags & ITASK_KNOWN_TO_LU);
5380 	mutex_enter(&w->worker_lock);
5381 	if (itask->itask_ncmds >= ITASK_MAX_NCMDS) {
5382 		mutex_exit(&w->worker_lock);
5383 		return (STMF_BUSY);
5384 	}
5385 	for (i = 0; i < itask->itask_ncmds; i++) {
5386 		if (itask->itask_cmd_stack[i] == ITASK_CMD_POLL_LU) {
5387 			mutex_exit(&w->worker_lock);
5388 			return (STMF_SUCCESS);
5389 		}
5390 	}
5391 	itask->itask_cmd_stack[itask->itask_ncmds++] = ITASK_CMD_POLL_LU;
5392 	if (timeout == ITASK_DEFAULT_POLL_TIMEOUT) {
5393 		itask->itask_poll_timeout = ddi_get_lbolt() + 1;
5394 	} else {
5395 		clock_t t = drv_usectohz(timeout * 1000);
5396 		if (t == 0)
5397 			t = 1;
5398 		itask->itask_poll_timeout = ddi_get_lbolt() + t;
5399 	}
5400 	if ((itask->itask_flags & ITASK_IN_WORKER_QUEUE) == 0) {
5401 		itask->itask_worker_next = NULL;
5402 		if (w->worker_task_tail) {
5403 			w->worker_task_tail->itask_worker_next = itask;
5404 		} else {
5405 			w->worker_task_head = itask;
5406 		}
5407 		w->worker_task_tail = itask;
5408 		if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
5409 			w->worker_max_qdepth_pu = w->worker_queue_depth;
5410 		}
5411 		atomic_or_32(&itask->itask_flags, ITASK_IN_WORKER_QUEUE);
5412 		if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0)
5413 			cv_signal(&w->worker_cv);
5414 	}
5415 	mutex_exit(&w->worker_lock);
5416 	return (STMF_SUCCESS);
5417 }
5418 
5419 stmf_status_t
5420 stmf_task_poll_lport(scsi_task_t *task, uint32_t timeout)
5421 {
5422 	stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
5423 	    task->task_stmf_private;
5424 	stmf_worker_t *w = itask->itask_worker;
5425 	int i;
5426 
5427 	ASSERT(itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT);
5428 	mutex_enter(&w->worker_lock);
5429 	if (itask->itask_ncmds >= ITASK_MAX_NCMDS) {
5430 		mutex_exit(&w->worker_lock);
5431 		return (STMF_BUSY);
5432 	}
5433 	for (i = 0; i < itask->itask_ncmds; i++) {
5434 		if (itask->itask_cmd_stack[i] == ITASK_CMD_POLL_LPORT) {
5435 			mutex_exit(&w->worker_lock);
5436 			return (STMF_SUCCESS);
5437 		}
5438 	}
5439 	itask->itask_cmd_stack[itask->itask_ncmds++] = ITASK_CMD_POLL_LPORT;
5440 	if (timeout == ITASK_DEFAULT_POLL_TIMEOUT) {
5441 		itask->itask_poll_timeout = ddi_get_lbolt() + 1;
5442 	} else {
5443 		clock_t t = drv_usectohz(timeout * 1000);
5444 		if (t == 0)
5445 			t = 1;
5446 		itask->itask_poll_timeout = ddi_get_lbolt() + t;
5447 	}
5448 	if ((itask->itask_flags & ITASK_IN_WORKER_QUEUE) == 0) {
5449 		itask->itask_worker_next = NULL;
5450 		if (w->worker_task_tail) {
5451 			w->worker_task_tail->itask_worker_next = itask;
5452 		} else {
5453 			w->worker_task_head = itask;
5454 		}
5455 		w->worker_task_tail = itask;
5456 		if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
5457 			w->worker_max_qdepth_pu = w->worker_queue_depth;
5458 		}
5459 		if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0)
5460 			cv_signal(&w->worker_cv);
5461 	}
5462 	mutex_exit(&w->worker_lock);
5463 	return (STMF_SUCCESS);
5464 }
5465 
5466 void
5467 stmf_do_task_abort(scsi_task_t *task)
5468 {
5469 	stmf_i_scsi_task_t	*itask = TASK_TO_ITASK(task);
5470 	stmf_lu_t		*lu;
5471 	stmf_local_port_t	*lport;
5472 	unsigned long long	 ret;
5473 	uint32_t		 old, new;
5474 	uint8_t			 call_lu_abort, call_port_abort;
5475 	char			 info[STMF_CHANGE_INFO_LEN];
5476 
5477 	lu = task->task_lu;
5478 	lport = task->task_lport;
5479 	do {
5480 		old = new = itask->itask_flags;
5481 		if ((old & (ITASK_KNOWN_TO_LU | ITASK_LU_ABORT_CALLED)) ==
5482 		    ITASK_KNOWN_TO_LU) {
5483 			new |= ITASK_LU_ABORT_CALLED;
5484 			call_lu_abort = 1;
5485 		} else {
5486 			call_lu_abort = 0;
5487 		}
5488 	} while (atomic_cas_32(&itask->itask_flags, old, new) != old);
5489 
5490 	if (call_lu_abort) {
5491 		if ((itask->itask_flags & ITASK_DEFAULT_HANDLING) == 0) {
5492 			ret = lu->lu_abort(lu, STMF_LU_ABORT_TASK, task, 0);
5493 		} else {
5494 			ret = dlun0->lu_abort(lu, STMF_LU_ABORT_TASK, task, 0);
5495 		}
5496 		if ((ret == STMF_ABORT_SUCCESS) || (ret == STMF_NOT_FOUND)) {
5497 			stmf_task_lu_aborted(task, ret, STMF_IOF_LU_DONE);
5498 		} else if (ret == STMF_BUSY) {
5499 			atomic_and_32(&itask->itask_flags,
5500 			    ~ITASK_LU_ABORT_CALLED);
5501 		} else if (ret != STMF_SUCCESS) {
5502 			(void) snprintf(info, sizeof (info),
5503 			    "Abort failed by LU %p, ret %llx", (void *)lu, ret);
5504 			stmf_abort_task_offline(task, 1, info);
5505 		}
5506 	} else if (itask->itask_flags & ITASK_KNOWN_TO_LU) {
5507 		if (ddi_get_lbolt() > (itask->itask_start_time +
5508 		    STMF_SEC2TICK(lu->lu_abort_timeout?
5509 		    lu->lu_abort_timeout : ITASK_DEFAULT_ABORT_TIMEOUT))) {
5510 			(void) snprintf(info, sizeof (info),
5511 			    "lu abort timed out");
5512 			stmf_abort_task_offline(itask->itask_task, 1, info);
5513 		}
5514 	}
5515 
5516 	do {
5517 		old = new = itask->itask_flags;
5518 		if ((old & (ITASK_KNOWN_TO_TGT_PORT |
5519 		    ITASK_TGT_PORT_ABORT_CALLED)) == ITASK_KNOWN_TO_TGT_PORT) {
5520 			new |= ITASK_TGT_PORT_ABORT_CALLED;
5521 			call_port_abort = 1;
5522 		} else {
5523 			call_port_abort = 0;
5524 		}
5525 	} while (atomic_cas_32(&itask->itask_flags, old, new) != old);
5526 	if (call_port_abort) {
5527 		ret = lport->lport_abort(lport, STMF_LPORT_ABORT_TASK, task, 0);
5528 		if ((ret == STMF_ABORT_SUCCESS) || (ret == STMF_NOT_FOUND)) {
5529 			stmf_task_lport_aborted(task, ret, STMF_IOF_LPORT_DONE);
5530 		} else if (ret == STMF_BUSY) {
5531 			atomic_and_32(&itask->itask_flags,
5532 			    ~ITASK_TGT_PORT_ABORT_CALLED);
5533 		} else if (ret != STMF_SUCCESS) {
5534 			(void) snprintf(info, sizeof (info),
5535 			    "Abort failed by tgt port %p ret %llx",
5536 			    (void *)lport, ret);
5537 			stmf_abort_task_offline(task, 0, info);
5538 		}
5539 	} else if (itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT) {
5540 		if (ddi_get_lbolt() > (itask->itask_start_time +
5541 		    STMF_SEC2TICK(lport->lport_abort_timeout?
5542 		    lport->lport_abort_timeout :
5543 		    ITASK_DEFAULT_ABORT_TIMEOUT))) {
5544 			(void) snprintf(info, sizeof (info),
5545 			    "lport abort timed out");
5546 			stmf_abort_task_offline(itask->itask_task, 0, info);
5547 		}
5548 	}
5549 }
5550 
5551 stmf_status_t
5552 stmf_ctl(int cmd, void *obj, void *arg)
5553 {
5554 	stmf_status_t			ret;
5555 	stmf_i_lu_t			*ilu;
5556 	stmf_i_local_port_t		*ilport;
5557 	stmf_state_change_info_t	*ssci = (stmf_state_change_info_t *)arg;
5558 
5559 	mutex_enter(&stmf_state.stmf_lock);
5560 	ret = STMF_INVALID_ARG;
5561 	if (cmd & STMF_CMD_LU_OP) {
5562 		ilu = stmf_lookup_lu((stmf_lu_t *)obj);
5563 		if (ilu == NULL) {
5564 			goto stmf_ctl_lock_exit;
5565 		}
5566 		DTRACE_PROBE3(lu__state__change,
5567 		    stmf_lu_t *, ilu->ilu_lu,
5568 		    int, cmd, stmf_state_change_info_t *, ssci);
5569 	} else if (cmd & STMF_CMD_LPORT_OP) {
5570 		ilport = stmf_lookup_lport((stmf_local_port_t *)obj);
5571 		if (ilport == NULL) {
5572 			goto stmf_ctl_lock_exit;
5573 		}
5574 		DTRACE_PROBE3(lport__state__change,
5575 		    stmf_local_port_t *, ilport->ilport_lport,
5576 		    int, cmd, stmf_state_change_info_t *, ssci);
5577 	} else {
5578 		goto stmf_ctl_lock_exit;
5579 	}
5580 
5581 	switch (cmd) {
5582 	case STMF_CMD_LU_ONLINE:
5583 		switch (ilu->ilu_state) {
5584 			case STMF_STATE_OFFLINE:
5585 				ret = STMF_SUCCESS;
5586 				break;
5587 			case STMF_STATE_ONLINE:
5588 			case STMF_STATE_ONLINING:
5589 				ret = STMF_ALREADY;
5590 				break;
5591 			case STMF_STATE_OFFLINING:
5592 				ret = STMF_BUSY;
5593 				break;
5594 			default:
5595 				ret = STMF_BADSTATE;
5596 				break;
5597 		}
5598 		if (ret != STMF_SUCCESS)
5599 			goto stmf_ctl_lock_exit;
5600 
5601 		ilu->ilu_state = STMF_STATE_ONLINING;
5602 		mutex_exit(&stmf_state.stmf_lock);
5603 		stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
5604 		break;
5605 
5606 	case STMF_CMD_LU_ONLINE_COMPLETE:
5607 		if (ilu->ilu_state != STMF_STATE_ONLINING) {
5608 			ret = STMF_BADSTATE;
5609 			goto stmf_ctl_lock_exit;
5610 		}
5611 		if (((stmf_change_status_t *)arg)->st_completion_status ==
5612 		    STMF_SUCCESS) {
5613 			ilu->ilu_state = STMF_STATE_ONLINE;
5614 			mutex_exit(&stmf_state.stmf_lock);
5615 			((stmf_lu_t *)obj)->lu_ctl((stmf_lu_t *)obj,
5616 			    STMF_ACK_LU_ONLINE_COMPLETE, arg);
5617 			mutex_enter(&stmf_state.stmf_lock);
5618 			stmf_add_lu_to_active_sessions((stmf_lu_t *)obj);
5619 		} else {
5620 			/* XXX: should throw a meesage an record more data */
5621 			ilu->ilu_state = STMF_STATE_OFFLINE;
5622 		}
5623 		ret = STMF_SUCCESS;
5624 		goto stmf_ctl_lock_exit;
5625 
5626 	case STMF_CMD_LU_OFFLINE:
5627 		switch (ilu->ilu_state) {
5628 			case STMF_STATE_ONLINE:
5629 				ret = STMF_SUCCESS;
5630 				break;
5631 			case STMF_STATE_OFFLINE:
5632 			case STMF_STATE_OFFLINING:
5633 				ret = STMF_ALREADY;
5634 				break;
5635 			case STMF_STATE_ONLINING:
5636 				ret = STMF_BUSY;
5637 				break;
5638 			default:
5639 				ret = STMF_BADSTATE;
5640 				break;
5641 		}
5642 		if (ret != STMF_SUCCESS)
5643 			goto stmf_ctl_lock_exit;
5644 		ilu->ilu_state = STMF_STATE_OFFLINING;
5645 		mutex_exit(&stmf_state.stmf_lock);
5646 		stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
5647 		break;
5648 
5649 	case STMF_CMD_LU_OFFLINE_COMPLETE:
5650 		if (ilu->ilu_state != STMF_STATE_OFFLINING) {
5651 			ret = STMF_BADSTATE;
5652 			goto stmf_ctl_lock_exit;
5653 		}
5654 		if (((stmf_change_status_t *)arg)->st_completion_status ==
5655 		    STMF_SUCCESS) {
5656 			ilu->ilu_state = STMF_STATE_OFFLINE;
5657 			mutex_exit(&stmf_state.stmf_lock);
5658 			((stmf_lu_t *)obj)->lu_ctl((stmf_lu_t *)obj,
5659 			    STMF_ACK_LU_OFFLINE_COMPLETE, arg);
5660 			mutex_enter(&stmf_state.stmf_lock);
5661 		} else {
5662 			ilu->ilu_state = STMF_STATE_ONLINE;
5663 			stmf_add_lu_to_active_sessions((stmf_lu_t *)obj);
5664 		}
5665 		mutex_exit(&stmf_state.stmf_lock);
5666 		break;
5667 
5668 	/*
5669 	 * LPORT_ONLINE/OFFLINE has nothing to do with link offline/online.
5670 	 * It's related with hardware disable/enable.
5671 	 */
5672 	case STMF_CMD_LPORT_ONLINE:
5673 		switch (ilport->ilport_state) {
5674 			case STMF_STATE_OFFLINE:
5675 				ret = STMF_SUCCESS;
5676 				break;
5677 			case STMF_STATE_ONLINE:
5678 			case STMF_STATE_ONLINING:
5679 				ret = STMF_ALREADY;
5680 				break;
5681 			case STMF_STATE_OFFLINING:
5682 				ret = STMF_BUSY;
5683 				break;
5684 			default:
5685 				ret = STMF_BADSTATE;
5686 				break;
5687 		}
5688 		if (ret != STMF_SUCCESS)
5689 			goto stmf_ctl_lock_exit;
5690 
5691 		/*
5692 		 * Only user request can recover the port from the
5693 		 * FORCED_OFFLINE state
5694 		 */
5695 		if (ilport->ilport_flags & ILPORT_FORCED_OFFLINE) {
5696 			if (!(ssci->st_rflags & STMF_RFLAG_USER_REQUEST)) {
5697 				ret = STMF_FAILURE;
5698 				goto stmf_ctl_lock_exit;
5699 			}
5700 		}
5701 
5702 		/*
5703 		 * Avoid too frequent request to online
5704 		 */
5705 		if (ssci->st_rflags & STMF_RFLAG_USER_REQUEST) {
5706 			ilport->ilport_online_times = 0;
5707 			ilport->ilport_avg_interval = 0;
5708 		}
5709 		if ((ilport->ilport_avg_interval < STMF_AVG_ONLINE_INTERVAL) &&
5710 		    (ilport->ilport_online_times >= 4)) {
5711 			ret = STMF_FAILURE;
5712 			ilport->ilport_flags |= ILPORT_FORCED_OFFLINE;
5713 			stmf_trace(NULL, "stmf_ctl: too frequent request to "
5714 			    "online the port");
5715 			cmn_err(CE_WARN, "stmf_ctl: too frequent request to "
5716 			    "online the port, set FORCED_OFFLINE now");
5717 			goto stmf_ctl_lock_exit;
5718 		}
5719 		if (ilport->ilport_online_times > 0) {
5720 			if (ilport->ilport_online_times == 1) {
5721 				ilport->ilport_avg_interval = ddi_get_lbolt() -
5722 				    ilport->ilport_last_online_clock;
5723 			} else {
5724 				ilport->ilport_avg_interval =
5725 				    (ilport->ilport_avg_interval +
5726 				    ddi_get_lbolt() -
5727 				    ilport->ilport_last_online_clock) >> 1;
5728 			}
5729 		}
5730 		ilport->ilport_last_online_clock = ddi_get_lbolt();
5731 		ilport->ilport_online_times++;
5732 
5733 		/*
5734 		 * Submit online service request
5735 		 */
5736 		ilport->ilport_flags &= ~ILPORT_FORCED_OFFLINE;
5737 		ilport->ilport_state = STMF_STATE_ONLINING;
5738 		mutex_exit(&stmf_state.stmf_lock);
5739 		stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
5740 		break;
5741 
5742 	case STMF_CMD_LPORT_ONLINE_COMPLETE:
5743 		if (ilport->ilport_state != STMF_STATE_ONLINING) {
5744 			ret = STMF_BADSTATE;
5745 			goto stmf_ctl_lock_exit;
5746 		}
5747 		if (((stmf_change_status_t *)arg)->st_completion_status ==
5748 		    STMF_SUCCESS) {
5749 			ilport->ilport_state = STMF_STATE_ONLINE;
5750 			mutex_exit(&stmf_state.stmf_lock);
5751 			((stmf_local_port_t *)obj)->lport_ctl(
5752 			    (stmf_local_port_t *)obj,
5753 			    STMF_ACK_LPORT_ONLINE_COMPLETE, arg);
5754 			mutex_enter(&stmf_state.stmf_lock);
5755 		} else {
5756 			ilport->ilport_state = STMF_STATE_OFFLINE;
5757 		}
5758 		ret = STMF_SUCCESS;
5759 		goto stmf_ctl_lock_exit;
5760 
5761 	case STMF_CMD_LPORT_OFFLINE:
5762 		switch (ilport->ilport_state) {
5763 			case STMF_STATE_ONLINE:
5764 				ret = STMF_SUCCESS;
5765 				break;
5766 			case STMF_STATE_OFFLINE:
5767 			case STMF_STATE_OFFLINING:
5768 				ret = STMF_ALREADY;
5769 				break;
5770 			case STMF_STATE_ONLINING:
5771 				ret = STMF_BUSY;
5772 				break;
5773 			default:
5774 				ret = STMF_BADSTATE;
5775 				break;
5776 		}
5777 		if (ret != STMF_SUCCESS)
5778 			goto stmf_ctl_lock_exit;
5779 
5780 		ilport->ilport_state = STMF_STATE_OFFLINING;
5781 		mutex_exit(&stmf_state.stmf_lock);
5782 		stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
5783 		break;
5784 
5785 	case STMF_CMD_LPORT_OFFLINE_COMPLETE:
5786 		if (ilport->ilport_state != STMF_STATE_OFFLINING) {
5787 			ret = STMF_BADSTATE;
5788 			goto stmf_ctl_lock_exit;
5789 		}
5790 		if (((stmf_change_status_t *)arg)->st_completion_status ==
5791 		    STMF_SUCCESS) {
5792 			ilport->ilport_state = STMF_STATE_OFFLINE;
5793 			mutex_exit(&stmf_state.stmf_lock);
5794 			((stmf_local_port_t *)obj)->lport_ctl(
5795 			    (stmf_local_port_t *)obj,
5796 			    STMF_ACK_LPORT_OFFLINE_COMPLETE, arg);
5797 			mutex_enter(&stmf_state.stmf_lock);
5798 		} else {
5799 			ilport->ilport_state = STMF_STATE_ONLINE;
5800 		}
5801 		mutex_exit(&stmf_state.stmf_lock);
5802 		break;
5803 
5804 	default:
5805 		cmn_err(CE_WARN, "Invalid ctl cmd received %x", cmd);
5806 		ret = STMF_INVALID_ARG;
5807 		goto stmf_ctl_lock_exit;
5808 	}
5809 
5810 	return (STMF_SUCCESS);
5811 
5812 stmf_ctl_lock_exit:;
5813 	mutex_exit(&stmf_state.stmf_lock);
5814 	return (ret);
5815 }
5816 
5817 /* ARGSUSED */
5818 stmf_status_t
5819 stmf_info_impl(uint32_t cmd, void *arg1, void *arg2, uint8_t *buf,
5820 						uint32_t *bufsizep)
5821 {
5822 	return (STMF_NOT_SUPPORTED);
5823 }
5824 
5825 /* ARGSUSED */
5826 stmf_status_t
5827 stmf_info(uint32_t cmd, void *arg1, void *arg2, uint8_t *buf,
5828 						uint32_t *bufsizep)
5829 {
5830 	uint32_t cl = SI_GET_CLASS(cmd);
5831 
5832 	if (cl == SI_STMF) {
5833 		return (stmf_info_impl(cmd, arg1, arg2, buf, bufsizep));
5834 	}
5835 	if (cl == SI_LPORT) {
5836 		return (((stmf_local_port_t *)arg1)->lport_info(cmd, arg1,
5837 		    arg2, buf, bufsizep));
5838 	} else if (cl == SI_LU) {
5839 		return (((stmf_lu_t *)arg1)->lu_info(cmd, arg1, arg2, buf,
5840 		    bufsizep));
5841 	}
5842 
5843 	return (STMF_NOT_SUPPORTED);
5844 }
5845 
5846 /*
5847  * Used by port providers. pwwn is 8 byte wwn, sdid is the devid used by
5848  * stmf to register local ports. The ident should have 20 bytes in buffer
5849  * space to convert the wwn to "wwn.xxxxxxxxxxxxxxxx" string.
5850  */
5851 void
5852 stmf_wwn_to_devid_desc(scsi_devid_desc_t *sdid, uint8_t *wwn,
5853     uint8_t protocol_id)
5854 {
5855 	char wwn_str[20+1];
5856 
5857 	sdid->protocol_id = protocol_id;
5858 	sdid->piv = 1;
5859 	sdid->code_set = CODE_SET_ASCII;
5860 	sdid->association = ID_IS_TARGET_PORT;
5861 	sdid->ident_length = 20;
5862 	/* Convert wwn value to "wwn.XXXXXXXXXXXXXXXX" format */
5863 	(void) snprintf(wwn_str, sizeof (wwn_str),
5864 	    "wwn.%02X%02X%02X%02X%02X%02X%02X%02X",
5865 	    wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
5866 	bcopy(wwn_str, (char *)sdid->ident, 20);
5867 }
5868 
5869 
5870 stmf_xfer_data_t *
5871 stmf_prepare_tpgs_data(uint8_t ilu_alua)
5872 {
5873 	stmf_xfer_data_t *xd;
5874 	stmf_i_local_port_t *ilport;
5875 	uint8_t *p;
5876 	uint32_t sz, asz, nports = 0, nports_standby = 0;
5877 
5878 	mutex_enter(&stmf_state.stmf_lock);
5879 	/* check if any ports are standby and create second group */
5880 	for (ilport = stmf_state.stmf_ilportlist; ilport;
5881 	    ilport = ilport->ilport_next) {
5882 		if (ilport->ilport_standby == 1) {
5883 			nports_standby++;
5884 		} else {
5885 			nports++;
5886 		}
5887 	}
5888 
5889 	/* The spec only allows for 255 ports to be reported per group */
5890 	nports = min(nports, 255);
5891 	nports_standby = min(nports_standby, 255);
5892 	sz = (nports * 4) + 12;
5893 	if (nports_standby && ilu_alua) {
5894 		sz += (nports_standby * 4) + 8;
5895 	}
5896 	asz = sz + sizeof (*xd) - 4;
5897 	xd = (stmf_xfer_data_t *)kmem_zalloc(asz, KM_NOSLEEP);
5898 	if (xd == NULL) {
5899 		mutex_exit(&stmf_state.stmf_lock);
5900 		return (NULL);
5901 	}
5902 	xd->alloc_size = asz;
5903 	xd->size_left = sz;
5904 
5905 	p = xd->buf;
5906 
5907 	*((uint32_t *)p) = BE_32(sz - 4);
5908 	p += 4;
5909 	p[0] = 0x80;	/* PREF */
5910 	p[1] = 5;	/* AO_SUP, S_SUP */
5911 	if (stmf_state.stmf_alua_node == 1) {
5912 		p[3] = 1;	/* Group 1 */
5913 	} else {
5914 		p[3] = 0;	/* Group 0 */
5915 	}
5916 	p[7] = nports & 0xff;
5917 	p += 8;
5918 	for (ilport = stmf_state.stmf_ilportlist; ilport;
5919 	    ilport = ilport->ilport_next) {
5920 		if (ilport->ilport_standby == 1) {
5921 			continue;
5922 		}
5923 		((uint16_t *)p)[1] = BE_16(ilport->ilport_rtpid);
5924 		p += 4;
5925 	}
5926 	if (nports_standby && ilu_alua) {
5927 		p[0] = 0x02;	/* Non PREF, Standby */
5928 		p[1] = 5;	/* AO_SUP, S_SUP */
5929 		if (stmf_state.stmf_alua_node == 1) {
5930 			p[3] = 0;	/* Group 0 */
5931 		} else {
5932 			p[3] = 1;	/* Group 1 */
5933 		}
5934 		p[7] = nports_standby & 0xff;
5935 		p += 8;
5936 		for (ilport = stmf_state.stmf_ilportlist; ilport;
5937 		    ilport = ilport->ilport_next) {
5938 			if (ilport->ilport_standby == 0) {
5939 				continue;
5940 			}
5941 			((uint16_t *)p)[1] = BE_16(ilport->ilport_rtpid);
5942 			p += 4;
5943 		}
5944 	}
5945 
5946 	mutex_exit(&stmf_state.stmf_lock);
5947 
5948 	return (xd);
5949 }
5950 
5951 struct scsi_devid_desc *
5952 stmf_scsilib_get_devid_desc(uint16_t rtpid)
5953 {
5954 	scsi_devid_desc_t *devid = NULL;
5955 	stmf_i_local_port_t *ilport;
5956 
5957 	mutex_enter(&stmf_state.stmf_lock);
5958 
5959 	for (ilport = stmf_state.stmf_ilportlist; ilport;
5960 	    ilport = ilport->ilport_next) {
5961 		if (ilport->ilport_rtpid == rtpid) {
5962 			scsi_devid_desc_t *id = ilport->ilport_lport->lport_id;
5963 			uint32_t id_sz = sizeof (scsi_devid_desc_t) - 1 +
5964 			    id->ident_length;
5965 			devid = (scsi_devid_desc_t *)kmem_zalloc(id_sz,
5966 			    KM_NOSLEEP);
5967 			if (devid != NULL) {
5968 				bcopy(id, devid, id_sz);
5969 			}
5970 			break;
5971 		}
5972 	}
5973 
5974 	mutex_exit(&stmf_state.stmf_lock);
5975 	return (devid);
5976 }
5977 
5978 uint16_t
5979 stmf_scsilib_get_lport_rtid(struct scsi_devid_desc *devid)
5980 {
5981 	stmf_i_local_port_t	*ilport;
5982 	scsi_devid_desc_t	*id;
5983 	uint16_t		rtpid = 0;
5984 
5985 	mutex_enter(&stmf_state.stmf_lock);
5986 	for (ilport = stmf_state.stmf_ilportlist; ilport;
5987 	    ilport = ilport->ilport_next) {
5988 		id = ilport->ilport_lport->lport_id;
5989 		if ((devid->ident_length == id->ident_length) &&
5990 		    (memcmp(devid->ident, id->ident, id->ident_length) == 0)) {
5991 			rtpid = ilport->ilport_rtpid;
5992 			break;
5993 		}
5994 	}
5995 	mutex_exit(&stmf_state.stmf_lock);
5996 	return (rtpid);
5997 }
5998 
5999 static uint16_t stmf_lu_id_gen_number = 0;
6000 
6001 stmf_status_t
6002 stmf_scsilib_uniq_lu_id(uint32_t company_id, scsi_devid_desc_t *lu_id)
6003 {
6004 	return (stmf_scsilib_uniq_lu_id2(company_id, 0, lu_id));
6005 }
6006 
6007 stmf_status_t
6008 stmf_scsilib_uniq_lu_id2(uint32_t company_id, uint32_t host_id,
6009     scsi_devid_desc_t *lu_id)
6010 {
6011 	uint8_t *p;
6012 	struct timeval32 timestamp32;
6013 	uint32_t *t = (uint32_t *)&timestamp32;
6014 	struct ether_addr mac;
6015 	uint8_t *e = (uint8_t *)&mac;
6016 	int hid = (int)host_id;
6017 
6018 	if (company_id == COMPANY_ID_NONE)
6019 		company_id = COMPANY_ID_SUN;
6020 
6021 	if (lu_id->ident_length != 0x10)
6022 		return (STMF_INVALID_ARG);
6023 
6024 	p = (uint8_t *)lu_id;
6025 
6026 	atomic_add_16(&stmf_lu_id_gen_number, 1);
6027 
6028 	p[0] = 0xf1; p[1] = 3; p[2] = 0; p[3] = 0x10;
6029 	p[4] = ((company_id >> 20) & 0xf) | 0x60;
6030 	p[5] = (company_id >> 12) & 0xff;
6031 	p[6] = (company_id >> 4) & 0xff;
6032 	p[7] = (company_id << 4) & 0xf0;
6033 	if (hid == 0 && !localetheraddr((struct ether_addr *)NULL, &mac)) {
6034 		hid = BE_32((int)zone_get_hostid(NULL));
6035 	}
6036 	if (hid != 0) {
6037 		e[0] = (hid >> 24) & 0xff;
6038 		e[1] = (hid >> 16) & 0xff;
6039 		e[2] = (hid >> 8) & 0xff;
6040 		e[3] = hid & 0xff;
6041 		e[4] = e[5] = 0;
6042 	}
6043 	bcopy(e, p+8, 6);
6044 	uniqtime32(&timestamp32);
6045 	*t = BE_32(*t);
6046 	bcopy(t, p+14, 4);
6047 	p[18] = (stmf_lu_id_gen_number >> 8) & 0xff;
6048 	p[19] = stmf_lu_id_gen_number & 0xff;
6049 
6050 	return (STMF_SUCCESS);
6051 }
6052 
6053 /*
6054  * saa is sense key, ASC, ASCQ
6055  */
6056 void
6057 stmf_scsilib_send_status(scsi_task_t *task, uint8_t st, uint32_t saa)
6058 {
6059 	uint8_t sd[18];
6060 	task->task_scsi_status = st;
6061 	if (st == 2) {
6062 		bzero(sd, 18);
6063 		sd[0] = 0x70;
6064 		sd[2] = (saa >> 16) & 0xf;
6065 		sd[7] = 10;
6066 		sd[12] = (saa >> 8) & 0xff;
6067 		sd[13] = saa & 0xff;
6068 		task->task_sense_data = sd;
6069 		task->task_sense_length = 18;
6070 	} else {
6071 		task->task_sense_data = NULL;
6072 		task->task_sense_length = 0;
6073 	}
6074 	(void) stmf_send_scsi_status(task, STMF_IOF_LU_DONE);
6075 }
6076 
6077 uint32_t
6078 stmf_scsilib_prepare_vpd_page83(scsi_task_t *task, uint8_t *page,
6079     uint32_t page_len, uint8_t byte0, uint32_t vpd_mask)
6080 {
6081 	uint8_t		*p = NULL;
6082 	uint8_t		small_buf[32];
6083 	uint32_t	sz = 0;
6084 	uint32_t	n = 4;
6085 	uint32_t	m = 0;
6086 	uint32_t	last_bit = 0;
6087 
6088 	if (page_len < 4)
6089 		return (0);
6090 	if (page_len > 65535)
6091 		page_len = 65535;
6092 
6093 	page[0] = byte0;
6094 	page[1] = 0x83;
6095 
6096 	/* CONSTCOND */
6097 	while (1) {
6098 		m += sz;
6099 		if (sz && (page_len > n)) {
6100 			uint32_t copysz;
6101 			copysz = page_len > (n + sz) ? sz : page_len - n;
6102 			bcopy(p, page + n, copysz);
6103 			n += copysz;
6104 		}
6105 		vpd_mask &= ~last_bit;
6106 		if (vpd_mask == 0)
6107 			break;
6108 
6109 		if (vpd_mask & STMF_VPD_LU_ID) {
6110 			last_bit = STMF_VPD_LU_ID;
6111 			sz = task->task_lu->lu_id->ident_length + 4;
6112 			p = (uint8_t *)task->task_lu->lu_id;
6113 			continue;
6114 		} else if (vpd_mask & STMF_VPD_TARGET_ID) {
6115 			last_bit = STMF_VPD_TARGET_ID;
6116 			sz = task->task_lport->lport_id->ident_length + 4;
6117 			p = (uint8_t *)task->task_lport->lport_id;
6118 			continue;
6119 		} else if (vpd_mask & STMF_VPD_TP_GROUP) {
6120 			stmf_i_local_port_t *ilport;
6121 			last_bit = STMF_VPD_TP_GROUP;
6122 			p = small_buf;
6123 			bzero(p, 8);
6124 			p[0] = 1;
6125 			p[1] = 0x15;
6126 			p[3] = 4;
6127 			ilport = (stmf_i_local_port_t *)
6128 			    task->task_lport->lport_stmf_private;
6129 			/*
6130 			 * If we're in alua mode, group 1 contains all alua
6131 			 * participating ports and all standby ports
6132 			 * > 255. Otherwise, if we're in alua mode, any local
6133 			 * ports (non standby/pppt) are also in group 1 if the
6134 			 * alua node is 1. Otherwise the group is 0.
6135 			 */
6136 			if ((stmf_state.stmf_alua_state &&
6137 			    (ilport->ilport_alua || ilport->ilport_standby) &&
6138 			    ilport->ilport_rtpid > 255) ||
6139 			    (stmf_state.stmf_alua_node == 1 &&
6140 			    ilport->ilport_standby != 1)) {
6141 				p[7] = 1;	/* Group 1 */
6142 			}
6143 			sz = 8;
6144 			continue;
6145 		} else if (vpd_mask & STMF_VPD_RELATIVE_TP_ID) {
6146 			stmf_i_local_port_t *ilport;
6147 
6148 			last_bit = STMF_VPD_RELATIVE_TP_ID;
6149 			p = small_buf;
6150 			bzero(p, 8);
6151 			p[0] = 1;
6152 			p[1] = 0x14;
6153 			p[3] = 4;
6154 			ilport = (stmf_i_local_port_t *)
6155 			    task->task_lport->lport_stmf_private;
6156 			p[6] = (ilport->ilport_rtpid >> 8) & 0xff;
6157 			p[7] = ilport->ilport_rtpid & 0xff;
6158 			sz = 8;
6159 			continue;
6160 		} else {
6161 			cmn_err(CE_WARN, "Invalid vpd_mask");
6162 			break;
6163 		}
6164 	}
6165 
6166 	page[2] = (m >> 8) & 0xff;
6167 	page[3] = m & 0xff;
6168 
6169 	return (n);
6170 }
6171 
6172 void
6173 stmf_scsilib_handle_report_tpgs(scsi_task_t *task, stmf_data_buf_t *dbuf)
6174 {
6175 	stmf_i_scsi_task_t *itask =
6176 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
6177 	stmf_i_lu_t *ilu =
6178 	    (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
6179 	stmf_xfer_data_t *xd;
6180 	uint32_t sz, minsz;
6181 
6182 	itask->itask_flags |= ITASK_DEFAULT_HANDLING;
6183 	task->task_cmd_xfer_length =
6184 	    ((((uint32_t)task->task_cdb[6]) << 24) |
6185 	    (((uint32_t)task->task_cdb[7]) << 16) |
6186 	    (((uint32_t)task->task_cdb[8]) << 8) |
6187 	    ((uint32_t)task->task_cdb[9]));
6188 
6189 	if (task->task_additional_flags &
6190 	    TASK_AF_NO_EXPECTED_XFER_LENGTH) {
6191 		task->task_expected_xfer_length =
6192 		    task->task_cmd_xfer_length;
6193 	}
6194 
6195 	if (task->task_cmd_xfer_length == 0) {
6196 		stmf_scsilib_send_status(task, STATUS_GOOD, 0);
6197 		return;
6198 	}
6199 	if (task->task_cmd_xfer_length < 4) {
6200 		stmf_scsilib_send_status(task, STATUS_CHECK,
6201 		    STMF_SAA_INVALID_FIELD_IN_CDB);
6202 		return;
6203 	}
6204 
6205 	sz = min(task->task_expected_xfer_length,
6206 	    task->task_cmd_xfer_length);
6207 
6208 	xd = stmf_prepare_tpgs_data(ilu->ilu_alua);
6209 
6210 	if (xd == NULL) {
6211 		stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6212 		    STMF_ALLOC_FAILURE, NULL);
6213 		return;
6214 	}
6215 
6216 	sz = min(sz, xd->size_left);
6217 	xd->size_left = sz;
6218 	minsz = min(512, sz);
6219 
6220 	if (dbuf == NULL)
6221 		dbuf = stmf_alloc_dbuf(task, sz, &minsz, 0);
6222 	if (dbuf == NULL) {
6223 		kmem_free(xd, xd->alloc_size);
6224 		stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6225 		    STMF_ALLOC_FAILURE, NULL);
6226 		return;
6227 	}
6228 	dbuf->db_lu_private = xd;
6229 	stmf_xd_to_dbuf(dbuf, 1);
6230 
6231 	dbuf->db_flags = DB_DIRECTION_TO_RPORT;
6232 	(void) stmf_xfer_data(task, dbuf, 0);
6233 
6234 }
6235 
6236 void
6237 stmf_scsilib_handle_task_mgmt(scsi_task_t *task)
6238 {
6239 
6240 	switch (task->task_mgmt_function) {
6241 	/*
6242 	 * For now we will abort all I/Os on the LU in case of ABORT_TASK_SET
6243 	 * and ABORT_TASK. But unlike LUN_RESET we will not reset LU state
6244 	 * in these cases. This needs to be changed to abort only the required
6245 	 * set.
6246 	 */
6247 	case TM_ABORT_TASK:
6248 	case TM_ABORT_TASK_SET:
6249 	case TM_CLEAR_TASK_SET:
6250 	case TM_LUN_RESET:
6251 		stmf_handle_lun_reset(task);
6252 		/* issue the reset to the proxy node as well */
6253 		if (stmf_state.stmf_alua_state == 1) {
6254 			(void) stmf_proxy_scsi_cmd(task, NULL);
6255 		}
6256 		return;
6257 	case TM_TARGET_RESET:
6258 	case TM_TARGET_COLD_RESET:
6259 	case TM_TARGET_WARM_RESET:
6260 		stmf_handle_target_reset(task);
6261 		return;
6262 	default:
6263 		/* We dont support this task mgmt function */
6264 		stmf_scsilib_send_status(task, STATUS_CHECK,
6265 		    STMF_SAA_INVALID_FIELD_IN_CMD_IU);
6266 		return;
6267 	}
6268 }
6269 
6270 void
6271 stmf_handle_lun_reset(scsi_task_t *task)
6272 {
6273 	stmf_i_scsi_task_t *itask;
6274 	stmf_i_lu_t *ilu;
6275 
6276 	itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
6277 	ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
6278 
6279 	/*
6280 	 * To sync with target reset, grab this lock. The LU is not going
6281 	 * anywhere as there is atleast one task pending (this task).
6282 	 */
6283 	mutex_enter(&stmf_state.stmf_lock);
6284 
6285 	if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
6286 		mutex_exit(&stmf_state.stmf_lock);
6287 		stmf_scsilib_send_status(task, STATUS_CHECK,
6288 		    STMF_SAA_OPERATION_IN_PROGRESS);
6289 		return;
6290 	}
6291 	atomic_or_32(&ilu->ilu_flags, ILU_RESET_ACTIVE);
6292 	mutex_exit(&stmf_state.stmf_lock);
6293 
6294 	/*
6295 	 * Mark this task as the one causing LU reset so that we know who
6296 	 * was responsible for setting the ILU_RESET_ACTIVE. In case this
6297 	 * task itself gets aborted, we will clear ILU_RESET_ACTIVE.
6298 	 */
6299 	itask->itask_flags |= ITASK_DEFAULT_HANDLING | ITASK_CAUSING_LU_RESET;
6300 
6301 	/* Initiatiate abort on all commands on this LU except this one */
6302 	stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED, task->task_lu);
6303 
6304 	/* Start polling on this task */
6305 	if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
6306 	    != STMF_SUCCESS) {
6307 		stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ALLOC_FAILURE,
6308 		    NULL);
6309 		return;
6310 	}
6311 }
6312 
6313 void
6314 stmf_handle_target_reset(scsi_task_t *task)
6315 {
6316 	stmf_i_scsi_task_t *itask;
6317 	stmf_i_lu_t *ilu;
6318 	stmf_i_scsi_session_t *iss;
6319 	stmf_lun_map_t *lm;
6320 	stmf_lun_map_ent_t *lm_ent;
6321 	int i, lf;
6322 
6323 	itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
6324 	iss = (stmf_i_scsi_session_t *)task->task_session->ss_stmf_private;
6325 	ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
6326 
6327 	/*
6328 	 * To sync with LUN reset, grab this lock. The session is not going
6329 	 * anywhere as there is atleast one task pending (this task).
6330 	 */
6331 	mutex_enter(&stmf_state.stmf_lock);
6332 
6333 	/* Grab the session lock as a writer to prevent any changes in it */
6334 	rw_enter(iss->iss_lockp, RW_WRITER);
6335 
6336 	if (iss->iss_flags & ISS_RESET_ACTIVE) {
6337 		rw_exit(iss->iss_lockp);
6338 		mutex_exit(&stmf_state.stmf_lock);
6339 		stmf_scsilib_send_status(task, STATUS_CHECK,
6340 		    STMF_SAA_OPERATION_IN_PROGRESS);
6341 		return;
6342 	}
6343 	atomic_or_32(&iss->iss_flags, ISS_RESET_ACTIVE);
6344 
6345 	/*
6346 	 * Now go through each LUN in this session and make sure all of them
6347 	 * can be reset.
6348 	 */
6349 	lm = iss->iss_sm;
6350 	for (i = 0, lf = 0; i < lm->lm_nentries; i++) {
6351 		if (lm->lm_plus[i] == NULL)
6352 			continue;
6353 		lf++;
6354 		lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
6355 		ilu = (stmf_i_lu_t *)(lm_ent->ent_lu->lu_stmf_private);
6356 		if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
6357 			atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
6358 			rw_exit(iss->iss_lockp);
6359 			mutex_exit(&stmf_state.stmf_lock);
6360 			stmf_scsilib_send_status(task, STATUS_CHECK,
6361 			    STMF_SAA_OPERATION_IN_PROGRESS);
6362 			return;
6363 		}
6364 	}
6365 	if (lf == 0) {
6366 		/* No luns in this session */
6367 		atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
6368 		rw_exit(iss->iss_lockp);
6369 		mutex_exit(&stmf_state.stmf_lock);
6370 		stmf_scsilib_send_status(task, STATUS_GOOD, 0);
6371 		return;
6372 	}
6373 
6374 	/* ok, start the damage */
6375 	itask->itask_flags |= ITASK_DEFAULT_HANDLING |
6376 	    ITASK_CAUSING_TARGET_RESET;
6377 	for (i = 0; i < lm->lm_nentries; i++) {
6378 		if (lm->lm_plus[i] == NULL)
6379 			continue;
6380 		lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
6381 		ilu = (stmf_i_lu_t *)(lm_ent->ent_lu->lu_stmf_private);
6382 		atomic_or_32(&ilu->ilu_flags, ILU_RESET_ACTIVE);
6383 	}
6384 
6385 	for (i = 0; i < lm->lm_nentries; i++) {
6386 		if (lm->lm_plus[i] == NULL)
6387 			continue;
6388 		lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
6389 		stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED,
6390 		    lm_ent->ent_lu);
6391 	}
6392 
6393 	rw_exit(iss->iss_lockp);
6394 	mutex_exit(&stmf_state.stmf_lock);
6395 
6396 	/* Start polling on this task */
6397 	if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
6398 	    != STMF_SUCCESS) {
6399 		stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ALLOC_FAILURE,
6400 		    NULL);
6401 		return;
6402 	}
6403 }
6404 
6405 int
6406 stmf_handle_cmd_during_ic(stmf_i_scsi_task_t *itask)
6407 {
6408 	scsi_task_t *task = itask->itask_task;
6409 	stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
6410 	    task->task_session->ss_stmf_private;
6411 
6412 	rw_enter(iss->iss_lockp, RW_WRITER);
6413 	if (((iss->iss_flags & ISS_LUN_INVENTORY_CHANGED) == 0) ||
6414 	    (task->task_cdb[0] == SCMD_INQUIRY)) {
6415 		rw_exit(iss->iss_lockp);
6416 		return (0);
6417 	}
6418 	atomic_and_32(&iss->iss_flags,
6419 	    ~(ISS_LUN_INVENTORY_CHANGED | ISS_GOT_INITIAL_LUNS));
6420 	rw_exit(iss->iss_lockp);
6421 
6422 	if (task->task_cdb[0] == SCMD_REPORT_LUNS) {
6423 		return (0);
6424 	}
6425 	stmf_scsilib_send_status(task, STATUS_CHECK,
6426 	    STMF_SAA_REPORT_LUN_DATA_HAS_CHANGED);
6427 	return (1);
6428 }
6429 
6430 void
6431 stmf_worker_init()
6432 {
6433 	uint32_t i;
6434 
6435 	/* Make local copy of global tunables */
6436 	stmf_i_max_nworkers = stmf_max_nworkers;
6437 	stmf_i_min_nworkers = stmf_min_nworkers;
6438 
6439 	ASSERT(stmf_workers == NULL);
6440 	if (stmf_i_min_nworkers < 4) {
6441 		stmf_i_min_nworkers = 4;
6442 	}
6443 	if (stmf_i_max_nworkers < stmf_i_min_nworkers) {
6444 		stmf_i_max_nworkers = stmf_i_min_nworkers;
6445 	}
6446 	stmf_workers = (stmf_worker_t *)kmem_zalloc(
6447 	    sizeof (stmf_worker_t) * stmf_i_max_nworkers, KM_SLEEP);
6448 	for (i = 0; i < stmf_i_max_nworkers; i++) {
6449 		stmf_worker_t *w = &stmf_workers[i];
6450 		mutex_init(&w->worker_lock, NULL, MUTEX_DRIVER, NULL);
6451 		cv_init(&w->worker_cv, NULL, CV_DRIVER, NULL);
6452 	}
6453 	stmf_worker_mgmt_delay = drv_usectohz(20 * 1000);
6454 	stmf_workers_state = STMF_WORKERS_ENABLED;
6455 
6456 	/* Workers will be started by stmf_worker_mgmt() */
6457 
6458 	/* Lets wait for atleast one worker to start */
6459 	while (stmf_nworkers_cur == 0)
6460 		delay(drv_usectohz(20 * 1000));
6461 	stmf_worker_mgmt_delay = drv_usectohz(3 * 1000 * 1000);
6462 }
6463 
6464 stmf_status_t
6465 stmf_worker_fini()
6466 {
6467 	int i;
6468 	clock_t sb;
6469 
6470 	if (stmf_workers_state == STMF_WORKERS_DISABLED)
6471 		return (STMF_SUCCESS);
6472 	ASSERT(stmf_workers);
6473 	stmf_workers_state = STMF_WORKERS_DISABLED;
6474 	stmf_worker_mgmt_delay = drv_usectohz(20 * 1000);
6475 	cv_signal(&stmf_state.stmf_cv);
6476 
6477 	sb = ddi_get_lbolt() + drv_usectohz(10 * 1000 * 1000);
6478 	/* Wait for all the threads to die */
6479 	while (stmf_nworkers_cur != 0) {
6480 		if (ddi_get_lbolt() > sb) {
6481 			stmf_workers_state = STMF_WORKERS_ENABLED;
6482 			return (STMF_BUSY);
6483 		}
6484 		delay(drv_usectohz(100 * 1000));
6485 	}
6486 	for (i = 0; i < stmf_i_max_nworkers; i++) {
6487 		stmf_worker_t *w = &stmf_workers[i];
6488 		mutex_destroy(&w->worker_lock);
6489 		cv_destroy(&w->worker_cv);
6490 	}
6491 	kmem_free(stmf_workers, sizeof (stmf_worker_t) * stmf_i_max_nworkers);
6492 	stmf_workers = NULL;
6493 
6494 	return (STMF_SUCCESS);
6495 }
6496 
6497 void
6498 stmf_worker_task(void *arg)
6499 {
6500 	stmf_worker_t *w;
6501 	stmf_i_scsi_session_t *iss;
6502 	scsi_task_t *task;
6503 	stmf_i_scsi_task_t *itask;
6504 	stmf_data_buf_t *dbuf;
6505 	stmf_lu_t *lu;
6506 	clock_t wait_timer = 0;
6507 	clock_t wait_ticks, wait_delta = 0;
6508 	uint32_t old, new;
6509 	uint8_t curcmd;
6510 	uint8_t abort_free;
6511 	uint8_t wait_queue;
6512 	uint8_t dec_qdepth;
6513 
6514 	w = (stmf_worker_t *)arg;
6515 	wait_ticks = drv_usectohz(10000);
6516 
6517 	DTRACE_PROBE1(worker__create, stmf_worker_t, w);
6518 	mutex_enter(&w->worker_lock);
6519 	w->worker_flags |= STMF_WORKER_STARTED | STMF_WORKER_ACTIVE;
6520 stmf_worker_loop:;
6521 	if ((w->worker_ref_count == 0) &&
6522 	    (w->worker_flags & STMF_WORKER_TERMINATE)) {
6523 		w->worker_flags &= ~(STMF_WORKER_STARTED |
6524 		    STMF_WORKER_ACTIVE | STMF_WORKER_TERMINATE);
6525 		w->worker_tid = NULL;
6526 		mutex_exit(&w->worker_lock);
6527 		DTRACE_PROBE1(worker__destroy, stmf_worker_t, w);
6528 		thread_exit();
6529 	}
6530 	/* CONSTCOND */
6531 	while (1) {
6532 		dec_qdepth = 0;
6533 		if (wait_timer && (ddi_get_lbolt() >= wait_timer)) {
6534 			wait_timer = 0;
6535 			wait_delta = 0;
6536 			if (w->worker_wait_head) {
6537 				ASSERT(w->worker_wait_tail);
6538 				if (w->worker_task_head == NULL)
6539 					w->worker_task_head =
6540 					    w->worker_wait_head;
6541 				else
6542 					w->worker_task_tail->itask_worker_next =
6543 					    w->worker_wait_head;
6544 				w->worker_task_tail = w->worker_wait_tail;
6545 				w->worker_wait_head = w->worker_wait_tail =
6546 				    NULL;
6547 			}
6548 		}
6549 		if ((itask = w->worker_task_head) == NULL) {
6550 			break;
6551 		}
6552 		task = itask->itask_task;
6553 		DTRACE_PROBE2(worker__active, stmf_worker_t, w,
6554 		    scsi_task_t *, task);
6555 		w->worker_task_head = itask->itask_worker_next;
6556 		if (w->worker_task_head == NULL)
6557 			w->worker_task_tail = NULL;
6558 
6559 		wait_queue = 0;
6560 		abort_free = 0;
6561 		if (itask->itask_ncmds > 0) {
6562 			curcmd = itask->itask_cmd_stack[itask->itask_ncmds - 1];
6563 		} else {
6564 			ASSERT(itask->itask_flags & ITASK_BEING_ABORTED);
6565 		}
6566 		do {
6567 			old = itask->itask_flags;
6568 			if (old & ITASK_BEING_ABORTED) {
6569 				itask->itask_ncmds = 1;
6570 				curcmd = itask->itask_cmd_stack[0] =
6571 				    ITASK_CMD_ABORT;
6572 				goto out_itask_flag_loop;
6573 			} else if ((curcmd & ITASK_CMD_MASK) ==
6574 			    ITASK_CMD_NEW_TASK) {
6575 				/*
6576 				 * set ITASK_KSTAT_IN_RUNQ, this flag
6577 				 * will not reset until task completed
6578 				 */
6579 				new = old | ITASK_KNOWN_TO_LU |
6580 				    ITASK_KSTAT_IN_RUNQ;
6581 			} else {
6582 				goto out_itask_flag_loop;
6583 			}
6584 		} while (atomic_cas_32(&itask->itask_flags, old, new) != old);
6585 
6586 out_itask_flag_loop:
6587 
6588 		/*
6589 		 * Decide if this task needs to go to a queue and/or if
6590 		 * we can decrement the itask_cmd_stack.
6591 		 */
6592 		if (curcmd == ITASK_CMD_ABORT) {
6593 			if (itask->itask_flags & (ITASK_KNOWN_TO_LU |
6594 			    ITASK_KNOWN_TO_TGT_PORT)) {
6595 				wait_queue = 1;
6596 			} else {
6597 				abort_free = 1;
6598 			}
6599 		} else if ((curcmd & ITASK_CMD_POLL) &&
6600 		    (itask->itask_poll_timeout > ddi_get_lbolt())) {
6601 			wait_queue = 1;
6602 		}
6603 
6604 		if (wait_queue) {
6605 			itask->itask_worker_next = NULL;
6606 			if (w->worker_wait_tail) {
6607 				w->worker_wait_tail->itask_worker_next = itask;
6608 			} else {
6609 				w->worker_wait_head = itask;
6610 			}
6611 			w->worker_wait_tail = itask;
6612 			if (wait_timer == 0) {
6613 				wait_timer = ddi_get_lbolt() + wait_ticks;
6614 				wait_delta = wait_ticks;
6615 			}
6616 		} else if ((--(itask->itask_ncmds)) != 0) {
6617 			itask->itask_worker_next = NULL;
6618 			if (w->worker_task_tail) {
6619 				w->worker_task_tail->itask_worker_next = itask;
6620 			} else {
6621 				w->worker_task_head = itask;
6622 			}
6623 			w->worker_task_tail = itask;
6624 		} else {
6625 			atomic_and_32(&itask->itask_flags,
6626 			    ~ITASK_IN_WORKER_QUEUE);
6627 			/*
6628 			 * This is where the queue depth should go down by
6629 			 * one but we delay that on purpose to account for
6630 			 * the call into the provider. The actual decrement
6631 			 * happens after the worker has done its job.
6632 			 */
6633 			dec_qdepth = 1;
6634 			itask->itask_waitq_time +=
6635 			    gethrtime() - itask->itask_waitq_enter_timestamp;
6636 		}
6637 
6638 		/* We made it here means we are going to call LU */
6639 		if ((itask->itask_flags & ITASK_DEFAULT_HANDLING) == 0)
6640 			lu = task->task_lu;
6641 		else
6642 			lu = dlun0;
6643 		dbuf = itask->itask_dbufs[ITASK_CMD_BUF_NDX(curcmd)];
6644 		mutex_exit(&w->worker_lock);
6645 		curcmd &= ITASK_CMD_MASK;
6646 		stmf_task_audit(itask, TE_PROCESS_CMD, curcmd, dbuf);
6647 		switch (curcmd) {
6648 		case ITASK_CMD_NEW_TASK:
6649 			iss = (stmf_i_scsi_session_t *)
6650 			    task->task_session->ss_stmf_private;
6651 			stmf_itl_lu_new_task(itask);
6652 			if (iss->iss_flags & ISS_LUN_INVENTORY_CHANGED) {
6653 				if (stmf_handle_cmd_during_ic(itask))
6654 					break;
6655 			}
6656 #ifdef	DEBUG
6657 			if (stmf_drop_task_counter > 0) {
6658 				if (atomic_add_32_nv(
6659 				    (uint32_t *)&stmf_drop_task_counter,
6660 				    -1) == 1) {
6661 					break;
6662 				}
6663 			}
6664 #endif
6665 			DTRACE_PROBE1(scsi__task__start, scsi_task_t *, task);
6666 			lu->lu_new_task(task, dbuf);
6667 			break;
6668 		case ITASK_CMD_DATA_XFER_DONE:
6669 			lu->lu_dbuf_xfer_done(task, dbuf);
6670 			break;
6671 		case ITASK_CMD_STATUS_DONE:
6672 			lu->lu_send_status_done(task);
6673 			break;
6674 		case ITASK_CMD_ABORT:
6675 			if (abort_free) {
6676 				stmf_task_free(task);
6677 			} else {
6678 				stmf_do_task_abort(task);
6679 			}
6680 			break;
6681 		case ITASK_CMD_POLL_LU:
6682 			if (!wait_queue) {
6683 				lu->lu_task_poll(task);
6684 			}
6685 			break;
6686 		case ITASK_CMD_POLL_LPORT:
6687 			if (!wait_queue)
6688 				task->task_lport->lport_task_poll(task);
6689 			break;
6690 		case ITASK_CMD_SEND_STATUS:
6691 		/* case ITASK_CMD_XFER_DATA: */
6692 			break;
6693 		}
6694 		mutex_enter(&w->worker_lock);
6695 		if (dec_qdepth) {
6696 			w->worker_queue_depth--;
6697 		}
6698 	}
6699 	if ((w->worker_flags & STMF_WORKER_TERMINATE) && (wait_timer == 0)) {
6700 		if (w->worker_ref_count == 0)
6701 			goto stmf_worker_loop;
6702 		else {
6703 			wait_timer = ddi_get_lbolt() + 1;
6704 			wait_delta = 1;
6705 		}
6706 	}
6707 	w->worker_flags &= ~STMF_WORKER_ACTIVE;
6708 	if (wait_timer) {
6709 		DTRACE_PROBE1(worker__timed__sleep, stmf_worker_t, w);
6710 		(void) cv_reltimedwait(&w->worker_cv, &w->worker_lock,
6711 		    wait_delta, TR_CLOCK_TICK);
6712 	} else {
6713 		DTRACE_PROBE1(worker__sleep, stmf_worker_t, w);
6714 		cv_wait(&w->worker_cv, &w->worker_lock);
6715 	}
6716 	DTRACE_PROBE1(worker__wakeup, stmf_worker_t, w);
6717 	w->worker_flags |= STMF_WORKER_ACTIVE;
6718 	goto stmf_worker_loop;
6719 }
6720 
6721 void
6722 stmf_worker_mgmt()
6723 {
6724 	int i;
6725 	int workers_needed;
6726 	uint32_t qd;
6727 	clock_t tps, d = 0;
6728 	uint32_t cur_max_ntasks = 0;
6729 	stmf_worker_t *w;
6730 
6731 	/* Check if we are trying to increase the # of threads */
6732 	for (i = stmf_nworkers_cur; i < stmf_nworkers_needed; i++) {
6733 		if (stmf_workers[i].worker_flags & STMF_WORKER_STARTED) {
6734 			stmf_nworkers_cur++;
6735 			stmf_nworkers_accepting_cmds++;
6736 		} else {
6737 			/* Wait for transition to complete */
6738 			return;
6739 		}
6740 	}
6741 	/* Check if we are trying to decrease the # of workers */
6742 	for (i = (stmf_nworkers_cur - 1); i >= stmf_nworkers_needed; i--) {
6743 		if ((stmf_workers[i].worker_flags & STMF_WORKER_STARTED) == 0) {
6744 			stmf_nworkers_cur--;
6745 			/*
6746 			 * stmf_nworkers_accepting_cmds has already been
6747 			 * updated by the request to reduce the # of workers.
6748 			 */
6749 		} else {
6750 			/* Wait for transition to complete */
6751 			return;
6752 		}
6753 	}
6754 	/* Check if we are being asked to quit */
6755 	if (stmf_workers_state != STMF_WORKERS_ENABLED) {
6756 		if (stmf_nworkers_cur) {
6757 			workers_needed = 0;
6758 			goto worker_mgmt_trigger_change;
6759 		}
6760 		return;
6761 	}
6762 	/* Check if we are starting */
6763 	if (stmf_nworkers_cur < stmf_i_min_nworkers) {
6764 		workers_needed = stmf_i_min_nworkers;
6765 		goto worker_mgmt_trigger_change;
6766 	}
6767 
6768 	tps = drv_usectohz(1 * 1000 * 1000);
6769 	if ((stmf_wm_last != 0) &&
6770 	    ((d = ddi_get_lbolt() - stmf_wm_last) > tps)) {
6771 		qd = 0;
6772 		for (i = 0; i < stmf_nworkers_accepting_cmds; i++) {
6773 			qd += stmf_workers[i].worker_max_qdepth_pu;
6774 			stmf_workers[i].worker_max_qdepth_pu = 0;
6775 			if (stmf_workers[i].worker_max_sys_qdepth_pu >
6776 			    cur_max_ntasks) {
6777 				cur_max_ntasks =
6778 				    stmf_workers[i].worker_max_sys_qdepth_pu;
6779 			}
6780 			stmf_workers[i].worker_max_sys_qdepth_pu = 0;
6781 		}
6782 	}
6783 	stmf_wm_last = ddi_get_lbolt();
6784 	if (d <= tps) {
6785 		/* still ramping up */
6786 		return;
6787 	}
6788 	/* max qdepth cannot be more than max tasks */
6789 	if (qd > cur_max_ntasks)
6790 		qd = cur_max_ntasks;
6791 
6792 	/* See if we have more workers */
6793 	if (qd < stmf_nworkers_accepting_cmds) {
6794 		/*
6795 		 * Since we dont reduce the worker count right away, monitor
6796 		 * the highest load during the scale_down_delay.
6797 		 */
6798 		if (qd > stmf_worker_scale_down_qd)
6799 			stmf_worker_scale_down_qd = qd;
6800 		if (stmf_worker_scale_down_timer == 0) {
6801 			stmf_worker_scale_down_timer = ddi_get_lbolt() +
6802 			    drv_usectohz(stmf_worker_scale_down_delay *
6803 			    1000 * 1000);
6804 			return;
6805 		}
6806 		if (ddi_get_lbolt() < stmf_worker_scale_down_timer) {
6807 			return;
6808 		}
6809 		/* Its time to reduce the workers */
6810 		if (stmf_worker_scale_down_qd < stmf_i_min_nworkers)
6811 			stmf_worker_scale_down_qd = stmf_i_min_nworkers;
6812 		if (stmf_worker_scale_down_qd > stmf_i_max_nworkers)
6813 			stmf_worker_scale_down_qd = stmf_i_max_nworkers;
6814 		if (stmf_worker_scale_down_qd == stmf_nworkers_cur)
6815 			return;
6816 		workers_needed = stmf_worker_scale_down_qd;
6817 		stmf_worker_scale_down_qd = 0;
6818 		goto worker_mgmt_trigger_change;
6819 	}
6820 	stmf_worker_scale_down_qd = 0;
6821 	stmf_worker_scale_down_timer = 0;
6822 	if (qd > stmf_i_max_nworkers)
6823 		qd = stmf_i_max_nworkers;
6824 	if (qd < stmf_i_min_nworkers)
6825 		qd = stmf_i_min_nworkers;
6826 	if (qd == stmf_nworkers_cur)
6827 		return;
6828 	workers_needed = qd;
6829 	goto worker_mgmt_trigger_change;
6830 
6831 	/* NOTREACHED */
6832 	return;
6833 
6834 worker_mgmt_trigger_change:
6835 	ASSERT(workers_needed != stmf_nworkers_cur);
6836 	if (workers_needed > stmf_nworkers_cur) {
6837 		stmf_nworkers_needed = workers_needed;
6838 		for (i = stmf_nworkers_cur; i < workers_needed; i++) {
6839 			w = &stmf_workers[i];
6840 			w->worker_tid = thread_create(NULL, 0, stmf_worker_task,
6841 			    (void *)&stmf_workers[i], 0, &p0, TS_RUN,
6842 			    minclsyspri);
6843 		}
6844 		return;
6845 	}
6846 	/* At this point we know that we are decreasing the # of workers */
6847 	stmf_nworkers_accepting_cmds = workers_needed;
6848 	stmf_nworkers_needed = workers_needed;
6849 	/* Signal the workers that its time to quit */
6850 	for (i = (stmf_nworkers_cur - 1); i >= stmf_nworkers_needed; i--) {
6851 		w = &stmf_workers[i];
6852 		ASSERT(w && (w->worker_flags & STMF_WORKER_STARTED));
6853 		mutex_enter(&w->worker_lock);
6854 		w->worker_flags |= STMF_WORKER_TERMINATE;
6855 		if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0)
6856 			cv_signal(&w->worker_cv);
6857 		mutex_exit(&w->worker_lock);
6858 	}
6859 }
6860 
6861 /*
6862  * Fills out a dbuf from stmf_xfer_data_t (contained in the db_lu_private).
6863  * If all the data has been filled out, frees the xd and makes
6864  * db_lu_private NULL.
6865  */
6866 void
6867 stmf_xd_to_dbuf(stmf_data_buf_t *dbuf, int set_rel_off)
6868 {
6869 	stmf_xfer_data_t *xd;
6870 	uint8_t *p;
6871 	int i;
6872 	uint32_t s;
6873 
6874 	xd = (stmf_xfer_data_t *)dbuf->db_lu_private;
6875 	dbuf->db_data_size = 0;
6876 	if (set_rel_off)
6877 		dbuf->db_relative_offset = xd->size_done;
6878 	for (i = 0; i < dbuf->db_sglist_length; i++) {
6879 		s = min(xd->size_left, dbuf->db_sglist[i].seg_length);
6880 		p = &xd->buf[xd->size_done];
6881 		bcopy(p, dbuf->db_sglist[i].seg_addr, s);
6882 		xd->size_left -= s;
6883 		xd->size_done += s;
6884 		dbuf->db_data_size += s;
6885 		if (xd->size_left == 0) {
6886 			kmem_free(xd, xd->alloc_size);
6887 			dbuf->db_lu_private = NULL;
6888 			return;
6889 		}
6890 	}
6891 }
6892 
6893 /* ARGSUSED */
6894 stmf_status_t
6895 stmf_dlun0_task_alloc(scsi_task_t *task)
6896 {
6897 	return (STMF_SUCCESS);
6898 }
6899 
6900 void
6901 stmf_dlun0_new_task(scsi_task_t *task, stmf_data_buf_t *dbuf)
6902 {
6903 	uint8_t *cdbp = (uint8_t *)&task->task_cdb[0];
6904 	stmf_i_scsi_session_t *iss;
6905 	uint32_t sz, minsz;
6906 	uint8_t *p;
6907 	stmf_xfer_data_t *xd;
6908 	uint8_t inq_page_length = 31;
6909 
6910 	if (task->task_mgmt_function) {
6911 		stmf_scsilib_handle_task_mgmt(task);
6912 		return;
6913 	}
6914 
6915 	switch (cdbp[0]) {
6916 	case SCMD_INQUIRY:
6917 		/*
6918 		 * Basic protocol checks.  In addition, only reply to
6919 		 * standard inquiry.  Otherwise, the LU provider needs
6920 		 * to respond.
6921 		 */
6922 
6923 		if (cdbp[2] || (cdbp[1] & 1) || cdbp[5]) {
6924 			stmf_scsilib_send_status(task, STATUS_CHECK,
6925 			    STMF_SAA_INVALID_FIELD_IN_CDB);
6926 			return;
6927 		}
6928 
6929 		task->task_cmd_xfer_length =
6930 		    (((uint32_t)cdbp[3]) << 8) | cdbp[4];
6931 
6932 		if (task->task_additional_flags &
6933 		    TASK_AF_NO_EXPECTED_XFER_LENGTH) {
6934 			task->task_expected_xfer_length =
6935 			    task->task_cmd_xfer_length;
6936 		}
6937 
6938 		sz = min(task->task_expected_xfer_length,
6939 		    min(36, task->task_cmd_xfer_length));
6940 		minsz = 36;
6941 
6942 		if (sz == 0) {
6943 			stmf_scsilib_send_status(task, STATUS_GOOD, 0);
6944 			return;
6945 		}
6946 
6947 		if (dbuf && (dbuf->db_sglist[0].seg_length < 36)) {
6948 			/*
6949 			 * Ignore any preallocated dbuf if the size is less
6950 			 * than 36. It will be freed during the task_free.
6951 			 */
6952 			dbuf = NULL;
6953 		}
6954 		if (dbuf == NULL)
6955 			dbuf = stmf_alloc_dbuf(task, minsz, &minsz, 0);
6956 		if ((dbuf == NULL) || (dbuf->db_sglist[0].seg_length < sz)) {
6957 			stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6958 			    STMF_ALLOC_FAILURE, NULL);
6959 			return;
6960 		}
6961 		dbuf->db_lu_private = NULL;
6962 
6963 		p = dbuf->db_sglist[0].seg_addr;
6964 
6965 		/*
6966 		 * Standard inquiry handling only.
6967 		 */
6968 
6969 		bzero(p, inq_page_length + 5);
6970 
6971 		p[0] = DPQ_SUPPORTED | DTYPE_UNKNOWN;
6972 		p[2] = 5;
6973 		p[3] = 0x12;
6974 		p[4] = inq_page_length;
6975 		p[6] = 0x80;
6976 
6977 		(void) strncpy((char *)p+8, "SUN     ", 8);
6978 		(void) strncpy((char *)p+16, "COMSTAR	       ", 16);
6979 		(void) strncpy((char *)p+32, "1.0 ", 4);
6980 
6981 		dbuf->db_data_size = sz;
6982 		dbuf->db_relative_offset = 0;
6983 		dbuf->db_flags = DB_DIRECTION_TO_RPORT;
6984 		(void) stmf_xfer_data(task, dbuf, 0);
6985 
6986 		return;
6987 
6988 	case SCMD_REPORT_LUNS:
6989 		task->task_cmd_xfer_length =
6990 		    ((((uint32_t)task->task_cdb[6]) << 24) |
6991 		    (((uint32_t)task->task_cdb[7]) << 16) |
6992 		    (((uint32_t)task->task_cdb[8]) << 8) |
6993 		    ((uint32_t)task->task_cdb[9]));
6994 
6995 		if (task->task_additional_flags &
6996 		    TASK_AF_NO_EXPECTED_XFER_LENGTH) {
6997 			task->task_expected_xfer_length =
6998 			    task->task_cmd_xfer_length;
6999 		}
7000 
7001 		sz = min(task->task_expected_xfer_length,
7002 		    task->task_cmd_xfer_length);
7003 
7004 		if (sz < 16) {
7005 			stmf_scsilib_send_status(task, STATUS_CHECK,
7006 			    STMF_SAA_INVALID_FIELD_IN_CDB);
7007 			return;
7008 		}
7009 
7010 		iss = (stmf_i_scsi_session_t *)
7011 		    task->task_session->ss_stmf_private;
7012 		rw_enter(iss->iss_lockp, RW_WRITER);
7013 		xd = stmf_session_prepare_report_lun_data(iss->iss_sm);
7014 		rw_exit(iss->iss_lockp);
7015 
7016 		if (xd == NULL) {
7017 			stmf_abort(STMF_QUEUE_TASK_ABORT, task,
7018 			    STMF_ALLOC_FAILURE, NULL);
7019 			return;
7020 		}
7021 
7022 		sz = min(sz, xd->size_left);
7023 		xd->size_left = sz;
7024 		minsz = min(512, sz);
7025 
7026 		if (dbuf == NULL)
7027 			dbuf = stmf_alloc_dbuf(task, sz, &minsz, 0);
7028 		if (dbuf == NULL) {
7029 			kmem_free(xd, xd->alloc_size);
7030 			stmf_abort(STMF_QUEUE_TASK_ABORT, task,
7031 			    STMF_ALLOC_FAILURE, NULL);
7032 			return;
7033 		}
7034 		dbuf->db_lu_private = xd;
7035 		stmf_xd_to_dbuf(dbuf, 1);
7036 
7037 		atomic_and_32(&iss->iss_flags,
7038 		    ~(ISS_LUN_INVENTORY_CHANGED | ISS_GOT_INITIAL_LUNS));
7039 		dbuf->db_flags = DB_DIRECTION_TO_RPORT;
7040 		(void) stmf_xfer_data(task, dbuf, 0);
7041 		return;
7042 	}
7043 
7044 	stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INVALID_OPCODE);
7045 }
7046 
7047 void
7048 stmf_dlun0_dbuf_done(scsi_task_t *task, stmf_data_buf_t *dbuf)
7049 {
7050 	stmf_i_scsi_task_t *itask =
7051 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
7052 
7053 	if (dbuf->db_xfer_status != STMF_SUCCESS) {
7054 		stmf_abort(STMF_QUEUE_TASK_ABORT, task,
7055 		    dbuf->db_xfer_status, NULL);
7056 		return;
7057 	}
7058 	task->task_nbytes_transferred += dbuf->db_data_size;
7059 	if (dbuf->db_lu_private) {
7060 		/* There is more */
7061 		stmf_xd_to_dbuf(dbuf, 1);
7062 		(void) stmf_xfer_data(task, dbuf, 0);
7063 		return;
7064 	}
7065 
7066 	stmf_free_dbuf(task, dbuf);
7067 	/*
7068 	 * If this is a proxy task, it will need to be completed from the
7069 	 * proxy port provider. This message lets pppt know that the xfer
7070 	 * is complete. When we receive the status from pppt, we will
7071 	 * then relay that status back to the lport.
7072 	 */
7073 	if (itask->itask_flags & ITASK_PROXY_TASK) {
7074 		stmf_ic_msg_t *ic_xfer_done_msg = NULL;
7075 		stmf_status_t ic_ret = STMF_FAILURE;
7076 		uint64_t session_msg_id;
7077 		mutex_enter(&stmf_state.stmf_lock);
7078 		session_msg_id = stmf_proxy_msg_id++;
7079 		mutex_exit(&stmf_state.stmf_lock);
7080 		/* send xfer done status to pppt */
7081 		ic_xfer_done_msg = ic_scsi_data_xfer_done_msg_alloc(
7082 		    itask->itask_proxy_msg_id,
7083 		    task->task_session->ss_session_id,
7084 		    STMF_SUCCESS, session_msg_id);
7085 		if (ic_xfer_done_msg) {
7086 			ic_ret = ic_tx_msg(ic_xfer_done_msg);
7087 			if (ic_ret != STMF_IC_MSG_SUCCESS) {
7088 				cmn_err(CE_WARN, "unable to xmit session msg");
7089 			}
7090 		}
7091 		/* task will be completed from pppt */
7092 		return;
7093 	}
7094 	stmf_scsilib_send_status(task, STATUS_GOOD, 0);
7095 }
7096 
7097 /* ARGSUSED */
7098 void
7099 stmf_dlun0_status_done(scsi_task_t *task)
7100 {
7101 }
7102 
7103 /* ARGSUSED */
7104 void
7105 stmf_dlun0_task_free(scsi_task_t *task)
7106 {
7107 }
7108 
7109 /* ARGSUSED */
7110 stmf_status_t
7111 stmf_dlun0_abort(struct stmf_lu *lu, int abort_cmd, void *arg, uint32_t flags)
7112 {
7113 	scsi_task_t *task = (scsi_task_t *)arg;
7114 	stmf_i_scsi_task_t *itask =
7115 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
7116 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7117 	int i;
7118 	uint8_t map;
7119 
7120 	if ((task->task_mgmt_function) && (itask->itask_flags &
7121 	    (ITASK_CAUSING_LU_RESET | ITASK_CAUSING_TARGET_RESET))) {
7122 		switch (task->task_mgmt_function) {
7123 		case TM_ABORT_TASK:
7124 		case TM_ABORT_TASK_SET:
7125 		case TM_CLEAR_TASK_SET:
7126 		case TM_LUN_RESET:
7127 			atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE);
7128 			break;
7129 		case TM_TARGET_RESET:
7130 		case TM_TARGET_COLD_RESET:
7131 		case TM_TARGET_WARM_RESET:
7132 			stmf_abort_target_reset(task);
7133 			break;
7134 		}
7135 		return (STMF_ABORT_SUCCESS);
7136 	}
7137 
7138 	/*
7139 	 * OK so its not a task mgmt. Make sure we free any xd sitting
7140 	 * inside any dbuf.
7141 	 */
7142 	if ((map = itask->itask_allocated_buf_map) != 0) {
7143 		for (i = 0; i < 4; i++) {
7144 			if ((map & 1) &&
7145 			    ((itask->itask_dbufs[i])->db_lu_private)) {
7146 				stmf_xfer_data_t *xd;
7147 				stmf_data_buf_t *dbuf;
7148 
7149 				dbuf = itask->itask_dbufs[i];
7150 				xd = (stmf_xfer_data_t *)dbuf->db_lu_private;
7151 				dbuf->db_lu_private = NULL;
7152 				kmem_free(xd, xd->alloc_size);
7153 			}
7154 			map >>= 1;
7155 		}
7156 	}
7157 	return (STMF_ABORT_SUCCESS);
7158 }
7159 
7160 void
7161 stmf_dlun0_task_poll(struct scsi_task *task)
7162 {
7163 	/* Right now we only do this for handling task management functions */
7164 	ASSERT(task->task_mgmt_function);
7165 
7166 	switch (task->task_mgmt_function) {
7167 	case TM_ABORT_TASK:
7168 	case TM_ABORT_TASK_SET:
7169 	case TM_CLEAR_TASK_SET:
7170 	case TM_LUN_RESET:
7171 		(void) stmf_lun_reset_poll(task->task_lu, task, 0);
7172 		return;
7173 	case TM_TARGET_RESET:
7174 	case TM_TARGET_COLD_RESET:
7175 	case TM_TARGET_WARM_RESET:
7176 		stmf_target_reset_poll(task);
7177 		return;
7178 	}
7179 }
7180 
7181 /* ARGSUSED */
7182 void
7183 stmf_dlun0_ctl(struct stmf_lu *lu, int cmd, void *arg)
7184 {
7185 	/* This function will never be called */
7186 	cmn_err(CE_WARN, "stmf_dlun0_ctl called with cmd %x", cmd);
7187 }
7188 
7189 void
7190 stmf_dlun_init()
7191 {
7192 	stmf_i_lu_t *ilu;
7193 
7194 	dlun0 = stmf_alloc(STMF_STRUCT_STMF_LU, 0, 0);
7195 	dlun0->lu_task_alloc = stmf_dlun0_task_alloc;
7196 	dlun0->lu_new_task = stmf_dlun0_new_task;
7197 	dlun0->lu_dbuf_xfer_done = stmf_dlun0_dbuf_done;
7198 	dlun0->lu_send_status_done = stmf_dlun0_status_done;
7199 	dlun0->lu_task_free = stmf_dlun0_task_free;
7200 	dlun0->lu_abort = stmf_dlun0_abort;
7201 	dlun0->lu_task_poll = stmf_dlun0_task_poll;
7202 	dlun0->lu_ctl = stmf_dlun0_ctl;
7203 
7204 	ilu = (stmf_i_lu_t *)dlun0->lu_stmf_private;
7205 	ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1;
7206 }
7207 
7208 stmf_status_t
7209 stmf_dlun_fini()
7210 {
7211 	stmf_i_lu_t *ilu;
7212 
7213 	ilu = (stmf_i_lu_t *)dlun0->lu_stmf_private;
7214 
7215 	ASSERT(ilu->ilu_ntasks == ilu->ilu_ntasks_free);
7216 	if (ilu->ilu_ntasks) {
7217 		stmf_i_scsi_task_t *itask, *nitask;
7218 
7219 		nitask = ilu->ilu_tasks;
7220 		do {
7221 			itask = nitask;
7222 			nitask = itask->itask_lu_next;
7223 			dlun0->lu_task_free(itask->itask_task);
7224 			stmf_free(itask->itask_task);
7225 		} while (nitask != NULL);
7226 
7227 	}
7228 	stmf_free(dlun0);
7229 	return (STMF_SUCCESS);
7230 }
7231 
7232 void
7233 stmf_abort_target_reset(scsi_task_t *task)
7234 {
7235 	stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
7236 	    task->task_session->ss_stmf_private;
7237 	stmf_lun_map_t *lm;
7238 	stmf_lun_map_ent_t *lm_ent;
7239 	stmf_i_lu_t *ilu;
7240 	int i;
7241 
7242 	rw_enter(iss->iss_lockp, RW_READER);
7243 	lm = iss->iss_sm;
7244 	for (i = 0; i < lm->lm_nentries; i++) {
7245 		if (lm->lm_plus[i] == NULL)
7246 			continue;
7247 		lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
7248 		ilu = (stmf_i_lu_t *)lm_ent->ent_lu->lu_stmf_private;
7249 		if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
7250 			atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE);
7251 		}
7252 	}
7253 	atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
7254 	rw_exit(iss->iss_lockp);
7255 }
7256 
7257 /*
7258  * The return value is only used by function managing target reset.
7259  */
7260 stmf_status_t
7261 stmf_lun_reset_poll(stmf_lu_t *lu, struct scsi_task *task, int target_reset)
7262 {
7263 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
7264 	int ntasks_pending;
7265 
7266 	ntasks_pending = ilu->ilu_ntasks - ilu->ilu_ntasks_free;
7267 	/*
7268 	 * This function is also used during Target reset. The idea is that
7269 	 * once all the commands are aborted, call the LU's reset entry
7270 	 * point (abort entry point with a reset flag). But if this Task
7271 	 * mgmt is running on this LU then all the tasks cannot be aborted.
7272 	 * one task (this task) will still be running which is OK.
7273 	 */
7274 	if ((ntasks_pending == 0) || ((task->task_lu == lu) &&
7275 	    (ntasks_pending == 1))) {
7276 		stmf_status_t ret;
7277 
7278 		if ((task->task_mgmt_function == TM_LUN_RESET) ||
7279 		    (task->task_mgmt_function == TM_TARGET_RESET) ||
7280 		    (task->task_mgmt_function == TM_TARGET_WARM_RESET) ||
7281 		    (task->task_mgmt_function == TM_TARGET_COLD_RESET)) {
7282 			ret = lu->lu_abort(lu, STMF_LU_RESET_STATE, task, 0);
7283 		} else {
7284 			ret = STMF_SUCCESS;
7285 		}
7286 		if (ret == STMF_SUCCESS) {
7287 			atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE);
7288 		}
7289 		if (target_reset) {
7290 			return (ret);
7291 		}
7292 		if (ret == STMF_SUCCESS) {
7293 			stmf_scsilib_send_status(task, STATUS_GOOD, 0);
7294 			return (ret);
7295 		}
7296 		if (ret != STMF_BUSY) {
7297 			stmf_abort(STMF_QUEUE_TASK_ABORT, task, ret, NULL);
7298 			return (ret);
7299 		}
7300 	}
7301 
7302 	if (target_reset) {
7303 		/* Tell target reset polling code that we are not done */
7304 		return (STMF_BUSY);
7305 	}
7306 
7307 	if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
7308 	    != STMF_SUCCESS) {
7309 		stmf_abort(STMF_QUEUE_TASK_ABORT, task,
7310 		    STMF_ALLOC_FAILURE, NULL);
7311 		return (STMF_SUCCESS);
7312 	}
7313 
7314 	return (STMF_SUCCESS);
7315 }
7316 
7317 void
7318 stmf_target_reset_poll(struct scsi_task *task)
7319 {
7320 	stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
7321 	    task->task_session->ss_stmf_private;
7322 	stmf_lun_map_t *lm;
7323 	stmf_lun_map_ent_t *lm_ent;
7324 	stmf_i_lu_t *ilu;
7325 	stmf_status_t ret;
7326 	int i;
7327 	int not_done = 0;
7328 
7329 	ASSERT(iss->iss_flags & ISS_RESET_ACTIVE);
7330 
7331 	rw_enter(iss->iss_lockp, RW_READER);
7332 	lm = iss->iss_sm;
7333 	for (i = 0; i < lm->lm_nentries; i++) {
7334 		if (lm->lm_plus[i] == NULL)
7335 			continue;
7336 		lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
7337 		ilu = (stmf_i_lu_t *)lm_ent->ent_lu->lu_stmf_private;
7338 		if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
7339 			rw_exit(iss->iss_lockp);
7340 			ret = stmf_lun_reset_poll(lm_ent->ent_lu, task, 1);
7341 			rw_enter(iss->iss_lockp, RW_READER);
7342 			if (ret == STMF_SUCCESS)
7343 				continue;
7344 			not_done = 1;
7345 			if (ret != STMF_BUSY) {
7346 				rw_exit(iss->iss_lockp);
7347 				stmf_abort(STMF_QUEUE_TASK_ABORT, task,
7348 				    STMF_ABORTED, NULL);
7349 				return;
7350 			}
7351 		}
7352 	}
7353 	rw_exit(iss->iss_lockp);
7354 
7355 	if (not_done) {
7356 		if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
7357 		    != STMF_SUCCESS) {
7358 			stmf_abort(STMF_QUEUE_TASK_ABORT, task,
7359 			    STMF_ALLOC_FAILURE, NULL);
7360 			return;
7361 		}
7362 		return;
7363 	}
7364 
7365 	atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
7366 
7367 	stmf_scsilib_send_status(task, STATUS_GOOD, 0);
7368 }
7369 
7370 stmf_status_t
7371 stmf_lu_add_event(stmf_lu_t *lu, int eventid)
7372 {
7373 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
7374 
7375 	if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
7376 		return (STMF_INVALID_ARG);
7377 	}
7378 
7379 	STMF_EVENT_ADD(ilu->ilu_event_hdl, eventid);
7380 	return (STMF_SUCCESS);
7381 }
7382 
7383 stmf_status_t
7384 stmf_lu_remove_event(stmf_lu_t *lu, int eventid)
7385 {
7386 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
7387 
7388 	if (eventid == STMF_EVENT_ALL) {
7389 		STMF_EVENT_CLEAR_ALL(ilu->ilu_event_hdl);
7390 		return (STMF_SUCCESS);
7391 	}
7392 
7393 	if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
7394 		return (STMF_INVALID_ARG);
7395 	}
7396 
7397 	STMF_EVENT_REMOVE(ilu->ilu_event_hdl, eventid);
7398 	return (STMF_SUCCESS);
7399 }
7400 
7401 stmf_status_t
7402 stmf_lport_add_event(stmf_local_port_t *lport, int eventid)
7403 {
7404 	stmf_i_local_port_t *ilport =
7405 	    (stmf_i_local_port_t *)lport->lport_stmf_private;
7406 
7407 	if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
7408 		return (STMF_INVALID_ARG);
7409 	}
7410 
7411 	STMF_EVENT_ADD(ilport->ilport_event_hdl, eventid);
7412 	return (STMF_SUCCESS);
7413 }
7414 
7415 stmf_status_t
7416 stmf_lport_remove_event(stmf_local_port_t *lport, int eventid)
7417 {
7418 	stmf_i_local_port_t *ilport =
7419 	    (stmf_i_local_port_t *)lport->lport_stmf_private;
7420 
7421 	if (eventid == STMF_EVENT_ALL) {
7422 		STMF_EVENT_CLEAR_ALL(ilport->ilport_event_hdl);
7423 		return (STMF_SUCCESS);
7424 	}
7425 
7426 	if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
7427 		return (STMF_INVALID_ARG);
7428 	}
7429 
7430 	STMF_EVENT_REMOVE(ilport->ilport_event_hdl, eventid);
7431 	return (STMF_SUCCESS);
7432 }
7433 
7434 void
7435 stmf_generate_lu_event(stmf_i_lu_t *ilu, int eventid, void *arg, uint32_t flags)
7436 {
7437 	if (STMF_EVENT_ENABLED(ilu->ilu_event_hdl, eventid) &&
7438 	    (ilu->ilu_lu->lu_event_handler != NULL)) {
7439 		ilu->ilu_lu->lu_event_handler(ilu->ilu_lu, eventid, arg, flags);
7440 	}
7441 }
7442 
7443 void
7444 stmf_generate_lport_event(stmf_i_local_port_t *ilport, int eventid, void *arg,
7445 				uint32_t flags)
7446 {
7447 	if (STMF_EVENT_ENABLED(ilport->ilport_event_hdl, eventid) &&
7448 	    (ilport->ilport_lport->lport_event_handler != NULL)) {
7449 		ilport->ilport_lport->lport_event_handler(
7450 		    ilport->ilport_lport, eventid, arg, flags);
7451 	}
7452 }
7453 
7454 /*
7455  * With the possibility of having multiple itl sessions pointing to the
7456  * same itl_kstat_info, the ilu_kstat_lock mutex is used to synchronize
7457  * the kstat update of the ilu_kstat_io, itl_kstat_taskq and itl_kstat_lu_xfer
7458  * statistics.
7459  */
7460 void
7461 stmf_itl_task_start(stmf_i_scsi_task_t *itask)
7462 {
7463 	stmf_itl_data_t	*itl = itask->itask_itl_datap;
7464 	scsi_task_t	*task = itask->itask_task;
7465 	stmf_i_lu_t	*ilu;
7466 
7467 	if (itl == NULL || task->task_lu == dlun0)
7468 		return;
7469 	ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7470 	mutex_enter(ilu->ilu_kstat_io->ks_lock);
7471 	itask->itask_start_timestamp = gethrtime();
7472 	kstat_waitq_enter(KSTAT_IO_PTR(itl->itl_kstat_taskq));
7473 	stmf_update_kstat_lu_q(itask->itask_task, kstat_waitq_enter);
7474 	mutex_exit(ilu->ilu_kstat_io->ks_lock);
7475 
7476 	stmf_update_kstat_lport_q(itask->itask_task, kstat_waitq_enter);
7477 }
7478 
7479 void
7480 stmf_itl_lu_new_task(stmf_i_scsi_task_t *itask)
7481 {
7482 	stmf_itl_data_t	*itl = itask->itask_itl_datap;
7483 	scsi_task_t	*task = itask->itask_task;
7484 	stmf_i_lu_t	*ilu;
7485 
7486 	if (itl == NULL || task->task_lu == dlun0)
7487 		return;
7488 	ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7489 	mutex_enter(ilu->ilu_kstat_io->ks_lock);
7490 	kstat_waitq_to_runq(KSTAT_IO_PTR(itl->itl_kstat_taskq));
7491 	stmf_update_kstat_lu_q(itask->itask_task, kstat_waitq_to_runq);
7492 	mutex_exit(ilu->ilu_kstat_io->ks_lock);
7493 
7494 	stmf_update_kstat_lport_q(itask->itask_task, kstat_waitq_to_runq);
7495 }
7496 
7497 void
7498 stmf_itl_task_done(stmf_i_scsi_task_t *itask)
7499 {
7500 	stmf_itl_data_t		*itl = itask->itask_itl_datap;
7501 	scsi_task_t		*task = itask->itask_task;
7502 	kstat_io_t		*kip;
7503 	hrtime_t		elapsed_time;
7504 	stmf_kstat_itl_info_t	*itli;
7505 	stmf_i_lu_t	*ilu;
7506 
7507 	if (itl == NULL || task->task_lu == dlun0)
7508 		return;
7509 	ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7510 
7511 	mutex_enter(ilu->ilu_kstat_io->ks_lock);
7512 	itli = (stmf_kstat_itl_info_t *)KSTAT_NAMED_PTR(itl->itl_kstat_info);
7513 	kip = KSTAT_IO_PTR(itl->itl_kstat_taskq);
7514 
7515 	itli->i_task_waitq_elapsed.value.ui64 += itask->itask_waitq_time;
7516 
7517 	itask->itask_done_timestamp = gethrtime();
7518 	elapsed_time =
7519 	    itask->itask_done_timestamp - itask->itask_start_timestamp;
7520 
7521 	if (task->task_flags & TF_READ_DATA) {
7522 		kip->reads++;
7523 		kip->nread += itask->itask_read_xfer;
7524 		itli->i_task_read_elapsed.value.ui64 += elapsed_time;
7525 		itli->i_lu_read_elapsed.value.ui64 +=
7526 		    itask->itask_lu_read_time;
7527 		itli->i_lport_read_elapsed.value.ui64 +=
7528 		    itask->itask_lport_read_time;
7529 	}
7530 
7531 	if (task->task_flags & TF_WRITE_DATA) {
7532 		kip->writes++;
7533 		kip->nwritten += itask->itask_write_xfer;
7534 		itli->i_task_write_elapsed.value.ui64 += elapsed_time;
7535 		itli->i_lu_write_elapsed.value.ui64 +=
7536 		    itask->itask_lu_write_time;
7537 		itli->i_lport_write_elapsed.value.ui64 +=
7538 		    itask->itask_lport_write_time;
7539 	}
7540 
7541 	if (itask->itask_flags & ITASK_KSTAT_IN_RUNQ) {
7542 		kstat_runq_exit(kip);
7543 		stmf_update_kstat_lu_q(task, kstat_runq_exit);
7544 		mutex_exit(ilu->ilu_kstat_io->ks_lock);
7545 		stmf_update_kstat_lport_q(task, kstat_runq_exit);
7546 	} else {
7547 		kstat_waitq_exit(kip);
7548 		stmf_update_kstat_lu_q(task, kstat_waitq_exit);
7549 		mutex_exit(ilu->ilu_kstat_io->ks_lock);
7550 		stmf_update_kstat_lport_q(task, kstat_waitq_exit);
7551 	}
7552 }
7553 
7554 void
7555 stmf_lu_xfer_start(scsi_task_t *task)
7556 {
7557 	stmf_i_scsi_task_t *itask = task->task_stmf_private;
7558 	stmf_itl_data_t	*itl = itask->itask_itl_datap;
7559 	stmf_i_lu_t	*ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7560 	kstat_io_t		*kip;
7561 
7562 	if (itl == NULL || task->task_lu == dlun0)
7563 		return;
7564 
7565 	kip = KSTAT_IO_PTR(itl->itl_kstat_lu_xfer);
7566 	mutex_enter(ilu->ilu_kstat_io->ks_lock);
7567 	kstat_runq_enter(kip);
7568 	mutex_exit(ilu->ilu_kstat_io->ks_lock);
7569 }
7570 
7571 void
7572 stmf_lu_xfer_done(scsi_task_t *task, boolean_t read, uint64_t xfer_bytes,
7573     hrtime_t elapsed_time)
7574 {
7575 	stmf_i_scsi_task_t	*itask = task->task_stmf_private;
7576 	stmf_itl_data_t		*itl = itask->itask_itl_datap;
7577 	stmf_i_lu_t	*ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7578 	kstat_io_t		*kip;
7579 
7580 	if (itl == NULL || task->task_lu == dlun0)
7581 		return;
7582 
7583 	if (read) {
7584 		atomic_add_64((uint64_t *)&itask->itask_lu_read_time,
7585 		    elapsed_time);
7586 	} else {
7587 		atomic_add_64((uint64_t *)&itask->itask_lu_write_time,
7588 		    elapsed_time);
7589 	}
7590 
7591 	kip = KSTAT_IO_PTR(itl->itl_kstat_lu_xfer);
7592 	mutex_enter(ilu->ilu_kstat_io->ks_lock);
7593 	kstat_runq_exit(kip);
7594 	if (read) {
7595 		kip->reads++;
7596 		kip->nread += xfer_bytes;
7597 	} else {
7598 		kip->writes++;
7599 		kip->nwritten += xfer_bytes;
7600 	}
7601 	mutex_exit(ilu->ilu_kstat_io->ks_lock);
7602 }
7603 
7604 static void
7605 stmf_lport_xfer_start(stmf_i_scsi_task_t *itask, stmf_data_buf_t *dbuf)
7606 {
7607 	stmf_itl_data_t		*itl = itask->itask_itl_datap;
7608 
7609 	if (itl == NULL)
7610 		return;
7611 
7612 	DTRACE_PROBE2(scsi__xfer__start, scsi_task_t *, itask->itask_task,
7613 	    stmf_data_buf_t *, dbuf);
7614 
7615 	dbuf->db_xfer_start_timestamp = gethrtime();
7616 }
7617 
7618 static void
7619 stmf_lport_xfer_done(stmf_i_scsi_task_t *itask, stmf_data_buf_t *dbuf)
7620 {
7621 	stmf_itl_data_t		*itl = itask->itask_itl_datap;
7622 	scsi_task_t		*task;
7623 	stmf_i_local_port_t	*ilp;
7624 	kstat_io_t		*kip;
7625 	hrtime_t		elapsed_time;
7626 	uint64_t		xfer_size;
7627 
7628 	if (itl == NULL)
7629 		return;
7630 
7631 	task = (scsi_task_t *)itask->itask_task;
7632 	ilp = (stmf_i_local_port_t *)task->task_lport->lport_stmf_private;
7633 	xfer_size = (dbuf->db_xfer_status == STMF_SUCCESS) ?
7634 	    dbuf->db_data_size : 0;
7635 
7636 	elapsed_time = gethrtime() - dbuf->db_xfer_start_timestamp;
7637 	if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
7638 		atomic_add_64((uint64_t *)&itask->itask_lport_read_time,
7639 		    elapsed_time);
7640 		atomic_add_64((uint64_t *)&itask->itask_read_xfer,
7641 		    xfer_size);
7642 	} else {
7643 		atomic_add_64((uint64_t *)&itask->itask_lport_write_time,
7644 		    elapsed_time);
7645 		atomic_add_64((uint64_t *)&itask->itask_write_xfer,
7646 		    xfer_size);
7647 	}
7648 
7649 	DTRACE_PROBE3(scsi__xfer__end, scsi_task_t *, itask->itask_task,
7650 	    stmf_data_buf_t *, dbuf, hrtime_t, elapsed_time);
7651 
7652 	kip = KSTAT_IO_PTR(itl->itl_kstat_lport_xfer);
7653 	mutex_enter(ilp->ilport_kstat_io->ks_lock);
7654 	if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
7655 		kip->reads++;
7656 		kip->nread += xfer_size;
7657 	} else {
7658 		kip->writes++;
7659 		kip->nwritten += xfer_size;
7660 	}
7661 	mutex_exit(ilp->ilport_kstat_io->ks_lock);
7662 
7663 	dbuf->db_xfer_start_timestamp = 0;
7664 }
7665 
7666 void
7667 stmf_svc_init()
7668 {
7669 	if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED)
7670 		return;
7671 	stmf_state.stmf_svc_taskq = ddi_taskq_create(0, "STMF_SVC_TASKQ", 1,
7672 	    TASKQ_DEFAULTPRI, 0);
7673 	(void) ddi_taskq_dispatch(stmf_state.stmf_svc_taskq,
7674 	    stmf_svc, 0, DDI_SLEEP);
7675 }
7676 
7677 stmf_status_t
7678 stmf_svc_fini()
7679 {
7680 	uint32_t i;
7681 
7682 	mutex_enter(&stmf_state.stmf_lock);
7683 	if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED) {
7684 		stmf_state.stmf_svc_flags |= STMF_SVC_TERMINATE;
7685 		cv_signal(&stmf_state.stmf_cv);
7686 	}
7687 	mutex_exit(&stmf_state.stmf_lock);
7688 
7689 	/* Wait for 5 seconds */
7690 	for (i = 0; i < 500; i++) {
7691 		if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED)
7692 			delay(drv_usectohz(10000));
7693 		else
7694 			break;
7695 	}
7696 	if (i == 500)
7697 		return (STMF_BUSY);
7698 
7699 	ddi_taskq_destroy(stmf_state.stmf_svc_taskq);
7700 
7701 	return (STMF_SUCCESS);
7702 }
7703 
7704 /* ARGSUSED */
7705 void
7706 stmf_svc(void *arg)
7707 {
7708 	stmf_svc_req_t *req, **preq;
7709 	clock_t td;
7710 	clock_t	drain_start, drain_next = 0;
7711 	clock_t	timing_start, timing_next = 0;
7712 	clock_t worker_delay = 0;
7713 	int deq;
7714 	stmf_lu_t *lu;
7715 	stmf_i_lu_t *ilu;
7716 	stmf_local_port_t *lport;
7717 	stmf_i_local_port_t *ilport, *next_ilport;
7718 	stmf_i_scsi_session_t *iss;
7719 
7720 	td = drv_usectohz(20000);
7721 
7722 	mutex_enter(&stmf_state.stmf_lock);
7723 	stmf_state.stmf_svc_flags |= STMF_SVC_STARTED | STMF_SVC_ACTIVE;
7724 
7725 stmf_svc_loop:
7726 	if (stmf_state.stmf_svc_flags & STMF_SVC_TERMINATE) {
7727 		stmf_state.stmf_svc_flags &=
7728 		    ~(STMF_SVC_STARTED | STMF_SVC_ACTIVE);
7729 		mutex_exit(&stmf_state.stmf_lock);
7730 		return;
7731 	}
7732 
7733 	if (stmf_state.stmf_svc_active) {
7734 		int waitq_add = 0;
7735 		req = stmf_state.stmf_svc_active;
7736 		stmf_state.stmf_svc_active = req->svc_next;
7737 
7738 		switch (req->svc_cmd) {
7739 		case STMF_CMD_LPORT_ONLINE:
7740 			/* Fallthrough */
7741 		case STMF_CMD_LPORT_OFFLINE:
7742 			/* Fallthrough */
7743 		case STMF_CMD_LU_ONLINE:
7744 			/* Nothing to do */
7745 			waitq_add = 1;
7746 			break;
7747 
7748 		case STMF_CMD_LU_OFFLINE:
7749 			/* Remove all mappings of this LU */
7750 			stmf_session_lu_unmapall((stmf_lu_t *)req->svc_obj);
7751 			/* Kill all the pending I/Os for this LU */
7752 			mutex_exit(&stmf_state.stmf_lock);
7753 			stmf_task_lu_killall((stmf_lu_t *)req->svc_obj, NULL,
7754 			    STMF_ABORTED);
7755 			mutex_enter(&stmf_state.stmf_lock);
7756 			waitq_add = 1;
7757 			break;
7758 		default:
7759 			cmn_err(CE_PANIC, "stmf_svc: unknown cmd %d",
7760 			    req->svc_cmd);
7761 		}
7762 
7763 		if (waitq_add) {
7764 			/* Put it in the wait queue */
7765 			req->svc_next = stmf_state.stmf_svc_waiting;
7766 			stmf_state.stmf_svc_waiting = req;
7767 		}
7768 	}
7769 
7770 	/* The waiting list is not going to be modified by anybody else */
7771 	mutex_exit(&stmf_state.stmf_lock);
7772 
7773 	for (preq = &stmf_state.stmf_svc_waiting; (*preq) != NULL; ) {
7774 		req = *preq;
7775 		deq = 0;
7776 
7777 		switch (req->svc_cmd) {
7778 		case STMF_CMD_LU_ONLINE:
7779 			lu = (stmf_lu_t *)req->svc_obj;
7780 			deq = 1;
7781 			lu->lu_ctl(lu, req->svc_cmd, &req->svc_info);
7782 			break;
7783 
7784 		case STMF_CMD_LU_OFFLINE:
7785 			lu = (stmf_lu_t *)req->svc_obj;
7786 			ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
7787 			if (ilu->ilu_ntasks != ilu->ilu_ntasks_free)
7788 				break;
7789 			deq = 1;
7790 			lu->lu_ctl(lu, req->svc_cmd, &req->svc_info);
7791 			break;
7792 
7793 		case STMF_CMD_LPORT_OFFLINE:
7794 			/* Fallthrough */
7795 		case STMF_CMD_LPORT_ONLINE:
7796 			lport = (stmf_local_port_t *)req->svc_obj;
7797 			deq = 1;
7798 			lport->lport_ctl(lport, req->svc_cmd, &req->svc_info);
7799 			break;
7800 		}
7801 		if (deq) {
7802 			*preq = req->svc_next;
7803 			kmem_free(req, req->svc_req_alloc_size);
7804 		} else {
7805 			preq = &req->svc_next;
7806 		}
7807 	}
7808 
7809 	mutex_enter(&stmf_state.stmf_lock);
7810 	if (stmf_state.stmf_svc_active == NULL) {
7811 		/* Do timeouts */
7812 		if (stmf_state.stmf_nlus &&
7813 		    ((!timing_next) || (ddi_get_lbolt() >= timing_next))) {
7814 			if (!stmf_state.stmf_svc_ilu_timing) {
7815 				/* we are starting a new round */
7816 				stmf_state.stmf_svc_ilu_timing =
7817 				    stmf_state.stmf_ilulist;
7818 				timing_start = ddi_get_lbolt();
7819 			}
7820 			stmf_check_ilu_timing();
7821 			if (!stmf_state.stmf_svc_ilu_timing) {
7822 				/* we finished a complete round */
7823 				timing_next =
7824 				    timing_start + drv_usectohz(5*1000*1000);
7825 			} else {
7826 				/* we still have some ilu items to check */
7827 				timing_next =
7828 				    ddi_get_lbolt() + drv_usectohz(1*1000*1000);
7829 			}
7830 			if (stmf_state.stmf_svc_active)
7831 				goto stmf_svc_loop;
7832 		}
7833 		/* Check if there are free tasks to clear */
7834 		if (stmf_state.stmf_nlus &&
7835 		    ((!drain_next) || (ddi_get_lbolt() >= drain_next))) {
7836 			if (!stmf_state.stmf_svc_ilu_draining) {
7837 				/* we are starting a new round */
7838 				stmf_state.stmf_svc_ilu_draining =
7839 				    stmf_state.stmf_ilulist;
7840 				drain_start = ddi_get_lbolt();
7841 			}
7842 			stmf_check_freetask();
7843 			if (!stmf_state.stmf_svc_ilu_draining) {
7844 				/* we finished a complete round */
7845 				drain_next =
7846 				    drain_start + drv_usectohz(10*1000*1000);
7847 			} else {
7848 				/* we still have some ilu items to check */
7849 				drain_next =
7850 				    ddi_get_lbolt() + drv_usectohz(1*1000*1000);
7851 			}
7852 			if (stmf_state.stmf_svc_active)
7853 				goto stmf_svc_loop;
7854 		}
7855 
7856 		/* Check if we need to run worker_mgmt */
7857 		if (ddi_get_lbolt() > worker_delay) {
7858 			stmf_worker_mgmt();
7859 			worker_delay = ddi_get_lbolt() +
7860 			    stmf_worker_mgmt_delay;
7861 		}
7862 
7863 		/* Check if any active session got its 1st LUN */
7864 		if (stmf_state.stmf_process_initial_luns) {
7865 			int stmf_level = 0;
7866 			int port_level;
7867 			for (ilport = stmf_state.stmf_ilportlist; ilport;
7868 			    ilport = next_ilport) {
7869 				int ilport_lock_held;
7870 				next_ilport = ilport->ilport_next;
7871 				if ((ilport->ilport_flags &
7872 				    ILPORT_SS_GOT_INITIAL_LUNS) == 0) {
7873 					continue;
7874 				}
7875 				port_level = 0;
7876 				rw_enter(&ilport->ilport_lock, RW_READER);
7877 				ilport_lock_held = 1;
7878 				for (iss = ilport->ilport_ss_list; iss;
7879 				    iss = iss->iss_next) {
7880 					if ((iss->iss_flags &
7881 					    ISS_GOT_INITIAL_LUNS) == 0) {
7882 						continue;
7883 					}
7884 					port_level++;
7885 					stmf_level++;
7886 					atomic_and_32(&iss->iss_flags,
7887 					    ~ISS_GOT_INITIAL_LUNS);
7888 					atomic_or_32(&iss->iss_flags,
7889 					    ISS_EVENT_ACTIVE);
7890 					rw_exit(&ilport->ilport_lock);
7891 					ilport_lock_held = 0;
7892 					mutex_exit(&stmf_state.stmf_lock);
7893 					stmf_generate_lport_event(ilport,
7894 					    LPORT_EVENT_INITIAL_LUN_MAPPED,
7895 					    iss->iss_ss, 0);
7896 					atomic_and_32(&iss->iss_flags,
7897 					    ~ISS_EVENT_ACTIVE);
7898 					mutex_enter(&stmf_state.stmf_lock);
7899 					/*
7900 					 * scan all the ilports again as the
7901 					 * ilport list might have changed.
7902 					 */
7903 					next_ilport =
7904 					    stmf_state.stmf_ilportlist;
7905 					break;
7906 				}
7907 				if (port_level == 0) {
7908 					atomic_and_32(&ilport->ilport_flags,
7909 					    ~ILPORT_SS_GOT_INITIAL_LUNS);
7910 				}
7911 				/* drop the lock if we are holding it. */
7912 				if (ilport_lock_held == 1)
7913 					rw_exit(&ilport->ilport_lock);
7914 
7915 				/* Max 4 session at a time */
7916 				if (stmf_level >= 4) {
7917 					break;
7918 				}
7919 			}
7920 			if (stmf_level == 0) {
7921 				stmf_state.stmf_process_initial_luns = 0;
7922 			}
7923 		}
7924 
7925 		stmf_state.stmf_svc_flags &= ~STMF_SVC_ACTIVE;
7926 		(void) cv_reltimedwait(&stmf_state.stmf_cv,
7927 		    &stmf_state.stmf_lock, td, TR_CLOCK_TICK);
7928 		stmf_state.stmf_svc_flags |= STMF_SVC_ACTIVE;
7929 	}
7930 	goto stmf_svc_loop;
7931 }
7932 
7933 void
7934 stmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info)
7935 {
7936 	stmf_svc_req_t *req;
7937 	int s;
7938 
7939 	ASSERT(!mutex_owned(&stmf_state.stmf_lock));
7940 	s = sizeof (stmf_svc_req_t);
7941 	if (info->st_additional_info) {
7942 		s += strlen(info->st_additional_info) + 1;
7943 	}
7944 	req = kmem_zalloc(s, KM_SLEEP);
7945 
7946 	req->svc_cmd = cmd;
7947 	req->svc_obj = obj;
7948 	req->svc_info.st_rflags = info->st_rflags;
7949 	if (info->st_additional_info) {
7950 		req->svc_info.st_additional_info = (char *)(GET_BYTE_OFFSET(req,
7951 		    sizeof (stmf_svc_req_t)));
7952 		(void) strcpy(req->svc_info.st_additional_info,
7953 		    info->st_additional_info);
7954 	}
7955 	req->svc_req_alloc_size = s;
7956 
7957 	mutex_enter(&stmf_state.stmf_lock);
7958 	req->svc_next = stmf_state.stmf_svc_active;
7959 	stmf_state.stmf_svc_active = req;
7960 	if ((stmf_state.stmf_svc_flags & STMF_SVC_ACTIVE) == 0) {
7961 		cv_signal(&stmf_state.stmf_cv);
7962 	}
7963 	mutex_exit(&stmf_state.stmf_lock);
7964 }
7965 
7966 void
7967 stmf_trace(caddr_t ident, const char *fmt, ...)
7968 {
7969 	va_list args;
7970 	char tbuf[160];
7971 	int len;
7972 
7973 	if (!stmf_trace_on)
7974 		return;
7975 	len = snprintf(tbuf, 158, "%s:%07lu: ", ident ? ident : "",
7976 	    ddi_get_lbolt());
7977 	va_start(args, fmt);
7978 	len += vsnprintf(tbuf + len, 158 - len, fmt, args);
7979 	va_end(args);
7980 
7981 	if (len > 158) {
7982 		len = 158;
7983 	}
7984 	tbuf[len++] = '\n';
7985 	tbuf[len] = 0;
7986 
7987 	mutex_enter(&trace_buf_lock);
7988 	bcopy(tbuf, &stmf_trace_buf[trace_buf_curndx], len+1);
7989 	trace_buf_curndx += len;
7990 	if (trace_buf_curndx > (trace_buf_size - 320))
7991 		trace_buf_curndx = 0;
7992 	mutex_exit(&trace_buf_lock);
7993 }
7994 
7995 void
7996 stmf_trace_clear()
7997 {
7998 	if (!stmf_trace_on)
7999 		return;
8000 	mutex_enter(&trace_buf_lock);
8001 	trace_buf_curndx = 0;
8002 	if (trace_buf_size > 0)
8003 		stmf_trace_buf[0] = 0;
8004 	mutex_exit(&trace_buf_lock);
8005 }
8006 
8007 static void
8008 stmf_abort_task_offline(scsi_task_t *task, int offline_lu, char *info)
8009 {
8010 	stmf_state_change_info_t	change_info;
8011 	void				*ctl_private;
8012 	uint32_t			ctl_cmd;
8013 	int				msg = 0;
8014 
8015 	stmf_trace("FROM STMF", "abort_task_offline called for %s: %s",
8016 	    offline_lu ? "LU" : "LPORT", info ? info : "no additional info");
8017 	change_info.st_additional_info = info;
8018 	if (offline_lu) {
8019 		change_info.st_rflags = STMF_RFLAG_RESET |
8020 		    STMF_RFLAG_LU_ABORT;
8021 		ctl_private = task->task_lu;
8022 		if (((stmf_i_lu_t *)
8023 		    task->task_lu->lu_stmf_private)->ilu_state ==
8024 		    STMF_STATE_ONLINE) {
8025 			msg = 1;
8026 		}
8027 		ctl_cmd = STMF_CMD_LU_OFFLINE;
8028 	} else {
8029 		change_info.st_rflags = STMF_RFLAG_RESET |
8030 		    STMF_RFLAG_LPORT_ABORT;
8031 		ctl_private = task->task_lport;
8032 		if (((stmf_i_local_port_t *)
8033 		    task->task_lport->lport_stmf_private)->ilport_state ==
8034 		    STMF_STATE_ONLINE) {
8035 			msg = 1;
8036 		}
8037 		ctl_cmd = STMF_CMD_LPORT_OFFLINE;
8038 	}
8039 
8040 	if (msg) {
8041 		stmf_trace(0, "Calling stmf_ctl to offline %s : %s",
8042 		    offline_lu ? "LU" : "LPORT", info ? info :
8043 		    "<no additional info>");
8044 	}
8045 	(void) stmf_ctl(ctl_cmd, ctl_private, &change_info);
8046 }
8047