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