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