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