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